From 0be8e524c6352498667d9cf780a570471a674782 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Mon, 2 Sep 2013 09:45:42 +0200 Subject: [PATCH] wined3d: Avoid some forward declarations. --- dlls/wined3d/surface.c | 628 ++++++++++++++++++++--------------------- 1 file changed, 310 insertions(+), 318 deletions(-) diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index c2c14b5239e..2bf55215f2b 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -36,13 +36,6 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d); #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) { struct wined3d_surface *overlay, *cur; @@ -1428,315 +1421,6 @@ static HRESULT wined3d_surface_depth_blt(struct wined3d_surface *src_surface, DW 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, struct wined3d_surface *render_target) { @@ -1786,8 +1470,7 @@ static BOOL surface_init_sysmem(struct wined3d_surface *surface) { if (!surface->resource.heap_memory) { - surface->resource.heap_memory = wined3d_resource_allocate_sysmem(surface->resource.size); - if (!surface->resource.heap_memory) + if (!(surface->resource.heap_memory = wined3d_resource_allocate_sysmem(surface->resource.size))) { ERR("Failed to allocate memory.\n"); return FALSE; @@ -6885,6 +6568,315 @@ const struct blit_shader cpu_blit = { 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, enum wined3d_multisample_type multisample_type, UINT multisample_quality, struct wined3d_device *device, DWORD usage, enum wined3d_format_id format_id,