diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index d19b681174b..dbcd12a2c0e 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -914,6 +914,17 @@ static BOOL match_broken_arb_fog(const struct wined3d_gl_info *gl_info, struct w return data[0] != 0x00ff0000 || data[3] != 0x0000ff00; } +static BOOL match_broken_viewport_subpixel_bits(const struct wined3d_gl_info *gl_info, + struct wined3d_caps_gl_ctx *ctx, const char *gl_renderer, enum wined3d_gl_vendor gl_vendor, + enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device) +{ + if (!gl_info->supported[ARB_VIEWPORT_ARRAY]) + return FALSE; + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) + return FALSE; + return !wined3d_caps_gl_ctx_test_viewport_subpixel_bits(ctx); +} + static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info) { /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms. @@ -1042,6 +1053,17 @@ static void quirk_broken_arb_fog(struct wined3d_gl_info *gl_info) gl_info->quirks |= WINED3D_QUIRK_BROKEN_ARB_FOG; } +static void quirk_broken_viewport_subpixel_bits(struct wined3d_gl_info *gl_info) +{ + TRACE("Disabling ARB_viewport_array.\n"); + gl_info->supported[ARB_VIEWPORT_ARRAY] = FALSE; + if (gl_info->supported[ARB_CLIP_CONTROL]) + { + TRACE("Disabling ARB_clip_control.\n"); + gl_info->supported[ARB_CLIP_CONTROL] = FALSE; + } +} + struct driver_quirk { BOOL (*match)(const struct wined3d_gl_info *gl_info, struct wined3d_caps_gl_ctx *ctx, @@ -1133,6 +1155,11 @@ static const struct driver_quirk quirk_table[] = quirk_broken_arb_fog, "ARBfp fogstart == fogend workaround" }, + { + match_broken_viewport_subpixel_bits, + quirk_broken_viewport_subpixel_bits, + "Nvidia viewport subpixel bits bug" + }, }; /* Certain applications (Steam) complain if we report an outdated driver version. In general, diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index b0767834710..c392388129f 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -3509,6 +3509,53 @@ fail: return FALSE; } +BOOL wined3d_caps_gl_ctx_test_viewport_subpixel_bits(struct wined3d_caps_gl_ctx *ctx) +{ + static const struct wined3d_color red = {1.0f, 0.0f, 0.0f, 1.0f}; + const struct wined3d_gl_info *gl_info = ctx->gl_info; + static const float offset = -63.0f / 128.0f; + GLuint texture, fbo; + DWORD readback[4]; + unsigned int i; + + gl_info->gl_ops.gl.p_glGenTextures(1, &texture); + gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, texture); + gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ARRAY_SIZE(readback), 1, 0, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + gl_info->fbo_ops.glGenFramebuffers(1, &fbo); + gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo); + gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, texture, 0); + checkGLcall("create resources"); + + gl_info->gl_ops.gl.p_glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT); + GL_EXTCALL(glViewportIndexedf(0, offset, offset, 4.0f, 1.0f)); + draw_test_quad(ctx, NULL, &red); + checkGLcall("draw"); + + gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, texture); + gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback); + checkGLcall("readback"); + + TRACE("Readback colors are 0x%08x, 0x%08x, 0x%08x, 0x%08x.\n", + readback[0], readback[1], readback[2], readback[3]); + + gl_info->gl_ops.gl.p_glDeleteTextures(1, &texture); + gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo); + gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0); + checkGLcall("delete resources"); + + for (i = 0; i < ARRAY_SIZE(readback); ++i) + { + if (readback[i] != 0xffff0000) + return FALSE; + } + return TRUE; +} + float wined3d_adapter_find_polyoffset_scale(struct wined3d_caps_gl_ctx *ctx, GLenum format) { const struct wined3d_gl_info *gl_info = ctx->gl_info; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 611b3b62a8c..613d1c91006 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2354,6 +2354,8 @@ BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter, struct wined3d_caps_gl_ctx *ctx) DECLSPEC_HIDDEN; UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, INT64 amount) DECLSPEC_HIDDEN; +BOOL wined3d_caps_gl_ctx_test_viewport_subpixel_bits(struct wined3d_caps_gl_ctx *ctx) DECLSPEC_HIDDEN; + void install_gl_compat_wrapper(struct wined3d_gl_info *gl_info, enum wined3d_gl_extension ext) DECLSPEC_HIDDEN; enum projection_types