* Sync up to trunk head (r64377).
[reactos.git] / dll / directx / wine / ddraw / executebuffer.c
index 4109d7a..c645aed 100644 (file)
@@ -45,12 +45,27 @@ 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)
 {
     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)
     {
@@ -87,8 +102,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                instr += count * size;
            } break;
 
-           case D3DOP_TRIANGLE: {
-                DWORD i;
+            case D3DOP_TRIANGLE:
+            {
                 D3DTLVERTEX *tl_vx = buffer->vertex_data;
                TRACE("TRIANGLE         (%d)\n", count);
 
@@ -139,10 +154,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                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;
@@ -164,13 +177,11 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                     }
 
                     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;
@@ -195,97 +206,42 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
 
                     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 */
@@ -297,157 +253,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);
@@ -463,10 +353,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                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;
@@ -492,8 +380,8 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                    }
 
                    instr += size;
-               }
-           } break;
+                }
+                break;
 
            case D3DOP_SPAN: {
                WARN("SPAN-s           (%d)\n", count);
@@ -501,16 +389,14 @@ HRESULT d3d_execute_buffer_execute(struct d3d_execute_buffer *buffer,
                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);
@@ -529,45 +415,24 @@ static inline struct d3d_execute_buffer *impl_from_IDirect3DExecuteBuffer(IDirec
     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
  *