Signed-off-by: Stefan Dösinger stefan@codeweavers.com --- dlls/wined3d/surface.c | 35 ++++++++++++++++++++-------------- dlls/wined3d/view.c | 14 ++++++++++++++ dlls/wined3d/wined3d_private.h | 2 ++ 3 files changed, 37 insertions(+), 14 deletions(-)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 5feeba3be2d..448c8689342 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1276,17 +1276,9 @@ static void surface_cpu_blt_colour_fill(struct wined3d_rendertarget_view *view,
c = wined3d_format_convert_from_float(view->format, colour); bpp = view->format->byte_count; - w = min(box->right, view->width) - min(box->left, view->width); - h = min(box->bottom, view->height) - min(box->top, view->height); - if (view->resource->type != WINED3D_RTYPE_TEXTURE_3D) - { - d = 1; - } - else - { - d = wined3d_texture_get_level_depth(texture, level); - d = min(box->back, d) - min(box->front, d); - } + w = box->right - box->left; + h = box->bottom - box->top; + d = box->back - box->front;
map_binding = texture->resource.map_binding; if (!wined3d_texture_load_location(texture, view->sub_resource_idx, context, map_binding)) @@ -1361,13 +1353,22 @@ static void surface_cpu_blt_colour_fill(struct wined3d_rendertarget_view *view, context_release(context); }
+static bool wined3d_box_intersect(struct wined3d_box *ret, const struct wined3d_box *b1, + const struct wined3d_box *b2) +{ + wined3d_box_set(ret, max(b1->left, b2->left), max(b1->top, b2->top), + min(b1->right, b2->right), min(b1->bottom, b2->bottom), + max(b1->front, b2->front), min(b1->back, b2->back)); + return ret->right > ret->left && ret->bottom > ret->top && ret->back > ret->front; +} + static void cpu_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_color c = {depth, 0.0f, 0.0f, 0.0f}; + struct wined3d_box box, box_clip, box_view; struct wined3d_rendertarget_view *view; - struct wined3d_box box; unsigned int i, j;
if (!rect_count) @@ -1393,7 +1394,11 @@ static void cpu_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de for (j = 0; j < rt_count; ++j) { if ((view = fb->render_targets[j])) - surface_cpu_blt_colour_fill(view, &box, colour); + { + wined3d_rendertarget_view_get_box(view, &box_view); + if (wined3d_box_intersect(&box_clip, &box_view, &box)) + surface_cpu_blt_colour_fill(view, &box_clip, colour); + } } }
@@ -1403,7 +1408,9 @@ static void cpu_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de || (view->format->stencil_size && !(flags & WINED3DCLEAR_STENCIL))) FIXME("Clearing %#x on %s.\n", flags, debug_d3dformat(view->format->id));
- surface_cpu_blt_colour_fill(view, &box, &c); + wined3d_rendertarget_view_get_box(view, &box_view); + if (wined3d_box_intersect(&box_clip, &box_view, &box)) + surface_cpu_blt_colour_fill(view, &box_clip, &c); } } } diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 752563508c8..f2dea8f0f9a 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -534,6 +534,20 @@ DWORD wined3d_rendertarget_view_get_locations(const struct wined3d_rendertarget_ return ret; }
+void wined3d_rendertarget_view_get_box(struct wined3d_rendertarget_view *view, + struct wined3d_box *box) +{ + if (view->resource->type != WINED3D_RTYPE_TEXTURE_3D) + { + wined3d_box_set(box, 0, 0, view->width, view->height, 0, 1); + } + else + { + struct wined3d_texture *texture = texture_from_resource(view->resource); + wined3d_texture_get_level_box(texture, view->sub_resource_idx, box); + } +} + static void wined3d_render_target_view_gl_cs_init(void *object) { struct wined3d_rendertarget_view_gl *view_gl = object; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 3a12f5ef261..17afc183adb 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -5287,6 +5287,8 @@ struct wined3d_rendertarget_view void wined3d_rendertarget_view_cleanup(struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; void wined3d_rendertarget_view_get_drawable_size(const struct wined3d_rendertarget_view *view, const struct wined3d_context *context, unsigned int *width, unsigned int *height) DECLSPEC_HIDDEN; +void wined3d_rendertarget_view_get_box(struct wined3d_rendertarget_view *view, + struct wined3d_box *box) DECLSPEC_HIDDEN; void wined3d_rendertarget_view_invalidate_location(struct wined3d_rendertarget_view *view, DWORD location) DECLSPEC_HIDDEN; void wined3d_rendertarget_view_load_location(struct wined3d_rendertarget_view *view,
Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
Version 2: The previous patch moved the box to surface size comparison out of the way.
Signed-off-by: Stefan Dösinger stefan@codeweavers.com --- dlls/wined3d/resource.c | 76 ++++++++++++++++++++++++++++++++++ dlls/wined3d/surface.c | 68 +----------------------------- dlls/wined3d/wined3d_private.h | 3 ++ 3 files changed, 81 insertions(+), 66 deletions(-)
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c index 437f9c9da69..7587a6455a4 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -613,3 +613,79 @@ void *resource_offset_map_pointer(struct wined3d_resource *resource, unsigned in + (box->left * format->byte_count); } } + +void wined3d_resource_memory_colour_fill(struct wined3d_resource *resource, + const struct wined3d_map_desc *map, const struct wined3d_color *colour, + const struct wined3d_box *box) +{ + const struct wined3d_format *format = resource->format; + unsigned int w, h, d, x, y, z, bpp; + uint8_t *dst, *dst2; + uint32_t c; + + w = box->right - box->left; + h = box->bottom - box->top; + d = box->back - box->front; + + dst = (uint8_t *)map->data + + (box->front * map->slice_pitch) + + ((box->top / format->block_height) * map->row_pitch) + + ((box->left / format->block_width) * format->block_byte_count); + + c = wined3d_format_convert_from_float(format, colour); + bpp = format->byte_count; + + switch (bpp) + { + case 1: + for (x = 0; x < w; ++x) + { + dst[x] = c; + } + break; + + case 2: + for (x = 0; x < w; ++x) + { + ((uint16_t *)dst)[x] = c; + } + break; + + case 3: + { + dst2 = dst; + for (x = 0; x < w; ++x, dst2 += 3) + { + dst2[0] = (c ) & 0xff; + dst2[1] = (c >> 8) & 0xff; + dst2[2] = (c >> 16) & 0xff; + } + break; + } + case 4: + for (x = 0; x < w; ++x) + { + ((uint32_t *)dst)[x] = c; + } + break; + + default: + FIXME("Not implemented for bpp %u.\n", bpp); + return; + } + + dst2 = dst; + for (y = 1; y < h; ++y) + { + dst2 += map->row_pitch; + memcpy(dst2, dst, w * bpp); + } + + dst2 = dst; + for (z = 1; z < d; ++z) + { + dst2 += map->slice_pitch; + memcpy(dst2, dst, w * h * bpp); + } + +} diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 448c8689342..0d4809ea55b 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1241,15 +1241,13 @@ static void surface_cpu_blt_colour_fill(struct wined3d_rendertarget_view *view, const struct wined3d_box *box, const struct wined3d_color *colour) { struct wined3d_device *device = view->resource->device; - unsigned int x, y, z, w, h, d, bpp, level; struct wined3d_context *context; struct wined3d_texture *texture; struct wined3d_bo_address data; struct wined3d_map_desc map; struct wined3d_range range; + unsigned int level; DWORD map_binding; - uint8_t *dst; - DWORD c;
TRACE("view %p, box %s, colour %s.\n", view, debug_box(box), debug_color(colour));
@@ -1274,12 +1272,6 @@ static void surface_cpu_blt_colour_fill(struct wined3d_rendertarget_view *view, texture = texture_from_resource(view->resource); level = view->sub_resource_idx % texture->level_count;
- c = wined3d_format_convert_from_float(view->format, colour); - bpp = view->format->byte_count; - w = box->right - box->left; - h = box->bottom - box->top; - d = box->back - box->front; - map_binding = texture->resource.map_binding; if (!wined3d_texture_load_location(texture, view->sub_resource_idx, context, map_binding)) ERR("Failed to load the sub-resource into %s.\n", wined3d_debug_location(map_binding)); @@ -1288,66 +1280,10 @@ static void surface_cpu_blt_colour_fill(struct wined3d_rendertarget_view *view, wined3d_texture_get_bo_address(texture, view->sub_resource_idx, &data, map_binding); map.data = wined3d_context_map_bo_address(context, &data, texture->sub_resources[view->sub_resource_idx].size, WINED3D_MAP_WRITE); - map.data = (BYTE *)map.data - + (box->front * map.slice_pitch) - + ((box->top / view->format->block_height) * map.row_pitch) - + ((box->left / view->format->block_width) * view->format->block_byte_count); range.offset = 0; range.size = texture->sub_resources[view->sub_resource_idx].size;
- switch (bpp) - { - case 1: - for (x = 0; x < w; ++x) - { - ((BYTE *)map.data)[x] = c; - } - break; - - case 2: - for (x = 0; x < w; ++x) - { - ((WORD *)map.data)[x] = c; - } - break; - - case 3: - { - dst = map.data; - for (x = 0; x < w; ++x, dst += 3) - { - dst[0] = (c ) & 0xff; - dst[1] = (c >> 8) & 0xff; - dst[2] = (c >> 16) & 0xff; - } - break; - } - case 4: - for (x = 0; x < w; ++x) - { - ((DWORD *)map.data)[x] = c; - } - break; - - default: - FIXME("Not implemented for bpp %u.\n", bpp); - wined3d_resource_unmap(view->resource, view->sub_resource_idx); - return; - } - - dst = map.data; - for (y = 1; y < h; ++y) - { - dst += map.row_pitch; - memcpy(dst, map.data, w * bpp); - } - - dst = map.data; - for (z = 1; z < d; ++z) - { - dst += map.slice_pitch; - memcpy(dst, map.data, w * h * bpp); - } + wined3d_resource_memory_colour_fill(view->resource, &map, colour, box);
wined3d_context_unmap_bo_address(context, &data, 1, &range); context_release(context); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 17afc183adb..05d71140a16 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4366,6 +4366,9 @@ GLbitfield wined3d_resource_gl_storage_flags(const struct wined3d_resource *reso BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN; BOOL wined3d_resource_prepare_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) DECLSPEC_HIDDEN; +void wined3d_resource_memory_colour_fill(struct wined3d_resource *resource, + const struct wined3d_map_desc *map, const struct wined3d_color *colour, + const struct wined3d_box *box) DECLSPEC_HIDDEN;
/* Tests show that the start address of resources is 32 byte aligned */ #define RESOURCE_ALIGNMENT 16
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
Version 2: Don't insist on a 16 byte output buffer.
Signed-off-by: Stefan Dösinger stefan@codeweavers.com --- dlls/wined3d/device.c | 4 +-- dlls/wined3d/resource.c | 16 ++++----- dlls/wined3d/utils.c | 61 ++++++++++++++++++++++++---------- dlls/wined3d/wined3d_private.h | 4 +-- 4 files changed, 56 insertions(+), 29 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 8937c7fc0fc..d39634c49fc 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -3689,7 +3689,7 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO diffuse_colour = material_diffuse; } wined3d_color_clamp(&diffuse_colour, &diffuse_colour, 0.0f, 1.0f); - *((DWORD *)dest_ptr) = wined3d_format_convert_from_float(output_colour_format, &diffuse_colour); + wined3d_format_convert_from_float(output_colour_format, &diffuse_colour, dest_ptr); dest_ptr += sizeof(DWORD); }
@@ -3713,7 +3713,7 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO } update_fog_factor(&specular_colour.a, &ls); wined3d_color_clamp(&specular_colour, &specular_colour, 0.0f, 1.0f); - *((DWORD *)dest_ptr) = wined3d_format_convert_from_float(output_colour_format, &specular_colour); + wined3d_format_convert_from_float(output_colour_format, &specular_colour, dest_ptr); dest_ptr += sizeof(DWORD); }
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c index 7587a6455a4..073bc5b5834 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -621,7 +621,7 @@ void wined3d_resource_memory_colour_fill(struct wined3d_resource *resource, const struct wined3d_format *format = resource->format; unsigned int w, h, d, x, y, z, bpp; uint8_t *dst, *dst2; - uint32_t c; + uint32_t c[4];
w = box->right - box->left; h = box->bottom - box->top; @@ -632,7 +632,7 @@ void wined3d_resource_memory_colour_fill(struct wined3d_resource *resource, + ((box->top / format->block_height) * map->row_pitch) + ((box->left / format->block_width) * format->block_byte_count);
- c = wined3d_format_convert_from_float(format, colour); + wined3d_format_convert_from_float(format, colour, c); bpp = format->byte_count;
switch (bpp) @@ -640,14 +640,14 @@ void wined3d_resource_memory_colour_fill(struct wined3d_resource *resource, case 1: for (x = 0; x < w; ++x) { - dst[x] = c; + dst[x] = c[0]; } break;
case 2: for (x = 0; x < w; ++x) { - ((uint16_t *)dst)[x] = c; + ((uint16_t *)dst)[x] = c[0]; } break;
@@ -656,16 +656,16 @@ void wined3d_resource_memory_colour_fill(struct wined3d_resource *resource, dst2 = dst; for (x = 0; x < w; ++x, dst2 += 3) { - dst2[0] = (c ) & 0xff; - dst2[1] = (c >> 8) & 0xff; - dst2[2] = (c >> 16) & 0xff; + dst2[0] = (c[0] ) & 0xff; + dst2[1] = (c[0] >> 8) & 0xff; + dst2[2] = (c[0] >> 16) & 0xff; } break; } case 4: for (x = 0; x < w; ++x) { - ((uint32_t *)dst)[x] = c; + ((uint32_t *)dst)[x] = c[0]; } break;
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 401d815a365..3017265ccb0 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -6000,8 +6000,12 @@ uint32_t wined3d_format_pack(const struct wined3d_format *format, const struct w
/* Note: It's the caller's responsibility to ensure values can be expressed * in the requested format. UNORM formats for example can only express values - * in the range 0.0f -> 1.0f. */ -DWORD wined3d_format_convert_from_float(const struct wined3d_format *format, const struct wined3d_color *color) + * in the range 0.0f -> 1.0f. + * + * The code below assumes that no component crosses the 32 bit boundary (like + * e.g. a hypothetical, and totally braindead, B30G30R4 format would.) */ +void wined3d_format_convert_from_float(const struct wined3d_format *format, const struct wined3d_color *color, + void *ret) { static const struct { @@ -6044,10 +6048,11 @@ DWORD wined3d_format_convert_from_float(const struct wined3d_format *format, con }; enum wined3d_format_id format_id = format->id; struct wined3d_color colour_srgb; + struct wined3d_uvec4 idx, shift; unsigned int i; - DWORD ret;
TRACE("Converting colour %s to format %s.\n", debug_color(color), debug_d3dformat(format_id)); + memset(ret, 0, format->byte_count);
for (i = 0; i < ARRAY_SIZE(format_srgb_info); ++i) { @@ -6062,37 +6067,59 @@ DWORD wined3d_format_convert_from_float(const struct wined3d_format *format, con
for (i = 0; i < ARRAY_SIZE(float_conv); ++i) { + uint32_t *ret_i = ret; + if (format_id != float_conv[i].format_id) continue;
- ret = ((DWORD)((color->r * float_conv[i].mul.x) + 0.5f)) << float_conv[i].shift.x; - ret |= ((DWORD)((color->g * float_conv[i].mul.y) + 0.5f)) << float_conv[i].shift.y; - ret |= ((DWORD)((color->b * float_conv[i].mul.z) + 0.5f)) << float_conv[i].shift.z; - ret |= ((DWORD)((color->a * float_conv[i].mul.w) + 0.5f)) << float_conv[i].shift.w; + idx.x = float_conv[i].shift.x / 32; + idx.y = float_conv[i].shift.y / 32; + idx.z = float_conv[i].shift.z / 32; + idx.w = float_conv[i].shift.w / 32; + shift.x = float_conv[i].shift.x % 32; + shift.y = float_conv[i].shift.y % 32; + shift.z = float_conv[i].shift.z % 32; + shift.w = float_conv[i].shift.w % 32; + + ret_i[idx.x] = ((uint32_t)((color->r * float_conv[i].mul.x) + 0.5f)) << shift.x; + ret_i[idx.y] |= ((uint32_t)((color->g * float_conv[i].mul.y) + 0.5f)) << shift.y; + ret_i[idx.z] |= ((uint32_t)((color->b * float_conv[i].mul.z) + 0.5f)) << shift.z; + ret_i[idx.w] |= ((uint32_t)((color->a * float_conv[i].mul.w) + 0.5f)) << shift.w;
- TRACE("Returning 0x%08x.\n", ret); + TRACE("Returning 0x%08x 0x%08x 0x%08x 0x%08x.\n", + ret_i[0], ret_i[1], ret_i[2], ret_i[3]);
- return ret; + return; }
for (i = 0; i < ARRAY_SIZE(double_conv); ++i) { + uint32_t *ret_i; + if (format_id != double_conv[i].format_id) continue;
- ret = ((DWORD)((color->r * double_conv[i].mul.x) + 0.5)) << double_conv[i].shift.x; - ret |= ((DWORD)((color->g * double_conv[i].mul.y) + 0.5)) << double_conv[i].shift.y; - ret |= ((DWORD)((color->b * double_conv[i].mul.z) + 0.5)) << double_conv[i].shift.z; - ret |= ((DWORD)((color->a * double_conv[i].mul.w) + 0.5)) << double_conv[i].shift.w; + idx.x = float_conv[i].shift.x / 32; + idx.y = float_conv[i].shift.y / 32; + idx.z = float_conv[i].shift.z / 32; + idx.w = float_conv[i].shift.w / 32; + shift.x = float_conv[i].shift.x % 32; + shift.y = float_conv[i].shift.y % 32; + shift.z = float_conv[i].shift.z % 32; + shift.w = float_conv[i].shift.w % 32;
- TRACE("Returning 0x%08x.\n", ret); + ret_i = ret; + ret_i[idx.x] = ((uint32_t)((color->r * double_conv[i].mul.x) + 0.5)) << double_conv[i].shift.x; + ret_i[idx.y] |= ((uint32_t)((color->g * double_conv[i].mul.y) + 0.5)) << double_conv[i].shift.y; + ret_i[idx.z] |= ((uint32_t)((color->b * double_conv[i].mul.z) + 0.5)) << double_conv[i].shift.z; + ret_i[idx.w] |= ((uint32_t)((color->a * double_conv[i].mul.w) + 0.5)) << double_conv[i].shift.w;
- return ret; + TRACE("Returning 0x%08x 0x%08x 0x%08x 0x%08x.\n", ret_i[0], ret_i[1], ret_i[2], ret_i[3]); + + return; }
FIXME("Conversion for format %s not implemented.\n", debug_d3dformat(format_id)); - - return 0; }
static float color_to_float(DWORD color, DWORD size, DWORD offset) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 05d71140a16..c5c2a51bc5e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -6151,8 +6151,8 @@ void wined3d_format_calculate_pitch(const struct wined3d_format *format, unsigne unsigned int width, unsigned int height, unsigned int *row_pitch, unsigned int *slice_pitch) DECLSPEC_HIDDEN; UINT wined3d_format_calculate_size(const struct wined3d_format *format, UINT alignment, UINT width, UINT height, UINT depth) DECLSPEC_HIDDEN; -DWORD wined3d_format_convert_from_float(const struct wined3d_format *format, - const struct wined3d_color *color) DECLSPEC_HIDDEN; +void wined3d_format_convert_from_float(const struct wined3d_format *format, + const struct wined3d_color *color, void *ret) DECLSPEC_HIDDEN; void wined3d_format_copy_data(const struct wined3d_format *format, const uint8_t *src, unsigned int src_row_pitch, unsigned int src_slice_pitch, uint8_t *dst, unsigned int dst_row_pitch, unsigned int dst_slice_pitch, unsigned int w, unsigned int h, unsigned int d) DECLSPEC_HIDDEN;
On Fri, 13 May 2022 at 14:55, Stefan Dösinger stefan@codeweavers.com wrote:
@@ -6062,37 +6067,59 @@ DWORD wined3d_format_convert_from_float(const struct wined3d_format *format, con
for (i = 0; i < ARRAY_SIZE(float_conv); ++i) {
uint32_t *ret_i = ret;
if (format_id != float_conv[i].format_id) continue;
ret = ((DWORD)((color->r * float_conv[i].mul.x) + 0.5f)) << float_conv[i].shift.x;
ret |= ((DWORD)((color->g * float_conv[i].mul.y) + 0.5f)) << float_conv[i].shift.y;
ret |= ((DWORD)((color->b * float_conv[i].mul.z) + 0.5f)) << float_conv[i].shift.z;
ret |= ((DWORD)((color->a * float_conv[i].mul.w) + 0.5f)) << float_conv[i].shift.w;
idx.x = float_conv[i].shift.x / 32;
idx.y = float_conv[i].shift.y / 32;
idx.z = float_conv[i].shift.z / 32;
idx.w = float_conv[i].shift.w / 32;
shift.x = float_conv[i].shift.x % 32;
shift.y = float_conv[i].shift.y % 32;
shift.z = float_conv[i].shift.z % 32;
shift.w = float_conv[i].shift.w % 32;
ret_i[idx.x] = ((uint32_t)((color->r * float_conv[i].mul.x) + 0.5f)) << shift.x;
ret_i[idx.y] |= ((uint32_t)((color->g * float_conv[i].mul.y) + 0.5f)) << shift.y;
ret_i[idx.z] |= ((uint32_t)((color->b * float_conv[i].mul.z) + 0.5f)) << shift.z;
ret_i[idx.w] |= ((uint32_t)((color->a * float_conv[i].mul.w) + 0.5f)) << shift.w;
TRACE("Returning 0x%08x.\n", ret);
TRACE("Returning 0x%08x 0x%08x 0x%08x 0x%08x.\n",
ret_i[0], ret_i[1], ret_i[2], ret_i[3]);
That TRACE isn't safe, I'm afraid. I think technically this doesn't quite do the right thing for formats with bpp < 4 like B5G6R5_UNORM, although we should be fine in practice due to how this is used.
for (i = 0; i < ARRAY_SIZE(double_conv); ++i) {
uint32_t *ret_i;
if (format_id != double_conv[i].format_id) continue;
ret = ((DWORD)((color->r * double_conv[i].mul.x) + 0.5)) << double_conv[i].shift.x;
ret |= ((DWORD)((color->g * double_conv[i].mul.y) + 0.5)) << double_conv[i].shift.y;
ret |= ((DWORD)((color->b * double_conv[i].mul.z) + 0.5)) << double_conv[i].shift.z;
ret |= ((DWORD)((color->a * double_conv[i].mul.w) + 0.5)) << double_conv[i].shift.w;
idx.x = float_conv[i].shift.x / 32;
idx.y = float_conv[i].shift.y / 32;
idx.z = float_conv[i].shift.z / 32;
idx.w = float_conv[i].shift.w / 32;
shift.x = float_conv[i].shift.x % 32;
shift.y = float_conv[i].shift.y % 32;
shift.z = float_conv[i].shift.z % 32;
shift.w = float_conv[i].shift.w % 32;
TRACE("Returning 0x%08x.\n", ret);
ret_i = ret;
ret_i[idx.x] = ((uint32_t)((color->r * double_conv[i].mul.x) + 0.5)) << double_conv[i].shift.x;
ret_i[idx.y] |= ((uint32_t)((color->g * double_conv[i].mul.y) + 0.5)) << double_conv[i].shift.y;
ret_i[idx.z] |= ((uint32_t)((color->b * double_conv[i].mul.z) + 0.5)) << double_conv[i].shift.z;
ret_i[idx.w] |= ((uint32_t)((color->a * double_conv[i].mul.w) + 0.5)) << double_conv[i].shift.w;
return ret;
TRACE("Returning 0x%08x 0x%08x 0x%08x 0x%08x.\n", ret_i[0], ret_i[1], ret_i[2], ret_i[3]);
Likewise.
Am Freitag, 13. Mai 2022, 19:02:40 EAT schrieb Henri Verbeet:
That TRACE isn't safe, I'm afraid.
Oh right, it used to be in v1... I'll fix that.
Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
Version 2: Check for WINED3DFMT_FLAG_FLOAT instead of explicitly listing expected float formats.
Signed-off-by: Stefan Dösinger stefan@codeweavers.com --- dlls/wined3d/resource.c | 6 ++++++ dlls/wined3d/utils.c | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+)
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c index 073bc5b5834..ed5d5d63250 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -668,6 +668,12 @@ void wined3d_resource_memory_colour_fill(struct wined3d_resource *resource, ((uint32_t *)dst)[x] = c[0]; } break; + case 8: + case 12: + case 16: + for (x = 0; x < w; ++x) + memcpy(((uint8_t *)map->data) + x * bpp, c, bpp); + break;
default: FIXME("Not implemented for bpp %u.\n", bpp); diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 3017265ccb0..e4fcf18600e 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -6119,6 +6119,27 @@ void wined3d_format_convert_from_float(const struct wined3d_format *format, cons return; }
+ /* 32 bit float formats. We don't handle D32_FLOAT and D32_FLOAT_S8X24_UINT for now. */ + if ((format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_FLOAT) && format->red_size == 32) + { + float *ret_f = ret; + + switch (format->byte_count) + { + case 16: ret_f[3] = color->a; + case 12: ret_f[2] = color->b; + case 8: ret_f[1] = color->g; + case 4: ret_f[0] = color->r; + break; + + default: + ERR("Unexpected byte count %u: Format %s\n", format->byte_count, debug_d3dformat(format_id)); + break; + } + + return; + } + FIXME("Conversion for format %s not implemented.\n", debug_d3dformat(format_id)); }
Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
Version 2: Like in the float32 patch, don't explicitly list the formats.
Signed-off-by: Stefan Dösinger stefan@codeweavers.com --- dlls/wined3d/surface.c | 63 ---------------------------- dlls/wined3d/utils.c | 25 ++++++++++++ dlls/wined3d/wined3d_private.h | 75 ++++++++++++++++++++++++++++++---- 3 files changed, 93 insertions(+), 70 deletions(-)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 0d4809ea55b..29bdef9844f 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -39,69 +39,6 @@ static void get_color_masks(const struct wined3d_format *format, uint32_t *masks masks[2] = wined3d_mask_from_size(format->blue_size) << format->blue_offset; }
-/* See also float_16_to_32() in wined3d_private.h */ -static inline unsigned short float_32_to_16(const float *in) -{ - int exp = 0; - float tmp = fabsf(*in); - unsigned int mantissa; - unsigned short ret; - - /* Deal with special numbers */ - if (*in == 0.0f) - return 0x0000; - if (isnan(*in)) - return 0x7c01; - if (isinf(*in)) - return (*in < 0.0f ? 0xfc00 : 0x7c00); - - if (tmp < (float)(1u << 10)) - { - do - { - tmp = tmp * 2.0f; - exp--; - } while (tmp < (float)(1u << 10)); - } - else if (tmp >= (float)(1u << 11)) - { - do - { - tmp /= 2.0f; - exp++; - } while (tmp >= (float)(1u << 11)); - } - - mantissa = (unsigned int)tmp; - if (tmp - mantissa >= 0.5f) - ++mantissa; /* Round to nearest, away from zero. */ - - exp += 10; /* Normalize the mantissa. */ - exp += 15; /* Exponent is encoded with excess 15. */ - - if (exp > 30) /* too big */ - { - ret = 0x7c00; /* INF */ - } - else if (exp <= 0) - { - /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers. */ - while (exp <= 0) - { - mantissa = mantissa >> 1; - ++exp; - } - ret = mantissa & 0x3ff; - } - else - { - ret = (exp << 10) | (mantissa & 0x3ff); - } - - ret |= ((*in < 0.0f ? 1 : 0) << 15); /* Add the sign */ - return ret; -} - static void convert_r32_float_r16_float(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h) { diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index e4fcf18600e..f159224cf91 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -6140,6 +6140,31 @@ void wined3d_format_convert_from_float(const struct wined3d_format *format, cons return; }
+ if ((format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_FLOAT) && format->red_size == 16) + { + uint16_t *ret_s = ret; + + switch (format->byte_count) + { + case 8: + ret_s[3] = float_32_to_16(&color->a); + ret_s[2] = float_32_to_16(&color->b); + /* fall through */ + case 4: + ret_s[1] = float_32_to_16(&color->g); + /* fall through */ + case 2: + ret_s[0] = float_32_to_16(&color->r); + break; + + default: + ERR("Unexpected byte count %u: Format %s\n", format->byte_count, debug_d3dformat(format_id)); + break; + } + + return; + } + FIXME("Conversion for format %s not implemented.\n", debug_d3dformat(format_id)); }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c5c2a51bc5e..82e61a42acf 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -354,13 +354,12 @@ static inline GLenum wined3d_gl_min_mip_filter(enum wined3d_texture_filter_type return minMipLookup[min_filter].mip[mip_filter]; }
-/* float_16_to_32() and float_32_to_16() (see implementation in - * surface_base.c) convert 16 bit floats in the FLOAT16 data type - * to standard C floats and vice versa. They do not depend on the encoding - * of the C float, so they are platform independent, but slow. On x86 and - * other IEEE 754 compliant platforms the conversion can be accelerated by - * bit shifting the exponent and mantissa. There are also some SSE-based - * assembly routines out there. +/* float_16_to_32() and float_32_to_16() convert 16 bit floats in the + * FLOAT16 data type to standard C floats and vice versa. They do not + * depend on the encoding of the C float, so they are platform independent, + * but slow. On x86 and other IEEE 754 compliant platforms the conversion + * can be accelerated by bit shifting the exponent and mantissa. There are + * also some SSE-based assembly routines out there. * * See GL_NV_half_float for a reference of the FLOAT16 / GL_HALF format */ @@ -404,6 +403,68 @@ static inline float float_24_to_32(DWORD in) } }
+static inline unsigned short float_32_to_16(const float *in) +{ + int exp = 0; + float tmp = fabsf(*in); + unsigned int mantissa; + unsigned short ret; + + /* Deal with special numbers */ + if (*in == 0.0f) + return 0x0000; + if (isnan(*in)) + return 0x7c01; + if (isinf(*in)) + return (*in < 0.0f ? 0xfc00 : 0x7c00); + + if (tmp < (float)(1u << 10)) + { + do + { + tmp = tmp * 2.0f; + exp--; + } while (tmp < (float)(1u << 10)); + } + else if (tmp >= (float)(1u << 11)) + { + do + { + tmp /= 2.0f; + exp++; + } while (tmp >= (float)(1u << 11)); + } + + mantissa = (unsigned int)tmp; + if (tmp - mantissa >= 0.5f) + ++mantissa; /* Round to nearest, away from zero. */ + + exp += 10; /* Normalize the mantissa. */ + exp += 15; /* Exponent is encoded with excess 15. */ + + if (exp > 30) /* too big */ + { + ret = 0x7c00; /* INF */ + } + else if (exp <= 0) + { + /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers. */ + while (exp <= 0) + { + mantissa = mantissa >> 1; + ++exp; + } + ret = mantissa & 0x3ff; + } + else + { + ret = (exp << 10) | (mantissa & 0x3ff); + } + + ret |= ((*in < 0.0f ? 1 : 0) << 15); /* Add the sign */ + return ret; +} + static inline unsigned int wined3d_popcount(unsigned int x) { #if defined(__MINGW32__)