Signed-off-by: Alistair Leslie-Hughes leslie_alistair@hotmail.com
-- v4: d3drm: Implement IDirect3DRMViewport Render d3drm: Implement IDirect3DRMFrame{1/2/3}::SetSceneBackgroundImage
From: Alistair Leslie-Hughes leslie_alistair@hotmail.com
Signed-off-by: Alistair Leslie-Hughes leslie_alistair@hotmail.com --- dlls/d3drm/d3drm_private.h | 1 + dlls/d3drm/frame.c | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/dlls/d3drm/d3drm_private.h b/dlls/d3drm/d3drm_private.h index 2fb6bafe951..31fdd4984a1 100644 --- a/dlls/d3drm/d3drm_private.h +++ b/dlls/d3drm/d3drm_private.h @@ -81,6 +81,7 @@ struct d3drm_frame IDirect3DRMFrame3 IDirect3DRMFrame3_iface; IDirect3DRM *d3drm; LONG ref; + IUnknown *backgroundimage; struct d3drm_frame *parent; SIZE_T nb_children; SIZE_T children_size; diff --git a/dlls/d3drm/frame.c b/dlls/d3drm/frame.c index 5cc3ad585d4..9365e02cc47 100644 --- a/dlls/d3drm/frame.c +++ b/dlls/d3drm/frame.c @@ -608,6 +608,8 @@ static ULONG WINAPI d3drm_frame3_Release(IDirect3DRMFrame3 *iface)
if (!refcount) { + if (frame->backgroundimage) + IUnknown_Release(frame->backgroundimage); d3drm_object_cleanup((IDirect3DRMObject *)&frame->IDirect3DRMFrame_iface, &frame->obj); for (i = 0; i < frame->nb_children; ++i) { @@ -2222,25 +2224,47 @@ static HRESULT WINAPI d3drm_frame1_SetSceneBackgroundDepth(IDirect3DRMFrame *ifa static HRESULT WINAPI d3drm_frame3_SetSceneBackgroundImage(IDirect3DRMFrame3 *iface, IDirect3DRMTexture3 *texture) { - FIXME("iface %p, texture %p stub!\n", iface, texture); + struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface); + IUnknown *unk = NULL;
- return E_NOTIMPL; + TRACE("iface %p, texture %p\n", iface, texture); + + if (texture) + IDirect3DRMTexture3_QueryInterface(texture, &IID_IUnknown, (void**)&unk); + + if (frame->backgroundimage) + IUnknown_Release(frame->backgroundimage); + + frame->backgroundimage = unk; + + return S_OK; }
static HRESULT WINAPI d3drm_frame2_SetSceneBackgroundImage(IDirect3DRMFrame2 *iface, IDirect3DRMTexture *texture) { - FIXME("iface %p, texture %p stub!\n", iface, texture); + struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface); + IUnknown *unk = NULL;
- return E_NOTIMPL; + TRACE("iface %p, texture %p\n", iface, texture); + + if (texture) + IDirect3DRMTexture_QueryInterface(texture, &IID_IUnknown, (void**)&unk); + + if (frame->backgroundimage) + IUnknown_Release(frame->backgroundimage); + + frame->backgroundimage = unk; + + return S_OK; }
static HRESULT WINAPI d3drm_frame1_SetSceneBackgroundImage(IDirect3DRMFrame *iface, IDirect3DRMTexture *texture) { - FIXME("iface %p, texture %p stub!\n", iface, texture); - - return E_NOTIMPL; + struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface); + TRACE("iface %p, texture %p\n", iface, texture); + return d3drm_frame2_SetSceneBackgroundImage(&frame->IDirect3DRMFrame2_iface, texture); }
static HRESULT WINAPI d3drm_frame3_SetSceneFogEnable(IDirect3DRMFrame3 *iface, BOOL enable)
From: Alistair Leslie-Hughes leslie_alistair@hotmail.com
Signed-off-by: Alistair Leslie-Hughes leslie_alistair@hotmail.com --- dlls/d3drm/Makefile.in | 2 +- dlls/d3drm/d3drm_private.h | 3 ++ dlls/d3drm/device.c | 9 ++++ dlls/d3drm/frame.c | 10 +++- dlls/d3drm/texture.c | 15 ++++++ dlls/d3drm/viewport.c | 101 +++++++++++++++++++++++++++++++++++-- 6 files changed, 133 insertions(+), 7 deletions(-)
diff --git a/dlls/d3drm/Makefile.in b/dlls/d3drm/Makefile.in index 8daaa426c8f..d243ced546d 100644 --- a/dlls/d3drm/Makefile.in +++ b/dlls/d3drm/Makefile.in @@ -1,6 +1,6 @@ MODULE = d3drm.dll IMPORTLIB = d3drm -IMPORTS = d3dxof ddraw +IMPORTS = d3dxof ddraw gdi32
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/d3drm/d3drm_private.h b/dlls/d3drm/d3drm_private.h index 31fdd4984a1..c3ba97797a0 100644 --- a/dlls/d3drm/d3drm_private.h +++ b/dlls/d3drm/d3drm_private.h @@ -292,8 +292,11 @@ void d3drm_object_cleanup(IDirect3DRMObject *iface, struct d3drm_object *object) struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame(IDirect3DRMFrame *iface) DECLSPEC_HIDDEN; struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame3(IDirect3DRMFrame3 *iface) DECLSPEC_HIDDEN;
+struct d3drm_device *unsafe_impl_from_IDirect3DRMDevice(IDirect3DRMDevice *iface) DECLSPEC_HIDDEN; struct d3drm_device *unsafe_impl_from_IDirect3DRMDevice3(IDirect3DRMDevice3 *iface) DECLSPEC_HIDDEN;
+struct d3drm_texture *unsafe_impl_from_IDirect3DRMTexture(IDirect3DRMTexture *iface) DECLSPEC_HIDDEN; + HRESULT d3drm_texture_create(struct d3drm_texture **texture, IDirect3DRM *d3drm) DECLSPEC_HIDDEN; HRESULT d3drm_frame_create(struct d3drm_frame **frame, IUnknown *parent_frame, IDirect3DRM *d3drm) DECLSPEC_HIDDEN; HRESULT d3drm_face_create(struct d3drm_face **face) DECLSPEC_HIDDEN; diff --git a/dlls/d3drm/device.c b/dlls/d3drm/device.c index 970b171c656..7f6b436e985 100644 --- a/dlls/d3drm/device.c +++ b/dlls/d3drm/device.c @@ -1644,6 +1644,15 @@ static const struct IDirect3DRMWinDeviceVtbl d3drm_device_win_vtbl = d3drm_device_win_HandleActivate, };
+struct d3drm_device *unsafe_impl_from_IDirect3DRMDevice(IDirect3DRMDevice *iface) +{ + if (!iface) + return NULL; + assert(iface->lpVtbl == &d3drm_device1_vtbl); + + return impl_from_IDirect3DRMDevice(iface); +} + struct d3drm_device *unsafe_impl_from_IDirect3DRMDevice3(IDirect3DRMDevice3 *iface) { if (!iface) diff --git a/dlls/d3drm/frame.c b/dlls/d3drm/frame.c index 9365e02cc47..4396e3e9edf 100644 --- a/dlls/d3drm/frame.c +++ b/dlls/d3drm/frame.c @@ -3145,9 +3145,15 @@ struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame(IDirect3DRMFrame *iface) { if (!iface) return NULL; - assert(iface->lpVtbl == &d3drm_frame1_vtbl);
- return impl_from_IDirect3DRMFrame(iface); + if (iface->lpVtbl == &d3drm_frame1_vtbl) + return impl_from_IDirect3DRMFrame(iface); + else if (iface->lpVtbl == (void*)&d3drm_frame2_vtbl) + return impl_from_IDirect3DRMFrame2((IDirect3DRMFrame2*)iface); + + ERR("invalid IDirect3DRMFrame pointer: %p\n", iface); + + return NULL; }
HRESULT d3drm_frame_create(struct d3drm_frame **frame, IUnknown *parent_frame, IDirect3DRM *d3drm) diff --git a/dlls/d3drm/texture.c b/dlls/d3drm/texture.c index a60317b48bc..8a081c4c29a 100644 --- a/dlls/d3drm/texture.c +++ b/dlls/d3drm/texture.c @@ -1441,6 +1441,21 @@ static const struct IDirect3DRMTexture3Vtbl d3drm_texture3_vtbl = d3drm_texture3_SetValidationCallback, };
+struct d3drm_texture *unsafe_impl_from_IDirect3DRMTexture(IDirect3DRMTexture *iface) +{ + { + if (!iface) + return NULL; + + if (iface->lpVtbl == &d3drm_texture1_vtbl) + return impl_from_IDirect3DRMTexture(iface); + + ERR("invalid IDirect3DRMTexture pointer: %p\n", iface); + + return NULL; +} +} + HRESULT d3drm_texture_create(struct d3drm_texture **texture, IDirect3DRM *d3drm) { static const char classname[] = "Texture"; diff --git a/dlls/d3drm/viewport.c b/dlls/d3drm/viewport.c index 36a80c95675..92f0a0a314c 100644 --- a/dlls/d3drm/viewport.c +++ b/dlls/d3drm/viewport.c @@ -470,18 +470,111 @@ static HRESULT WINAPI d3drm_viewport1_Clear(IDirect3DRMViewport *iface) return d3drm_viewport2_Clear(&viewport->IDirect3DRMViewport2_iface, D3DRMCLEAR_ALL); }
+static HRESULT create_surface_from_image(IDirectDraw *ddraw, D3DRMIMAGE *image, IDirectDrawSurface **out) +{ + IDirectDrawSurface *surface; + DDSURFACEDESC desc; + HRESULT hr; + HBITMAP bitmap; + HDC hdc, hdcImage; + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE; + desc.dwWidth = image->width; + desc.dwHeight = image->height; + desc.u1.lPitch = 3; + + desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat); + desc.ddpfPixelFormat.dwFlags = DDPF_RGB; + + desc.ddpfPixelFormat.u1.dwRGBBitCount = 16; + desc.ddpfPixelFormat.u2.dwRBitMask = 0x00007c00; + desc.ddpfPixelFormat.u3.dwGBitMask = 0x000003e0; + desc.ddpfPixelFormat.u4.dwBBitMask = 0x0000001f; + + hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL); + if (FAILED(hr)) + return hr; + + bitmap = CreateBitmap(image->width, image->height, 1, 1, image->buffer1); + if(!bitmap) + { + ERR("Failed to create Bitmap\n"); + IDirectDrawSurface_Release(surface); + return E_FAIL; + } + + hdcImage = CreateCompatibleDC(NULL); + SelectObject(hdcImage, bitmap); + + IDirectDrawSurface_GetDC(surface, &hdc); + BitBlt(hdc, 0, 0, image->width, image->height, hdcImage, 0, 0, SRCCOPY); + IDirectDrawSurface_ReleaseDC(surface, hdc); + DeleteDC(hdcImage); + DeleteObject(hdcImage); + + *out = surface; + + return hr; +} + +static HRESULT viewport_render(struct d3drm_viewport *viewport, struct d3drm_frame *drmframe) +{ + HRESULT hr = S_OK; + + if (drmframe->backgroundimage) + { + IDirect3DRMTexture *drmtexture; + + hr = IUnknown_QueryInterface(drmframe->backgroundimage, &IID_IDirect3DRMTexture, (void**)&drmtexture); + if (hr == S_OK) + { + struct d3drm_texture *texture = unsafe_impl_from_IDirect3DRMTexture(drmtexture); + if (!texture) + { + FIXME("Unsupported IDirect3DRMTexture interface\n"); + return D3DRM_OK; + } + + if (!texture->surface) + hr = create_surface_from_image(viewport->device->ddraw, texture->image, &texture->surface); + + hr = IDirectDrawSurface_Blt(viewport->device->render_target, NULL, texture->surface, NULL, DDBLT_WAIT, NULL); + FIXME("IDirectDrawSurface_BltFast %08lx\n", hr); + + IDirect3DRMTexture_Release(drmtexture); + } + } + + return hr; +} + static HRESULT WINAPI d3drm_viewport2_Render(IDirect3DRMViewport2 *iface, IDirect3DRMFrame3 *frame) { - FIXME("iface %p, frame %p stub!\n", iface, frame); + struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface); + struct d3drm_frame *drmframe = unsafe_impl_from_IDirect3DRMFrame3(frame); + HRESULT hr;
- return D3DRM_OK; + TRACE("iface %p, frame %p\n", iface, frame); + + hr = viewport_render(viewport, drmframe); + + return hr; }
static HRESULT WINAPI d3drm_viewport1_Render(IDirect3DRMViewport *iface, IDirect3DRMFrame *frame) { - FIXME("iface %p, frame %p stub!\n", iface, frame); + struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface); + struct d3drm_frame *drmframe = unsafe_impl_from_IDirect3DRMFrame(frame); + HRESULT hr;
- return D3DRM_OK; + TRACE("iface %p, frame %p\n", iface, frame); + + hr = viewport_render(viewport, drmframe); + + return hr; }
static HRESULT WINAPI d3drm_viewport2_SetFront(IDirect3DRMViewport2 *iface, D3DVALUE front)
The points re Clear and render sound all good, now bake them into a test!
E.g. 1) clear the ddraw render target using ddraw directly to color 12345678 2) invoke d3drm::clear 3) check that the color in the target was changed 4) clear with ddraw directly to some other color 5) invoke d3drm::render 6) check that the color was unchanged
Or with less direct ddraw involvement: 1) set background color 12345678 2) d3drm::clear 3) check color in ddraw surface 4) set background color deadbeef 5) d3drm::render 6) check color in ddraw surface
Copy some of the ddraw test helpers if they are not there already. Don't bother sharing the test helper function code though.
I am closing this merge request in favor of MR 477 and expected future merge requests that gradually introduce the ability to draw a background image and test this functionality.
This merge request was closed by Stefan D��singer.