wined3d: Avoid some forward declarations.
This commit is contained in:
parent
b5e0c5d052
commit
0be8e524c6
|
@ -36,13 +36,6 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d);
|
||||||
|
|
||||||
#define MAXLOCKCOUNT 50 /* After this amount of locks do not free the sysmem copy. */
|
#define MAXLOCKCOUNT 50 /* After this amount of locks do not free the sysmem copy. */
|
||||||
|
|
||||||
static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect,
|
|
||||||
struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags,
|
|
||||||
const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter);
|
|
||||||
static HRESULT IWineD3DSurfaceImpl_BltOverride(struct wined3d_surface *dst_surface, const RECT *dst_rect,
|
|
||||||
struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, const WINEDDBLTFX *fx,
|
|
||||||
enum wined3d_texture_filter_type filter);
|
|
||||||
|
|
||||||
static void surface_cleanup(struct wined3d_surface *surface)
|
static void surface_cleanup(struct wined3d_surface *surface)
|
||||||
{
|
{
|
||||||
struct wined3d_surface *overlay, *cur;
|
struct wined3d_surface *overlay, *cur;
|
||||||
|
@ -1428,315 +1421,6 @@ static HRESULT wined3d_surface_depth_blt(struct wined3d_surface *src_surface, DW
|
||||||
return WINED3D_OK;
|
return WINED3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect_in,
|
|
||||||
struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags,
|
|
||||||
const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter)
|
|
||||||
{
|
|
||||||
struct wined3d_swapchain *src_swapchain, *dst_swapchain;
|
|
||||||
struct wined3d_device *device = dst_surface->resource.device;
|
|
||||||
DWORD src_ds_flags, dst_ds_flags;
|
|
||||||
RECT src_rect, dst_rect;
|
|
||||||
BOOL scale, convert;
|
|
||||||
|
|
||||||
static const DWORD simple_blit = WINEDDBLT_ASYNC
|
|
||||||
| WINEDDBLT_COLORFILL
|
|
||||||
| WINEDDBLT_WAIT
|
|
||||||
| WINEDDBLT_DEPTHFILL
|
|
||||||
| WINEDDBLT_DONOTWAIT;
|
|
||||||
|
|
||||||
TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n",
|
|
||||||
dst_surface, wine_dbgstr_rect(dst_rect_in), src_surface, wine_dbgstr_rect(src_rect_in),
|
|
||||||
flags, fx, debug_d3dtexturefiltertype(filter));
|
|
||||||
TRACE("Usage is %s.\n", debug_d3dusage(dst_surface->resource.usage));
|
|
||||||
|
|
||||||
if (fx)
|
|
||||||
{
|
|
||||||
TRACE("dwSize %#x.\n", fx->dwSize);
|
|
||||||
TRACE("dwDDFX %#x.\n", fx->dwDDFX);
|
|
||||||
TRACE("dwROP %#x.\n", fx->dwROP);
|
|
||||||
TRACE("dwDDROP %#x.\n", fx->dwDDROP);
|
|
||||||
TRACE("dwRotationAngle %#x.\n", fx->dwRotationAngle);
|
|
||||||
TRACE("dwZBufferOpCode %#x.\n", fx->dwZBufferOpCode);
|
|
||||||
TRACE("dwZBufferLow %#x.\n", fx->dwZBufferLow);
|
|
||||||
TRACE("dwZBufferHigh %#x.\n", fx->dwZBufferHigh);
|
|
||||||
TRACE("dwZBufferBaseDest %#x.\n", fx->dwZBufferBaseDest);
|
|
||||||
TRACE("dwZDestConstBitDepth %#x.\n", fx->dwZDestConstBitDepth);
|
|
||||||
TRACE("lpDDSZBufferDest %p.\n", fx->u1.lpDDSZBufferDest);
|
|
||||||
TRACE("dwZSrcConstBitDepth %#x.\n", fx->dwZSrcConstBitDepth);
|
|
||||||
TRACE("lpDDSZBufferSrc %p.\n", fx->u2.lpDDSZBufferSrc);
|
|
||||||
TRACE("dwAlphaEdgeBlendBitDepth %#x.\n", fx->dwAlphaEdgeBlendBitDepth);
|
|
||||||
TRACE("dwAlphaEdgeBlend %#x.\n", fx->dwAlphaEdgeBlend);
|
|
||||||
TRACE("dwReserved %#x.\n", fx->dwReserved);
|
|
||||||
TRACE("dwAlphaDestConstBitDepth %#x.\n", fx->dwAlphaDestConstBitDepth);
|
|
||||||
TRACE("lpDDSAlphaDest %p.\n", fx->u3.lpDDSAlphaDest);
|
|
||||||
TRACE("dwAlphaSrcConstBitDepth %#x.\n", fx->dwAlphaSrcConstBitDepth);
|
|
||||||
TRACE("lpDDSAlphaSrc %p.\n", fx->u4.lpDDSAlphaSrc);
|
|
||||||
TRACE("lpDDSPattern %p.\n", fx->u5.lpDDSPattern);
|
|
||||||
TRACE("ddckDestColorkey {%#x, %#x}.\n",
|
|
||||||
fx->ddckDestColorkey.color_space_low_value,
|
|
||||||
fx->ddckDestColorkey.color_space_high_value);
|
|
||||||
TRACE("ddckSrcColorkey {%#x, %#x}.\n",
|
|
||||||
fx->ddckSrcColorkey.color_space_low_value,
|
|
||||||
fx->ddckSrcColorkey.color_space_high_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dst_surface->resource.map_count || (src_surface && src_surface->resource.map_count))
|
|
||||||
{
|
|
||||||
WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n");
|
|
||||||
return WINEDDERR_SURFACEBUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
surface_get_rect(dst_surface, dst_rect_in, &dst_rect);
|
|
||||||
|
|
||||||
if (dst_rect.left >= dst_rect.right || dst_rect.top >= dst_rect.bottom
|
|
||||||
|| dst_rect.left > dst_surface->resource.width || dst_rect.left < 0
|
|
||||||
|| dst_rect.top > dst_surface->resource.height || dst_rect.top < 0
|
|
||||||
|| dst_rect.right > dst_surface->resource.width || dst_rect.right < 0
|
|
||||||
|| dst_rect.bottom > dst_surface->resource.height || dst_rect.bottom < 0)
|
|
||||||
{
|
|
||||||
WARN("The application gave us a bad destination rectangle.\n");
|
|
||||||
return WINEDDERR_INVALIDRECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (src_surface)
|
|
||||||
{
|
|
||||||
surface_get_rect(src_surface, src_rect_in, &src_rect);
|
|
||||||
|
|
||||||
if (src_rect.left >= src_rect.right || src_rect.top >= src_rect.bottom
|
|
||||||
|| src_rect.left > src_surface->resource.width || src_rect.left < 0
|
|
||||||
|| src_rect.top > src_surface->resource.height || src_rect.top < 0
|
|
||||||
|| src_rect.right > src_surface->resource.width || src_rect.right < 0
|
|
||||||
|| src_rect.bottom > src_surface->resource.height || src_rect.bottom < 0)
|
|
||||||
{
|
|
||||||
WARN("Application gave us bad source rectangle for Blt.\n");
|
|
||||||
return WINEDDERR_INVALIDRECT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memset(&src_rect, 0, sizeof(src_rect));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fx || !(fx->dwDDFX))
|
|
||||||
flags &= ~WINEDDBLT_DDFX;
|
|
||||||
|
|
||||||
if (flags & WINEDDBLT_WAIT)
|
|
||||||
flags &= ~WINEDDBLT_WAIT;
|
|
||||||
|
|
||||||
if (flags & WINEDDBLT_ASYNC)
|
|
||||||
{
|
|
||||||
static unsigned int once;
|
|
||||||
|
|
||||||
if (!once++)
|
|
||||||
FIXME("Can't handle WINEDDBLT_ASYNC flag.\n");
|
|
||||||
flags &= ~WINEDDBLT_ASYNC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* WINEDDBLT_DONOTWAIT appeared in DX7. */
|
|
||||||
if (flags & WINEDDBLT_DONOTWAIT)
|
|
||||||
{
|
|
||||||
static unsigned int once;
|
|
||||||
|
|
||||||
if (!once++)
|
|
||||||
FIXME("Can't handle WINEDDBLT_DONOTWAIT flag.\n");
|
|
||||||
flags &= ~WINEDDBLT_DONOTWAIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!device->d3d_initialized)
|
|
||||||
{
|
|
||||||
WARN("D3D not initialized, using fallback.\n");
|
|
||||||
goto cpu;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We want to avoid invalidating the sysmem location for converted
|
|
||||||
* surfaces, since otherwise we'd have to convert the data back when
|
|
||||||
* locking them. */
|
|
||||||
if (dst_surface->flags & SFLAG_CONVERTED)
|
|
||||||
{
|
|
||||||
WARN_(d3d_perf)("Converted surface, using CPU blit.\n");
|
|
||||||
return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & ~simple_blit)
|
|
||||||
{
|
|
||||||
WARN_(d3d_perf)("Using fallback for complex blit (%#x).\n", flags);
|
|
||||||
goto fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (src_surface)
|
|
||||||
src_swapchain = src_surface->swapchain;
|
|
||||||
else
|
|
||||||
src_swapchain = NULL;
|
|
||||||
|
|
||||||
dst_swapchain = dst_surface->swapchain;
|
|
||||||
|
|
||||||
/* This isn't strictly needed. FBO blits for example could deal with
|
|
||||||
* cross-swapchain blits by first downloading the source to a texture
|
|
||||||
* before switching to the destination context. We just have this here to
|
|
||||||
* not have to deal with the issue, since cross-swapchain blits should be
|
|
||||||
* rare. */
|
|
||||||
if (src_swapchain && dst_swapchain && src_swapchain != dst_swapchain)
|
|
||||||
{
|
|
||||||
FIXME("Using fallback for cross-swapchain blit.\n");
|
|
||||||
goto fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
scale = src_surface
|
|
||||||
&& (src_rect.right - src_rect.left != dst_rect.right - dst_rect.left
|
|
||||||
|| src_rect.bottom - src_rect.top != dst_rect.bottom - dst_rect.top);
|
|
||||||
convert = src_surface && src_surface->resource.format->id != dst_surface->resource.format->id;
|
|
||||||
|
|
||||||
dst_ds_flags = dst_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
|
|
||||||
if (src_surface)
|
|
||||||
src_ds_flags = src_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
|
|
||||||
else
|
|
||||||
src_ds_flags = 0;
|
|
||||||
|
|
||||||
if (src_ds_flags || dst_ds_flags)
|
|
||||||
{
|
|
||||||
if (flags & WINEDDBLT_DEPTHFILL)
|
|
||||||
{
|
|
||||||
float depth;
|
|
||||||
|
|
||||||
TRACE("Depth fill.\n");
|
|
||||||
|
|
||||||
if (!surface_convert_depth_to_float(dst_surface, fx->u5.dwFillDepth, &depth))
|
|
||||||
return WINED3DERR_INVALIDCALL;
|
|
||||||
|
|
||||||
if (SUCCEEDED(wined3d_surface_depth_fill(dst_surface, &dst_rect, depth)))
|
|
||||||
return WINED3D_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (src_ds_flags != dst_ds_flags)
|
|
||||||
{
|
|
||||||
WARN("Rejecting depth / stencil blit between incompatible formats.\n");
|
|
||||||
return WINED3DERR_INVALIDCALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, src_surface->draw_binding, &src_rect,
|
|
||||||
dst_surface, dst_surface->draw_binding, &dst_rect)))
|
|
||||||
return WINED3D_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* In principle this would apply to depth blits as well, but we don't
|
|
||||||
* implement those in the CPU blitter at the moment. */
|
|
||||||
if ((dst_surface->flags & SFLAG_INSYSMEM)
|
|
||||||
&& (!src_surface || (src_surface->flags & SFLAG_INSYSMEM)))
|
|
||||||
{
|
|
||||||
if (scale)
|
|
||||||
TRACE("Not doing sysmem blit because of scaling.\n");
|
|
||||||
else if (convert)
|
|
||||||
TRACE("Not doing sysmem blit because of format conversion.\n");
|
|
||||||
else
|
|
||||||
return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & WINEDDBLT_COLORFILL)
|
|
||||||
{
|
|
||||||
struct wined3d_color color;
|
|
||||||
|
|
||||||
TRACE("Color fill.\n");
|
|
||||||
|
|
||||||
if (!surface_convert_color_to_float(dst_surface, fx->u5.dwFillColor, &color))
|
|
||||||
goto fallback;
|
|
||||||
|
|
||||||
if (SUCCEEDED(surface_color_fill(dst_surface, &dst_rect, &color)))
|
|
||||||
return WINED3D_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TRACE("Color blit.\n");
|
|
||||||
|
|
||||||
/* Upload */
|
|
||||||
if ((src_surface->flags & SFLAG_INSYSMEM) && !(dst_surface->flags & SFLAG_INSYSMEM))
|
|
||||||
{
|
|
||||||
if (scale)
|
|
||||||
TRACE("Not doing upload because of scaling.\n");
|
|
||||||
else if (convert)
|
|
||||||
TRACE("Not doing upload because of format conversion.\n");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
POINT dst_point = {dst_rect.left, dst_rect.top};
|
|
||||||
|
|
||||||
if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, &src_rect)))
|
|
||||||
{
|
|
||||||
if (!surface_is_offscreen(dst_surface))
|
|
||||||
surface_load_location(dst_surface, dst_surface->draw_binding, NULL);
|
|
||||||
return WINED3D_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use present for back -> front blits. The idea behind this is
|
|
||||||
* that present is potentially faster than a blit, in particular
|
|
||||||
* when FBO blits aren't available. Some ddraw applications like
|
|
||||||
* Half-Life and Prince of Persia 3D use Blt() from the backbuffer
|
|
||||||
* to the frontbuffer instead of doing a Flip(). D3D8 and D3D9
|
|
||||||
* applications can't blit directly to the frontbuffer. */
|
|
||||||
if (dst_swapchain && dst_swapchain->back_buffers
|
|
||||||
&& dst_surface == dst_swapchain->front_buffer
|
|
||||||
&& src_surface == dst_swapchain->back_buffers[0])
|
|
||||||
{
|
|
||||||
enum wined3d_swap_effect swap_effect = dst_swapchain->desc.swap_effect;
|
|
||||||
|
|
||||||
TRACE("Using present for backbuffer -> frontbuffer blit.\n");
|
|
||||||
|
|
||||||
/* Set the swap effect to COPY, we don't want the backbuffer
|
|
||||||
* to become undefined. */
|
|
||||||
dst_swapchain->desc.swap_effect = WINED3D_SWAP_EFFECT_COPY;
|
|
||||||
wined3d_swapchain_present(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, NULL, 0);
|
|
||||||
dst_swapchain->desc.swap_effect = swap_effect;
|
|
||||||
|
|
||||||
return WINED3D_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fbo_blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
|
|
||||||
&src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
|
|
||||||
&dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
|
|
||||||
{
|
|
||||||
TRACE("Using FBO blit.\n");
|
|
||||||
|
|
||||||
surface_blt_fbo(device, filter,
|
|
||||||
src_surface, src_surface->draw_binding, &src_rect,
|
|
||||||
dst_surface, dst_surface->draw_binding, &dst_rect);
|
|
||||||
surface_modify_location(dst_surface, dst_surface->draw_binding, TRUE);
|
|
||||||
return WINED3D_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arbfp_blit.blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
|
|
||||||
&src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
|
|
||||||
&dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
|
|
||||||
{
|
|
||||||
TRACE("Using arbfp blit.\n");
|
|
||||||
|
|
||||||
if (SUCCEEDED(arbfp_blit_surface(device, filter, src_surface, &src_rect, dst_surface, &dst_rect)))
|
|
||||||
return WINED3D_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fallback:
|
|
||||||
|
|
||||||
/* Special cases for render targets. */
|
|
||||||
if ((dst_surface->resource.usage & WINED3DUSAGE_RENDERTARGET)
|
|
||||||
|| (src_surface && (src_surface->resource.usage & WINED3DUSAGE_RENDERTARGET)))
|
|
||||||
{
|
|
||||||
if (SUCCEEDED(IWineD3DSurfaceImpl_BltOverride(dst_surface, &dst_rect,
|
|
||||||
src_surface, &src_rect, flags, fx, filter)))
|
|
||||||
return WINED3D_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu:
|
|
||||||
|
|
||||||
/* For the rest call the X11 surface implementation. For render targets
|
|
||||||
* this should be implemented OpenGL accelerated in BltOverride, other
|
|
||||||
* blits are rather rare. */
|
|
||||||
return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT CDECL wined3d_surface_get_render_target_data(struct wined3d_surface *surface,
|
HRESULT CDECL wined3d_surface_get_render_target_data(struct wined3d_surface *surface,
|
||||||
struct wined3d_surface *render_target)
|
struct wined3d_surface *render_target)
|
||||||
{
|
{
|
||||||
|
@ -1786,8 +1470,7 @@ static BOOL surface_init_sysmem(struct wined3d_surface *surface)
|
||||||
{
|
{
|
||||||
if (!surface->resource.heap_memory)
|
if (!surface->resource.heap_memory)
|
||||||
{
|
{
|
||||||
surface->resource.heap_memory = wined3d_resource_allocate_sysmem(surface->resource.size);
|
if (!(surface->resource.heap_memory = wined3d_resource_allocate_sysmem(surface->resource.size)))
|
||||||
if (!surface->resource.heap_memory)
|
|
||||||
{
|
{
|
||||||
ERR("Failed to allocate memory.\n");
|
ERR("Failed to allocate memory.\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -6885,6 +6568,315 @@ const struct blit_shader cpu_blit = {
|
||||||
cpu_blit_depth_fill,
|
cpu_blit_depth_fill,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect_in,
|
||||||
|
struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags,
|
||||||
|
const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter)
|
||||||
|
{
|
||||||
|
struct wined3d_swapchain *src_swapchain, *dst_swapchain;
|
||||||
|
struct wined3d_device *device = dst_surface->resource.device;
|
||||||
|
DWORD src_ds_flags, dst_ds_flags;
|
||||||
|
RECT src_rect, dst_rect;
|
||||||
|
BOOL scale, convert;
|
||||||
|
|
||||||
|
static const DWORD simple_blit = WINEDDBLT_ASYNC
|
||||||
|
| WINEDDBLT_COLORFILL
|
||||||
|
| WINEDDBLT_WAIT
|
||||||
|
| WINEDDBLT_DEPTHFILL
|
||||||
|
| WINEDDBLT_DONOTWAIT;
|
||||||
|
|
||||||
|
TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n",
|
||||||
|
dst_surface, wine_dbgstr_rect(dst_rect_in), src_surface, wine_dbgstr_rect(src_rect_in),
|
||||||
|
flags, fx, debug_d3dtexturefiltertype(filter));
|
||||||
|
TRACE("Usage is %s.\n", debug_d3dusage(dst_surface->resource.usage));
|
||||||
|
|
||||||
|
if (fx)
|
||||||
|
{
|
||||||
|
TRACE("dwSize %#x.\n", fx->dwSize);
|
||||||
|
TRACE("dwDDFX %#x.\n", fx->dwDDFX);
|
||||||
|
TRACE("dwROP %#x.\n", fx->dwROP);
|
||||||
|
TRACE("dwDDROP %#x.\n", fx->dwDDROP);
|
||||||
|
TRACE("dwRotationAngle %#x.\n", fx->dwRotationAngle);
|
||||||
|
TRACE("dwZBufferOpCode %#x.\n", fx->dwZBufferOpCode);
|
||||||
|
TRACE("dwZBufferLow %#x.\n", fx->dwZBufferLow);
|
||||||
|
TRACE("dwZBufferHigh %#x.\n", fx->dwZBufferHigh);
|
||||||
|
TRACE("dwZBufferBaseDest %#x.\n", fx->dwZBufferBaseDest);
|
||||||
|
TRACE("dwZDestConstBitDepth %#x.\n", fx->dwZDestConstBitDepth);
|
||||||
|
TRACE("lpDDSZBufferDest %p.\n", fx->u1.lpDDSZBufferDest);
|
||||||
|
TRACE("dwZSrcConstBitDepth %#x.\n", fx->dwZSrcConstBitDepth);
|
||||||
|
TRACE("lpDDSZBufferSrc %p.\n", fx->u2.lpDDSZBufferSrc);
|
||||||
|
TRACE("dwAlphaEdgeBlendBitDepth %#x.\n", fx->dwAlphaEdgeBlendBitDepth);
|
||||||
|
TRACE("dwAlphaEdgeBlend %#x.\n", fx->dwAlphaEdgeBlend);
|
||||||
|
TRACE("dwReserved %#x.\n", fx->dwReserved);
|
||||||
|
TRACE("dwAlphaDestConstBitDepth %#x.\n", fx->dwAlphaDestConstBitDepth);
|
||||||
|
TRACE("lpDDSAlphaDest %p.\n", fx->u3.lpDDSAlphaDest);
|
||||||
|
TRACE("dwAlphaSrcConstBitDepth %#x.\n", fx->dwAlphaSrcConstBitDepth);
|
||||||
|
TRACE("lpDDSAlphaSrc %p.\n", fx->u4.lpDDSAlphaSrc);
|
||||||
|
TRACE("lpDDSPattern %p.\n", fx->u5.lpDDSPattern);
|
||||||
|
TRACE("ddckDestColorkey {%#x, %#x}.\n",
|
||||||
|
fx->ddckDestColorkey.color_space_low_value,
|
||||||
|
fx->ddckDestColorkey.color_space_high_value);
|
||||||
|
TRACE("ddckSrcColorkey {%#x, %#x}.\n",
|
||||||
|
fx->ddckSrcColorkey.color_space_low_value,
|
||||||
|
fx->ddckSrcColorkey.color_space_high_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst_surface->resource.map_count || (src_surface && src_surface->resource.map_count))
|
||||||
|
{
|
||||||
|
WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n");
|
||||||
|
return WINEDDERR_SURFACEBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
surface_get_rect(dst_surface, dst_rect_in, &dst_rect);
|
||||||
|
|
||||||
|
if (dst_rect.left >= dst_rect.right || dst_rect.top >= dst_rect.bottom
|
||||||
|
|| dst_rect.left > dst_surface->resource.width || dst_rect.left < 0
|
||||||
|
|| dst_rect.top > dst_surface->resource.height || dst_rect.top < 0
|
||||||
|
|| dst_rect.right > dst_surface->resource.width || dst_rect.right < 0
|
||||||
|
|| dst_rect.bottom > dst_surface->resource.height || dst_rect.bottom < 0)
|
||||||
|
{
|
||||||
|
WARN("The application gave us a bad destination rectangle.\n");
|
||||||
|
return WINEDDERR_INVALIDRECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_surface)
|
||||||
|
{
|
||||||
|
surface_get_rect(src_surface, src_rect_in, &src_rect);
|
||||||
|
|
||||||
|
if (src_rect.left >= src_rect.right || src_rect.top >= src_rect.bottom
|
||||||
|
|| src_rect.left > src_surface->resource.width || src_rect.left < 0
|
||||||
|
|| src_rect.top > src_surface->resource.height || src_rect.top < 0
|
||||||
|
|| src_rect.right > src_surface->resource.width || src_rect.right < 0
|
||||||
|
|| src_rect.bottom > src_surface->resource.height || src_rect.bottom < 0)
|
||||||
|
{
|
||||||
|
WARN("Application gave us bad source rectangle for Blt.\n");
|
||||||
|
return WINEDDERR_INVALIDRECT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(&src_rect, 0, sizeof(src_rect));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fx || !(fx->dwDDFX))
|
||||||
|
flags &= ~WINEDDBLT_DDFX;
|
||||||
|
|
||||||
|
if (flags & WINEDDBLT_WAIT)
|
||||||
|
flags &= ~WINEDDBLT_WAIT;
|
||||||
|
|
||||||
|
if (flags & WINEDDBLT_ASYNC)
|
||||||
|
{
|
||||||
|
static unsigned int once;
|
||||||
|
|
||||||
|
if (!once++)
|
||||||
|
FIXME("Can't handle WINEDDBLT_ASYNC flag.\n");
|
||||||
|
flags &= ~WINEDDBLT_ASYNC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WINEDDBLT_DONOTWAIT appeared in DX7. */
|
||||||
|
if (flags & WINEDDBLT_DONOTWAIT)
|
||||||
|
{
|
||||||
|
static unsigned int once;
|
||||||
|
|
||||||
|
if (!once++)
|
||||||
|
FIXME("Can't handle WINEDDBLT_DONOTWAIT flag.\n");
|
||||||
|
flags &= ~WINEDDBLT_DONOTWAIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!device->d3d_initialized)
|
||||||
|
{
|
||||||
|
WARN("D3D not initialized, using fallback.\n");
|
||||||
|
goto cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We want to avoid invalidating the sysmem location for converted
|
||||||
|
* surfaces, since otherwise we'd have to convert the data back when
|
||||||
|
* locking them. */
|
||||||
|
if (dst_surface->flags & SFLAG_CONVERTED)
|
||||||
|
{
|
||||||
|
WARN_(d3d_perf)("Converted surface, using CPU blit.\n");
|
||||||
|
return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & ~simple_blit)
|
||||||
|
{
|
||||||
|
WARN_(d3d_perf)("Using fallback for complex blit (%#x).\n", flags);
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_surface)
|
||||||
|
src_swapchain = src_surface->swapchain;
|
||||||
|
else
|
||||||
|
src_swapchain = NULL;
|
||||||
|
|
||||||
|
dst_swapchain = dst_surface->swapchain;
|
||||||
|
|
||||||
|
/* This isn't strictly needed. FBO blits for example could deal with
|
||||||
|
* cross-swapchain blits by first downloading the source to a texture
|
||||||
|
* before switching to the destination context. We just have this here to
|
||||||
|
* not have to deal with the issue, since cross-swapchain blits should be
|
||||||
|
* rare. */
|
||||||
|
if (src_swapchain && dst_swapchain && src_swapchain != dst_swapchain)
|
||||||
|
{
|
||||||
|
FIXME("Using fallback for cross-swapchain blit.\n");
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
scale = src_surface
|
||||||
|
&& (src_rect.right - src_rect.left != dst_rect.right - dst_rect.left
|
||||||
|
|| src_rect.bottom - src_rect.top != dst_rect.bottom - dst_rect.top);
|
||||||
|
convert = src_surface && src_surface->resource.format->id != dst_surface->resource.format->id;
|
||||||
|
|
||||||
|
dst_ds_flags = dst_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
|
||||||
|
if (src_surface)
|
||||||
|
src_ds_flags = src_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
|
||||||
|
else
|
||||||
|
src_ds_flags = 0;
|
||||||
|
|
||||||
|
if (src_ds_flags || dst_ds_flags)
|
||||||
|
{
|
||||||
|
if (flags & WINEDDBLT_DEPTHFILL)
|
||||||
|
{
|
||||||
|
float depth;
|
||||||
|
|
||||||
|
TRACE("Depth fill.\n");
|
||||||
|
|
||||||
|
if (!surface_convert_depth_to_float(dst_surface, fx->u5.dwFillDepth, &depth))
|
||||||
|
return WINED3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
if (SUCCEEDED(wined3d_surface_depth_fill(dst_surface, &dst_rect, depth)))
|
||||||
|
return WINED3D_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (src_ds_flags != dst_ds_flags)
|
||||||
|
{
|
||||||
|
WARN("Rejecting depth / stencil blit between incompatible formats.\n");
|
||||||
|
return WINED3DERR_INVALIDCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, src_surface->draw_binding, &src_rect,
|
||||||
|
dst_surface, dst_surface->draw_binding, &dst_rect)))
|
||||||
|
return WINED3D_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* In principle this would apply to depth blits as well, but we don't
|
||||||
|
* implement those in the CPU blitter at the moment. */
|
||||||
|
if ((dst_surface->flags & SFLAG_INSYSMEM)
|
||||||
|
&& (!src_surface || (src_surface->flags & SFLAG_INSYSMEM)))
|
||||||
|
{
|
||||||
|
if (scale)
|
||||||
|
TRACE("Not doing sysmem blit because of scaling.\n");
|
||||||
|
else if (convert)
|
||||||
|
TRACE("Not doing sysmem blit because of format conversion.\n");
|
||||||
|
else
|
||||||
|
return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & WINEDDBLT_COLORFILL)
|
||||||
|
{
|
||||||
|
struct wined3d_color color;
|
||||||
|
|
||||||
|
TRACE("Color fill.\n");
|
||||||
|
|
||||||
|
if (!surface_convert_color_to_float(dst_surface, fx->u5.dwFillColor, &color))
|
||||||
|
goto fallback;
|
||||||
|
|
||||||
|
if (SUCCEEDED(surface_color_fill(dst_surface, &dst_rect, &color)))
|
||||||
|
return WINED3D_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("Color blit.\n");
|
||||||
|
|
||||||
|
/* Upload */
|
||||||
|
if ((src_surface->flags & SFLAG_INSYSMEM) && !(dst_surface->flags & SFLAG_INSYSMEM))
|
||||||
|
{
|
||||||
|
if (scale)
|
||||||
|
TRACE("Not doing upload because of scaling.\n");
|
||||||
|
else if (convert)
|
||||||
|
TRACE("Not doing upload because of format conversion.\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
POINT dst_point = {dst_rect.left, dst_rect.top};
|
||||||
|
|
||||||
|
if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, &src_rect)))
|
||||||
|
{
|
||||||
|
if (!surface_is_offscreen(dst_surface))
|
||||||
|
surface_load_location(dst_surface, dst_surface->draw_binding, NULL);
|
||||||
|
return WINED3D_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use present for back -> front blits. The idea behind this is
|
||||||
|
* that present is potentially faster than a blit, in particular
|
||||||
|
* when FBO blits aren't available. Some ddraw applications like
|
||||||
|
* Half-Life and Prince of Persia 3D use Blt() from the backbuffer
|
||||||
|
* to the frontbuffer instead of doing a Flip(). D3D8 and D3D9
|
||||||
|
* applications can't blit directly to the frontbuffer. */
|
||||||
|
if (dst_swapchain && dst_swapchain->back_buffers
|
||||||
|
&& dst_surface == dst_swapchain->front_buffer
|
||||||
|
&& src_surface == dst_swapchain->back_buffers[0])
|
||||||
|
{
|
||||||
|
enum wined3d_swap_effect swap_effect = dst_swapchain->desc.swap_effect;
|
||||||
|
|
||||||
|
TRACE("Using present for backbuffer -> frontbuffer blit.\n");
|
||||||
|
|
||||||
|
/* Set the swap effect to COPY, we don't want the backbuffer
|
||||||
|
* to become undefined. */
|
||||||
|
dst_swapchain->desc.swap_effect = WINED3D_SWAP_EFFECT_COPY;
|
||||||
|
wined3d_swapchain_present(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, NULL, 0);
|
||||||
|
dst_swapchain->desc.swap_effect = swap_effect;
|
||||||
|
|
||||||
|
return WINED3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fbo_blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
|
||||||
|
&src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
|
||||||
|
&dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
|
||||||
|
{
|
||||||
|
TRACE("Using FBO blit.\n");
|
||||||
|
|
||||||
|
surface_blt_fbo(device, filter,
|
||||||
|
src_surface, src_surface->draw_binding, &src_rect,
|
||||||
|
dst_surface, dst_surface->draw_binding, &dst_rect);
|
||||||
|
surface_modify_location(dst_surface, dst_surface->draw_binding, TRUE);
|
||||||
|
return WINED3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arbfp_blit.blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
|
||||||
|
&src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
|
||||||
|
&dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
|
||||||
|
{
|
||||||
|
TRACE("Using arbfp blit.\n");
|
||||||
|
|
||||||
|
if (SUCCEEDED(arbfp_blit_surface(device, filter, src_surface, &src_rect, dst_surface, &dst_rect)))
|
||||||
|
return WINED3D_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fallback:
|
||||||
|
|
||||||
|
/* Special cases for render targets. */
|
||||||
|
if ((dst_surface->resource.usage & WINED3DUSAGE_RENDERTARGET)
|
||||||
|
|| (src_surface && (src_surface->resource.usage & WINED3DUSAGE_RENDERTARGET)))
|
||||||
|
{
|
||||||
|
if (SUCCEEDED(IWineD3DSurfaceImpl_BltOverride(dst_surface, &dst_rect,
|
||||||
|
src_surface, &src_rect, flags, fx, filter)))
|
||||||
|
return WINED3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu:
|
||||||
|
|
||||||
|
/* For the rest call the X11 surface implementation. For render targets
|
||||||
|
* this should be implemented OpenGL accelerated in BltOverride, other
|
||||||
|
* blits are rather rare. */
|
||||||
|
return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT surface_init(struct wined3d_surface *surface, UINT alignment, UINT width, UINT height,
|
static HRESULT surface_init(struct wined3d_surface *surface, UINT alignment, UINT width, UINT height,
|
||||||
enum wined3d_multisample_type multisample_type, UINT multisample_quality,
|
enum wined3d_multisample_type multisample_type, UINT multisample_quality,
|
||||||
struct wined3d_device *device, DWORD usage, enum wined3d_format_id format_id,
|
struct wined3d_device *device, DWORD usage, enum wined3d_format_id format_id,
|
||||||
|
|
Loading…
Reference in New Issue