[D3D8 PATCH] d3d8 shaders update - VS2

Raphaël Junqueira fenix at club-internet.fr
Tue Dec 17 18:24:27 CST 2002


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi again,

this second patch (who need the "[D3D8 PATCH] d3d8types updates - VS1" first patch) contains:
 - some fixes in CreateDevice init (jason will do a better auto-detect caps init)
 - vertex shader declaration parser (with output dump) and interpretation (generate the FVF descriptor for program input)
 - vertex shader program parser (with output dump)
 - software vertex shader program emulation

TODO:
 - vertex shader integration into DrawPrimitive (only in my prototype, i'll send it when it will be more clean)
 - hardware vertex shader program support (using auto-detect caps)
 - syntax validity of vertex shader declaration and vexter shader function code (Validate*Shader functions)
 - fix the declaration parser - FVF generation
 - vertex shader compilator (in D3DX8)
 - pixel shaders

thx again, Raphael
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD8DBQE9/8A7p7NA3AmQTU4RAm9fAJ9gtu/9Nu3mFLYTtbJ3pvgQG8+8GwCeIR4r
DE7s+ZD1WWaHv9V/kZqhJ1Q=
=112G
-----END PGP SIGNATURE-----
-------------- next part --------------
Index: device.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/device.c,v
retrieving revision 1.15
diff -u -r1.15 device.c
--- device.c	17 Dec 2002 04:14:34 -0000	1.15
+++ device.c	18 Dec 2002 00:12:17 -0000
@@ -177,7 +177,7 @@
 
         } else {
             glMatrixMode(GL_PROJECTION);
-	        checkGLcall("glMatrixMode");
+	    checkGLcall("glMatrixMode");
             glLoadMatrixf((float *) &This->StateBlock.transforms[D3DTS_PROJECTION].u.m[0][0]);
             checkGLcall("glLoadMatrixf");
 
@@ -2153,6 +2153,8 @@
     case D3DRS_INDEXEDVERTEXBLENDENABLE  :
     case D3DRS_COLORWRITEENABLE          :
     case D3DRS_TWEENFACTOR               :
+    case D3DRS_POSITIONORDER             :
+    case D3DRS_NORMALORDER               :
         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
         TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
         break;
@@ -3128,7 +3130,7 @@
     VERTEXSHADER8* object;
     UINT i;
 
-    FIXME("(%p) : VertexShader not fully supported yet\n", This);    
+    FIXME("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p\n", This, pDeclaration, pFunction);    
     if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
       return D3DERR_INVALIDCALL;
     }
@@ -3142,21 +3144,26 @@
     }
 
     object->usage = Usage;
-    object->data = NULL; /* TODO */
+    object->data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SHADER8Data));
 
     VertexShaders[i] = object;
     *pHandle = VS_HIGHESTFIXEDFXF + i;
 
     object->decl = pDeclaration;
+    object->function = pFunction;
+
+    /*
     for (i = 0; 0xFFFFFFFF != pDeclaration[i]; ++i) ;
     object->declLength = i + 1;
-    object->function = pFunction;
     if (NULL != pFunction) {
       for (i = 0; 0xFFFFFFFF != pFunction[i]; ++i) ;
       object->functionLength = i + 1;
     } else {
-      object->functionLength = 1; /* no Function defined use fixed function vertex processing */
+      object->functionLength = 1; // no Function defined use fixed function vertex processing
     }
+    */
+    vshader_decl_parse(object);
+    vshader_program_parse(object);
 
     return D3D_OK;
 }
@@ -3172,7 +3179,6 @@
         TRACE("Recording... not performing anything\n");
         return D3D_OK;
     }
-
     if (Handle <= VS_HIGHESTFIXEDFXF) {
         TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
         return D3D_OK;
@@ -3196,10 +3202,14 @@
       return D3DERR_INVALIDCALL;
     }
     object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
+    if (NULL == object) {
+      return D3DERR_INVALIDCALL;
+    }
     TRACE("(%p) : freing VertexShader %p\n", This, object);
     /* TODO: check validity of object */
+    if (NULL != object->data) HeapFree(GetProcessHeap(), 0, (void *)object->data);
     HeapFree(GetProcessHeap(), 0, (void *)object);
-    VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = 0;
+    VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
     return D3D_OK;
 }
 
@@ -3210,8 +3220,7 @@
   VERTEXSHADER8* object;
   DWORD Handle = This->UpdateStateBlock->VertexShader;
 
-  FIXME("(%p) : VertexShader_SetConstant not fully supported yet\n", This);   
-
+  /* FIXME("(%p) : VertexShader_SetConstant not fully supported yet\n", This); */
   if (Register + ConstantCount > VSHADER_MAX_CONSTANTS) {
     return D3DERR_INVALIDCALL;
   }
@@ -3219,7 +3228,11 @@
   if (NULL == object || NULL == pConstantData) {
     return D3DERR_INVALIDCALL;
   }
-  memcpy(object->data->constants + Register, pConstantData, ConstantCount * sizeof(SHADER8Vector));
+  if (NULL == object->data) { /* temporary while datas not supported */
+    FIXME("(%p) : VertexShader_SetConstant not fully supported yet\n", This);
+    return D3DERR_INVALIDCALL;
+  }
+  memcpy(object->data->C + Register, pConstantData, ConstantCount * sizeof(SHADER8Vector));
 
   return D3D_OK;
 }
@@ -3237,7 +3250,10 @@
   if (NULL == object || NULL == pConstantData) {
     return D3DERR_INVALIDCALL;
   }
-  memcpy(pConstantData, object->data->constants + Register, ConstantCount * sizeof(SHADER8Vector));
+  if (NULL == object->data) { /* temporary while datas not supported */
+    return D3DERR_INVALIDCALL;
+  }
+  memcpy(pConstantData, object->data->C + Register, ConstantCount * sizeof(SHADER8Vector));
 
   return D3D_OK;
 }
@@ -3288,10 +3304,9 @@
 }
 
 HRESULT  WINAPI  IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData,UINT BaseVertexIndex) {
-
+    ICOM_THIS(IDirect3DDevice8Impl,iface);
     IDirect3DIndexBuffer8 *oldIdxs;
 
-    ICOM_THIS(IDirect3DDevice8Impl,iface);
     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
     oldIdxs = This->StateBlock.pIndexData;
 
Index: directx.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/directx.c,v
retrieving revision 1.7
diff -u -r1.7 directx.c
--- directx.c	17 Dec 2002 01:15:16 -0000	1.7
+++ directx.c	18 Dec 2002 00:12:19 -0000
@@ -382,7 +382,10 @@
                                                             IDirect3DDevice8** ppReturnedDeviceInterface) {
     IDirect3DDevice8Impl *object;
     HWND whichHWND;
+    int num;
+    XVisualInfo template;
     const char *GL_Extensions = NULL;
+    const char *GLX_Extensions = NULL;
 
     ICOM_THIS(IDirect3D8Impl,iface);
     TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, PresParms: %p, RetDevInt: %p)\n", This, Adapter, DeviceType,
@@ -390,6 +393,9 @@
 
     /* Allocate the storage for the device */
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
+    if (NULL == object) {
+      return D3DERR_OUTOFVIDEOMEMORY;
+    }
     object->lpVtbl = &Direct3DDevice8_Vtbl;
     object->ref = 1;
     object->direct3d8 = This;
@@ -416,6 +422,7 @@
     {
         HDC hDc;
         int          dblBuf[]={GLX_STENCIL_SIZE,8,GLX_RGBA,GLX_DEPTH_SIZE,16,GLX_DOUBLEBUFFER,None};
+	//int          dblBuf[]={GLX_RGBA,GLX_RED_SIZE,4,GLX_GREEN_SIZE,4,GLX_BLUE_SIZE,4,GLX_DOUBLEBUFFER,None};
         /* FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat */
 
         /* Which hwnd are we using? */
@@ -437,12 +444,32 @@
         object->display = get_display(hDc);
 
         ENTER_GL();
-        object->visInfo = glXChooseVisual(object->display, DefaultScreen(object->display), dblBuf);
-        object->glCtx   = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
-
+	object->visInfo = glXChooseVisual(object->display, DefaultScreen(object->display), dblBuf);
+	if (NULL == object->visInfo) {
+	  FIXME("cannot choose needed glxVisual with Stencil Buffer\n"); 
+
+	  /**
+	   * second try using wine initialized visual ...
+	   * must be fixed reworking wine-glx init
+	   */
+	  template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
+	  object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
+	  if (NULL == object->visInfo) {
+	    ERR("cannot really get XVisual\n"); 
+	    LEAVE_GL();
+	    return D3DERR_NOTAVAILABLE;
+	  }
+	}
+
+        object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
+	if (NULL == object->visInfo) {
+	  ERR("cannot create glxContext\n"); 
+	  LEAVE_GL();
+	  return D3DERR_NOTAVAILABLE;
+	}
 	LEAVE_GL();
-        ReleaseDC(whichHWND, hDc);
 
+        ReleaseDC(whichHWND, hDc);
     }
 
     if (object->glCtx == NULL) {
@@ -492,8 +519,7 @@
 
     ENTER_GL();
     if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
-        ERR("Error in setting current context (context %p drawable %ld)!\n",
-            object->glCtx, object->win);
+      ERR("Error in setting current context (context %p drawable %ld)!\n", object->glCtx, object->win);
     }
     checkGLcall("glXMakeCurrent");
 
@@ -509,7 +535,7 @@
     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
     checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
 
-    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
+    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
     checkGLcall("glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
 
     /* Setup all the devices defaults */
@@ -518,21 +544,49 @@
     /* Parse the gl supported features, in theory enabling parts of our code appropriately */
     GL_Extensions = glGetString(GL_EXTENSIONS);
     TRACE("GL_Extensions reported:\n");  
-
-    while (*GL_Extensions!=0x00) {
+    
+    if (NULL == GL_Extensions) {
+      ERR("   GL_Extensions returns NULL\n");      
+    } else {
+      while (*GL_Extensions!=0x00) {
         const char *Start = GL_Extensions;
         char ThisExtn[256];
-
+	
         memset(ThisExtn, 0x00, sizeof(ThisExtn));
         while (*GL_Extensions!=' ' && *GL_Extensions!=0x00) {
-            GL_Extensions++;
+	  GL_Extensions++;
         }
         memcpy(ThisExtn, Start, (GL_Extensions-Start));
         TRACE ("   %s\n", ThisExtn);
         if (*GL_Extensions==' ') GL_Extensions++;
+      }
+    }
+
+    GLX_Extensions = glXQueryExtensionsString(object->display, DefaultScreen(object->display));
+    TRACE("GLX_Extensions reported:\n");  
+    
+    if (NULL == GLX_Extensions) {
+      ERR("   GLX_Extensions returns NULL\n");      
+    } else {
+      while (*GLX_Extensions!=0x00) {
+        const char *Start = GLX_Extensions;
+        char ThisExtn[256];
+	
+        memset(ThisExtn, 0x00, sizeof(ThisExtn));
+        while (*GLX_Extensions!=' ' && *GLX_Extensions!=0x00) {
+	  GLX_Extensions++;
+        }
+        memcpy(ThisExtn, Start, (GLX_Extensions-Start));
+        TRACE ("   %s\n", ThisExtn);
+        if (*GLX_Extensions==' ') GLX_Extensions++;
+      }
     }
 
     LEAVE_GL();
+
+    GLint gl_max_texture_units_arb;
+    glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max_texture_units_arb);
+    TRACE("GLCaps: GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max_texture_units_arb);
 
     { /* Set a default viewport */
        D3DVIEWPORT8 vp;
Index: shader.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/shader.c,v
retrieving revision 1.1
diff -u -r1.1 shader.c
--- shader.c	17 Dec 2002 01:15:16 -0000	1.1
+++ shader.c	18 Dec 2002 00:12:20 -0000
@@ -64,41 +64,24 @@
 } shader_opcode;
 
 typedef struct vshader_input_data {
-  /*SHADER8Vector V[16];//0-15 */
-  SHADER8Vector V0;
-  SHADER8Vector V1;
-  SHADER8Vector V2;
-  SHADER8Vector V3;
-  SHADER8Vector V4;
-  SHADER8Vector V5;
-  SHADER8Vector V6;
-  SHADER8Vector V7;
-  SHADER8Vector V8;
-  SHADER8Vector V9;
-  SHADER8Vector V10;
-  SHADER8Vector V11;
-  SHADER8Vector V12;
-  SHADER8Vector V13;
-  SHADER8Vector V14;
-  SHADER8Vector V15;
+  /*SHADER8Vector V[16];//0-15*/
+  SHADER8Vector V[16];
 } vshader_input_data;
 
 typedef struct vshader_output_data {
   SHADER8Vector oPos;
-  /*SHADER8Vector oD[2];//0-1 */
-  SHADER8Vector oD0;
-  SHADER8Vector oD1;
-  /*SHADER8Vector oT[4];//0-3 */
-  SHADER8Vector oT0;
-  SHADER8Vector oT1;
-  SHADER8Vector oT2;
-  SHADER8Vector oT3;
-  SHADER8Scalar oFog;
-  SHADER8Scalar oPts;
+  /*SHADER8Vector oD[2];//0-1*/
+  SHADER8Vector oD[2];
+  /*SHADER8Vector oT[4];//0-3*/
+  SHADER8Vector oT[4];
+  /*SHADER8Scalar oFog;*/
+  /*SHADER8Scalar oPts;*/
+  SHADER8Vector oFog;
+  SHADER8Vector oPts;
 } vshader_output_data;
 
-/*********************
- * vshader software VM
+/*******************************
+ * vshader functions software VM
  */
 
 void vshader_add(SHADER8Vector* d, SHADER8Vector* s0, SHADER8Vector* s1) {
@@ -215,123 +198,490 @@
  *
  * @TODO: find this fucking really opcodes values
  */
-static CONST shader_opcode vshader_ins [] =
-  {
-    {0, "mov",  2, vshader_mov},
-    {0, "max",  3, vshader_max},
-    {0, "min",  3, vshader_min},
-    {0, "sge",  3, vshader_sge},
-    {0, "slt",  3, vshader_slt},
-    {0, "add",  3, vshader_add},
-    {0, "sub",  3, vshader_sub},
-    {0, "mul",  3, vshader_mul},
-    {0, "rcp",  2, vshader_rcp},
-    {0, "mad",  4, vshader_mad},
-    {0, "dp3",  3, vshader_dp3},
-    {0, "dp4",  3, vshader_dp4},
-    {0, "rsq",  2, vshader_rsq},
-    {0, "dst",  3, vshader_dst},
-    {0, "lit",  2, vshader_lit},
-    {0, "expp", 2, vshader_expp},
-    {0, "logp", 2, vshader_logp},
-    {0, "nop",  0, vshader_nop},
-    {0, NULL, 0, NULL}
-  };
+static CONST shader_opcode vshader_ins [] = {
+  {D3DSIO_MOV,  "mov",  2, vshader_mov},
+  {D3DSIO_MAX,  "max",  3, vshader_max},
+  {D3DSIO_MIN,  "min",  3, vshader_min},
+  {D3DSIO_SGE,  "sge",  3, vshader_sge},
+  {D3DSIO_SLT,  "slt",  3, vshader_slt},
+  {D3DSIO_ADD,  "add",  3, vshader_add},
+  {D3DSIO_SUB,  "sub",  3, vshader_sub},
+  {D3DSIO_MUL,  "mul",  3, vshader_mul},
+  {D3DSIO_RCP,  "rcp",  2, vshader_rcp},
+  {D3DSIO_MAD,  "mad",  4, vshader_mad},
+  {D3DSIO_DP3,  "dp3",  3, vshader_dp3},
+  {D3DSIO_DP4,  "dp4",  3, vshader_dp4},
+  {D3DSIO_RSQ,  "rsq",  2, vshader_rsq},
+  {D3DSIO_DST,  "dst",  3, vshader_dst},
+  {D3DSIO_LIT,  "lit",  2, vshader_lit},
+  {D3DSIO_EXPP, "expp", 2, vshader_expp},
+  {D3DSIO_LOGP, "logp", 2, vshader_logp},
+  {D3DSIO_NOP,  "nop",  0, vshader_nop},
+  {0, NULL, 0, NULL}
+};
 
 
-shader_opcode* vshader_get_opcode(const DWORD code) {
+shader_opcode* vshader_program_get_opcode(const DWORD code) {
+  DWORD i = 0;
+  while (NULL != vshader_ins[i].name) {
+    if ((code & D3DSI_OPCODE_MASK) == vshader_ins[i].opcode) {
+      return &vshader_ins[i];
+    }
+    ++i;
+  }
   return NULL;
 }
 
+void vshader_program_dump_param(const DWORD param, int input) {
+  static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
+  static const char swizzle_reg_chars[] = "xyzw";
+
+  DWORD reg = param & 0x00001FFF;
+  DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
+
+  if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) DPRINTF("-");
+  
+  switch (regtype << D3DSP_REGTYPE_SHIFT) {
+  case D3DSPR_TEMP:
+    DPRINTF("R[%lu]", reg);
+    break;
+  case D3DSPR_INPUT:
+    DPRINTF("V[%lu]", reg);
+    break;
+  case D3DSPR_CONST:
+    DPRINTF("C[%s%lu]", (reg & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
+    break;
+  case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
+    DPRINTF("a[%lu]", reg);
+    break;
+  case D3DSPR_RASTOUT:
+    DPRINTF("%s", rastout_reg_names[reg]);
+    break;
+  case D3DSPR_ATTROUT:
+    DPRINTF("oD[%lu]", reg);
+    break;
+  case D3DSPR_TEXCRDOUT:
+    DPRINTF("oT[%lu]", reg);
+    break;
+  default:
+    break;
+  }
+
+  if (!input) {
+    /** operand output */
+    if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
+      if (param & D3DSP_WRITEMASK_0) DPRINTF(".x");
+      if (param & D3DSP_WRITEMASK_1) DPRINTF(".y");
+      if (param & D3DSP_WRITEMASK_2) DPRINTF(".z");
+      if (param & D3DSP_WRITEMASK_3) DPRINTF(".w");
+    }
+  } else {
+    /** operand input */
+    DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
+    DWORD swizzle_x = swizzle & 0x03;
+    DWORD swizzle_y = (swizzle >> 2) & 0x03;
+    DWORD swizzle_z = (swizzle >> 4) & 0x03;
+    DWORD swizzle_w = (swizzle >> 6) & 0x03;
+    /**
+     * swizzle bits fields:
+     *  WWZZYYXX
+     */
+    if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
+      if (swizzle_x == swizzle_y && 
+	  swizzle_x == swizzle_z && 
+	  swizzle_x == swizzle_w) {
+	DPRINTF(".%c", swizzle_reg_chars[swizzle_x]);
+      } else {
+	DPRINTF(".%c%c%c%c", 
+		swizzle_reg_chars[swizzle_x], 
+		swizzle_reg_chars[swizzle_y], 
+		swizzle_reg_chars[swizzle_z], 
+		swizzle_reg_chars[swizzle_w]);
+      }
+    }
+  }
+}
+
 /**
  * Function parser ...
  */
-BOOL vshader_parse_function(const DWORD* function) {
-  return TRUE;
+DWORD vshader_program_parse(VERTEXSHADER8* vshader) {
+  const DWORD* pToken = vshader->function;
+  shader_opcode* curOpcode = NULL;
+  DWORD len = 0;  
+  DWORD i;
+
+  if (NULL != pToken) {
+    while (D3DVS_END() != *pToken) {
+      curOpcode = vshader_program_get_opcode(*pToken);
+      ++pToken;
+      ++len;
+      if (NULL == curOpcode) {
+	/* unkown current opcode ... */
+	while (*pToken & 0x80000000) {
+	  DPRINTF("unrecognized opcode: %08lX\n", *pToken);
+	  ++pToken;
+	  ++len;
+	}
+      } else {
+	DPRINTF("%s ", curOpcode->name);
+	if (curOpcode->num_params > 0) {
+	  vshader_program_dump_param(*pToken, 0);
+	  ++pToken;
+	  ++len;
+	  for (i = 1; i < curOpcode->num_params; ++i) {
+	    DPRINTF(", ");
+	    vshader_program_dump_param(*pToken, 1);
+	    ++pToken;
+	    ++len;
+	  }
+	}
+	DPRINTF("\n");
+      }
+    }
+    vshader->functionLength = len * sizeof(DWORD);
+  } else {
+    vshader->functionLength = 1; /* no Function defined use fixed function vertex processing */
+  }
+  return len * sizeof(DWORD);
 }
 
-BOOL vshader_hardware_execute_function(VERTEXSHADER8* vshader,
-				       const vshader_input_data* input,
-				       vshader_output_data* output) {
+BOOL vshader_program_execute_HAL(VERTEXSHADER8* vshader,
+				 const vshader_input_data* input,
+				 vshader_output_data* output) {
   /** 
-   * TODO: use the GL_NV_vertex_program 
-   *  and specifics vendors variants for it 
+   * TODO: use the NV_vertex_program (or 1_1) extension 
+   *  and specifics vendors (ARB_vertex_program??) variants for it 
    */
   return TRUE;
 }
 
-BOOL vshader_software_execute_function(VERTEXSHADER8* vshader,
-				       const vshader_input_data* input,
-				       vshader_output_data* output) {
+BOOL vshader_program_execute_SW(VERTEXSHADER8* vshader,
+				const vshader_input_data* input,
+				vshader_output_data* output) {
   /** Vertex Shader Temporary Registers */
-  /*SHADER8Vector R[12];*/
+  SHADER8Vector R[12];
   /*SHADER8Scalar A0;*/
+  SHADER8Vector A[1];
   /** temporary Vector for modifier management */
-  /*SHADER8Vector d;*/
+  SHADER8Vector d;
+  SHADER8Vector s[3];
   /** parser datas */
   const DWORD* pToken = vshader->function;
   shader_opcode* curOpcode = NULL;
-  
+  /** functions parameters */
+  SHADER8Vector* p[4];
+  SHADER8Vector* p_send[4];
+
+  DWORD i;
+
   /* the first dword is the version tag */
   /* TODO: parse it */
   
   ++pToken;
-  while (0xFFFFFFFF != *pToken) {
-    curOpcode = vshader_get_opcode(*pToken);
+  while (D3DVS_END() != *pToken) {
+    curOpcode = vshader_program_get_opcode(*pToken);
     ++pToken;
     if (NULL == curOpcode) {
       /* unkown current opcode ... */
-      return FALSE;
-    }
-    if (curOpcode->num_params > 0) {
-      /* TODO */
+      while (*pToken & 0x80000000) {
+	DPRINTF("unrecognized opcode: %08lX\n", *pToken);
+	++pToken;
+      }
+      /*return FALSE;*/
+    } else {     
+      if (curOpcode->num_params > 0) {
+	
+	for (i = 0; i < curOpcode->num_params; ++i) {
+	  DWORD reg = pToken[i] & 0x00001FFF;
+	  DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
+
+	  switch (regtype << D3DSP_REGTYPE_SHIFT) {
+	  case D3DSPR_TEMP:
+	    p[i] = &R[reg];
+	    break;
+	  case D3DSPR_INPUT:
+	    p[i] = &input->V[reg];
+	    break;
+	  case D3DSPR_CONST:
+	    if (reg & D3DVS_ADDRMODE_RELATIVE) {
+	      p[i] = &vshader->data->C[(DWORD) A[0].x + reg];
+	    } else {
+	      p[i] = &vshader->data->C[reg];
+	    }
+	    break;
+	  case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
+	    if (0 != reg)
+	      ERR("cannot handle address registers != a0");
+	    p[i] = &A[reg];
+	    break;
+	  case D3DSPR_RASTOUT:
+	    switch (reg) {
+	    case D3DSRO_POSITION:
+	      p[i] = &output->oPos;
+	      break;
+	    case D3DSRO_FOG:
+	      p[i] = &output->oFog;
+	      break;
+	    case D3DSRO_POINT_SIZE:
+	      p[i] = &output->oPts;
+	      break;
+	    }
+	    break;
+	  case D3DSPR_ATTROUT:
+	    p[i] = &output->oD[reg];
+	    break;
+	  case D3DSPR_TEXCRDOUT:
+	    p[i] = &output->oT[reg];
+	    break;
+	  default:
+	    break;
+	  }
+	  
+	  if (i > 1) { /* input reg */
+	    DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
+	    DWORD swizzle_x = swizzle & 0x03;
+	    DWORD swizzle_y = (swizzle >> 2) & 0x03;
+	    DWORD swizzle_z = (swizzle >> 4) & 0x03;
+	    DWORD swizzle_w = (swizzle >> 6) & 0x03;
+	    if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
+	      p_send[i] = p[i];
+	    } else {
+	      float* tt = (float*) p[i];
+	      s[i].x = tt[swizzle_x];
+	      s[i].y = tt[swizzle_y];
+	      s[i].z = tt[swizzle_z];
+	      s[i].w = tt[swizzle_w];
+	      p_send[i] = &s[i];
+	    }
+	  } else { /* output reg */
+	    if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
+	      p_send[i] = p[i];
+	    } else {
+	      p_send[i] = &d; /* to be post-processed for modifiers management */
+	    }
+	  }
+	}      
+      }
+
+      switch (curOpcode->num_params) {	
+      case 0:
+	curOpcode->soft_fct();
+	break;
+      case 1:
+	curOpcode->soft_fct(p_send[0]);
+	break;
+      case 2:
+	curOpcode->soft_fct(p_send[0], p_send[1]);
+	break;
+      case 3:
+	curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
+	break;
+      case 4:
+	curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
+	break;
+      default:
+	ERR("%s too many params: %lu\n", curOpcode->name, curOpcode->num_params);
+      }
+
+      /* check if output reg modifier post-process */
+      if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
+	if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x; 
+	if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y; 
+	if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z; 
+	if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w; 
+      }
+      
+      /* to next opcode token */
+      pToken += curOpcode->num_params;
     }
   }
   return TRUE;
 }
 
-/**
- * Declaration Parser First draft ...
+/************************************
+ * Vertex Shader Declaration Parser First draft ...
  */
 
-#if 0
-static CONST char* vshader_decl [] =
-  {
-    "D3DVSDT_D3DCOLOR",
-    "D3DVSDT_FLOAT1",
-    "D3DVSDT_FLOAT2",
-    "D3DVSDT_FLOAT3",
-    "D3DVSDT_FLOAT4",
-    "D3DVSDT_UBYTE4",
-    NULL
-  };
-#endif
-
-/** Vertex Shader Declaration parser tokens */
-enum D3DVSD_TOKENS {
-  D3DVSD_STREAM,
-  
-  D3DVSD_END
+/** Vertex Shader Declaration data types tokens */
+static CONST char* VertexShaderDeclDataTypes [] = {
+  "D3DVSDT_FLOAT1",
+  "D3DVSDT_FLOAT2",
+  "D3DVSDT_FLOAT3",
+  "D3DVSDT_FLOAT4",
+  "D3DVSDT_D3DCOLOR",
+  "D3DVSDT_UBYTE4",
+  "D3DVSDT_SHORT2",
+  "D3DVSDT_SHORT4",
+  NULL
+};
+
+static CONST char* VertexShaderDeclRegister [] = {
+  "D3DVSDE_POSITION",
+  "D3DVSDE_BLENDWEIGHT",
+  "D3DVSDE_BLENDINDICES",
+  "D3DVSDE_NORMAL",
+  "D3DVSDE_PSIZE",
+  "D3DVSDE_DIFFUSE",
+  "D3DVSDE_SPECULAR",
+  "D3DVSDE_TEXCOORD0",
+  "D3DVSDE_TEXCOORD1",
+  "D3DVSDE_TEXCOORD2",
+  "D3DVSDE_TEXCOORD3",
+  "D3DVSDE_TEXCOORD4",
+  "D3DVSDE_TEXCOORD5",
+  "D3DVSDE_TEXCOORD6",
+  "D3DVSDE_TEXCOORD7",
+  "D3DVSDE_POSITION2",
+  "D3DVSDE_NORMAL2",
+  NULL
 };
 
-BOOL vshader_parse_declaration(VERTEXSHADER8* vshader) {
+
+/** todo check decl validity */
+DWORD vshader_decl_parse_token(const DWORD* pToken) {
+  const DWORD token = *pToken;
+  DWORD tokenlen = 1;
+
+  switch ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT) { /* maybe a macro to inverse ... */
+  case D3DVSD_TOKEN_NOP:
+    TRACE(" 0x%08x NOP()\n", token);
+    break;
+  case D3DVSD_TOKEN_STREAM:
+    if (token & D3DVSD_STREAMTESSMASK) {
+      TRACE(" 0x%08x STREAM_TESS()\n", token);
+    } else {
+      TRACE(" 0x%08x STREAM(%lu)\n", token, ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT));
+    }
+    break;
+  case D3DVSD_TOKEN_STREAMDATA:
+    if (token & 0x10000000) {
+      TRACE(" 0x%08x SKIP(%lu)\n", token, ((token & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT));
+    } else {
+      DWORD type = ((token & D3DVSD_DATATYPEMASK)  >> D3DVSD_DATATYPESHIFT);
+      DWORD reg  = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+      TRACE(" 0x%08x REG(%s, %s)\n", token, VertexShaderDeclRegister[reg], VertexShaderDeclDataTypes[type]);
+    }
+    break;
+  case D3DVSD_TOKEN_TESSELLATOR:
+    if (token & 0x10000000) {
+      DWORD type = ((token & D3DVSD_DATATYPEMASK)  >> D3DVSD_DATATYPESHIFT);
+      DWORD reg  = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+      TRACE(" 0x%08x TESSUV(%s) as %s\n", token, VertexShaderDeclRegister[reg], VertexShaderDeclDataTypes[type]);
+    } else {
+      DWORD type   = ((token & D3DVSD_DATATYPEMASK)    >> D3DVSD_DATATYPESHIFT);
+      DWORD regout = ((token & D3DVSD_VERTEXREGMASK)   >> D3DVSD_VERTEXREGSHIFT);
+      DWORD regin  = ((token & D3DVSD_VERTEXREGINMASK) >> D3DVSD_VERTEXREGINSHIFT);
+      TRACE(" 0x%08x TESSNORMAL(%s, %s) as %s\n", token, VertexShaderDeclRegister[regin], VertexShaderDeclRegister[regout], VertexShaderDeclDataTypes[type]);
+    }
+    break;
+  case D3DVSD_TOKEN_CONSTMEM:
+    {
+      DWORD count        = ((token & D3DVSD_CONSTCOUNTMASK)   >> D3DVSD_CONSTCOUNTSHIFT);
+      DWORD constaddress = ((token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT);
+      TRACE(" 0x%08x CONST(%lu, %lu)\n", token, constaddress, count);
+      ++pToken;
+      DWORD i;
+      for (i = 0; i < count; ++i) {
+	TRACE("        c[%lu] = (0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n", 
+		constaddress, 
+		*pToken, 
+		*(pToken + 1), 
+		*(pToken + 2), 
+		*(pToken + 3));
+	pToken += 4; 
+	++constaddress;
+      }
+      tokenlen = count + 1;
+    }
+    break;
+  case D3DVSD_TOKEN_EXT:
+    {
+      DWORD count   = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT);
+      DWORD extinfo = ((token & D3DVSD_EXTINFOMASK)    >> D3DVSD_EXTINFOSHIFT);
+      TRACE(" 0x%08x EXT(%lu, %lu)\n", token, count, extinfo);
+      /* todo ... print extension */
+      tokenlen = count + 1;
+    }
+    break;
+  case D3DVSD_TOKEN_END:
+    TRACE(" 0x%08x END()\n", token);
+    break;
+  default:
+    TRACE(" 0x%08x UNKNOWN\n", token);
+    /* argg error */
+  }
+  return tokenlen;
+}
+
+DWORD vshader_decl_parse(VERTEXSHADER8* vshader) {
   /** parser data */
   const DWORD* pToken = vshader->decl;
-
-  ++pToken;
-  while (0xFFFFFFFF != *pToken) {
-    /** TODO */
-    ++pToken;
+  DWORD fvf = 0;
+  DWORD len = 0;  
+  DWORD token;
+  DWORD tokenlen;
+  DWORD tokentype;
+
+  while (D3DVSD_END() != *pToken) {
+    token = *pToken;
+    tokenlen = vshader_decl_parse_token(pToken); 
+    tokentype = ((*pToken & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT);
+    
+    /** FVF generation block */
+    if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 == (0x10000000 & tokentype)) {
+      DWORD type = ((token & D3DVSD_DATATYPEMASK)  >> D3DVSD_DATATYPESHIFT);
+      DWORD reg  = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+      switch (reg) {
+      case D3DVSDE_POSITION:     fvf |= D3DFVF_XYZ;             break;
+      case D3DVSDE_BLENDWEIGHT:
+	switch (type) {
+	case D3DVSDT_FLOAT1:     fvf |= D3DFVF_XYZB1;           break;
+	case D3DVSDT_FLOAT2:     fvf |= D3DFVF_XYZB2;           break;
+	case D3DVSDT_FLOAT3:     fvf |= D3DFVF_XYZB3;           break;
+	case D3DVSDT_FLOAT4:     fvf |= D3DFVF_XYZB4;           break;
+	default:
+	  /** errooooorr what to do ? */
+	  ERR("Error in VertexShader declaration of D3DVSDE_BLENDWEIGHT register: unsupported type %lu\n", type);
+	}
+	break;
+
+      case D3DVSDE_BLENDINDICES: fvf |= D3DFVF_LASTBETA_UBYTE4; break;
+      case D3DVSDE_NORMAL:       fvf |= D3DFVF_NORMAL;          break;
+      case D3DVSDE_PSIZE:        fvf |= D3DFVF_PSIZE;           break;
+      case D3DVSDE_DIFFUSE:      fvf |= D3DFVF_DIFFUSE;         break;
+      case D3DVSDE_SPECULAR:     fvf |= D3DFVF_SPECULAR;        break;
+      case D3DVSDE_TEXCOORD0:    fvf |= D3DFVF_TEX1;            break;
+      case D3DVSDE_TEXCOORD1:    fvf |= D3DFVF_TEX2;            break;
+      case D3DVSDE_TEXCOORD2:    fvf |= D3DFVF_TEX3;            break;
+      case D3DVSDE_TEXCOORD3:    fvf |= D3DFVF_TEX4;            break;
+      case D3DVSDE_TEXCOORD4:    fvf |= D3DFVF_TEX5;            break;
+      case D3DVSDE_TEXCOORD5:    fvf |= D3DFVF_TEX6;            break;
+      case D3DVSDE_TEXCOORD6:    fvf |= D3DFVF_TEX7;            break;
+      case D3DVSDE_TEXCOORD7:    fvf |= D3DFVF_TEX8;            break;
+      case D3DVSDE_POSITION2:   /* maybe D3DFVF_XYZRHW instead D3DFVF_XYZ (of D3DVDE_POSITION) ... to see */
+      case D3DVSDE_NORMAL2:     /* FIXME i don't know what to do here ;( */
+	FIXME("[%lu] registers in VertexShader declaration not supported yet (token:0x%08x)\n", reg, token);
+	break;
+      }
+    }
+    len += tokenlen;
+    pToken += tokenlen;
   }
-  return TRUE;
+  /* here D3DVSD_END() */
+  len += vshader_decl_parse_token(pToken);
+  if (NULL == vshader->function) vshader->fvf = fvf;
+  vshader->declLength = len * sizeof(DWORD);
+  return len * sizeof(DWORD);
 }
 
-HRESULT WINAPI ValidatePixelShader(void) {
+HRESULT WINAPI ValidateVertexShader(void) {
   FIXME("(void): stub\n");
   return 0;
 }
 
-HRESULT WINAPI ValidateVertexShader(void) {
+HRESULT WINAPI ValidatePixelShader(void) {
   FIXME("(void): stub\n");
   return 0;
 }
+
Index: texture.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/texture.c,v
retrieving revision 1.2
diff -u -r1.2 texture.c
--- texture.c	17 Dec 2002 01:15:16 -0000	1.2
+++ texture.c	18 Dec 2002 00:12:21 -0000
@@ -107,7 +107,7 @@
     return This->ResourceType;
 }
 
-/* IDirect3DTexture8 (Inherited from IDirect3DBaseTexture8) */
+/* IDirect3DTexture8 IDirect3DBaseTexture8 Interface follow: */
 DWORD    WINAPI        IDirect3DTexture8Impl_SetLOD(LPDIRECT3DTEXTURE8 iface, DWORD LODNew) {
     ICOM_THIS(IDirect3DTexture8Impl,iface);
     FIXME("(%p) : stub\n", This);    return D3D_OK;
Index: volumetexture.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/volumetexture.c,v
retrieving revision 1.2
diff -u -r1.2 volumetexture.c
--- volumetexture.c	21 Oct 2002 18:21:59 -0000	1.2
+++ volumetexture.c	18 Dec 2002 00:12:21 -0000
@@ -36,7 +36,9 @@
 
     TRACE("(%p) : QueryInterface\n", This);
     if (IsEqualGUID(riid, &IID_IUnknown)
-        || IsEqualGUID(riid, &IID_IClassFactory)) {
+	|| IsEqualGUID(riid, &IID_IDirect3DResource8)
+	|| IsEqualGUID(riid, &IID_IDirect3DBaseTexture8)
+	|| IsEqualGUID(riid, &IID_IDirect3DVolumeTexture8)) {
         IDirect3DVolumeTexture8Impl_AddRef(iface);
         *ppobj = This;
         return D3D_OK;
@@ -55,7 +57,7 @@
 ULONG WINAPI IDirect3DVolumeTexture8Impl_Release(LPDIRECT3DVOLUMETEXTURE8 iface) {
     ICOM_THIS(IDirect3DVolumeTexture8Impl,iface);
     ULONG ref = --This->ref;
-    int   i;
+    UINT  i;
 
     TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
     if (ref == 0) {
@@ -107,7 +109,7 @@
     return This->ResourceType;
 }
 
-/* IDirect3DVolumeTexture8 (Inherited from IDirect3DBaseTexture8) */
+/* IDirect3DVolumeTexture8 IDirect3DBaseTexture8 Interface follow: */
 DWORD    WINAPI        IDirect3DVolumeTexture8Impl_SetLOD(LPDIRECT3DVOLUMETEXTURE8 iface, DWORD LODNew) {
     ICOM_THIS(IDirect3DVolumeTexture8Impl,iface);
     FIXME("(%p) : stub\n", This);    return D3D_OK;
Index: d3d8_private.h
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/d3d8_private.h,v
retrieving revision 1.7
diff -u -r1.7 d3d8_private.h
--- d3d8_private.h	17 Dec 2002 01:15:16 -0000	1.7
+++ d3d8_private.h	18 Dec 2002 00:12:25 -0000
@@ -170,8 +170,8 @@
 
 typedef struct SHADER8Data {
   /** Run Time Shader Function Constants */
-  /*D3DXBUFFER* constants; */
-  SHADER8Constants constants;
+  /*D3DXBUFFER* constants;*/
+  SHADER8Constants C;
   /** Shader Code as char ... */
   CONST DWORD* code;
   UINT codeLength;
@@ -183,6 +183,8 @@
   DWORD usage; /* 0 || D3DUSAGE_SOFTWAREPROCESSING */
   UINT declLength;
   UINT functionLength;
+ 
+  DWORD fvf;
 
   /* run time datas */
   SHADER8Data* data;
@@ -904,5 +906,12 @@
 extern HRESULT  WINAPI        IDirect3DVolumeTexture8Impl_LockBox(LPDIRECT3DVOLUMETEXTURE8 iface, UINT Level,D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox,DWORD Flags);
 extern HRESULT  WINAPI        IDirect3DVolumeTexture8Impl_UnlockBox(LPDIRECT3DVOLUMETEXTURE8 iface, UINT Level);
 extern HRESULT  WINAPI        IDirect3DVolumeTexture8Impl_AddDirtyBox(LPDIRECT3DVOLUMETEXTURE8 iface, CONST D3DBOX* pDirtyBox);
+
+/*******************
+ * private functions
+ */
+DWORD vshader_decl_parse(VERTEXSHADER8* vshader);
+DWORD vshader_program_parse(VERTEXSHADER8* vshader);
+
 
 #endif /* __WINE_D3DX8_PRIVATE_H */


More information about the wine-patches mailing list