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)
{
DWORD vs = buffer->data.dwVertexOffset;
DWORD is = buffer->data.dwInstructionOffset;
char *instr = (char *)buffer->desc.lpData + is;
+ unsigned int i;
if (viewport->active_device != device)
{
instr += count * size;
} break;
- case D3DOP_TRIANGLE: {
- DWORD i;
+ case D3DOP_TRIANGLE:
+ {
D3DTLVERTEX *tl_vx = buffer->vertex_data;
TRACE("TRIANGLE (%d)\n", count);
instr += count * size;
break;
- case D3DOP_MATRIXMULTIPLY: {
- DWORD i;
- TRACE("MATRIXMULTIPLY (%d)\n", count);
-
+ case D3DOP_MATRIXMULTIPLY:
+ TRACE("MATRIXMULTIPLY (%d)\n", count);
for (i = 0; i < count; ++i)
{
D3DMATRIXMULTIPLY *ci = (D3DMATRIXMULTIPLY *)instr;
}
instr += size;
- }
- } break;
+ }
+ break;
- case D3DOP_STATETRANSFORM: {
- DWORD i;
- TRACE("STATETRANSFORM (%d)\n", count);
-
+ case D3DOP_STATETRANSFORM:
+ TRACE("STATETRANSFORM (%d)\n", count);
for (i = 0; i < count; ++i)
{
D3DSTATE *ci = (D3DSTATE *)instr;
instr += size;
}
- } break;
-
- case D3DOP_STATELIGHT: {
- DWORD i;
- TRACE("STATELIGHT (%d)\n", count);
+ break;
+ case D3DOP_STATELIGHT:
+ TRACE("STATELIGHT (%d)\n", count);
for (i = 0; i < count; ++i)
{
D3DSTATE *ci = (D3DSTATE *)instr;
- TRACE("(%08x,%08x)\n", ci->u1.dlstLightStateType, ci->u2.dwArg[0]);
-
- if (!ci->u1.dlstLightStateType || (ci->u1.dlstLightStateType > D3DLIGHTSTATE_COLORVERTEX))
- ERR("Unexpected Light State Type %d\n", ci->u1.dlstLightStateType);
- else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
- {
- struct d3d_material *m;
-
- m = ddraw_get_object(&device->handle_table, ci->u2.dwArg[0] - 1, DDRAW_HANDLE_MATERIAL);
- if (!m)
- ERR("Invalid material handle %#x.\n", ci->u2.dwArg[0]);
- else
- material_activate(m);
- }
- else if (ci->u1.dlstLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
- {
- switch (ci->u2.dwArg[0]) {
- case D3DCOLOR_MONO:
- ERR("DDCOLOR_MONO should not happen!\n");
- break;
- case D3DCOLOR_RGB:
- /* We are already in this mode */
- break;
- default:
- ERR("Unknown color model!\n");
- }
- } else {
- D3DRENDERSTATETYPE rs = 0;
- switch (ci->u1.dlstLightStateType) {
-
- case D3DLIGHTSTATE_AMBIENT: /* 2 */
- rs = D3DRENDERSTATE_AMBIENT;
- break;
- case D3DLIGHTSTATE_FOGMODE: /* 4 */
- rs = D3DRENDERSTATE_FOGVERTEXMODE;
- break;
- case D3DLIGHTSTATE_FOGSTART: /* 5 */
- rs = D3DRENDERSTATE_FOGSTART;
- break;
- case D3DLIGHTSTATE_FOGEND: /* 6 */
- rs = D3DRENDERSTATE_FOGEND;
- break;
- case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
- rs = D3DRENDERSTATE_FOGDENSITY;
- break;
- case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
- rs = D3DRENDERSTATE_COLORVERTEX;
- break;
- default:
- break;
- }
-
- IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, ci->u2.dwArg[0]);
- }
-
- instr += size;
- }
- } break;
+ if (FAILED(IDirect3DDevice3_SetLightState(&device->IDirect3DDevice3_iface,
+ ci->u1.dlstLightStateType, ci->u2.dwArg[0])))
+ WARN("Failed to set light state.\n");
- case D3DOP_STATERENDER: {
- DWORD i;
- IDirect3DDevice2 *d3d_device2 = &device->IDirect3DDevice2_iface;
- TRACE("STATERENDER (%d)\n", count);
+ instr += size;
+ }
+ break;
+ case D3DOP_STATERENDER:
+ TRACE("STATERENDER (%d)\n", count);
for (i = 0; i < count; ++i)
{
D3DSTATE *ci = (D3DSTATE *)instr;
- IDirect3DDevice2_SetRenderState(d3d_device2, ci->u1.drstRenderStateType, ci->u2.dwArg[0]);
+ if (FAILED(IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface,
+ ci->u1.drstRenderStateType, ci->u2.dwArg[0])))
+ WARN("Failed to set render state.\n");
- instr += size;
- }
- } break;
+ instr += size;
+ }
+ break;
case D3DOP_PROCESSVERTICES:
{
- /* TODO: Share code with IDirect3DVertexBuffer::ProcessVertices and / or
- * IWineD3DDevice::ProcessVertices
- */
- DWORD i;
- D3DMATRIX view_mat, world_mat, proj_mat;
+ /* TODO: Share code with d3d_vertex_buffer7_ProcessVertices()
+ * and / or wined3d_device_process_vertices(). */
+ D3DMATRIX view_mat, world_mat, proj_mat, mat;
+
TRACE("PROCESSVERTICES (%d)\n", count);
/* Get the transform and world matrix */
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);
goto end_of_buffer;
} break;
- case D3DOP_BRANCHFORWARD: {
- DWORD i;
- TRACE("BRANCHFORWARD (%d)\n", count);
-
+ case D3DOP_BRANCHFORWARD:
+ TRACE("BRANCHFORWARD (%d)\n", count);
for (i = 0; i < count; ++i)
{
D3DBRANCH *ci = (D3DBRANCH *)instr;
}
instr += size;
- }
- } break;
+ }
+ break;
case D3DOP_SPAN: {
WARN("SPAN-s (%d)\n", count);
instr += count * size;
} break;
- case D3DOP_SETSTATUS: {
- DWORD i;
- TRACE("SETSTATUS (%d)\n", count);
-
+ case D3DOP_SETSTATUS:
+ TRACE("SETSTATUS (%d)\n", count);
for (i = 0; i < count; ++i)
{
buffer->data.dsStatus = *(D3DSTATUS *)instr;
instr += size;
}
- } break;
+ break;
default:
ERR("Unhandled OpCode %d !!!\n",current->bOpcode);
return CONTAINING_RECORD(iface, struct d3d_execute_buffer, IDirect3DExecuteBuffer_iface);
}
-/*****************************************************************************
- * IDirect3DExecuteBuffer::QueryInterface
- *
- * Well, a usual QueryInterface function. Don't know fur sure which
- * interfaces it can Query.
- *
- * Params:
- * riid: The interface ID queried for
- * obj: Address to return the interface pointer at
- *
- * Returns:
- * D3D_OK in case of a success (S_OK? Think it's the same)
- * OLE_E_ENUM_NOMORE if the interface wasn't found.
- * (E_NOINTERFACE?? Don't know what I really need)
- *
- *****************************************************************************/
-static HRESULT WINAPI d3d_execute_buffer_QueryInterface(IDirect3DExecuteBuffer *iface, REFIID riid, void **obj)
+static HRESULT WINAPI d3d_execute_buffer_QueryInterface(IDirect3DExecuteBuffer *iface, REFIID iid, void **out)
{
- TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
+ TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
- *obj = NULL;
-
- if ( IsEqualGUID( &IID_IUnknown, riid ) ) {
- IDirect3DExecuteBuffer_AddRef(iface);
- *obj = iface;
- TRACE(" Creating IUnknown interface at %p.\n", *obj);
- return S_OK;
- }
- if ( IsEqualGUID( &IID_IDirect3DExecuteBuffer, riid ) ) {
+ if (IsEqualGUID(&IID_IDirect3DExecuteBuffer, iid)
+ || IsEqualGUID(&IID_IUnknown, iid))
+ {
IDirect3DExecuteBuffer_AddRef(iface);
- *obj = iface;
- TRACE(" Creating IDirect3DExecuteBuffer interface %p\n", *obj);
- return S_OK;
+ *out = iface;
+ return S_OK;
}
- FIXME("(%p): interface for IID %s NOT found!\n", iface, debugstr_guid(riid));
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+
+ *out = NULL;
return E_NOINTERFACE;
}
-
/*****************************************************************************
* IDirect3DExecuteBuffer::AddRef
*