[PATCH 3/5] ddraw: Cleanup the D3DOP_PROCESSVERTICES implementation a bit.

Henri Verbeet hverbeet at codeweavers.com
Tue Apr 29 03:41:04 CDT 2014


---
 dlls/ddraw/executebuffer.c |  227 +++++++++++++++++---------------------------
 1 file changed, 88 insertions(+), 139 deletions(-)

diff --git a/dlls/ddraw/executebuffer.c b/dlls/ddraw/executebuffer.c
index aec0a1a..41c6feb 100644
--- a/dlls/ddraw/executebuffer.c
+++ b/dlls/ddraw/executebuffer.c
@@ -50,6 +50,20 @@ static void _dump_D3DEXECUTEBUFFERDESC(const D3DEXECUTEBUFFERDESC *lpDesc) {
     TRACE("lpData       : %p\n", lpDesc->lpData);
 }
 
+static void transform_vertex(D3DTLVERTEX *dst, const D3DMATRIX *mat,
+        const D3DVIEWPORT *vp, float x, float y, float z)
+{
+    dst->u1.sx = (x * mat->_11) + (y * mat->_21) + (z * mat->_31) + mat->_41;
+    dst->u2.sy = (x * mat->_12) + (y * mat->_22) + (z * mat->_32) + mat->_42;
+    dst->u3.sz = (x * mat->_13) + (y * mat->_23) + (z * mat->_33) + mat->_43;
+    dst->u4.rhw = (x * mat->_14) + (y * mat->_24) + (z * mat->_34) + mat->_44;
+
+    dst->u1.sx = dst->u1.sx / dst->u4.rhw * vp->dvScaleX + vp->dwX + vp->dwWidth / 2;
+    dst->u2.sy = -dst->u2.sy / dst->u4.rhw * vp->dvScaleY + vp->dwY + vp->dwHeight / 2;
+    dst->u3.sz /= dst->u4.rhw;
+    dst->u4.rhw = 1.0f / dst->u4.rhw;
+}
+
 HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
         struct d3d_device *device, struct d3d_viewport *viewport)
 {
@@ -231,7 +245,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
             {
                 /* TODO: Share code with d3d_vertex_buffer7_ProcessVertices()
                  * and / or wined3d_device_process_vertices(). */
-                D3DMATRIX view_mat, world_mat, proj_mat;
+                D3DMATRIX view_mat, world_mat, proj_mat, mat;
+
                 TRACE("PROCESSVERTICES  (%d)\n", count);
 
                 /* Get the transform and world matrix */
@@ -243,157 +258,91 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                 wined3d_device_get_transform(device->wined3d_device,
                         WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)&world_mat);
 
-                for (i = 0; i < count; ++i)
+                if (TRACE_ON(ddraw))
                 {
-                    D3DPROCESSVERTICES *ci = (D3DPROCESSVERTICES *)instr;
-
-                    TRACE("  Start : %d Dest : %d Count : %d\n",
-			  ci->wStart, ci->wDest, ci->dwCount);
-		    TRACE("  Flags : ");
-                    if (TRACE_ON(ddraw))
-                    {
-		        if (ci->dwFlags & D3DPROCESSVERTICES_COPY)
-			    TRACE("COPY ");
-			if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
-			    TRACE("NOCOLOR ");
-			if (ci->dwFlags == D3DPROCESSVERTICES_OPMASK)
-			    TRACE("OPMASK ");
-			if (ci->dwFlags & D3DPROCESSVERTICES_TRANSFORM)
-			    TRACE("TRANSFORM ");
-			if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT)
-			    TRACE("TRANSFORMLIGHT ");
-			if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
-			    TRACE("UPDATEEXTENTS ");
-			TRACE("\n");
-		    }
-
-		    /* This is where doing Direct3D on top on OpenGL is quite difficult.
-		       This method transforms a set of vertices using the CURRENT state
-		       (lighting, projection, ...) but does not rasterize them.
-		       They will only be put on screen later (with the POINT / LINE and
-		       TRIANGLE op-codes). The problem is that you can have a triangle
-		       with each point having been transformed using another state...
-
-		       In this implementation, I will emulate only ONE thing : each
-		       vertex can have its own "WORLD" transformation (this is used in the
-		       TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
-		       execute buffer use the same state.
-
-		       If I find applications that change other states, I will try to do a
-		       more 'fine-tuned' state emulation (but I may become quite tricky if
-		       it changes a light position in the middle of a triangle).
-
-		       In this case, a 'direct' approach (i.e. without using OpenGL, but
-		       writing our own 3D rasterizer) would be easier. */
-
-		    /* The current method (with the hypothesis that only the WORLD matrix
-		       will change between two points) is like this :
-		       - I transform 'manually' all the vertices with the current WORLD
-		         matrix and store them in the vertex buffer
-		       - during the rasterization phase, the WORLD matrix will be set to
-		         the Identity matrix */
-
-		    /* Enough for the moment */
-		    if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT) {
-		        unsigned int nb;
-                        D3DVERTEX *src = ((D3DVERTEX *)((char *)buffer->desc.lpData + vs)) + ci->wStart;
-                        D3DTLVERTEX *dst = ((D3DTLVERTEX *)buffer->vertex_data) + ci->wDest;
-                        D3DVIEWPORT *Viewport = &viewport->viewports.vp1;
-			D3DMATRIX mat;
-			
-                        if (TRACE_ON(ddraw))
-                        {
-			    TRACE("  Projection Matrix : (%p)\n", &proj_mat);
-			    dump_D3DMATRIX(&proj_mat);
-			    TRACE("  View       Matrix : (%p)\n", &view_mat);
-			    dump_D3DMATRIX(&view_mat);
-			    TRACE("  World Matrix : (%p)\n", &world_mat);
-			    dump_D3DMATRIX(&world_mat);
-			}
-
-                        multiply_matrix(&mat,&view_mat,&world_mat);
-                        multiply_matrix(&mat,&proj_mat,&mat);
-
-			for (nb = 0; nb < ci->dwCount; nb++) {
-			    /* No lighting yet */
-			    dst->u5.color = 0xFFFFFFFF; /* Opaque white */
-			    dst->u6.specular = 0xFF000000; /* No specular and no fog factor */
+                    TRACE("  Projection Matrix:\n");
+                    dump_D3DMATRIX(&proj_mat);
+                    TRACE("  View Matrix:\n");
+                    dump_D3DMATRIX(&view_mat);
+                    TRACE("  World Matrix:\n");
+                    dump_D3DMATRIX(&world_mat);
+                }
 
-			    dst->u7.tu  = src->u7.tu;
-			    dst->u8.tv  = src->u8.tv;
+                multiply_matrix(&mat, &view_mat, &world_mat);
+                multiply_matrix(&mat, &proj_mat, &mat);
 
-                            dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + mat._41;
-                            dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + mat._42;
-                            dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + mat._43;
-                            dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + mat._44;
+                for (i = 0; i < count; ++i)
+                {
+                    D3DPROCESSVERTICES *ci = (D3DPROCESSVERTICES *)instr;
+                    D3DTLVERTEX *dst = (D3DTLVERTEX *)buffer->vertex_data + ci->wDest;
+                    DWORD op = ci->dwFlags & D3DPROCESSVERTICES_OPMASK;
 
-			    dst->u1.sx = dst->u1.sx / dst->u4.rhw * Viewport->dvScaleX
-				       + Viewport->dwX + Viewport->dwWidth / 2;
-			    dst->u2.sy = (-dst->u2.sy) / dst->u4.rhw * Viewport->dvScaleY
-				       + Viewport->dwY + Viewport->dwHeight / 2;
-			    dst->u3.sz /= dst->u4.rhw;
-			    dst->u4.rhw = 1 / dst->u4.rhw;
+                    TRACE("  start %u, dest %u, count %u, flags %#x.\n",
+                            ci->wStart, ci->wDest, ci->dwCount, ci->dwFlags);
 
-			    src++;
-			    dst++;
+                    if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
+                        FIXME("D3DPROCESSVERTICES_UPDATEEXTENTS not implemented.\n");
+                    if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
+                        FIXME("D3DPROCESSVERTICES_NOCOLOR not implemented.\n");
 
-			}
-		    } else if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORM) {
-		        unsigned int nb;
-                        D3DLVERTEX *src = ((D3DLVERTEX *)((char *)buffer->desc.lpData + vs)) + ci->wStart;
-                        D3DTLVERTEX *dst = ((D3DTLVERTEX *)buffer->vertex_data) + ci->wDest;
-                        D3DVIEWPORT *Viewport = &viewport->viewports.vp1;
-			D3DMATRIX mat;
-			
-                        if (TRACE_ON(ddraw))
+                    switch (op)
+                    {
+                        case D3DPROCESSVERTICES_TRANSFORMLIGHT:
                         {
-			    TRACE("  Projection Matrix : (%p)\n", &proj_mat);
-			    dump_D3DMATRIX(&proj_mat);
-			    TRACE("  View       Matrix : (%p)\n",&view_mat);
-			    dump_D3DMATRIX(&view_mat);
-			    TRACE("  World Matrix : (%p)\n", &world_mat);
-			    dump_D3DMATRIX(&world_mat);
-			}
-
-			multiply_matrix(&mat,&view_mat,&world_mat);
-			multiply_matrix(&mat,&proj_mat,&mat);
-
-			for (nb = 0; nb < ci->dwCount; nb++) {
-			    dst->u5.color = src->u4.color;
-			    dst->u6.specular = src->u5.specular;
-			    dst->u7.tu = src->u6.tu;
-			    dst->u8.tv = src->u7.tv;
+                            const D3DVERTEX *src = (D3DVERTEX *)((char *)buffer->desc.lpData + vs) + ci->wStart;
+                            unsigned int vtx_idx;
+                            static unsigned int once;
+
+                            if (!once++)
+                                FIXME("Lighting not implemented.\n");
+
+                            for (vtx_idx = 0; vtx_idx < ci->dwCount; ++vtx_idx)
+                            {
+                                transform_vertex(&dst[vtx_idx], &mat, &viewport->viewports.vp1,
+                                        src[vtx_idx].u1.x, src[vtx_idx].u2.y, src[vtx_idx].u3.z);
+                                /* No lighting yet */
+                                dst[vtx_idx].u5.color = 0xffffffff; /* Opaque white */
+                                dst[vtx_idx].u6.specular = 0xff000000; /* No specular and no fog factor */
+                                dst[vtx_idx].u7.tu = src[vtx_idx].u7.tu;
+                                dst[vtx_idx].u8.tv = src[vtx_idx].u8.tv;
+                            }
+                            break;
+                        }
 
-                            dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + mat._41;
-                            dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + mat._42;
-                            dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + mat._43;
-                            dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + mat._44;
+                        case D3DPROCESSVERTICES_TRANSFORM:
+                        {
+                            const D3DLVERTEX *src = (D3DLVERTEX *)((char *)buffer->desc.lpData + vs) + ci->wStart;
+                            unsigned int vtx_idx;
+
+                            for (vtx_idx = 0; vtx_idx < ci->dwCount; ++vtx_idx)
+                            {
+                                transform_vertex(&dst[vtx_idx], &mat, &viewport->viewports.vp1,
+                                        src[vtx_idx].u1.x, src[vtx_idx].u2.y, src[vtx_idx].u3.z);
+                                dst[vtx_idx].u5.color = src[vtx_idx].u4.color;
+                                dst[vtx_idx].u6.specular = src[vtx_idx].u5.specular;
+                                dst[vtx_idx].u7.tu = src[vtx_idx].u6.tu;
+                                dst[vtx_idx].u8.tv = src[vtx_idx].u7.tv;
+                            }
+                            break;
+                        }
 
-			    dst->u1.sx = dst->u1.sx / dst->u4.rhw * Viewport->dvScaleX
-				       + Viewport->dwX + Viewport->dwWidth / 2;
-			    dst->u2.sy = (-dst->u2.sy) / dst->u4.rhw * Viewport->dvScaleY
-				       + Viewport->dwY + Viewport->dwHeight / 2;
+                        case D3DPROCESSVERTICES_COPY:
+                        {
+                            const D3DTLVERTEX *src = (D3DTLVERTEX *)((char *)buffer->desc.lpData + vs) + ci->wStart;
 
-			    dst->u3.sz /= dst->u4.rhw;
-			    dst->u4.rhw = 1 / dst->u4.rhw;
+                            memcpy(dst, src, ci->dwCount * sizeof(*dst));
+                            break;
+                        }
 
-			    src++;
-			    dst++;
-			}
+                        default:
+                            FIXME("Unhandled vertex processing op %#x.\n", op);
+                            break;
                     }
-                    else if (ci->dwFlags == D3DPROCESSVERTICES_COPY)
-                    {
-                        D3DTLVERTEX *src = ((D3DTLVERTEX *)((char *)buffer->desc.lpData + vs)) + ci->wStart;
-                        D3DTLVERTEX *dst = ((D3DTLVERTEX *)buffer->vertex_data) + ci->wDest;
 
-			memcpy(dst, src, ci->dwCount * sizeof(D3DTLVERTEX));
-		    } else {
-		        ERR("Unhandled vertex processing flag %#x.\n", ci->dwFlags);
-		    }
-
-		    instr += size;
-		}
-	    } break;
+                    instr += size;
+                }
+                break;
+            }
 
 	    case D3DOP_TEXTURELOAD: {
 	        WARN("TEXTURELOAD-s    (%d)\n", count);
-- 
1.7.10.4




More information about the wine-patches mailing list