mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-02 19:23:37 +00:00
wined3d: Introduce a blitter based on ARB_copy_image.
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
ac7768bfce
commit
786ebbdec3
|
@ -7705,6 +7705,14 @@ static BOOL arbfp_blit_supported(const struct wined3d_gl_info *gl_info,
|
|||
if (!gl_info->supported[ARB_FRAGMENT_PROGRAM])
|
||||
return FALSE;
|
||||
|
||||
if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_format->id == src_format->id)
|
||||
{
|
||||
if (dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
|
||||
blit_op = WINED3D_BLIT_OP_DEPTH_BLIT;
|
||||
else
|
||||
blit_op = WINED3D_BLIT_OP_COLOR_BLIT;
|
||||
}
|
||||
|
||||
switch (blit_op)
|
||||
{
|
||||
case WINED3D_BLIT_OP_COLOR_BLIT_CKEY:
|
||||
|
|
|
@ -1030,6 +1030,7 @@ static void wined3d_device_create_primary_opengl_context_cs(void *object)
|
|||
wined3d_ffp_blitter_create(&device->blitter, &device->adapter->gl_info);
|
||||
wined3d_arbfp_blitter_create(&device->blitter, device);
|
||||
wined3d_fbo_blitter_create(&device->blitter, &device->adapter->gl_info);
|
||||
wined3d_raw_blitter_create(&device->blitter, &device->adapter->gl_info);
|
||||
|
||||
swapchain = device->swapchains[0];
|
||||
target = swapchain->back_buffers ? swapchain->back_buffers[0] : swapchain->front_buffer;
|
||||
|
|
|
@ -118,6 +118,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
|
|||
{"GL_ARB_compute_shader", ARB_COMPUTE_SHADER },
|
||||
{"GL_ARB_conservative_depth", ARB_CONSERVATIVE_DEPTH },
|
||||
{"GL_ARB_copy_buffer", ARB_COPY_BUFFER },
|
||||
{"GL_ARB_copy_image", ARB_COPY_IMAGE },
|
||||
{"GL_ARB_debug_output", ARB_DEBUG_OUTPUT },
|
||||
{"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT },
|
||||
{"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE },
|
||||
|
@ -2708,6 +2709,8 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
|
|||
USE_GL_FUNC(glDispatchComputeIndirect)
|
||||
/* GL_ARB_copy_buffer */
|
||||
USE_GL_FUNC(glCopyBufferSubData)
|
||||
/* GL_ARB_copy_image */
|
||||
USE_GL_FUNC(glCopyImageSubData)
|
||||
/* GL_ARB_debug_output */
|
||||
USE_GL_FUNC(glDebugMessageCallbackARB)
|
||||
USE_GL_FUNC(glDebugMessageControlARB)
|
||||
|
@ -3898,6 +3901,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter,
|
|||
|
||||
{ARB_CLEAR_BUFFER_OBJECT, MAKEDWORD_VERSION(4, 3)},
|
||||
{ARB_COMPUTE_SHADER, MAKEDWORD_VERSION(4, 3)},
|
||||
{ARB_COPY_IMAGE, MAKEDWORD_VERSION(4, 3)},
|
||||
{ARB_DEBUG_OUTPUT, MAKEDWORD_VERSION(4, 3)},
|
||||
{ARB_ES3_COMPATIBILITY, MAKEDWORD_VERSION(4, 3)},
|
||||
{ARB_FRAGMENT_LAYER_VIEWPORT, MAKEDWORD_VERSION(4, 3)},
|
||||
|
|
|
@ -2417,9 +2417,18 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
|
|||
struct wined3d_resource *src_resource = &src_surface->container->resource;
|
||||
struct wined3d_resource *dst_resource = &dst_surface->container->resource;
|
||||
struct wined3d_device *device = dst_resource->device;
|
||||
enum wined3d_blit_op blit_op = op;
|
||||
struct wined3d_blitter *next;
|
||||
|
||||
if (!fbo_blitter_supported(&device->adapter->gl_info, op,
|
||||
if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_resource->format->id == src_resource->format->id)
|
||||
{
|
||||
if (dst_resource->format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
|
||||
blit_op = WINED3D_BLIT_OP_DEPTH_BLIT;
|
||||
else
|
||||
blit_op = WINED3D_BLIT_OP_COLOR_BLIT;
|
||||
}
|
||||
|
||||
if (!fbo_blitter_supported(&device->adapter->gl_info, blit_op,
|
||||
src_resource->usage, src_resource->pool, src_resource->format, src_location,
|
||||
src_resource->usage, dst_resource->pool, dst_resource->format, dst_location))
|
||||
{
|
||||
|
@ -2428,7 +2437,7 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
|
|||
src_rect, dst_surface, dst_location, dst_rect, colour_key, filter);
|
||||
}
|
||||
|
||||
if (op == WINED3D_BLIT_OP_COLOR_BLIT)
|
||||
if (blit_op == WINED3D_BLIT_OP_COLOR_BLIT)
|
||||
{
|
||||
TRACE("Colour blit.\n");
|
||||
surface_blt_fbo(device, context, filter, src_surface, src_location,
|
||||
|
@ -2436,14 +2445,14 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
|
|||
return dst_location;
|
||||
}
|
||||
|
||||
if (op == WINED3D_BLIT_OP_DEPTH_BLIT)
|
||||
if (blit_op == WINED3D_BLIT_OP_DEPTH_BLIT)
|
||||
{
|
||||
TRACE("Depth/stencil blit.\n");
|
||||
surface_depth_blt_fbo(device, src_surface, src_location, src_rect, dst_surface, dst_location, dst_rect);
|
||||
return dst_location;
|
||||
}
|
||||
|
||||
ERR("This blitter does not implement blit op %#x.\n", op);
|
||||
ERR("This blitter does not implement blit op %#x.\n", blit_op);
|
||||
return dst_location;
|
||||
}
|
||||
|
||||
|
@ -2471,6 +2480,138 @@ void wined3d_fbo_blitter_create(struct wined3d_blitter **next, const struct wine
|
|||
*next = blitter;
|
||||
}
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
static void raw_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context)
|
||||
{
|
||||
struct wined3d_blitter *next;
|
||||
|
||||
if ((next = blitter->next))
|
||||
next->ops->blitter_destroy(next, context);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, blitter);
|
||||
}
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
static void raw_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_device *device,
|
||||
unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects,
|
||||
const RECT *draw_rect, DWORD flags, const struct wined3d_color *colour, float depth, DWORD stencil)
|
||||
{
|
||||
struct wined3d_blitter *next;
|
||||
|
||||
if (!(next = blitter->next))
|
||||
{
|
||||
ERR("No blitter to handle clear.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE("Forwarding to blitter %p.\n", next);
|
||||
next->ops->blitter_clear(next, device, rt_count, fb, rect_count,
|
||||
clear_rects, draw_rect, flags, colour, depth, stencil);
|
||||
}
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
static DWORD raw_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
|
||||
struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location,
|
||||
const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect,
|
||||
const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter)
|
||||
{
|
||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||
unsigned int src_sub_resource_idx, dst_sub_resource_idx;
|
||||
struct wined3d_texture *src_texture, *dst_texture;
|
||||
struct wined3d_blitter *next;
|
||||
GLuint src_name, dst_name;
|
||||
DWORD location;
|
||||
|
||||
src_texture = src_surface->container;
|
||||
dst_texture = dst_surface->container;
|
||||
|
||||
/* If we would need to copy from a renderbuffer or drawable, we'd probably
|
||||
* be better of using the FBO blitter directly, since we'd need to use it
|
||||
* to copy the resource contents to the texture anyway. */
|
||||
if (op != WINED3D_BLIT_OP_RAW_BLIT
|
||||
|| (src_texture->resource.format->id == dst_texture->resource.format->id
|
||||
&& (!(src_location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
|
||||
|| !(dst_location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)))))
|
||||
{
|
||||
if (!(next = blitter->next))
|
||||
{
|
||||
ERR("No blitter to handle blit op %#x.\n", op);
|
||||
return dst_location;
|
||||
}
|
||||
|
||||
TRACE("Forwarding to blitter %p.\n", next);
|
||||
return next->ops->blitter_blit(next, op, context, src_surface, src_location,
|
||||
src_rect, dst_surface, dst_location, dst_rect, colour_key, filter);
|
||||
}
|
||||
|
||||
TRACE("Blit using ARB_copy_image.\n");
|
||||
|
||||
src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
|
||||
dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface);
|
||||
|
||||
location = src_location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB);
|
||||
if (!location)
|
||||
location = src_texture->flags & WINED3D_TEXTURE_IS_SRGB
|
||||
? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
|
||||
if (!wined3d_texture_load_location(src_texture, src_sub_resource_idx, context, location))
|
||||
ERR("Failed to load the source sub-resource into %s.\n", wined3d_debug_location(location));
|
||||
src_name = wined3d_texture_get_texture_name(src_texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB);
|
||||
|
||||
location = dst_location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB);
|
||||
if (!location)
|
||||
location = dst_texture->flags & WINED3D_TEXTURE_IS_SRGB
|
||||
? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB;
|
||||
if (surface_is_full_rect(dst_surface, dst_rect))
|
||||
{
|
||||
if (!wined3d_texture_prepare_location(dst_texture, dst_sub_resource_idx, context, location))
|
||||
ERR("Failed to prepare the destination sub-resource into %s.\n", wined3d_debug_location(location));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, location))
|
||||
ERR("Failed to load the destination sub-resource into %s.\n", wined3d_debug_location(location));
|
||||
}
|
||||
dst_name = wined3d_texture_get_texture_name(dst_texture, context, location == WINED3D_LOCATION_TEXTURE_SRGB);
|
||||
|
||||
GL_EXTCALL(glCopyImageSubData(src_name, src_texture->target, src_surface->texture_level,
|
||||
src_rect->left, src_rect->top, src_surface->texture_layer,
|
||||
dst_name, dst_texture->target, dst_surface->texture_level,
|
||||
dst_rect->left, dst_rect->top, dst_surface->texture_layer,
|
||||
src_rect->right - src_rect->left, src_rect->bottom - src_rect->top, 1));
|
||||
checkGLcall("copy image data");
|
||||
|
||||
wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, location);
|
||||
wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~location);
|
||||
if (!wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, dst_location))
|
||||
ERR("Failed to load the destination sub-resource into %s.\n", wined3d_debug_location(dst_location));
|
||||
|
||||
return dst_location | location;
|
||||
}
|
||||
|
||||
static const struct wined3d_blitter_ops raw_blitter_ops =
|
||||
{
|
||||
raw_blitter_destroy,
|
||||
raw_blitter_clear,
|
||||
raw_blitter_blit,
|
||||
};
|
||||
|
||||
void wined3d_raw_blitter_create(struct wined3d_blitter **next, const struct wined3d_gl_info *gl_info)
|
||||
{
|
||||
struct wined3d_blitter *blitter;
|
||||
|
||||
if (!gl_info->supported[ARB_COPY_IMAGE])
|
||||
return;
|
||||
|
||||
if (!(blitter = HeapAlloc(GetProcessHeap(), 0, sizeof(*blitter))))
|
||||
return;
|
||||
|
||||
TRACE("Created blitter %p.\n", blitter);
|
||||
|
||||
blitter->ops = &raw_blitter_ops;
|
||||
blitter->next = *next;
|
||||
*next = blitter;
|
||||
}
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
static void ffp_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context)
|
||||
{
|
||||
|
@ -2497,6 +2638,14 @@ static BOOL ffp_blit_supported(const struct wined3d_gl_info *gl_info,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_format->id == src_format->id)
|
||||
{
|
||||
if (dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
|
||||
blit_op = WINED3D_BLIT_OP_DEPTH_BLIT;
|
||||
else
|
||||
blit_op = WINED3D_BLIT_OP_COLOR_BLIT;
|
||||
}
|
||||
|
||||
switch (blit_op)
|
||||
{
|
||||
case WINED3D_BLIT_OP_COLOR_BLIT_CKEY:
|
||||
|
@ -2540,7 +2689,7 @@ static BOOL ffp_blit_supported(const struct wined3d_gl_info *gl_info,
|
|||
return TRUE;
|
||||
|
||||
default:
|
||||
TRACE("Unsupported blit_op=%d\n", blit_op);
|
||||
TRACE("Unsupported blit operation %#x.\n", blit_op);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -3521,6 +3670,7 @@ static DWORD cpu_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
|
|||
{
|
||||
case WINED3D_BLIT_OP_COLOR_BLIT:
|
||||
case WINED3D_BLIT_OP_DEPTH_BLIT:
|
||||
case WINED3D_BLIT_OP_RAW_BLIT:
|
||||
break;
|
||||
case WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST:
|
||||
flags |= WINED3D_BLT_ALPHA_TEST;
|
||||
|
@ -3758,6 +3908,10 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst
|
|||
|
||||
return WINED3D_OK;
|
||||
}
|
||||
else if (!scale && !convert)
|
||||
{
|
||||
blit_op = WINED3D_BLIT_OP_RAW_BLIT;
|
||||
}
|
||||
|
||||
if (dst_texture->resource.pool == WINED3D_POOL_SYSTEM_MEM)
|
||||
dst_location = dst_texture->resource.map_binding;
|
||||
|
|
|
@ -51,6 +51,7 @@ enum wined3d_gl_extension
|
|||
ARB_COMPUTE_SHADER,
|
||||
ARB_CONSERVATIVE_DEPTH,
|
||||
ARB_COPY_BUFFER,
|
||||
ARB_COPY_IMAGE,
|
||||
ARB_DEBUG_OUTPUT,
|
||||
ARB_DEPTH_BUFFER_FLOAT,
|
||||
ARB_DEPTH_TEXTURE,
|
||||
|
|
|
@ -2083,6 +2083,7 @@ enum wined3d_blit_op
|
|||
WINED3D_BLIT_OP_COLOR_FILL,
|
||||
WINED3D_BLIT_OP_DEPTH_FILL,
|
||||
WINED3D_BLIT_OP_DEPTH_BLIT,
|
||||
WINED3D_BLIT_OP_RAW_BLIT,
|
||||
};
|
||||
|
||||
struct wined3d_blitter
|
||||
|
@ -2110,6 +2111,8 @@ void wined3d_fbo_blitter_create(struct wined3d_blitter **next,
|
|||
const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
|
||||
void wined3d_ffp_blitter_create(struct wined3d_blitter **next,
|
||||
const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
|
||||
void wined3d_raw_blitter_create(struct wined3d_blitter **next,
|
||||
const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
|
||||
|
||||
BOOL wined3d_clip_blit(const RECT *clip_rect, RECT *clipped, RECT *other) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
Loading…
Reference in a new issue