[PATCH 3/5] wined3d: Avoid some forward declarations.
Henri Verbeet
hverbeet at codeweavers.com
Mon Sep 2 02:45:42 CDT 2013
This just moves wined3d_surface_blt() down a bit, but unfortunately the diff
doesn't show that very clearly.
---
dlls/wined3d/surface.c | 1270 ++++++++++++++++++++++++------------------------
1 file changed, 631 insertions(+), 639 deletions(-)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index c2c14b5..2bf5521 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,737 +1421,427 @@ 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)
+HRESULT CDECL wined3d_surface_get_render_target_data(struct wined3d_surface *surface,
+ struct wined3d_surface *render_target)
{
- 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;
+ TRACE("surface %p, render_target %p.\n", surface, render_target);
- static const DWORD simple_blit = WINEDDBLT_ASYNC
- | WINEDDBLT_COLORFILL
- | WINEDDBLT_WAIT
- | WINEDDBLT_DEPTHFILL
- | WINEDDBLT_DONOTWAIT;
+ /* TODO: Check surface sizes, pools, etc. */
- 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 (render_target->resource.multisample_type)
+ return WINED3DERR_INVALIDCALL;
- if (fx)
+ return wined3d_surface_blt(surface, NULL, render_target, NULL, 0, NULL, WINED3D_TEXF_POINT);
+}
+
+/* Context activation is done by the caller. */
+static void surface_remove_pbo(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
+{
+ if (surface->flags & SFLAG_DIBSECTION)
{
- 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);
+ surface->resource.allocatedMemory = surface->dib.bitmap_data;
}
-
- if (dst_surface->resource.map_count || (src_surface && src_surface->resource.map_count))
+ else
{
- WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n");
- return WINEDDERR_SURFACEBUSY;
+ if (!surface->resource.heap_memory)
+ surface->resource.heap_memory = wined3d_resource_allocate_sysmem(surface->resource.size);
+ else if (!(surface->flags & SFLAG_CLIENT))
+ ERR("Surface %p has heap_memory %p and flags %#x.\n",
+ surface, surface->resource.heap_memory, surface->flags);
+
+ surface->resource.allocatedMemory = surface->resource.heap_memory;
}
- surface_get_rect(dst_surface, dst_rect_in, &dst_rect);
+ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo));
+ checkGLcall("glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, surface->pbo)");
+ GL_EXTCALL(glGetBufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0,
+ surface->resource.size, surface->resource.allocatedMemory));
+ checkGLcall("glGetBufferSubDataARB");
+ GL_EXTCALL(glDeleteBuffersARB(1, &surface->pbo));
+ checkGLcall("glDeleteBuffersARB");
- 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;
- }
+ surface->pbo = 0;
+ surface->flags &= ~SFLAG_PBO;
+}
- if (src_surface)
+static BOOL surface_init_sysmem(struct wined3d_surface *surface)
+{
+ if (!surface->resource.allocatedMemory)
{
- 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)
+ if (!surface->resource.heap_memory)
{
- WARN("Application gave us bad source rectangle for Blt.\n");
- return WINEDDERR_INVALIDRECT;
+ if (!(surface->resource.heap_memory = wined3d_resource_allocate_sysmem(surface->resource.size)))
+ {
+ ERR("Failed to allocate memory.\n");
+ return FALSE;
+ }
+ }
+ else if (!(surface->flags & SFLAG_CLIENT))
+ {
+ ERR("Surface %p has heap_memory %p and flags %#x.\n",
+ surface, surface->resource.heap_memory, surface->flags);
}
+
+ surface->resource.allocatedMemory = surface->resource.heap_memory;
}
else
{
- memset(&src_rect, 0, sizeof(src_rect));
+ memset(surface->resource.allocatedMemory, 0, surface->resource.size);
}
- if (!fx || !(fx->dwDDFX))
- flags &= ~WINEDDBLT_DDFX;
+ surface_modify_location(surface, SFLAG_INSYSMEM, TRUE);
- if (flags & WINEDDBLT_WAIT)
- flags &= ~WINEDDBLT_WAIT;
+ return TRUE;
+}
- if (flags & WINEDDBLT_ASYNC)
- {
- static unsigned int once;
+static void surface_unload(struct wined3d_resource *resource)
+{
+ struct wined3d_surface *surface = surface_from_resource(resource);
+ struct wined3d_renderbuffer_entry *entry, *entry2;
+ struct wined3d_device *device = resource->device;
+ const struct wined3d_gl_info *gl_info;
+ struct wined3d_context *context;
- if (!once++)
- FIXME("Can't handle WINEDDBLT_ASYNC flag.\n");
- flags &= ~WINEDDBLT_ASYNC;
- }
+ TRACE("surface %p.\n", surface);
- /* WINEDDBLT_DONOTWAIT appeared in DX7. */
- if (flags & WINEDDBLT_DONOTWAIT)
+ if (resource->pool == WINED3D_POOL_DEFAULT)
{
- static unsigned int once;
-
- if (!once++)
- FIXME("Can't handle WINEDDBLT_DONOTWAIT flag.\n");
- flags &= ~WINEDDBLT_DONOTWAIT;
+ /* Default pool resources are supposed to be destroyed before Reset is called.
+ * Implicit resources stay however. So this means we have an implicit render target
+ * or depth stencil. The content may be destroyed, but we still have to tear down
+ * opengl resources, so we cannot leave early.
+ *
+ * Put the surfaces into sysmem, and reset the content. The D3D content is undefined,
+ * but we can't set the sysmem INDRAWABLE because when we're rendering the swapchain
+ * or the depth stencil into an FBO the texture or render buffer will be removed
+ * and all flags get lost
+ */
+ if (!(surface->flags & SFLAG_PBO))
+ surface_init_sysmem(surface);
+ /* We also get here when the ddraw swapchain is destroyed, for example
+ * for a mode switch. In this case this surface won't necessarily be
+ * an implicit surface. We have to mark it lost so that the
+ * application can restore it after the mode switch. */
+ surface->flags |= SFLAG_LOST;
}
-
- if (!device->d3d_initialized)
+ else
{
- WARN("D3D not initialized, using fallback.\n");
- goto cpu;
+ /* Load the surface into system memory */
+ surface_load_location(surface, SFLAG_INSYSMEM, NULL);
+ surface_modify_location(surface, surface->draw_binding, FALSE);
}
+ surface_modify_location(surface, SFLAG_INTEXTURE, FALSE);
+ surface_modify_location(surface, SFLAG_INSRGBTEX, FALSE);
+ surface->flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED);
- /* 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)
+ context = context_acquire(device, NULL);
+ gl_info = context->gl_info;
+
+ /* Destroy PBOs, but load them into real sysmem before */
+ if (surface->flags & SFLAG_PBO)
+ surface_remove_pbo(surface, gl_info);
+
+ /* Destroy fbo render buffers. This is needed for implicit render targets, for
+ * all application-created targets the application has to release the surface
+ * before calling _Reset
+ */
+ LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
{
- WARN_(d3d_perf)("Converted surface, using CPU blit.\n");
- return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter);
+ gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
+ list_remove(&entry->entry);
+ HeapFree(GetProcessHeap(), 0, entry);
}
+ list_init(&surface->renderbuffers);
+ surface->current_renderbuffer = NULL;
- if (flags & ~simple_blit)
+ /* If we're in a texture, the texture name belongs to the texture.
+ * Otherwise, destroy it. */
+ if (!surface->container)
{
- WARN_(d3d_perf)("Using fallback for complex blit (%#x).\n", flags);
- goto fallback;
+ gl_info->gl_ops.gl.p_glDeleteTextures(1, &surface->texture_name);
+ surface->texture_name = 0;
+ gl_info->gl_ops.gl.p_glDeleteTextures(1, &surface->texture_name_srgb);
+ surface->texture_name_srgb = 0;
}
-
- 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)
+ if (surface->rb_multisample)
{
- FIXME("Using fallback for cross-swapchain blit.\n");
- goto fallback;
+ gl_info->fbo_ops.glDeleteRenderbuffers(1, &surface->rb_multisample);
+ surface->rb_multisample = 0;
}
-
- 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 (surface->rb_resolved)
{
- if (flags & WINEDDBLT_DEPTHFILL)
- {
- float depth;
+ gl_info->fbo_ops.glDeleteRenderbuffers(1, &surface->rb_resolved);
+ surface->rb_resolved = 0;
+ }
- TRACE("Depth fill.\n");
+ context_release(context);
- 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);
- }
+ resource_unload(resource);
+}
- if (flags & WINEDDBLT_COLORFILL)
- {
- struct wined3d_color color;
+static const struct wined3d_resource_ops surface_resource_ops =
+{
+ surface_unload,
+};
- TRACE("Color fill.\n");
+static const struct wined3d_surface_ops surface_ops =
+{
+ surface_private_setup,
+ surface_realize_palette,
+ surface_map,
+ surface_unmap,
+};
- if (!surface_convert_color_to_float(dst_surface, fx->u5.dwFillColor, &color))
- goto fallback;
+/*****************************************************************************
+ * Initializes the GDI surface, aka creates the DIB section we render to
+ * The DIB section creation is done by calling GetDC, which will create the
+ * section and releasing the dc to allow the app to use it. The dib section
+ * will stay until the surface is released
+ *
+ * GDI surfaces do not need to be a power of 2 in size, so the pow2 sizes
+ * are set to the real sizes to save memory. The NONPOW2 flag is unset to
+ * avoid confusion in the shared surface code.
+ *
+ * Returns:
+ * WINED3D_OK on success
+ * The return values of called methods on failure
+ *
+ *****************************************************************************/
+static HRESULT gdi_surface_private_setup(struct wined3d_surface *surface)
+{
+ HRESULT hr;
- if (SUCCEEDED(surface_color_fill(dst_surface, &dst_rect, &color)))
- return WINED3D_OK;
- }
- else
- {
- TRACE("Color blit.\n");
+ TRACE("surface %p.\n", surface);
- /* 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 (surface->resource.usage & WINED3DUSAGE_OVERLAY)
+ {
+ ERR("Overlays not yet supported by GDI surfaces.\n");
+ return WINED3DERR_INVALIDCALL;
+ }
- 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;
- }
- }
- }
+ /* Sysmem textures have memory already allocated - release it,
+ * this avoids an unnecessary memcpy. */
+ hr = surface_create_dib_section(surface);
+ if (SUCCEEDED(hr))
+ {
+ wined3d_resource_free_sysmem(surface->resource.heap_memory);
+ surface->resource.heap_memory = NULL;
+ surface->resource.allocatedMemory = surface->dib.bitmap_data;
+ }
- /* 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;
+ /* We don't mind the nonpow2 stuff in GDI. */
+ surface->pow2Width = surface->resource.width;
+ surface->pow2Height = surface->resource.height;
- TRACE("Using present for backbuffer -> frontbuffer blit.\n");
+ return WINED3D_OK;
+}
- /* 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;
+static void gdi_surface_realize_palette(struct wined3d_surface *surface)
+{
+ struct wined3d_palette *palette = surface->palette;
- return WINED3D_OK;
- }
+ TRACE("surface %p.\n", surface);
- 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");
+ if (!palette) return;
- 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 (surface->flags & SFLAG_DIBSECTION)
+ {
+ RGBQUAD col[256];
+ unsigned int i;
- 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");
+ TRACE("Updating the DC's palette.\n");
- if (SUCCEEDED(arbfp_blit_surface(device, filter, src_surface, &src_rect, dst_surface, &dst_rect)))
- return WINED3D_OK;
- }
+ for (i = 0; i < 256; ++i)
+ {
+ col[i].rgbRed = palette->palents[i].peRed;
+ col[i].rgbGreen = palette->palents[i].peGreen;
+ col[i].rgbBlue = palette->palents[i].peBlue;
+ col[i].rgbReserved = 0;
}
+ SetDIBColorTable(surface->hDC, 0, 256, col);
}
-fallback:
+ /* Update the image because of the palette change. Some games like e.g.
+ * Red Alert call SetEntries a lot to implement fading. */
+ /* Tell the swapchain to update the screen. */
+ if (surface->swapchain && surface == surface->swapchain->front_buffer)
+ x11_copy_to_screen(surface->swapchain, NULL);
+}
- /* 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;
- }
+static void gdi_surface_map(struct wined3d_surface *surface, const RECT *rect, DWORD flags)
+{
+ TRACE("surface %p, rect %s, flags %#x.\n",
+ surface, wine_dbgstr_rect(rect), flags);
-cpu:
+ if (!(surface->flags & SFLAG_DIBSECTION))
+ {
+ HRESULT hr;
- /* 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);
+ /* This happens on gdi surfaces if the application set a user pointer
+ * and resets it. Recreate the DIB section. */
+ if (FAILED(hr = surface_create_dib_section(surface)))
+ {
+ ERR("Failed to create dib section, hr %#x.\n", hr);
+ return;
+ }
+ wined3d_resource_free_sysmem(surface->resource.heap_memory);
+ surface->resource.heap_memory = NULL;
+ surface->resource.allocatedMemory = surface->dib.bitmap_data;
+ }
}
-HRESULT CDECL wined3d_surface_get_render_target_data(struct wined3d_surface *surface,
- struct wined3d_surface *render_target)
+static void gdi_surface_unmap(struct wined3d_surface *surface)
{
- TRACE("surface %p, render_target %p.\n", surface, render_target);
-
- /* TODO: Check surface sizes, pools, etc. */
+ TRACE("surface %p.\n", surface);
- if (render_target->resource.multisample_type)
- return WINED3DERR_INVALIDCALL;
+ /* Tell the swapchain to update the screen. */
+ if (surface->swapchain && surface == surface->swapchain->front_buffer)
+ x11_copy_to_screen(surface->swapchain, &surface->lockedRect);
- return wined3d_surface_blt(surface, NULL, render_target, NULL, 0, NULL, WINED3D_TEXF_POINT);
+ memset(&surface->lockedRect, 0, sizeof(RECT));
}
-/* Context activation is done by the caller. */
-static void surface_remove_pbo(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
+static const struct wined3d_surface_ops gdi_surface_ops =
{
- if (surface->flags & SFLAG_DIBSECTION)
+ gdi_surface_private_setup,
+ gdi_surface_realize_palette,
+ gdi_surface_map,
+ gdi_surface_unmap,
+};
+
+void surface_set_texture_name(struct wined3d_surface *surface, GLuint new_name, BOOL srgb)
+{
+ GLuint *name;
+ DWORD flag;
+
+ TRACE("surface %p, new_name %u, srgb %#x.\n", surface, new_name, srgb);
+
+ if(srgb)
{
- surface->resource.allocatedMemory = surface->dib.bitmap_data;
+ name = &surface->texture_name_srgb;
+ flag = SFLAG_INSRGBTEX;
}
else
{
- if (!surface->resource.heap_memory)
- surface->resource.heap_memory = wined3d_resource_allocate_sysmem(surface->resource.size);
- else if (!(surface->flags & SFLAG_CLIENT))
- ERR("Surface %p has heap_memory %p and flags %#x.\n",
- surface, surface->resource.heap_memory, surface->flags);
-
- surface->resource.allocatedMemory = surface->resource.heap_memory;
+ name = &surface->texture_name;
+ flag = SFLAG_INTEXTURE;
}
- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo));
- checkGLcall("glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, surface->pbo)");
- GL_EXTCALL(glGetBufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0,
- surface->resource.size, surface->resource.allocatedMemory));
- checkGLcall("glGetBufferSubDataARB");
- GL_EXTCALL(glDeleteBuffersARB(1, &surface->pbo));
- checkGLcall("glDeleteBuffersARB");
+ if (!*name && new_name)
+ {
+ /* FIXME: We shouldn't need to remove SFLAG_INTEXTURE if the
+ * surface has no texture name yet. See if we can get rid of this. */
+ if (surface->flags & flag)
+ {
+ ERR("Surface has %s set, but no texture name.\n", debug_surflocation(flag));
+ surface_modify_location(surface, flag, FALSE);
+ }
+ }
- surface->pbo = 0;
- surface->flags &= ~SFLAG_PBO;
+ *name = new_name;
+ surface_force_reload(surface);
}
-static BOOL surface_init_sysmem(struct wined3d_surface *surface)
+void surface_set_texture_target(struct wined3d_surface *surface, GLenum target, GLint level)
{
- if (!surface->resource.allocatedMemory)
+ TRACE("surface %p, target %#x.\n", surface, target);
+
+ if (surface->texture_target != target)
{
- if (!surface->resource.heap_memory)
+ if (target == GL_TEXTURE_RECTANGLE_ARB)
{
- surface->resource.heap_memory = wined3d_resource_allocate_sysmem(surface->resource.size);
- if (!surface->resource.heap_memory)
- {
- ERR("Failed to allocate memory.\n");
- return FALSE;
- }
+ surface->flags &= ~SFLAG_NORMCOORD;
}
- else if (!(surface->flags & SFLAG_CLIENT))
+ else if (surface->texture_target == GL_TEXTURE_RECTANGLE_ARB)
{
- ERR("Surface %p has heap_memory %p and flags %#x.\n",
- surface, surface->resource.heap_memory, surface->flags);
+ surface->flags |= SFLAG_NORMCOORD;
}
-
- surface->resource.allocatedMemory = surface->resource.heap_memory;
- }
- else
- {
- memset(surface->resource.allocatedMemory, 0, surface->resource.size);
}
-
- surface_modify_location(surface, SFLAG_INSYSMEM, TRUE);
-
- return TRUE;
+ surface->texture_target = target;
+ surface->texture_level = level;
+ surface_force_reload(surface);
}
-static void surface_unload(struct wined3d_resource *resource)
+/* This call just downloads data, the caller is responsible for binding the
+ * correct texture. */
+/* Context activation is done by the caller. */
+static void surface_download_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
{
- struct wined3d_surface *surface = surface_from_resource(resource);
- struct wined3d_renderbuffer_entry *entry, *entry2;
- struct wined3d_device *device = resource->device;
- const struct wined3d_gl_info *gl_info;
- struct wined3d_context *context;
-
- TRACE("surface %p.\n", surface);
-
- if (resource->pool == WINED3D_POOL_DEFAULT)
- {
- /* Default pool resources are supposed to be destroyed before Reset is called.
- * Implicit resources stay however. So this means we have an implicit render target
- * or depth stencil. The content may be destroyed, but we still have to tear down
- * opengl resources, so we cannot leave early.
- *
- * Put the surfaces into sysmem, and reset the content. The D3D content is undefined,
- * but we can't set the sysmem INDRAWABLE because when we're rendering the swapchain
- * or the depth stencil into an FBO the texture or render buffer will be removed
- * and all flags get lost
- */
- if (!(surface->flags & SFLAG_PBO))
- surface_init_sysmem(surface);
- /* We also get here when the ddraw swapchain is destroyed, for example
- * for a mode switch. In this case this surface won't necessarily be
- * an implicit surface. We have to mark it lost so that the
- * application can restore it after the mode switch. */
- surface->flags |= SFLAG_LOST;
- }
- else
- {
- /* Load the surface into system memory */
- surface_load_location(surface, SFLAG_INSYSMEM, NULL);
- surface_modify_location(surface, surface->draw_binding, FALSE);
- }
- surface_modify_location(surface, SFLAG_INTEXTURE, FALSE);
- surface_modify_location(surface, SFLAG_INSRGBTEX, FALSE);
- surface->flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED);
-
- context = context_acquire(device, NULL);
- gl_info = context->gl_info;
-
- /* Destroy PBOs, but load them into real sysmem before */
- if (surface->flags & SFLAG_PBO)
- surface_remove_pbo(surface, gl_info);
+ const struct wined3d_format *format = surface->resource.format;
- /* Destroy fbo render buffers. This is needed for implicit render targets, for
- * all application-created targets the application has to release the surface
- * before calling _Reset
- */
- LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
+ /* Only support read back of converted P8 surfaces. */
+ if (surface->flags & SFLAG_CONVERTED && format->id != WINED3DFMT_P8_UINT)
{
- gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
- list_remove(&entry->entry);
- HeapFree(GetProcessHeap(), 0, entry);
+ ERR("Trying to read back converted surface %p with format %s.\n", surface, debug_d3dformat(format->id));
+ return;
}
- list_init(&surface->renderbuffers);
- surface->current_renderbuffer = NULL;
- /* If we're in a texture, the texture name belongs to the texture.
- * Otherwise, destroy it. */
- if (!surface->container)
- {
- gl_info->gl_ops.gl.p_glDeleteTextures(1, &surface->texture_name);
- surface->texture_name = 0;
- gl_info->gl_ops.gl.p_glDeleteTextures(1, &surface->texture_name_srgb);
- surface->texture_name_srgb = 0;
- }
- if (surface->rb_multisample)
- {
- gl_info->fbo_ops.glDeleteRenderbuffers(1, &surface->rb_multisample);
- surface->rb_multisample = 0;
- }
- if (surface->rb_resolved)
+ if (format->flags & WINED3DFMT_FLAG_COMPRESSED)
{
- gl_info->fbo_ops.glDeleteRenderbuffers(1, &surface->rb_resolved);
- surface->rb_resolved = 0;
- }
-
- context_release(context);
-
- resource_unload(resource);
-}
-
-static const struct wined3d_resource_ops surface_resource_ops =
-{
- surface_unload,
-};
-
-static const struct wined3d_surface_ops surface_ops =
-{
- surface_private_setup,
- surface_realize_palette,
- surface_map,
- surface_unmap,
-};
-
-/*****************************************************************************
- * Initializes the GDI surface, aka creates the DIB section we render to
- * The DIB section creation is done by calling GetDC, which will create the
- * section and releasing the dc to allow the app to use it. The dib section
- * will stay until the surface is released
- *
- * GDI surfaces do not need to be a power of 2 in size, so the pow2 sizes
- * are set to the real sizes to save memory. The NONPOW2 flag is unset to
- * avoid confusion in the shared surface code.
- *
- * Returns:
- * WINED3D_OK on success
- * The return values of called methods on failure
- *
- *****************************************************************************/
-static HRESULT gdi_surface_private_setup(struct wined3d_surface *surface)
-{
- HRESULT hr;
-
- TRACE("surface %p.\n", surface);
+ TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p.\n",
+ surface, surface->texture_level, format->glFormat, format->glType,
+ surface->resource.allocatedMemory);
- if (surface->resource.usage & WINED3DUSAGE_OVERLAY)
- {
- ERR("Overlays not yet supported by GDI surfaces.\n");
- return WINED3DERR_INVALIDCALL;
+ if (surface->flags & SFLAG_PBO)
+ {
+ GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, surface->pbo));
+ checkGLcall("glBindBufferARB");
+ GL_EXTCALL(glGetCompressedTexImageARB(surface->texture_target, surface->texture_level, NULL));
+ checkGLcall("glGetCompressedTexImageARB");
+ GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
+ checkGLcall("glBindBufferARB");
+ }
+ else
+ {
+ GL_EXTCALL(glGetCompressedTexImageARB(surface->texture_target,
+ surface->texture_level, surface->resource.allocatedMemory));
+ checkGLcall("glGetCompressedTexImageARB");
+ }
}
-
- /* Sysmem textures have memory already allocated - release it,
- * this avoids an unnecessary memcpy. */
- hr = surface_create_dib_section(surface);
- if (SUCCEEDED(hr))
+ else
{
- wined3d_resource_free_sysmem(surface->resource.heap_memory);
- surface->resource.heap_memory = NULL;
- surface->resource.allocatedMemory = surface->dib.bitmap_data;
- }
-
- /* We don't mind the nonpow2 stuff in GDI. */
- surface->pow2Width = surface->resource.width;
- surface->pow2Height = surface->resource.height;
-
- return WINED3D_OK;
-}
+ void *mem;
+ GLenum gl_format = format->glFormat;
+ GLenum gl_type = format->glType;
+ int src_pitch = 0;
+ int dst_pitch = 0;
-static void gdi_surface_realize_palette(struct wined3d_surface *surface)
-{
- struct wined3d_palette *palette = surface->palette;
+ /* In case of P8 the index is stored in the alpha component if the primary render target uses P8. */
+ if (format->id == WINED3DFMT_P8_UINT && primary_render_target_is_p8(surface->resource.device))
+ {
+ gl_format = GL_ALPHA;
+ gl_type = GL_UNSIGNED_BYTE;
+ }
- TRACE("surface %p.\n", surface);
+ if (surface->flags & SFLAG_NONPOW2)
+ {
+ unsigned char alignment = surface->resource.device->surface_alignment;
+ src_pitch = format->byte_count * surface->pow2Width;
+ dst_pitch = wined3d_surface_get_pitch(surface);
+ src_pitch = (src_pitch + alignment - 1) & ~(alignment - 1);
+ mem = HeapAlloc(GetProcessHeap(), 0, src_pitch * surface->pow2Height);
+ }
+ else
+ {
+ mem = surface->resource.allocatedMemory;
+ }
- if (!palette) return;
+ TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n",
+ surface, surface->texture_level, gl_format, gl_type, mem);
- if (surface->flags & SFLAG_DIBSECTION)
- {
- RGBQUAD col[256];
- unsigned int i;
+ if (surface->flags & SFLAG_PBO)
+ {
+ GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, surface->pbo));
+ checkGLcall("glBindBufferARB");
- TRACE("Updating the DC's palette.\n");
+ gl_info->gl_ops.gl.p_glGetTexImage(surface->texture_target, surface->texture_level,
+ gl_format, gl_type, NULL);
+ checkGLcall("glGetTexImage");
- for (i = 0; i < 256; ++i)
- {
- col[i].rgbRed = palette->palents[i].peRed;
- col[i].rgbGreen = palette->palents[i].peGreen;
- col[i].rgbBlue = palette->palents[i].peBlue;
- col[i].rgbReserved = 0;
- }
- SetDIBColorTable(surface->hDC, 0, 256, col);
- }
-
- /* Update the image because of the palette change. Some games like e.g.
- * Red Alert call SetEntries a lot to implement fading. */
- /* Tell the swapchain to update the screen. */
- if (surface->swapchain && surface == surface->swapchain->front_buffer)
- x11_copy_to_screen(surface->swapchain, NULL);
-}
-
-static void gdi_surface_map(struct wined3d_surface *surface, const RECT *rect, DWORD flags)
-{
- TRACE("surface %p, rect %s, flags %#x.\n",
- surface, wine_dbgstr_rect(rect), flags);
-
- if (!(surface->flags & SFLAG_DIBSECTION))
- {
- HRESULT hr;
-
- /* This happens on gdi surfaces if the application set a user pointer
- * and resets it. Recreate the DIB section. */
- if (FAILED(hr = surface_create_dib_section(surface)))
- {
- ERR("Failed to create dib section, hr %#x.\n", hr);
- return;
- }
- wined3d_resource_free_sysmem(surface->resource.heap_memory);
- surface->resource.heap_memory = NULL;
- surface->resource.allocatedMemory = surface->dib.bitmap_data;
- }
-}
-
-static void gdi_surface_unmap(struct wined3d_surface *surface)
-{
- TRACE("surface %p.\n", surface);
-
- /* Tell the swapchain to update the screen. */
- if (surface->swapchain && surface == surface->swapchain->front_buffer)
- x11_copy_to_screen(surface->swapchain, &surface->lockedRect);
-
- memset(&surface->lockedRect, 0, sizeof(RECT));
-}
-
-static const struct wined3d_surface_ops gdi_surface_ops =
-{
- gdi_surface_private_setup,
- gdi_surface_realize_palette,
- gdi_surface_map,
- gdi_surface_unmap,
-};
-
-void surface_set_texture_name(struct wined3d_surface *surface, GLuint new_name, BOOL srgb)
-{
- GLuint *name;
- DWORD flag;
-
- TRACE("surface %p, new_name %u, srgb %#x.\n", surface, new_name, srgb);
-
- if(srgb)
- {
- name = &surface->texture_name_srgb;
- flag = SFLAG_INSRGBTEX;
- }
- else
- {
- name = &surface->texture_name;
- flag = SFLAG_INTEXTURE;
- }
-
- if (!*name && new_name)
- {
- /* FIXME: We shouldn't need to remove SFLAG_INTEXTURE if the
- * surface has no texture name yet. See if we can get rid of this. */
- if (surface->flags & flag)
- {
- ERR("Surface has %s set, but no texture name.\n", debug_surflocation(flag));
- surface_modify_location(surface, flag, FALSE);
- }
- }
-
- *name = new_name;
- surface_force_reload(surface);
-}
-
-void surface_set_texture_target(struct wined3d_surface *surface, GLenum target, GLint level)
-{
- TRACE("surface %p, target %#x.\n", surface, target);
-
- if (surface->texture_target != target)
- {
- if (target == GL_TEXTURE_RECTANGLE_ARB)
- {
- surface->flags &= ~SFLAG_NORMCOORD;
- }
- else if (surface->texture_target == GL_TEXTURE_RECTANGLE_ARB)
- {
- surface->flags |= SFLAG_NORMCOORD;
- }
- }
- surface->texture_target = target;
- surface->texture_level = level;
- surface_force_reload(surface);
-}
-
-/* This call just downloads data, the caller is responsible for binding the
- * correct texture. */
-/* Context activation is done by the caller. */
-static void surface_download_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info)
-{
- const struct wined3d_format *format = surface->resource.format;
-
- /* Only support read back of converted P8 surfaces. */
- if (surface->flags & SFLAG_CONVERTED && format->id != WINED3DFMT_P8_UINT)
- {
- ERR("Trying to read back converted surface %p with format %s.\n", surface, debug_d3dformat(format->id));
- return;
- }
-
- if (format->flags & WINED3DFMT_FLAG_COMPRESSED)
- {
- TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p.\n",
- surface, surface->texture_level, format->glFormat, format->glType,
- surface->resource.allocatedMemory);
-
- if (surface->flags & SFLAG_PBO)
- {
- GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, surface->pbo));
- checkGLcall("glBindBufferARB");
- GL_EXTCALL(glGetCompressedTexImageARB(surface->texture_target, surface->texture_level, NULL));
- checkGLcall("glGetCompressedTexImageARB");
- GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
- checkGLcall("glBindBufferARB");
- }
- else
- {
- GL_EXTCALL(glGetCompressedTexImageARB(surface->texture_target,
- surface->texture_level, surface->resource.allocatedMemory));
- checkGLcall("glGetCompressedTexImageARB");
- }
- }
- else
- {
- void *mem;
- GLenum gl_format = format->glFormat;
- GLenum gl_type = format->glType;
- int src_pitch = 0;
- int dst_pitch = 0;
-
- /* In case of P8 the index is stored in the alpha component if the primary render target uses P8. */
- if (format->id == WINED3DFMT_P8_UINT && primary_render_target_is_p8(surface->resource.device))
- {
- gl_format = GL_ALPHA;
- gl_type = GL_UNSIGNED_BYTE;
- }
-
- if (surface->flags & SFLAG_NONPOW2)
- {
- unsigned char alignment = surface->resource.device->surface_alignment;
- src_pitch = format->byte_count * surface->pow2Width;
- dst_pitch = wined3d_surface_get_pitch(surface);
- src_pitch = (src_pitch + alignment - 1) & ~(alignment - 1);
- mem = HeapAlloc(GetProcessHeap(), 0, src_pitch * surface->pow2Height);
- }
- else
- {
- mem = surface->resource.allocatedMemory;
- }
-
- TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n",
- surface, surface->texture_level, gl_format, gl_type, mem);
-
- if (surface->flags & SFLAG_PBO)
- {
- GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, surface->pbo));
- checkGLcall("glBindBufferARB");
-
- gl_info->gl_ops.gl.p_glGetTexImage(surface->texture_target, surface->texture_level,
- gl_format, gl_type, NULL);
- checkGLcall("glGetTexImage");
-
- GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
- checkGLcall("glBindBufferARB");
- }
- else
+ GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
+ checkGLcall("glBindBufferARB");
+ }
+ else
{
gl_info->gl_ops.gl.p_glGetTexImage(surface->texture_target, surface->texture_level,
gl_format, gl_type, mem);
@@ -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,
--
1.8.1.5
More information about the wine-patches
mailing list