From b9133d7de059035220ba95cf2fb96b6f4146dd6e Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Tue, 14 Jun 2011 20:28:08 +0200 Subject: [PATCH] wined3d: Implement wined3d_device_update_surface() on top of surface_upload_data(). --- dlls/wined3d/device.c | 100 +++++++++------------------------ dlls/wined3d/surface.c | 99 ++++++++++++++++++++------------ dlls/wined3d/wined3d_private.h | 3 + 3 files changed, 93 insertions(+), 109 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 529f5ce6b66..19a9a45a55f 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4736,13 +4736,12 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device, const struct wined3d_format *dst_format; const struct wined3d_gl_info *gl_info; struct wined3d_context *context; - const unsigned char *data; - UINT update_w, update_h; - CONVERT_TYPES convert; - UINT src_w, src_h; - UINT dst_x, dst_y; - DWORD sampler; + struct wined3d_bo_address data; struct wined3d_format format; + CONVERT_TYPES convert; + DWORD sampler; + POINT p; + RECT r; TRACE("device %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n", device, src_surface, wine_dbgstr_rect(src_rect), @@ -4764,8 +4763,12 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device, return WINED3DERR_INVALIDCALL; } - dst_x = dst_point ? dst_point->x : 0; - dst_y = dst_point ? dst_point->y : 0; + if (!dst_point) + { + p.x = 0; + p.y = 0; + dst_point = &p; + } /* This call loads the OpenGL surface directly, instead of copying the * surface to the destination's sysmem copy. If surface conversion is @@ -4773,7 +4776,7 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device, * loading. */ d3dfmt_get_conv(dst_surface, FALSE, TRUE, &format, &convert); if (convert != NO_CONVERSION || format.convert) - return wined3d_surface_bltfast(dst_surface, dst_x, dst_y, src_surface, src_rect, 0); + return wined3d_surface_bltfast(dst_surface, dst_point->x, dst_point->y, src_surface, src_rect, 0); context = context_acquire(device, NULL); gl_info = context->gl_info; @@ -4787,73 +4790,24 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device, surface_internal_preload(dst_surface, SRGB_RGB); surface_bind(dst_surface, gl_info, FALSE); - src_w = src_surface->resource.width; - src_h = src_surface->resource.height; - update_w = src_rect ? src_rect->right - src_rect->left : src_w; - update_h = src_rect ? src_rect->bottom - src_rect->top : src_h; - - data = src_surface->resource.allocatedMemory; - if (!data) ERR("Source surface has no allocated memory, but should be a sysmem surface.\n"); - - ENTER_GL(); - - if (dst_format->flags & WINED3DFMT_FLAG_COMPRESSED) + if (!src_rect) { - UINT row_length = wined3d_format_calculate_size(src_format, 1, update_w, 1); - UINT row_count = (update_h + src_format->block_height - 1) / src_format->block_height; - UINT src_pitch = wined3d_format_calculate_size(src_format, 1, src_w, 1); - - if (src_rect) - { - data += (src_rect->top / src_format->block_height) * src_pitch; - data += (src_rect->left / src_format->block_width) * src_format->block_byte_count; - } - - TRACE("glCompressedTexSubImage2DARB, target %#x, level %d, x %d, y %d, w %d, h %d, " - "format %#x, image_size %#x, data %p.\n", dst_surface->texture_target, dst_surface->texture_level, - dst_x, dst_y, update_w, update_h, dst_format->glFormat, row_count * row_length, data); - - if (row_length == src_pitch) - { - GL_EXTCALL(glCompressedTexSubImage2DARB(dst_surface->texture_target, dst_surface->texture_level, - dst_x, dst_y, update_w, update_h, dst_format->glInternal, row_count * row_length, data)); - } - else - { - UINT row, y; - - /* glCompressedTexSubImage2DARB() ignores pixel store state, so we - * can't use the unpack row length like below. */ - for (row = 0, y = dst_y; row < row_count; ++row) - { - GL_EXTCALL(glCompressedTexSubImage2DARB(dst_surface->texture_target, dst_surface->texture_level, - dst_x, y, update_w, src_format->block_height, dst_format->glInternal, row_length, data)); - y += src_format->block_height; - data += src_pitch; - } - } - checkGLcall("glCompressedTexSubImage2DARB"); - } - else - { - if (src_rect) - { - data += src_rect->top * src_w * src_format->byte_count; - data += src_rect->left * src_format->byte_count; - } - - TRACE("glTexSubImage2D, target %#x, level %d, x %d, y %d, w %d, h %d, format %#x, type %#x, data %p.\n", - dst_surface->texture_target, dst_surface->texture_level, dst_x, dst_y, - update_w, update_h, dst_format->glFormat, dst_format->glType, data); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, src_w); - glTexSubImage2D(dst_surface->texture_target, dst_surface->texture_level, dst_x, dst_y, - update_w, update_h, dst_format->glFormat, dst_format->glType, data); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - checkGLcall("glTexSubImage2D"); + r.left = 0; + r.top = 0; + r.right = src_surface->resource.width; + r.bottom = src_surface->resource.height; + src_rect = &r; } - LEAVE_GL(); + data.buffer_object = 0; + data.addr = src_surface->resource.allocatedMemory; + + if (!data.addr) + ERR("Source surface has no allocated memory, but should be a sysmem surface.\n"); + + surface_upload_data(dst_surface, gl_info, src_format, src_rect, + src_surface->resource.width, dst_point, FALSE, &data); + context_release(context); surface_modify_location(dst_surface, SFLAG_INTEXTURE, TRUE); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 77a4f2f8fec..62025132cc0 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -2161,32 +2161,19 @@ static void surface_download_data(struct wined3d_surface *surface, const struct /* This call just uploads data, the caller is responsible for binding the * correct texture. */ /* Context activation is done by the caller. */ -static void surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, - const struct wined3d_format *format, BOOL srgb, const struct wined3d_bo_address *data) +void surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, + const struct wined3d_format *format, const RECT *src_rect, UINT src_w, const POINT *dst_point, + BOOL srgb, const struct wined3d_bo_address *data) { - GLsizei width = surface->resource.width; - GLsizei height = surface->resource.height; - GLenum internal; + UINT update_w = src_rect->right - src_rect->left; + UINT update_h = src_rect->bottom - src_rect->top; - if (srgb) - { - internal = format->glGammaInternal; - } - else if (surface->resource.usage & WINED3DUSAGE_RENDERTARGET && surface_is_offscreen(surface)) - { - internal = format->rtInternal; - } - else - { - internal = format->glInternal; - } + TRACE("surface %p, gl_info %p, format %s, src_rect %s, src_w %u, dst_point %p, srgb %#x, data {%#x:%p}.\n", + surface, gl_info, debug_d3dformat(format->id), wine_dbgstr_rect(src_rect), src_w, + wine_dbgstr_point(dst_point), srgb, data->buffer_object, data->addr); - TRACE("surface %p, internal %#x, width %d, height %d, format %#x, type %#x, data {%#x:%p}.\n", - surface, internal, width, height, format->glFormat, format->glType, data->buffer_object, data->addr); - TRACE("target %#x, level %u, resource size %u.\n", - surface->texture_target, surface->texture_level, surface->resource.size); - - if (format->heightscale != 1.0f && format->heightscale != 0.0f) height *= format->heightscale; + if (format->heightscale != 1.0f && format->heightscale != 0.0f) + update_h *= format->heightscale; ENTER_GL(); @@ -2196,29 +2183,67 @@ static void surface_upload_data(struct wined3d_surface *surface, const struct wi checkGLcall("glBindBufferARB"); } - /* Make sure the correct pitch is used */ - glPixelStorei(GL_UNPACK_ROW_LENGTH, width); - if (format->flags & WINED3DFMT_FLAG_COMPRESSED) { - TRACE("Calling glCompressedTexSubImage2DARB.\n"); + UINT row_length = wined3d_format_calculate_size(format, 1, update_w, 1); + UINT row_count = (update_h + format->block_height - 1) / format->block_height; + UINT src_pitch = wined3d_format_calculate_size(format, 1, src_w, 1); + const BYTE *addr = data->addr; + GLenum internal; - GL_EXTCALL(glCompressedTexSubImage2DARB(surface->texture_target, surface->texture_level, - 0, 0, width, height, internal, surface->resource.size, data->addr)); + addr += (src_rect->top / format->block_height) * src_pitch; + addr += (src_rect->left / format->block_width) * format->block_byte_count; + + if (srgb) + internal = format->glGammaInternal; + else if (surface->resource.usage & WINED3DUSAGE_RENDERTARGET && surface_is_offscreen(surface)) + internal = format->rtInternal; + else + internal = format->glInternal; + + TRACE("glCompressedTexSubImage2DARB, target %#x, level %d, x %d, y %d, w %d, h %d, " + "format %#x, image_size %#x, addr %p.\n", surface->texture_target, surface->texture_level, + dst_point->x, dst_point->y, update_w, update_h, internal, row_count * row_length, addr); + + if (row_length == src_pitch) + { + GL_EXTCALL(glCompressedTexSubImage2DARB(surface->texture_target, surface->texture_level, + dst_point->x, dst_point->y, update_w, update_h, internal, row_count * row_length, addr)); + } + else + { + UINT row, y; + + /* glCompressedTexSubImage2DARB() ignores pixel store state, so we + * can't use the unpack row length like below. */ + for (row = 0, y = dst_point->y; row < row_count; ++row) + { + GL_EXTCALL(glCompressedTexSubImage2DARB(surface->texture_target, surface->texture_level, + dst_point->x, y, update_w, format->block_height, internal, row_length, addr)); + y += format->block_height; + addr += src_pitch; + } + } checkGLcall("glCompressedTexSubImage2DARB"); } else { - TRACE("Calling glTexSubImage2D.\n"); + const BYTE *addr = data->addr; - glTexSubImage2D(surface->texture_target, surface->texture_level, - 0, 0, width, height, format->glFormat, format->glType, data->addr); + addr += src_rect->top * src_w * format->byte_count; + addr += src_rect->left * format->byte_count; + + TRACE("glTexSubImage2D, target %#x, level %d, x %d, y %d, w %d, h %d, format %#x, type %#x, addr %p.\n", + surface->texture_target, surface->texture_level, dst_point->x, dst_point->y, + update_w, update_h, format->glFormat, format->glType, addr); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, src_w); + glTexSubImage2D(surface->texture_target, surface->texture_level, dst_point->x, dst_point->y, + update_w, update_h, format->glFormat, format->glType, addr); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); checkGLcall("glTexSubImage2D"); } - /* Restore the default pitch */ - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - if (data->buffer_object) { GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); @@ -6067,9 +6092,11 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD flag, const else { /* Upload from system memory */ + RECT src_rect = {0, 0, surface->resource.width, surface->resource.height}; BOOL srgb = flag == SFLAG_INSRGBTEX; struct wined3d_context *context = NULL; struct wined3d_bo_address data; + POINT dst_point = {0, 0}; d3dfmt_get_conv(surface, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &convert); @@ -6165,7 +6192,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD flag, const data.buffer_object = surface->flags & SFLAG_PBO ? surface->pbo : 0; data.addr = mem; - surface_upload_data(surface, gl_info, &format, srgb, &data); + surface_upload_data(surface, gl_info, &format, &src_rect, width, &dst_point, srgb, &data); if (context) context_release(context); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 83fa40f7513..d20800ac4df 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2130,6 +2130,9 @@ void surface_set_container(struct wined3d_surface *surface, void surface_set_texture_name(struct wined3d_surface *surface, GLuint name, BOOL srgb_name) DECLSPEC_HIDDEN; void surface_set_texture_target(struct wined3d_surface *surface, GLenum target) DECLSPEC_HIDDEN; void surface_translate_drawable_coords(struct wined3d_surface *surface, HWND window, RECT *rect) DECLSPEC_HIDDEN; +void surface_upload_data(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, + const struct wined3d_format *format, const RECT *src_rect, UINT src_w, const POINT *dst_point, + BOOL srgb, const struct wined3d_bo_address *data) DECLSPEC_HIDDEN; void get_drawable_size_swapchain(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN; void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN;