Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenexecutebuffer.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
1.7.6.1
|