wined3d: Use staging resources to blit from CPU resources in the GLSL blitter.
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
aa59d40a18
commit
29d506939e
|
@ -12428,11 +12428,9 @@ static BOOL glsl_blitter_supported(enum wined3d_blit_op blit_op, const struct wi
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* FIXME: We never want to blit from resources without
|
||||
/* We don't necessarily want to blit from resources without
|
||||
* WINED3D_RESOURCE_ACCESS_GPU, but that may be the only way to decompress
|
||||
* compressed textures. We should probably create an explicit staging
|
||||
* texture for this purpose instead of loading the resource into an
|
||||
* invalid location. */
|
||||
* compressed textures. */
|
||||
decompress = src_format && (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED)
|
||||
&& !(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED);
|
||||
if (!decompress && !(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU))
|
||||
|
@ -12465,8 +12463,10 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
|
|||
{
|
||||
struct wined3d_device *device = dst_texture->resource.device;
|
||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||
struct wined3d_texture *staging_texture = NULL;
|
||||
struct wined3d_glsl_blitter *glsl_blitter;
|
||||
struct wined3d_blitter *next;
|
||||
unsigned int src_level;
|
||||
GLuint program_id;
|
||||
RECT s, d;
|
||||
|
||||
|
@ -12491,12 +12491,45 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
|
|||
|
||||
glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter);
|
||||
|
||||
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
|
||||
if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
|
||||
{
|
||||
struct wined3d_resource_desc desc;
|
||||
struct wined3d_box upload_box;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("Source texture is not GPU accessible, creating a staging texture.\n");
|
||||
|
||||
src_level = src_sub_resource_idx % src_texture->level_count;
|
||||
desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
|
||||
desc.format = src_texture->resource.format->id;
|
||||
desc.multisample_type = src_texture->resource.multisample_type;
|
||||
desc.multisample_quality = src_texture->resource.multisample_quality;
|
||||
desc.usage = WINED3DUSAGE_PRIVATE;
|
||||
desc.access = WINED3D_RESOURCE_ACCESS_GPU;
|
||||
desc.width = wined3d_texture_get_level_width(src_texture, src_level);
|
||||
desc.height = wined3d_texture_get_level_height(src_texture, src_level);
|
||||
desc.depth = 1;
|
||||
desc.size = 0;
|
||||
|
||||
if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 0,
|
||||
NULL, NULL, &wined3d_null_parent_ops, &staging_texture)))
|
||||
{
|
||||
ERR("Failed to create staging texture, hr %#x.\n", hr);
|
||||
return dst_location;
|
||||
}
|
||||
|
||||
wined3d_box_set(&upload_box, 0, 0, desc.width, desc.height, 0, desc.depth);
|
||||
wined3d_texture_upload_from_texture(staging_texture, 0, 0, 0, 0,
|
||||
src_texture, src_sub_resource_idx, &upload_box);
|
||||
|
||||
src_texture = staging_texture;
|
||||
src_sub_resource_idx = 0;
|
||||
}
|
||||
else if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
|
||||
&& (src_texture->sub_resources[src_sub_resource_idx].locations
|
||||
& (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) == WINED3D_LOCATION_DRAWABLE
|
||||
&& !wined3d_resource_is_offscreen(&src_texture->resource))
|
||||
{
|
||||
unsigned int src_level = src_sub_resource_idx % src_texture->level_count;
|
||||
|
||||
/* Without FBO blits transferring from the drawable to the texture is
|
||||
* expensive, because we have to flip the data in sysmem. Since we can
|
||||
|
@ -12506,6 +12539,7 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
|
|||
texture2d_load_fb_texture(src_texture, src_sub_resource_idx, FALSE, context);
|
||||
|
||||
s = *src_rect;
|
||||
src_level = src_sub_resource_idx % src_texture->level_count;
|
||||
s.top = wined3d_texture_get_level_height(src_texture, src_level) - s.top;
|
||||
s.bottom = wined3d_texture_get_level_height(src_texture, src_level) - s.bottom;
|
||||
src_rect = &s;
|
||||
|
@ -12557,6 +12591,9 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
|
|||
if (dst_texture->swapchain && (dst_texture->swapchain->front_buffer == dst_texture))
|
||||
gl_info->gl_ops.gl.p_glFlush();
|
||||
|
||||
if (staging_texture)
|
||||
wined3d_texture_decref(staging_texture);
|
||||
|
||||
return dst_location;
|
||||
}
|
||||
|
||||
|
|
|
@ -566,52 +566,6 @@ static void texture2d_download_data(struct wined3d_texture *texture, unsigned in
|
|||
heap_free(temporary_mem);
|
||||
}
|
||||
|
||||
static HRESULT texture2d_upload_from_surface(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
|
||||
unsigned int dst_x, unsigned int dst_y, struct wined3d_texture *src_texture,
|
||||
unsigned int src_sub_resource_idx, const struct wined3d_box *src_box)
|
||||
{
|
||||
unsigned int src_row_pitch, src_slice_pitch;
|
||||
unsigned int src_level, dst_level;
|
||||
struct wined3d_context *context;
|
||||
struct wined3d_bo_address data;
|
||||
UINT update_w, update_h;
|
||||
|
||||
TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, "
|
||||
"src_texture %p, src_sub_resource_idx %u, src_box %s.\n",
|
||||
dst_texture, dst_sub_resource_idx, dst_x, dst_y,
|
||||
src_texture, src_sub_resource_idx, debug_box(src_box));
|
||||
|
||||
context = context_acquire(dst_texture->resource.device, NULL, 0);
|
||||
|
||||
/* Only load the sub-resource for partial updates. For newly allocated
|
||||
* textures the texture wouldn't be the current location, and we'd upload
|
||||
* zeroes just to overwrite them again. */
|
||||
update_w = src_box->right - src_box->left;
|
||||
update_h = src_box->bottom - src_box->top;
|
||||
dst_level = dst_sub_resource_idx % dst_texture->level_count;
|
||||
if (update_w == wined3d_texture_get_level_width(dst_texture, dst_level)
|
||||
&& update_h == wined3d_texture_get_level_height(dst_texture, dst_level))
|
||||
wined3d_texture_prepare_texture(dst_texture, context, FALSE);
|
||||
else
|
||||
wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
|
||||
wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
|
||||
|
||||
src_level = src_sub_resource_idx % src_texture->level_count;
|
||||
wined3d_texture_get_memory(src_texture, src_sub_resource_idx, &data,
|
||||
src_texture->sub_resources[src_sub_resource_idx].locations);
|
||||
wined3d_texture_get_pitch(src_texture, src_level, &src_row_pitch, &src_slice_pitch);
|
||||
|
||||
wined3d_texture_upload_data(dst_texture, dst_sub_resource_idx, context, src_texture->resource.format,
|
||||
src_box, wined3d_const_bo_address(&data), src_row_pitch, src_slice_pitch, dst_x, dst_y, 0, FALSE);
|
||||
|
||||
context_release(context);
|
||||
|
||||
wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
|
||||
wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
|
||||
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
/* See also float_16_to_32() in wined3d_private.h */
|
||||
static inline unsigned short float_32_to_16(const float *in)
|
||||
{
|
||||
|
@ -3459,9 +3413,8 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_
|
|||
TRACE("Not doing upload because the destination format needs conversion.\n");
|
||||
else
|
||||
{
|
||||
if (SUCCEEDED(texture2d_upload_from_surface(dst_texture, dst_sub_resource_idx,
|
||||
dst_box->left, dst_box->top, src_texture, src_sub_resource_idx, src_box)))
|
||||
{
|
||||
wined3d_texture_upload_from_texture(dst_texture, dst_sub_resource_idx, dst_box->left,
|
||||
dst_box->top, dst_box->front, src_texture, src_sub_resource_idx, src_box);
|
||||
if (!wined3d_resource_is_offscreen(&dst_texture->resource))
|
||||
{
|
||||
context = context_acquire(device, dst_texture, dst_sub_resource_idx);
|
||||
|
@ -3472,7 +3425,6 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_
|
|||
return WINED3D_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (dst_swapchain && dst_swapchain->back_buffers
|
||||
&& dst_texture == dst_swapchain->front_buffer
|
||||
&& src_texture == dst_swapchain->back_buffers[0])
|
||||
|
|
|
@ -3488,3 +3488,49 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign
|
|||
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
|
||||
unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_texture *src_texture,
|
||||
unsigned int src_sub_resource_idx, const struct wined3d_box *src_box)
|
||||
{
|
||||
unsigned int src_row_pitch, src_slice_pitch;
|
||||
unsigned int update_w, update_h, update_d;
|
||||
unsigned int src_level, dst_level;
|
||||
struct wined3d_context *context;
|
||||
struct wined3d_bo_address data;
|
||||
|
||||
TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
|
||||
"src_texture %p, src_sub_resource_idx %u, src_box %s.\n",
|
||||
dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z,
|
||||
src_texture, src_sub_resource_idx, debug_box(src_box));
|
||||
|
||||
context = context_acquire(dst_texture->resource.device, NULL, 0);
|
||||
|
||||
/* Only load the sub-resource for partial updates. For newly allocated
|
||||
* textures the texture wouldn't be the current location, and we'd upload
|
||||
* zeroes just to overwrite them again. */
|
||||
update_w = src_box->right - src_box->left;
|
||||
update_h = src_box->bottom - src_box->top;
|
||||
update_d = src_box->back - src_box->front;
|
||||
dst_level = dst_sub_resource_idx % dst_texture->level_count;
|
||||
if (update_w == wined3d_texture_get_level_width(dst_texture, dst_level)
|
||||
&& update_h == wined3d_texture_get_level_height(dst_texture, dst_level)
|
||||
&& update_d == wined3d_texture_get_level_depth(dst_texture, dst_level))
|
||||
wined3d_texture_prepare_texture(dst_texture, context, FALSE);
|
||||
else
|
||||
wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
|
||||
wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
|
||||
|
||||
src_level = src_sub_resource_idx % src_texture->level_count;
|
||||
wined3d_texture_get_memory(src_texture, src_sub_resource_idx, &data,
|
||||
src_texture->sub_resources[src_sub_resource_idx].locations);
|
||||
wined3d_texture_get_pitch(src_texture, src_level, &src_row_pitch, &src_slice_pitch);
|
||||
|
||||
wined3d_texture_upload_data(dst_texture, dst_sub_resource_idx, context, src_texture->resource.format,
|
||||
src_box, wined3d_const_bo_address(&data), src_row_pitch, src_slice_pitch, dst_x, dst_y, dst_z, FALSE);
|
||||
|
||||
context_release(context);
|
||||
|
||||
wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
|
||||
wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
|
||||
}
|
||||
|
|
|
@ -3305,6 +3305,9 @@ void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int s
|
|||
struct wined3d_context *context, const struct wined3d_format *format, const struct wined3d_box *src_box,
|
||||
const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch,
|
||||
unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, BOOL srgb) DECLSPEC_HIDDEN;
|
||||
void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
|
||||
unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_texture *src_texture,
|
||||
unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) DECLSPEC_HIDDEN;
|
||||
void wined3d_texture_validate_location(struct wined3d_texture *texture,
|
||||
unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
Loading…
Reference in New Issue