From 26a53f674c234aaba4a85ec36bae48384899b705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Wed, 3 Nov 2021 20:15:30 +0300 Subject: [PATCH] wined3d: Emulate fractional viewports if GL doesn't support them. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows test_fractional_viewports to pass regardless of GL capabilies. I don't think we can get rid of WINED3D_PIXEL_CENTER_INTEGER (and add +0.5 in the client libs) due to vpos in d3d9 shaders. Signed-off-by: Stefan Dösinger Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/adapter_gl.c | 3 +++ dlls/wined3d/adapter_vk.c | 1 + dlls/wined3d/state.c | 16 ++++++++++++++++ dlls/wined3d/wined3d_private.h | 14 +++++++++++--- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 2a91418b0d0..7ec30cb4356 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -991,6 +991,7 @@ static void quirk_broken_arb_fog(struct wined3d_gl_info *gl_info) static void quirk_broken_viewport_subpixel_bits(struct wined3d_gl_info *gl_info) { + gl_info->limits.viewport_subpixel_bits = 0; if (gl_info->supported[ARB_CLIP_CONTROL]) { TRACE("Disabling ARB_clip_control.\n"); @@ -3655,6 +3656,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, TRACE("Disabling ARB_clip_control because viewport subpixel bits < 8.\n"); gl_info->supported[ARB_CLIP_CONTROL] = FALSE; } + gl_info->limits.viewport_subpixel_bits = subpixel_bits; } if (gl_info->supported[ARB_CLIP_CONTROL] && !gl_info->supported[ARB_VIEWPORT_ARRAY]) { @@ -5141,6 +5143,7 @@ static void wined3d_adapter_gl_init_d3d_info(struct wined3d_adapter_gl *adapter_ d3d_info->full_ffp_varyings = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_FULL_FFP_VARYINGS); d3d_info->scaled_resolve = !!gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE_BLIT_SCALED]; d3d_info->pbo = !!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]; + d3d_info->subpixel_viewport = gl_info->limits.viewport_subpixel_bits >= 8; d3d_info->feature_level = feature_level_from_caps(gl_info, &shader_caps, &fragment_caps); d3d_info->filling_convention_offset = gl_info->filling_convention_offset; diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index ac768f8304f..2bd3aa31e49 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2257,6 +2257,7 @@ static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_ d3d_info->scaled_resolve = false; d3d_info->pbo = true; d3d_info->feature_level = feature_level_from_caps(&shader_caps); + d3d_info->subpixel_viewport = true; /* Like GL, Vulkan doesn't explicitly specify a filling convention and only mandates that a * shared edge of two adjacent triangles generate a fragment for exactly one of the triangles. diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 901771fdcc1..5e41f681c75 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -4208,6 +4208,22 @@ static void viewport_miscpart(struct wined3d_context *context, const struct wine viewports[i * 4 + 1] = vp[i].y; viewports[i * 4 + 2] = vp[i].width; viewports[i * 4 + 3] = vp[i].height; + + /* Don't pass fractionals to GL if we earlier decided not to use + * this functionality for two reasons: First, GL might offer us + * fewer than 8 bits, and still make use of the fractional, in + * addition to the emulation we apply in shader_get_position_fixup. + * Second, even if GL tells us it has no subpixel precision (Mac OS!) + * it might still do something with the fractional amount, e.g. + * round it upwards. I can't find any info on rounding in + * GL_ARB_viewport_array. */ + if (!context->d3d_info->subpixel_viewport) + { + viewports[i * 4] = floor(viewports[i * 4]); + viewports[i * 4 + 1] = floor(viewports[i * 4 + 1]); + viewports[i * 4 + 2] = floor(viewports[i * 4 + 2]); + viewports[i * 4 + 3] = floor(viewports[i * 4 + 3]); + } } if (context->viewport_count > state->viewport_count) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 6e0ab1ab499..8da8a60d28e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -240,6 +240,7 @@ struct wined3d_d3d_info uint32_t full_ffp_varyings : 1; uint32_t scaled_resolve : 1; uint32_t pbo : 1; + uint32_t subpixel_viewport : 1; enum wined3d_feature_level feature_level; DWORD multisample_draw_location; @@ -3237,6 +3238,7 @@ struct wined3d_gl_limits unsigned int framebuffer_width; unsigned int framebuffer_height; + unsigned int viewport_subpixel_bits; UINT glsl_varyings; UINT glsl_vs_float_constants; @@ -5771,7 +5773,7 @@ static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg) static inline void shader_get_position_fixup(const struct wined3d_context *context, const struct wined3d_state *state, unsigned int fixup_count, float *position_fixup) { - float center_offset; + float center_offset, x = 0.0f, y = 0.0f; unsigned int i; /* See get_projection_matrix() in utils.c for a discussion of the position fixup. @@ -5788,8 +5790,14 @@ static inline void shader_get_position_fixup(const struct wined3d_context *conte { position_fixup[4 * i ] = 1.0f; position_fixup[4 * i + 1] = 1.0f; - position_fixup[4 * i + 2] = center_offset / state->viewports[i].width; - position_fixup[4 * i + 3] = -center_offset / state->viewports[i].height; + if (!context->d3d_info->subpixel_viewport) + { + double dummy; + x = modf(state->viewports[i].x, &dummy) * 2.0f; + y = modf(state->viewports[i].y, &dummy) * 2.0f; + } + position_fixup[4 * i + 2] = (center_offset + x) / state->viewports[i].width; + position_fixup[4 * i + 3] = -(center_offset + y) / state->viewports[i].height; if (context->render_offscreen) {