ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

executebuffer.c
Go to the documentation of this file.
00001 /* Direct3D ExecuteBuffer
00002  * Copyright (c) 1998-2004 Lionel ULMER
00003  * Copyright (c) 2002-2004 Christian Costa
00004  * Copyright (c) 2006      Stefan Dösinger
00005  *
00006  * This file contains the implementation of IDirect3DExecuteBuffer.
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00021  */
00022 
00023 #include "config.h"
00024 #include "wine/port.h"
00025 
00026 #include "ddraw_private.h"
00027 
00028 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
00029 
00030 /*****************************************************************************
00031  * _dump_executedata
00032  * _dump_D3DEXECUTEBUFFERDESC
00033  *
00034  * Debug functions which write the executebuffer data to the console
00035  *
00036  *****************************************************************************/
00037 
00038 static void _dump_executedata(const D3DEXECUTEDATA *lpData) {
00039     TRACE("dwSize : %d\n", lpData->dwSize);
00040     TRACE("Vertex      Offset : %d  Count  : %d\n", lpData->dwVertexOffset, lpData->dwVertexCount);
00041     TRACE("Instruction Offset : %d  Length : %d\n", lpData->dwInstructionOffset, lpData->dwInstructionLength);
00042     TRACE("HVertex     Offset : %d\n", lpData->dwHVertexOffset);
00043 }
00044 
00045 static void _dump_D3DEXECUTEBUFFERDESC(const D3DEXECUTEBUFFERDESC *lpDesc) {
00046     TRACE("dwSize       : %d\n", lpDesc->dwSize);
00047     TRACE("dwFlags      : %x\n", lpDesc->dwFlags);
00048     TRACE("dwCaps       : %x\n", lpDesc->dwCaps);
00049     TRACE("dwBufferSize : %d\n", lpDesc->dwBufferSize);
00050     TRACE("lpData       : %p\n", lpDesc->lpData);
00051 }
00052 
00053 /*****************************************************************************
00054  * IDirect3DExecuteBufferImpl_Execute
00055  *
00056  * The main functionality of the execute buffer
00057  * It transforms the vertices if necessary, and calls IDirect3DDevice7
00058  * for drawing the vertices. It is called from
00059  * IDirect3DDevice::Execute
00060  *
00061  * TODO: Perhaps some comments about the various opcodes wouldn't hurt
00062  *
00063  * Don't declare this static, as it's called from device.c,
00064  * IDirect3DDevice::Execute
00065  *
00066  * Params:
00067  *  Device: 3D Device associated to use for drawing
00068  *  Viewport: Viewport for this operation
00069  *
00070  *****************************************************************************/
00071 HRESULT d3d_execute_buffer_execute(IDirect3DExecuteBufferImpl *This,
00072         IDirect3DDeviceImpl *lpDevice, IDirect3DViewportImpl *lpViewport)
00073 {
00074     /* DWORD bs = This->desc.dwBufferSize; */
00075     DWORD vs = This->data.dwVertexOffset;
00076     /* DWORD vc = This->data.dwVertexCount; */
00077     DWORD is = This->data.dwInstructionOffset;
00078     /* DWORD il = This->data.dwInstructionLength; */
00079 
00080     char *instr = (char *)This->desc.lpData + is;
00081 
00082     if (lpViewport->active_device != lpDevice)
00083     {
00084         WARN("Viewport %p active device is %p.\n",
00085                 lpViewport, lpViewport->active_device);
00086         return DDERR_INVALIDPARAMS;
00087     }
00088 
00089     /* Activate the viewport */
00090     viewport_activate(lpViewport, FALSE);
00091 
00092     TRACE("ExecuteData :\n");
00093     if (TRACE_ON(ddraw))
00094       _dump_executedata(&(This->data));
00095 
00096     while (1) {
00097         LPD3DINSTRUCTION current = (LPD3DINSTRUCTION) instr;
00098     BYTE size;
00099     WORD count;
00100     
00101     count = current->wCount;
00102     size = current->bSize;
00103     instr += sizeof(D3DINSTRUCTION);
00104     
00105     switch (current->bOpcode) {
00106         case D3DOP_POINT: {
00107             WARN("POINT-s          (%d)\n", count);
00108         instr += count * size;
00109         } break;
00110 
00111         case D3DOP_LINE: {
00112             WARN("LINE-s           (%d)\n", count);
00113         instr += count * size;
00114         } break;
00115 
00116         case D3DOP_TRIANGLE: {
00117             int i;
00118                 D3DTLVERTEX *tl_vx = This->vertex_data;
00119         TRACE("TRIANGLE         (%d)\n", count);
00120         
00121         if (count*3>This->nb_indices) {
00122             This->nb_indices = count * 3;
00123                     HeapFree(GetProcessHeap(),0,This->indices);
00124             This->indices = HeapAlloc(GetProcessHeap(),0,sizeof(WORD)*This->nb_indices);
00125         }
00126             
00127         for (i = 0; i < count; i++) {
00128                     LPD3DTRIANGLE ci = (LPD3DTRIANGLE) instr;
00129             TRACE("  v1: %d  v2: %d  v3: %d\n",ci->u1.v1, ci->u2.v2, ci->u3.v3);
00130             TRACE("  Flags : ");
00131                     if (TRACE_ON(ddraw))
00132                     {
00133                         /* Wireframe */
00134                         if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1)
00135                             TRACE("EDGEENABLE1 ");
00136                         if (ci->wFlags & D3DTRIFLAG_EDGEENABLE2)
00137                             TRACE("EDGEENABLE2 ");
00138                         if (ci->wFlags & D3DTRIFLAG_EDGEENABLE1)
00139                             TRACE("EDGEENABLE3 ");
00140                         /* Strips / Fans */
00141                         if (ci->wFlags == D3DTRIFLAG_EVEN)
00142                             TRACE("EVEN ");
00143                         if (ci->wFlags == D3DTRIFLAG_ODD)
00144                             TRACE("ODD ");
00145                         if (ci->wFlags == D3DTRIFLAG_START)
00146                             TRACE("START ");
00147                         if ((ci->wFlags > 0) && (ci->wFlags < 30))
00148                             TRACE("STARTFLAT(%u) ", ci->wFlags);
00149                         TRACE("\n");
00150                     }
00151             This->indices[(i * 3)    ] = ci->u1.v1;
00152             This->indices[(i * 3) + 1] = ci->u2.v2;
00153             This->indices[(i * 3) + 2] = ci->u3.v3;
00154                     instr += size;
00155         }
00156                 /* IDirect3DDevices have color keying always enabled -
00157                  * enable it before drawing. This overwrites any ALPHA*
00158                  * render state. */
00159                 wined3d_device_set_render_state(lpDevice->wined3d_device, WINED3D_RS_COLORKEYENABLE, 1);
00160                 IDirect3DDevice7_DrawIndexedPrimitive(&lpDevice->IDirect3DDevice7_iface,
00161                         D3DPT_TRIANGLELIST, D3DFVF_TLVERTEX, tl_vx, 0, This->indices, count * 3, 0);
00162         } break;
00163 
00164         case D3DOP_MATRIXLOAD:
00165             WARN("MATRIXLOAD-s     (%d)\n", count);
00166             instr += count * size;
00167             break;
00168 
00169         case D3DOP_MATRIXMULTIPLY: {
00170             int i;
00171         TRACE("MATRIXMULTIPLY   (%d)\n", count);
00172         
00173                 for (i = 0; i < count; ++i)
00174                 {
00175                     D3DMATRIXMULTIPLY *ci = (D3DMATRIXMULTIPLY *)instr;
00176                     D3DMATRIX *a, *b, *c;
00177 
00178                     a = ddraw_get_object(&lpDevice->handle_table, ci->hDestMatrix - 1, DDRAW_HANDLE_MATRIX);
00179                     b = ddraw_get_object(&lpDevice->handle_table, ci->hSrcMatrix1 - 1, DDRAW_HANDLE_MATRIX);
00180                     c = ddraw_get_object(&lpDevice->handle_table, ci->hSrcMatrix2 - 1, DDRAW_HANDLE_MATRIX);
00181 
00182                     if (!a || !b || !c)
00183                     {
00184                         ERR("Invalid matrix handle (a %#x -> %p, b %#x -> %p, c %#x -> %p).\n",
00185                                 ci->hDestMatrix, a, ci->hSrcMatrix1, b, ci->hSrcMatrix2, c);
00186                     }
00187                     else
00188                     {
00189                         TRACE("dst %p, src1 %p, src2 %p.\n", a, b, c);
00190                         multiply_matrix(a, c, b);
00191                     }
00192 
00193                     instr += size;
00194         }
00195         } break;
00196 
00197         case D3DOP_STATETRANSFORM: {
00198             int i;
00199         TRACE("STATETRANSFORM   (%d)\n", count);
00200         
00201                 for (i = 0; i < count; ++i)
00202                 {
00203                     D3DSTATE *ci = (D3DSTATE *)instr;
00204                     D3DMATRIX *m;
00205 
00206                     m = ddraw_get_object(&lpDevice->handle_table, ci->u2.dwArg[0] - 1, DDRAW_HANDLE_MATRIX);
00207                     if (!m)
00208                     {
00209                         ERR("Invalid matrix handle %#x.\n", ci->u2.dwArg[0]);
00210                     }
00211                     else
00212                     {
00213                         if (ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_WORLD)
00214                             lpDevice->world = ci->u2.dwArg[0];
00215                         if (ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_VIEW)
00216                             lpDevice->view = ci->u2.dwArg[0];
00217                         if (ci->u1.dtstTransformStateType == D3DTRANSFORMSTATE_PROJECTION)
00218                             lpDevice->proj = ci->u2.dwArg[0];
00219                         IDirect3DDevice7_SetTransform(&lpDevice->IDirect3DDevice7_iface,
00220                                 ci->u1.dtstTransformStateType, m);
00221                     }
00222 
00223                     instr += size;
00224                 }
00225         } break;
00226 
00227         case D3DOP_STATELIGHT: {
00228         int i;
00229         TRACE("STATELIGHT       (%d)\n", count);
00230 
00231         for (i = 0; i < count; i++) {
00232             LPD3DSTATE ci = (LPD3DSTATE) instr;
00233 
00234             TRACE("(%08x,%08x)\n", ci->u1.dlstLightStateType, ci->u2.dwArg[0]);
00235 
00236             if (!ci->u1.dlstLightStateType || (ci->u1.dlstLightStateType > D3DLIGHTSTATE_COLORVERTEX))
00237             ERR("Unexpected Light State Type %d\n", ci->u1.dlstLightStateType);
00238                     else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
00239                     {
00240                         IDirect3DMaterialImpl *m;
00241 
00242                         m = ddraw_get_object(&lpDevice->handle_table, ci->u2.dwArg[0] - 1, DDRAW_HANDLE_MATERIAL);
00243                         if (!m)
00244                             ERR("Invalid material handle %#x.\n", ci->u2.dwArg[0]);
00245                         else
00246                             material_activate(m);
00247                     }
00248                     else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
00249                     {
00250             switch (ci->u2.dwArg[0]) {
00251                 case D3DCOLOR_MONO:
00252                 ERR("DDCOLOR_MONO should not happen!\n");
00253                 break;
00254                 case D3DCOLOR_RGB:
00255                 /* We are already in this mode */
00256                 break;
00257                 default:
00258                 ERR("Unknown color model!\n");
00259             }
00260             } else {
00261             D3DRENDERSTATETYPE rs = 0;
00262             switch (ci->u1.dlstLightStateType) {
00263 
00264                 case D3DLIGHTSTATE_AMBIENT:       /* 2 */
00265                 rs = D3DRENDERSTATE_AMBIENT;
00266                 break;
00267                 case D3DLIGHTSTATE_FOGMODE:       /* 4 */
00268                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
00269                 break;
00270                 case D3DLIGHTSTATE_FOGSTART:      /* 5 */
00271                 rs = D3DRENDERSTATE_FOGSTART;
00272                 break;
00273                 case D3DLIGHTSTATE_FOGEND:        /* 6 */
00274                 rs = D3DRENDERSTATE_FOGEND;
00275                 break;
00276                 case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
00277                 rs = D3DRENDERSTATE_FOGDENSITY;
00278                 break;
00279                 case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
00280                 rs = D3DRENDERSTATE_COLORVERTEX;
00281                 break;
00282                 default:
00283                 break;
00284             }
00285 
00286                         IDirect3DDevice7_SetRenderState(&lpDevice->IDirect3DDevice7_iface, rs, ci->u2.dwArg[0]);
00287             }
00288 
00289             instr += size;
00290         }
00291         } break;
00292 
00293         case D3DOP_STATERENDER: {
00294             int i;
00295                 IDirect3DDevice2 *d3d_device2 = &lpDevice->IDirect3DDevice2_iface;
00296         TRACE("STATERENDER      (%d)\n", count);
00297 
00298         for (i = 0; i < count; i++) {
00299             LPD3DSTATE ci = (LPD3DSTATE) instr;
00300 
00301                     IDirect3DDevice2_SetRenderState(d3d_device2, ci->u1.drstRenderStateType, ci->u2.dwArg[0]);
00302 
00303             instr += size;
00304         }
00305         } break;
00306 
00307             case D3DOP_PROCESSVERTICES:
00308             {
00309                 /* TODO: Share code with IDirect3DVertexBuffer::ProcessVertices and / or
00310                  * IWineD3DDevice::ProcessVertices
00311                  */
00312                 int i;
00313                 D3DMATRIX view_mat, world_mat, proj_mat;
00314                 TRACE("PROCESSVERTICES  (%d)\n", count);
00315 
00316                 /* Get the transform and world matrix */
00317                 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
00318                 wined3d_device_get_transform(lpDevice->wined3d_device,
00319                         D3DTRANSFORMSTATE_VIEW, (struct wined3d_matrix *)&view_mat);
00320                 wined3d_device_get_transform(lpDevice->wined3d_device,
00321                         D3DTRANSFORMSTATE_PROJECTION, (struct wined3d_matrix *)&proj_mat);
00322                 wined3d_device_get_transform(lpDevice->wined3d_device,
00323                         WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)&world_mat);
00324 
00325         for (i = 0; i < count; i++) {
00326             LPD3DPROCESSVERTICES ci = (LPD3DPROCESSVERTICES) instr;
00327 
00328                     TRACE("  Start : %d Dest : %d Count : %d\n",
00329               ci->wStart, ci->wDest, ci->dwCount);
00330             TRACE("  Flags : ");
00331                     if (TRACE_ON(ddraw))
00332                     {
00333                 if (ci->dwFlags & D3DPROCESSVERTICES_COPY)
00334                 TRACE("COPY ");
00335             if (ci->dwFlags & D3DPROCESSVERTICES_NOCOLOR)
00336                 TRACE("NOCOLOR ");
00337             if (ci->dwFlags == D3DPROCESSVERTICES_OPMASK)
00338                 TRACE("OPMASK ");
00339             if (ci->dwFlags & D3DPROCESSVERTICES_TRANSFORM)
00340                 TRACE("TRANSFORM ");
00341             if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT)
00342                 TRACE("TRANSFORMLIGHT ");
00343             if (ci->dwFlags & D3DPROCESSVERTICES_UPDATEEXTENTS)
00344                 TRACE("UPDATEEXTENTS ");
00345             TRACE("\n");
00346             }
00347 
00348             /* This is where doing Direct3D on top on OpenGL is quite difficult.
00349                This method transforms a set of vertices using the CURRENT state
00350                (lighting, projection, ...) but does not rasterize them.
00351                They will only be put on screen later (with the POINT / LINE and
00352                TRIANGLE op-codes). The problem is that you can have a triangle
00353                with each point having been transformed using another state...
00354 
00355                In this implementation, I will emulate only ONE thing : each
00356                vertex can have its own "WORLD" transformation (this is used in the
00357                TWIST.EXE demo of the 5.2 SDK). I suppose that all vertices of the
00358                execute buffer use the same state.
00359 
00360                If I find applications that change other states, I will try to do a
00361                more 'fine-tuned' state emulation (but I may become quite tricky if
00362                it changes a light position in the middle of a triangle).
00363 
00364                In this case, a 'direct' approach (i.e. without using OpenGL, but
00365                writing our own 3D rasterizer) would be easier. */
00366 
00367             /* The current method (with the hypothesis that only the WORLD matrix
00368                will change between two points) is like this :
00369                - I transform 'manually' all the vertices with the current WORLD
00370                  matrix and store them in the vertex buffer
00371                - during the rasterization phase, the WORLD matrix will be set to
00372                  the Identity matrix */
00373 
00374             /* Enough for the moment */
00375             if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORMLIGHT) {
00376                 unsigned int nb;
00377             D3DVERTEX  *src = ((LPD3DVERTEX)  ((char *)This->desc.lpData + vs)) + ci->wStart;
00378             D3DTLVERTEX *dst = ((LPD3DTLVERTEX) (This->vertex_data)) + ci->wDest;
00379             D3DMATRIX mat;
00380             D3DVIEWPORT* Viewport = &lpViewport->viewports.vp1;
00381             
00382                         if (TRACE_ON(ddraw))
00383                         {
00384                 TRACE("  Projection Matrix : (%p)\n", &proj_mat);
00385                 dump_D3DMATRIX(&proj_mat);
00386                 TRACE("  View       Matrix : (%p)\n", &view_mat);
00387                 dump_D3DMATRIX(&view_mat);
00388                 TRACE("  World Matrix : (%p)\n", &world_mat);
00389                 dump_D3DMATRIX(&world_mat);
00390             }
00391 
00392                         multiply_matrix(&mat,&view_mat,&world_mat);
00393                         multiply_matrix(&mat,&proj_mat,&mat);
00394 
00395             for (nb = 0; nb < ci->dwCount; nb++) {
00396                 /* No lighting yet */
00397                 dst->u5.color = 0xFFFFFFFF; /* Opaque white */
00398                 dst->u6.specular = 0xFF000000; /* No specular and no fog factor */
00399 
00400                 dst->u7.tu  = src->u7.tu;
00401                 dst->u8.tv  = src->u8.tv;
00402 
00403                 /* Now, the matrix multiplication */
00404                 dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + (1.0 * mat._41);
00405                 dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + (1.0 * mat._42);
00406                 dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + (1.0 * mat._43);
00407                 dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + (1.0 * mat._44);
00408 
00409                 dst->u1.sx = dst->u1.sx / dst->u4.rhw * Viewport->dvScaleX
00410                        + Viewport->dwX + Viewport->dwWidth / 2;
00411                 dst->u2.sy = (-dst->u2.sy) / dst->u4.rhw * Viewport->dvScaleY
00412                        + Viewport->dwY + Viewport->dwHeight / 2;
00413                 dst->u3.sz /= dst->u4.rhw;
00414                 dst->u4.rhw = 1 / dst->u4.rhw;
00415 
00416                 src++;
00417                 dst++;
00418 
00419             }
00420             } else if (ci->dwFlags == D3DPROCESSVERTICES_TRANSFORM) {
00421                 unsigned int nb;
00422             D3DLVERTEX *src  = ((LPD3DLVERTEX) ((char *)This->desc.lpData + vs)) + ci->wStart;
00423             D3DTLVERTEX *dst = ((LPD3DTLVERTEX) (This->vertex_data)) + ci->wDest;
00424             D3DMATRIX mat;
00425             D3DVIEWPORT* Viewport = &lpViewport->viewports.vp1;
00426             
00427                         if (TRACE_ON(ddraw))
00428                         {
00429                 TRACE("  Projection Matrix : (%p)\n", &proj_mat);
00430                 dump_D3DMATRIX(&proj_mat);
00431                 TRACE("  View       Matrix : (%p)\n",&view_mat);
00432                 dump_D3DMATRIX(&view_mat);
00433                 TRACE("  World Matrix : (%p)\n", &world_mat);
00434                 dump_D3DMATRIX(&world_mat);
00435             }
00436 
00437             multiply_matrix(&mat,&view_mat,&world_mat);
00438             multiply_matrix(&mat,&proj_mat,&mat);
00439 
00440             for (nb = 0; nb < ci->dwCount; nb++) {
00441                 dst->u5.color = src->u4.color;
00442                 dst->u6.specular = src->u5.specular;
00443                 dst->u7.tu = src->u6.tu;
00444                 dst->u8.tv = src->u7.tv;
00445 
00446                 /* Now, the matrix multiplication */
00447                 dst->u1.sx = (src->u1.x * mat._11) + (src->u2.y * mat._21) + (src->u3.z * mat._31) + (1.0 * mat._41);
00448                 dst->u2.sy = (src->u1.x * mat._12) + (src->u2.y * mat._22) + (src->u3.z * mat._32) + (1.0 * mat._42);
00449                 dst->u3.sz = (src->u1.x * mat._13) + (src->u2.y * mat._23) + (src->u3.z * mat._33) + (1.0 * mat._43);
00450                 dst->u4.rhw = (src->u1.x * mat._14) + (src->u2.y * mat._24) + (src->u3.z * mat._34) + (1.0 * mat._44);
00451 
00452                 dst->u1.sx = dst->u1.sx / dst->u4.rhw * Viewport->dvScaleX
00453                        + Viewport->dwX + Viewport->dwWidth / 2;
00454                 dst->u2.sy = (-dst->u2.sy) / dst->u4.rhw * Viewport->dvScaleY
00455                        + Viewport->dwY + Viewport->dwHeight / 2;
00456 
00457                 dst->u3.sz /= dst->u4.rhw;
00458                 dst->u4.rhw = 1 / dst->u4.rhw;
00459 
00460                 src++;
00461                 dst++;
00462             }
00463             } else if (ci->dwFlags == D3DPROCESSVERTICES_COPY) {
00464                 D3DTLVERTEX *src = ((LPD3DTLVERTEX) ((char *)This->desc.lpData + vs)) + ci->wStart;
00465             D3DTLVERTEX *dst = ((LPD3DTLVERTEX) (This->vertex_data)) + ci->wDest;
00466             
00467             memcpy(dst, src, ci->dwCount * sizeof(D3DTLVERTEX));
00468             } else {
00469                 ERR("Unhandled vertex processing flag %#x.\n", ci->dwFlags);
00470             }
00471 
00472             instr += size;
00473         }
00474         } break;
00475 
00476         case D3DOP_TEXTURELOAD: {
00477             WARN("TEXTURELOAD-s    (%d)\n", count);
00478 
00479         instr += count * size;
00480         } break;
00481 
00482         case D3DOP_EXIT: {
00483             TRACE("EXIT             (%d)\n", count);
00484         /* We did this instruction */
00485         instr += size;
00486         /* Exit this loop */
00487         goto end_of_buffer;
00488         } break;
00489 
00490         case D3DOP_BRANCHFORWARD: {
00491             int i;
00492         TRACE("BRANCHFORWARD    (%d)\n", count);
00493 
00494         for (i = 0; i < count; i++) {
00495             LPD3DBRANCH ci = (LPD3DBRANCH) instr;
00496 
00497             if ((This->data.dsStatus.dwStatus & ci->dwMask) == ci->dwValue) {
00498                 if (!ci->bNegate) {
00499                             TRACE(" Branch to %d\n", ci->dwOffset);
00500                             if (ci->dwOffset) {
00501                                 instr = (char*)current + ci->dwOffset;
00502                                 break;
00503                             }
00504             }
00505             } else {
00506                 if (ci->bNegate) {
00507                             TRACE(" Branch to %d\n", ci->dwOffset);
00508                             if (ci->dwOffset) {
00509                                 instr = (char*)current + ci->dwOffset;
00510                                 break;
00511                             }
00512             }
00513             }
00514 
00515             instr += size;
00516         }
00517         } break;
00518 
00519         case D3DOP_SPAN: {
00520             WARN("SPAN-s           (%d)\n", count);
00521 
00522         instr += count * size;
00523         } break;
00524 
00525         case D3DOP_SETSTATUS: {
00526             int i;
00527         TRACE("SETSTATUS        (%d)\n", count);
00528 
00529         for (i = 0; i < count; i++) {
00530             LPD3DSTATUS ci = (LPD3DSTATUS) instr;
00531 
00532             This->data.dsStatus = *ci;
00533 
00534             instr += size;
00535         }
00536         } break;
00537 
00538         default:
00539             ERR("Unhandled OpCode %d !!!\n",current->bOpcode);
00540             /* Try to save ... */
00541             instr += count * size;
00542             break;
00543     }
00544     }
00545 
00546 end_of_buffer:
00547     return D3D_OK;
00548 }
00549 
00550 static inline IDirect3DExecuteBufferImpl *impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer *iface)
00551 {
00552     return CONTAINING_RECORD(iface, IDirect3DExecuteBufferImpl, IDirect3DExecuteBuffer_iface);
00553 }
00554 
00555 /*****************************************************************************
00556  * IDirect3DExecuteBuffer::QueryInterface
00557  *
00558  * Well, a usual QueryInterface function. Don't know fur sure which
00559  * interfaces it can Query.
00560  *
00561  * Params:
00562  *  riid: The interface ID queried for
00563  *  obj: Address to return the interface pointer at
00564  *
00565  * Returns:
00566  *  D3D_OK in case of a success (S_OK? Think it's the same)
00567  *  OLE_E_ENUM_NOMORE if the interface wasn't found.
00568  *   (E_NOINTERFACE?? Don't know what I really need)
00569  *
00570  *****************************************************************************/
00571 static HRESULT WINAPI
00572 IDirect3DExecuteBufferImpl_QueryInterface(IDirect3DExecuteBuffer *iface,
00573                                           REFIID riid,
00574                                           void **obj)
00575 {
00576     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
00577 
00578     *obj = NULL;
00579 
00580     if ( IsEqualGUID( &IID_IUnknown,  riid ) ) {
00581         IDirect3DExecuteBuffer_AddRef(iface);
00582     *obj = iface;
00583     TRACE("  Creating IUnknown interface at %p.\n", *obj);
00584     return S_OK;
00585     }
00586     if ( IsEqualGUID( &IID_IDirect3DExecuteBuffer, riid ) ) {
00587         IDirect3DExecuteBuffer_AddRef(iface);
00588         *obj = iface;
00589     TRACE("  Creating IDirect3DExecuteBuffer interface %p\n", *obj);
00590     return S_OK;
00591     }
00592     FIXME("(%p): interface for IID %s NOT found!\n", iface, debugstr_guid(riid));
00593     return E_NOINTERFACE;
00594 }
00595 
00596 
00597 /*****************************************************************************
00598  * IDirect3DExecuteBuffer::AddRef
00599  *
00600  * A normal AddRef method, nothing special
00601  *
00602  * Returns:
00603  *  The new refcount
00604  *
00605  *****************************************************************************/
00606 static ULONG WINAPI IDirect3DExecuteBufferImpl_AddRef(IDirect3DExecuteBuffer *iface)
00607 {
00608     IDirect3DExecuteBufferImpl *This = impl_from_IDirect3DExecuteBuffer(iface);
00609     ULONG ref = InterlockedIncrement(&This->ref);
00610 
00611     TRACE("%p increasing refcount to %u.\n", This, ref);
00612 
00613     return ref;
00614 }
00615 
00616 /*****************************************************************************
00617  * IDirect3DExecuteBuffer::Release
00618  *
00619  * A normal Release method, nothing special
00620  *
00621  * Returns:
00622  *  The new refcount
00623  *
00624  *****************************************************************************/
00625 static ULONG WINAPI IDirect3DExecuteBufferImpl_Release(IDirect3DExecuteBuffer *iface)
00626 {
00627     IDirect3DExecuteBufferImpl *This = impl_from_IDirect3DExecuteBuffer(iface);
00628     ULONG ref = InterlockedDecrement(&This->ref);
00629 
00630     TRACE("%p decreasing refcount to %u.\n", This, ref);
00631 
00632     if (!ref) {
00633         if (This->need_free)
00634         HeapFree(GetProcessHeap(),0,This->desc.lpData);
00635         HeapFree(GetProcessHeap(),0,This->vertex_data);
00636         HeapFree(GetProcessHeap(),0,This->indices);
00637     HeapFree(GetProcessHeap(),0,This);
00638     return 0;
00639     }
00640 
00641     return ref;
00642 }
00643 
00644 /*****************************************************************************
00645  * IDirect3DExecuteBuffer::Initialize
00646  *
00647  * Initializes the Execute Buffer. This method exists for COM compliance
00648  * Nothing to do here.
00649  *
00650  * Returns:
00651  *  D3D_OK
00652  *
00653  *****************************************************************************/
00654 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Initialize(IDirect3DExecuteBuffer *iface,
00655         IDirect3DDevice *device, D3DEXECUTEBUFFERDESC *desc)
00656 {
00657     TRACE("iface %p, device %p, desc %p.\n", iface, device, desc);
00658 
00659     return D3D_OK;
00660 }
00661 
00662 /*****************************************************************************
00663  * IDirect3DExecuteBuffer::Lock
00664  *
00665  * Locks the buffer, so the app can write into it.
00666  *
00667  * Params:
00668  *  Desc: Pointer to return the buffer description. This Description contains
00669  *        a pointer to the buffer data.
00670  *
00671  * Returns:
00672  *  This implementation always returns D3D_OK
00673  *
00674  *****************************************************************************/
00675 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Lock(IDirect3DExecuteBuffer *iface,
00676         D3DEXECUTEBUFFERDESC *lpDesc)
00677 {
00678     IDirect3DExecuteBufferImpl *This = impl_from_IDirect3DExecuteBuffer(iface);
00679     DWORD dwSize;
00680 
00681     TRACE("iface %p, desc %p.\n", iface, lpDesc);
00682 
00683     dwSize = lpDesc->dwSize;
00684     memcpy(lpDesc, &This->desc, dwSize);
00685 
00686     if (TRACE_ON(ddraw))
00687     {
00688         TRACE("  Returning description :\n");
00689     _dump_D3DEXECUTEBUFFERDESC(lpDesc);
00690     }
00691     return D3D_OK;
00692 }
00693 
00694 /*****************************************************************************
00695  * IDirect3DExecuteBuffer::Unlock
00696  *
00697  * Unlocks the buffer. We don't have anything to do here
00698  *
00699  * Returns:
00700  *  This implementation always returns D3D_OK
00701  *
00702  *****************************************************************************/
00703 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Unlock(IDirect3DExecuteBuffer *iface)
00704 {
00705     TRACE("iface %p.\n", iface);
00706 
00707     return D3D_OK;
00708 }
00709 
00710 /*****************************************************************************
00711  * IDirect3DExecuteBuffer::SetExecuteData
00712  *
00713  * Sets the execute data. This data is used to describe the buffer's content
00714  *
00715  * Params:
00716  *  Data: Pointer to a D3DEXECUTEDATA structure containing the data to
00717  *  assign
00718  *
00719  * Returns:
00720  *  D3D_OK on success
00721  *  DDERR_OUTOFMEMORY if the vertex buffer allocation failed
00722  *
00723  *****************************************************************************/
00724 static HRESULT WINAPI IDirect3DExecuteBufferImpl_SetExecuteData(IDirect3DExecuteBuffer *iface,
00725         D3DEXECUTEDATA *lpData)
00726 {
00727     IDirect3DExecuteBufferImpl *This = impl_from_IDirect3DExecuteBuffer(iface);
00728     DWORD nbvert;
00729 
00730     TRACE("iface %p, data %p.\n", iface, lpData);
00731 
00732     memcpy(&This->data, lpData, lpData->dwSize);
00733 
00734     /* Get the number of vertices in the execute buffer */
00735     nbvert = This->data.dwVertexCount;
00736 
00737     /* Prepares the transformed vertex buffer */
00738     HeapFree(GetProcessHeap(), 0, This->vertex_data);
00739     This->vertex_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nbvert * sizeof(D3DTLVERTEX));
00740 
00741     if (TRACE_ON(ddraw))
00742         _dump_executedata(lpData);
00743 
00744     return D3D_OK;
00745 }
00746 
00747 /*****************************************************************************
00748  * IDirect3DExecuteBuffer::GetExecuteData
00749  *
00750  * Returns the data in the execute buffer
00751  *
00752  * Params:
00753  *  Data: Pointer to a D3DEXECUTEDATA structure used to return data
00754  *
00755  * Returns:
00756  *  D3D_OK on success
00757  *
00758  *****************************************************************************/
00759 static HRESULT WINAPI IDirect3DExecuteBufferImpl_GetExecuteData(IDirect3DExecuteBuffer *iface,
00760         D3DEXECUTEDATA *lpData)
00761 {
00762     IDirect3DExecuteBufferImpl *This = impl_from_IDirect3DExecuteBuffer(iface);
00763     DWORD dwSize;
00764 
00765     TRACE("iface %p, data %p.\n", iface, lpData);
00766 
00767     dwSize = lpData->dwSize;
00768     memcpy(lpData, &This->data, dwSize);
00769 
00770     if (TRACE_ON(ddraw))
00771     {
00772         TRACE("Returning data :\n");
00773     _dump_executedata(lpData);
00774     }
00775 
00776     return DD_OK;
00777 }
00778 
00779 /*****************************************************************************
00780  * IDirect3DExecuteBuffer::Validate
00781  *
00782  * DirectX 5 SDK: "The IDirect3DExecuteBuffer::Validate method is not
00783  * currently implemented"
00784  *
00785  * Params:
00786  *  ?
00787  *
00788  * Returns:
00789  *  DDERR_UNSUPPORTED, because it's not implemented in Windows.
00790  *
00791  *****************************************************************************/
00792 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Validate(IDirect3DExecuteBuffer *iface,
00793         DWORD *offset, LPD3DVALIDATECALLBACK callback, void *context, DWORD reserved)
00794 {
00795     TRACE("iface %p, offset %p, callback %p, context %p, reserved %#x.\n",
00796             iface, offset, callback, context, reserved);
00797 
00798     WARN("Not implemented.\n");
00799 
00800     return DDERR_UNSUPPORTED; /* Unchecked */
00801 }
00802 
00803 /*****************************************************************************
00804  * IDirect3DExecuteBuffer::Optimize
00805  *
00806  * DirectX5 SDK: "The IDirect3DExecuteBuffer::Optimize method is not
00807  * currently supported"
00808  *
00809  * Params:
00810  *  Dummy: Seems to be an unused dummy ;)
00811  *
00812  * Returns:
00813  *  DDERR_UNSUPPORTED, because it's not implemented in Windows.
00814  *
00815  *****************************************************************************/
00816 static HRESULT WINAPI IDirect3DExecuteBufferImpl_Optimize(IDirect3DExecuteBuffer *iface, DWORD reserved)
00817 {
00818     TRACE("iface %p, reserved %#x.\n", iface, reserved);
00819 
00820     WARN("Not implemented.\n");
00821 
00822     return DDERR_UNSUPPORTED; /* Unchecked */
00823 }
00824 
00825 static const struct IDirect3DExecuteBufferVtbl d3d_execute_buffer_vtbl =
00826 {
00827     IDirect3DExecuteBufferImpl_QueryInterface,
00828     IDirect3DExecuteBufferImpl_AddRef,
00829     IDirect3DExecuteBufferImpl_Release,
00830     IDirect3DExecuteBufferImpl_Initialize,
00831     IDirect3DExecuteBufferImpl_Lock,
00832     IDirect3DExecuteBufferImpl_Unlock,
00833     IDirect3DExecuteBufferImpl_SetExecuteData,
00834     IDirect3DExecuteBufferImpl_GetExecuteData,
00835     IDirect3DExecuteBufferImpl_Validate,
00836     IDirect3DExecuteBufferImpl_Optimize,
00837 };
00838 
00839 HRESULT d3d_execute_buffer_init(IDirect3DExecuteBufferImpl *execute_buffer,
00840         IDirect3DDeviceImpl *device, D3DEXECUTEBUFFERDESC *desc)
00841 {
00842     execute_buffer->IDirect3DExecuteBuffer_iface.lpVtbl = &d3d_execute_buffer_vtbl;
00843     execute_buffer->ref = 1;
00844     execute_buffer->d3ddev = device;
00845 
00846     /* Initializes memory */
00847     memcpy(&execute_buffer->desc, desc, desc->dwSize);
00848 
00849     /* No buffer given */
00850     if (!(execute_buffer->desc.dwFlags & D3DDEB_LPDATA))
00851         execute_buffer->desc.lpData = NULL;
00852 
00853     /* No buffer size given */
00854     if (!(execute_buffer->desc.dwFlags & D3DDEB_BUFSIZE))
00855         execute_buffer->desc.dwBufferSize = 0;
00856 
00857     /* Create buffer if asked */
00858     if (!execute_buffer->desc.lpData && execute_buffer->desc.dwBufferSize)
00859     {
00860         execute_buffer->need_free = TRUE;
00861         execute_buffer->desc.lpData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, execute_buffer->desc.dwBufferSize);
00862         if (!execute_buffer->desc.lpData)
00863         {
00864             ERR("Failed to allocate execute buffer data.\n");
00865             return DDERR_OUTOFMEMORY;
00866         }
00867     }
00868 
00869     execute_buffer->desc.dwFlags |= D3DDEB_LPDATA;
00870 
00871     return D3D_OK;
00872 }
00873 
00874 IDirect3DExecuteBufferImpl *unsafe_impl_from_IDirect3DExecuteBuffer(IDirect3DExecuteBuffer *iface)
00875 {
00876     if (!iface)
00877         return NULL;
00878     assert(iface->lpVtbl == &d3d_execute_buffer_vtbl);
00879 
00880     return impl_from_IDirect3DExecuteBuffer(iface);
00881 }

Generated on Sun May 27 2012 04:22:15 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.