From 381cd03eb3860f4b963af9b37cc3258b3f45d17d Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 29 Mar 2017 23:17:28 +0200 Subject: [PATCH] ddraw: Implement depth/colour fills on top of wined3d_device_clear_rendertarget_view(). Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/ddraw/ddraw_private.h | 2 + dlls/ddraw/surface.c | 77 ++++++++++++++++++++++++---------- dlls/ddraw/utils.c | 86 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 22 deletions(-) diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 38ae28a7d11..0ae45328709 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -579,6 +579,8 @@ struct d3d_vertex_buffer *unsafe_impl_from_IDirect3DVertexBuffer7(IDirect3DVerte void ddrawformat_from_wined3dformat(DDPIXELFORMAT *ddraw_format, enum wined3d_format_id wined3d_format) DECLSPEC_HIDDEN; +BOOL wined3d_colour_from_ddraw_colour(const DDPIXELFORMAT *pf, const struct ddraw_palette *palette, + DWORD colour, struct wined3d_color *wined3d_colour) DECLSPEC_HIDDEN; enum wined3d_format_id wined3dformat_from_ddrawformat(const DDPIXELFORMAT *format) DECLSPEC_HIDDEN; void DDRAW_dump_surface_desc(const DDSURFACEDESC2 *lpddsd) DECLSPEC_HIDDEN; void dump_D3DMATRIX(const D3DMATRIX *mat) DECLSPEC_HIDDEN; diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 4c847834634..0a2e1db05cb 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -1407,12 +1407,49 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface * src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, flags); } -static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, const RECT *dst_rect_in, - struct ddraw_surface *src_surface, const RECT *src_rect_in, DWORD flags, +static HRESULT ddraw_surface_blt(struct ddraw_surface *dst_surface, const RECT *dst_rect, + struct ddraw_surface *src_surface, const RECT *src_rect, DWORD flags, DWORD fill_colour, + const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) +{ + struct wined3d_device *wined3d_device = dst_surface->ddraw->wined3d_device; + struct wined3d_color colour; + + if (flags & DDBLT_COLORFILL) + { + if (!wined3d_colour_from_ddraw_colour(&dst_surface->surface_desc.u4.ddpfPixelFormat, + dst_surface->palette, fill_colour, &colour)) + return DDERR_INVALIDPARAMS; + + return wined3d_device_clear_rendertarget_view(wined3d_device, + ddraw_surface_get_rendertarget_view(dst_surface), + dst_rect, WINED3DCLEAR_TARGET, &colour, 0.0f, 0); + } + + if (flags & DDBLT_DEPTHFILL) + { + if (!wined3d_colour_from_ddraw_colour(&dst_surface->surface_desc.u4.ddpfPixelFormat, + dst_surface->palette, fill_colour, &colour)) + return DDERR_INVALIDPARAMS; + + return wined3d_device_clear_rendertarget_view(wined3d_device, + ddraw_surface_get_rendertarget_view(dst_surface), + dst_rect, WINED3DCLEAR_ZBUFFER, NULL, colour.r, 0); + } + + if (flags & ~WINED3D_BLT_MASK) + { + FIXME("Unhandled flags %#x.\n", flags); + return E_NOTIMPL; + } + + return wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, dst_rect, + src_surface->wined3d_texture, src_surface->sub_resource_idx, src_rect, flags, fx, filter); +} + +static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, const RECT *dst_rect_in, + struct ddraw_surface *src_surface, const RECT *src_rect_in, DWORD flags, DWORD fill_colour, const struct wined3d_blt_fx *fx, enum wined3d_texture_filter_type filter) { - struct wined3d_texture *wined3d_src_texture; - unsigned int src_sub_resource_idx; RECT src_rect, dst_rect; float scale_x, scale_y; const RECT *clip_rect; @@ -1440,15 +1477,10 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons if (IsRectEmpty(&src_rect)) return DDERR_INVALIDRECT; - - wined3d_src_texture = src_surface->wined3d_texture; - src_sub_resource_idx = src_surface->sub_resource_idx; } else { SetRectEmpty(&src_rect); - wined3d_src_texture = NULL; - src_sub_resource_idx = 0; } if (!dst_surface->clipper) @@ -1456,8 +1488,7 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons if (src_surface && src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) hr = ddraw_surface_update_frontbuffer(src_surface, &src_rect, TRUE); if (SUCCEEDED(hr)) - hr = wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, &dst_rect, - wined3d_src_texture, src_sub_resource_idx, &src_rect, flags, fx, filter); + hr = ddraw_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fill_colour, fx, filter); if (SUCCEEDED(hr) && (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) hr = ddraw_surface_update_frontbuffer(dst_surface, &dst_rect, FALSE); @@ -1507,8 +1538,8 @@ static HRESULT ddraw_surface_blt_clipped(struct ddraw_surface *dst_surface, cons } } - if (FAILED(hr = wined3d_texture_blt(dst_surface->wined3d_texture, dst_surface->sub_resource_idx, - &clip_rect[i], wined3d_src_texture, src_sub_resource_idx, &src_rect_clipped, flags, fx, filter))) + if (FAILED(hr = ddraw_surface_blt(dst_surface, &clip_rect[i], + src_surface, &src_rect_clipped, flags, fill_colour, fx, filter))) break; if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) @@ -1544,6 +1575,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Blt(IDirectDrawSurface7 * struct ddraw_surface *dst_impl = impl_from_IDirectDrawSurface7(iface); struct ddraw_surface *src_impl = unsafe_impl_from_IDirectDrawSurface7(src_surface); struct wined3d_blt_fx wined3d_fx; + DWORD fill_colour = 0; HRESULT hr = DD_OK; DDBLTFX rop_fx; @@ -1622,6 +1654,14 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Blt(IDirectDrawSurface7 * return DDERR_INVALIDPARAMS; } + if (src_impl && src_rect + && ((ULONG)src_rect->left >= src_rect->right || src_rect->right > src_impl->surface_desc.dwWidth + || (ULONG)src_rect->top >= src_rect->bottom || src_rect->bottom > src_impl->surface_desc.dwHeight)) + { + WARN("Invalid source rectangle.\n"); + return DDERR_INVALIDRECT; + } + flags &= ~DDBLT_ROP; switch (fx->dwROP) { @@ -1665,17 +1705,10 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Blt(IDirectDrawSurface7 * return DDERR_INVALIDPARAMS; } - if (flags & ~WINED3D_BLT_MASK) - { - wined3d_mutex_unlock(); - FIXME("Unhandled flags %#x.\n", flags); - return E_NOTIMPL; - } - if (fx) { wined3d_fx.fx = fx->dwDDFX; - wined3d_fx.fill_color = fx->u5.dwFillColor; + fill_colour = fx->u5.dwFillColor; wined3d_fx.dst_color_key.color_space_low_value = fx->ddckDestColorkey.dwColorSpaceLowValue; wined3d_fx.dst_color_key.color_space_high_value = fx->ddckDestColorkey.dwColorSpaceHighValue; wined3d_fx.src_color_key.color_space_low_value = fx->ddckSrcColorkey.dwColorSpaceLowValue; @@ -1683,7 +1716,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface7_Blt(IDirectDrawSurface7 * } hr = ddraw_surface_blt_clipped(dst_impl, dst_rect, src_impl, - src_rect, flags, fx ? &wined3d_fx : NULL, WINED3D_TEXF_LINEAR); + src_rect, flags, fill_colour, fx ? &wined3d_fx : NULL, WINED3D_TEXF_LINEAR); wined3d_mutex_unlock(); switch(hr) diff --git a/dlls/ddraw/utils.c b/dlls/ddraw/utils.c index 3ec8768820d..37851589d20 100644 --- a/dlls/ddraw/utils.c +++ b/dlls/ddraw/utils.c @@ -561,6 +561,92 @@ enum wined3d_format_id wined3dformat_from_ddrawformat(const DDPIXELFORMAT *DDPix return WINED3DFMT_UNKNOWN; } +static float colour_to_float(DWORD colour, DWORD mask) +{ + if (!mask) + return 0.0f; + return (float)(colour & mask) / (float)mask; +} + +BOOL wined3d_colour_from_ddraw_colour(const DDPIXELFORMAT *pf, const struct ddraw_palette *palette, + DWORD colour, struct wined3d_color *wined3d_colour) +{ + if (pf->dwFlags & DDPF_ALPHA) + { + DWORD size, mask; + + size = pf->u1.dwAlphaBitDepth; + mask = size < 32 ? (1u << size) - 1 : ~0u; + wined3d_colour->r = 0.0f; + wined3d_colour->g = 0.0f; + wined3d_colour->b = 0.0f; + wined3d_colour->a = colour_to_float(colour, mask); + return TRUE; + } + + if (pf->dwFlags & DDPF_FOURCC) + { + WARN("FourCC formats not supported.\n"); + goto fail; + } + + if (pf->dwFlags & DDPF_PALETTEINDEXED8) + { + PALETTEENTRY entry; + + colour &= 0xff; + if (!palette || FAILED(wined3d_palette_get_entries(palette->wined3d_palette, 0, colour, 1, &entry))) + { + wined3d_colour->r = 0.0f; + wined3d_colour->g = 0.0f; + wined3d_colour->b = 0.0f; + } + else + { + wined3d_colour->r = entry.peRed / 255.0f; + wined3d_colour->g = entry.peGreen / 255.0f; + wined3d_colour->b = entry.peBlue / 255.0f; + } + wined3d_colour->a = colour / 255.0f; + return TRUE; + } + + if (pf->dwFlags & DDPF_RGB) + { + wined3d_colour->r = colour_to_float(colour, pf->u2.dwRBitMask); + wined3d_colour->g = colour_to_float(colour, pf->u3.dwGBitMask); + wined3d_colour->b = colour_to_float(colour, pf->u4.dwBBitMask); + if (pf->dwFlags & DDPF_ALPHAPIXELS) + wined3d_colour->a = colour_to_float(colour, pf->u5.dwRGBAlphaBitMask); + else + wined3d_colour->a = 0.0f; + return TRUE; + } + + if (pf->dwFlags & DDPF_ZBUFFER) + { + wined3d_colour->r = colour_to_float(colour, pf->u3.dwZBitMask); + if (pf->dwFlags & DDPF_STENCILBUFFER) + wined3d_colour->g = colour_to_float(colour, pf->u4.dwStencilBitMask); + else + wined3d_colour->g = 0.0f; + wined3d_colour->b = 0.0f; + wined3d_colour->a = 0.0f; + return TRUE; + } + + FIXME("Unhandled pixel format.\n"); + DDRAW_dump_pixelformat(pf); + +fail: + wined3d_colour->r = 0.0f; + wined3d_colour->g = 0.0f; + wined3d_colour->b = 0.0f; + wined3d_colour->a = 0.0f; + + return FALSE; +} + /***************************************************************************** * Various dumping functions. *