[PATCH 3/4] wined3d: Check resource types separately in check_fbo_compat.

Stefan Dösinger stefan at codeweavers.com
Sat May 16 08:29:14 CDT 2015


---
 dlls/wined3d/utils.c | 511 ++++++++++++++++++++++++++++++++-------------------
 1 file changed, 327 insertions(+), 184 deletions(-)

diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 94ed858..f0eb4f4 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -1401,6 +1401,124 @@ static BOOL init_format_block_info(struct wined3d_gl_info *gl_info)
     return TRUE;
 }
 
+static GLenum wined3d_gl_type_to_enum(enum wined3d_gl_resource_type type)
+{
+    switch (type)
+    {
+        case WINED3D_GL_RES_TYPE_TEX_1D:
+            return GL_TEXTURE_1D;
+        case WINED3D_GL_RES_TYPE_TEX_2D:
+            return GL_TEXTURE_2D;
+        case WINED3D_GL_RES_TYPE_TEX_3D:
+            return GL_TEXTURE_3D;
+        case WINED3D_GL_RES_TYPE_TEX_CUBE:
+            return GL_TEXTURE_CUBE_MAP_ARB;
+        case WINED3D_GL_RES_TYPE_TEX_RECT:
+            return GL_TEXTURE_RECTANGLE_ARB;
+        case WINED3D_GL_RES_TYPE_BUFFER:
+            return GL_TEXTURE_2D; /* TODO: GL_TEXTURE_BUFFER. */
+        case WINED3D_GL_RES_TYPE_COUNT:
+            break;
+    }
+    ERR("Unexpected GL resource type %u.\n", type);
+    return 0;
+}
+
+static void delete_fbo_attachment(const struct wined3d_gl_info *gl_info,
+        enum wined3d_gl_resource_type d3d_type)
+{
+    switch (d3d_type)
+    {
+        case WINED3D_GL_RES_TYPE_TEX_1D:
+            gl_info->fbo_ops.glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_1D, 0, 0);
+            break;
+
+        case WINED3D_GL_RES_TYPE_TEX_2D:
+        case WINED3D_GL_RES_TYPE_TEX_RECT:
+            gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                    wined3d_gl_type_to_enum(d3d_type), 0, 0);
+            break;
+
+        case WINED3D_GL_RES_TYPE_TEX_3D:
+            gl_info->fbo_ops.glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, 0, 0, 0);
+            break;
+
+        case WINED3D_GL_RES_TYPE_TEX_CUBE:
+            gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                    GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, 0);
+            break;
+
+        case WINED3D_GL_RES_TYPE_BUFFER:
+        case WINED3D_GL_RES_TYPE_COUNT:
+            break;
+    }
+}
+
+/* Context activation is done by the caller. */
+static void create_and_bind_fbo_attachment(const struct wined3d_gl_info *gl_info,
+        enum wined3d_gl_resource_type d3d_type, GLuint tex, GLenum internal, GLenum format, GLenum type)
+{
+    switch (d3d_type)
+    {
+        case WINED3D_GL_RES_TYPE_TEX_1D:
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, tex);
+            gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, internal, 16, 0, format, type, NULL);
+            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+            gl_info->fbo_ops.glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_1D, tex, 0);
+            break;
+
+        case WINED3D_GL_RES_TYPE_TEX_2D:
+        case WINED3D_GL_RES_TYPE_TEX_RECT:
+            gl_info->gl_ops.gl.p_glBindTexture(wined3d_gl_type_to_enum(d3d_type), tex);
+            gl_info->gl_ops.gl.p_glTexImage2D(wined3d_gl_type_to_enum(d3d_type), 0, internal, 16, 16, 0,
+                    format, type, NULL);
+            gl_info->gl_ops.gl.p_glTexParameteri(wined3d_gl_type_to_enum(d3d_type), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            gl_info->gl_ops.gl.p_glTexParameteri(wined3d_gl_type_to_enum(d3d_type), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+            gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                    wined3d_gl_type_to_enum(d3d_type), tex, 0);
+            break;
+
+        case WINED3D_GL_RES_TYPE_TEX_3D:
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, tex);
+            GL_EXTCALL(glTexImage3D)(GL_TEXTURE_3D, 0, internal, 16, 16, 16, 0,
+                    format, type, NULL);
+            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+            gl_info->fbo_ops.glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                    GL_TEXTURE_3D, tex, 0, 0);
+            break;
+
+        case WINED3D_GL_RES_TYPE_TEX_CUBE:
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, tex);
+            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, internal, 16, 16, 0,
+                    format, type, NULL);
+            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, internal, 16, 16, 0,
+                    format, type, NULL);
+            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, internal, 16, 16, 0,
+                    format, type, NULL);
+            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, internal, 16, 16, 0,
+                    format, type, NULL);
+            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, internal, 16, 16, 0,
+                    format, type, NULL);
+            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, internal, 16, 16, 0,
+                    format, type, NULL);
+            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+            gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                    GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, tex, 0);
+            break;
+
+        case WINED3D_GL_RES_TYPE_BUFFER:
+        case WINED3D_GL_RES_TYPE_COUNT:
+            break;
+    }
+}
+
 /* Context activation is done by the caller. */
 static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined3d_format *format)
 {
@@ -1408,230 +1526,255 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
      * target, otherwise fall back to the render target internal.
      *
      * Try to stick to the standard format if possible, this limits precision differences. */
-    GLenum status;
+    GLenum status, rt_internal = format->rtInternal;
     GLuint tex;
+    enum wined3d_gl_resource_type type;
+    BOOL fallback_fmt_used = FALSE, regular_fmt_used = FALSE;
 
-    while (gl_info->gl_ops.gl.p_glGetError());
     gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
 
-    gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
-    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
+    for (type = 0; type < ARRAY_SIZE(format->flags); ++type)
+    {
+        if (type == WINED3D_GL_RES_TYPE_BUFFER)
+            continue;
 
-    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->glInternal, 16, 16, 0,
-            format->glFormat, format->glType, NULL);
-    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        /* Ideally we'd skip all formats already known not to work on textures
+         * by checking for WINED3DFMT_FLAG_TEXTURE here. However, we want to
+         * know if we can attach WINED3DFMT_P8_UINT textures to FBOs, and this
+         * format never has WINED3DFMT_FLAG_TEXTURE set. Instead, swallow GL
+         * errors generated by invalid formats. */
 
-    gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+        gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
+        create_and_bind_fbo_attachment(gl_info, type, tex, format->glInternal,
+                format->glFormat, format->glType);
+        while (gl_info->gl_ops.gl.p_glGetError());
 
-    status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
-    checkGLcall("Framebuffer format check");
+        status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+        checkGLcall("Framebuffer format check");
 
-    if (status == GL_FRAMEBUFFER_COMPLETE)
-    {
-        TRACE("Format %s is supported as FBO color attachment.\n", debug_d3dformat(format->id));
-        format_set_flag(format, WINED3DFMT_FLAG_FBO_ATTACHABLE);
-        format->rtInternal = format->glInternal;
-    }
-    else
-    {
-        if (!format->rtInternal)
+        if (status == GL_FRAMEBUFFER_COMPLETE)
         {
-            if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_RENDERTARGET)
-            {
-                FIXME("Format %s with rendertarget flag is not supported as FBO color attachment,"
-                        " and no fallback specified.\n", debug_d3dformat(format->id));
-                format_clear_flag(format, WINED3DFMT_FLAG_RENDERTARGET);
-            }
-            else
-            {
-                TRACE("Format %s is not supported as FBO color attachment.\n", debug_d3dformat(format->id));
-            }
+            TRACE("Format %s is supported as FBO color attachment, type %u.\n",
+                    debug_d3dformat(format->id), type);
+            format->flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE;
             format->rtInternal = format->glInternal;
+            regular_fmt_used = TRUE;
         }
         else
         {
-            TRACE("Format %s is not supported as FBO color attachment, trying rtInternal format as fallback.\n",
-                    debug_d3dformat(format->id));
+            if (!rt_internal)
+            {
+                if (format->flags[type] & WINED3DFMT_FLAG_RENDERTARGET)
+                {
+                    FIXME("Format %s with rendertarget flag is not supported as FBO color attachment (type %u),"
+                            " and no fallback specified.\n", debug_d3dformat(format->id), type);
+                    format->flags[type] &= ~WINED3DFMT_FLAG_RENDERTARGET;
+                }
+                else
+                {
+                    TRACE("Format %s is not supported as FBO color attachment, type %u.\n",
+                            debug_d3dformat(format->id), type);
+                }
+                format->rtInternal = format->glInternal;
+            }
+            else
+            {
+                TRACE("Format %s is not supported as FBO color attachment (type %u),"
+                        " trying rtInternal format as fallback.\n", debug_d3dformat(format->id), type);
 
-            while (gl_info->gl_ops.gl.p_glGetError());
+                while (gl_info->gl_ops.gl.p_glGetError());
 
-            gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+                delete_fbo_attachment(gl_info, type);
+                create_and_bind_fbo_attachment(gl_info, type, tex, format->rtInternal,
+                        format->glFormat, format->glType);
 
-            gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->rtInternal, 16, 16, 0,
-                    format->glFormat, format->glType, NULL);
-            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-            gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+                status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+                checkGLcall("Framebuffer format check");
 
-            gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+                if (status == GL_FRAMEBUFFER_COMPLETE)
+                {
+                    TRACE("Format %s rtInternal format is supported as FBO color attachment, type %u.\n",
+                            debug_d3dformat(format->id), type);
+                    fallback_fmt_used = TRUE;
+                }
+                else
+                {
+                    FIXME("Format %s rtInternal format is not supported as FBO color attachment, type %u.\n",
+                            debug_d3dformat(format->id), type);
+                    format->flags[type] &= ~WINED3DFMT_FLAG_RENDERTARGET;
+                }
+            }
+        }
 
-            status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
-            checkGLcall("Framebuffer format check");
+        if (status == GL_FRAMEBUFFER_COMPLETE
+                && ((format->flags[type] & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)
+                || !(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
+                && format->id != WINED3DFMT_NULL && format->id != WINED3DFMT_P8_UINT
+                && format->glFormat != GL_LUMINANCE && format->glFormat != GL_LUMINANCE_ALPHA
+                && (format->red_size || format->alpha_size))
+        {
+            DWORD readback[16 * 16 * 16], color, r_range, a_range;
+            BYTE r, a;
+            BOOL match = TRUE;
+            GLuint rb;
 
-            if (status == GL_FRAMEBUFFER_COMPLETE)
+            if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
+                    || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
             {
-                TRACE("Format %s rtInternal format is supported as FBO color attachment.\n",
-                        debug_d3dformat(format->id));
+                gl_info->fbo_ops.glGenRenderbuffers(1, &rb);
+                gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, rb);
+                if (type == WINED3D_GL_RES_TYPE_TEX_1D)
+                    gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 1);
+                else
+                    gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
+                gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);
+                gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb);
+                checkGLcall("RB attachment");
             }
-            else
+
+            gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
+            gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+            gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
+            if (gl_info->gl_ops.gl.p_glGetError() == GL_INVALID_FRAMEBUFFER_OPERATION)
             {
-                FIXME("Format %s rtInternal format is not supported as FBO color attachment.\n",
-                        debug_d3dformat(format->id));
-                format_clear_flag(format, WINED3DFMT_FLAG_RENDERTARGET);
+                while (gl_info->gl_ops.gl.p_glGetError());
+                TRACE("Format %s doesn't support post-pixelshader blending, type %u.\n",
+                        debug_d3dformat(format->id), type);
+                format->flags[type] &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
             }
-        }
-    }
+            else
+            {
+                gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+                gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 16);
+                gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
+                gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+                gl_info->gl_ops.gl.p_glLoadIdentity();
+                gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
+                gl_info->gl_ops.gl.p_glLoadIdentity();
+
+                gl_info->gl_ops.gl.p_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+                /* Draw a full-black quad */
+                gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+                gl_info->gl_ops.gl.p_glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
+                gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
+                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
+                gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
+                gl_info->gl_ops.gl.p_glEnd();
+
+                gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
+                /* Draw a half-transparent red quad */
+                gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+                gl_info->gl_ops.gl.p_glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
+                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
+                gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
+                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
+                gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
+                gl_info->gl_ops.gl.p_glEnd();
+
+                gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+
+                /* Rebinding texture to workaround a fglrx bug. */
+                gl_info->gl_ops.gl.p_glBindTexture(wined3d_gl_type_to_enum(type), tex);
+                switch (type)
+                {
+                    case WINED3D_GL_RES_TYPE_TEX_1D:
+                        gl_info->gl_ops.gl.p_glGetTexImage(wined3d_gl_type_to_enum(type), 0, GL_BGRA,
+                                GL_UNSIGNED_INT_8_8_8_8_REV, readback);
+                        color = readback[7];
+                        break;
 
-    if (status == GL_FRAMEBUFFER_COMPLETE
-            && ((format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)
-            || !(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
-            && format->id != WINED3DFMT_NULL && format->id != WINED3DFMT_P8_UINT
-            && format->glFormat != GL_LUMINANCE && format->glFormat != GL_LUMINANCE_ALPHA
-            && (format->red_size || format->alpha_size))
-    {
-        DWORD readback[16 * 16], color, r_range, a_range;
-        BYTE r, a;
-        BOOL match = TRUE;
-        GLuint rb;
+                    case WINED3D_GL_RES_TYPE_TEX_2D:
+                    case WINED3D_GL_RES_TYPE_TEX_3D:
+                    case WINED3D_GL_RES_TYPE_TEX_RECT:
+                        gl_info->gl_ops.gl.p_glGetTexImage(wined3d_gl_type_to_enum(type), 0, GL_BGRA,
+                                GL_UNSIGNED_INT_8_8_8_8_REV, readback);
+                        color = readback[7 * 16 + 7];
+                        break;
 
-        if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
-                || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
-        {
-            gl_info->fbo_ops.glGenRenderbuffers(1, &rb);
-            gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, rb);
-            gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
-            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);
-            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb);
-            checkGLcall("RB attachment");
-        }
+                    case WINED3D_GL_RES_TYPE_TEX_CUBE:
+                        gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_BGRA,
+                                GL_UNSIGNED_INT_8_8_8_8_REV, readback);
+                        color = readback[7 * 16 + 7];
+                        break;
 
-        gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
-        gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-        gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
-        if (gl_info->gl_ops.gl.p_glGetError() == GL_INVALID_FRAMEBUFFER_OPERATION)
-        {
-            while (gl_info->gl_ops.gl.p_glGetError());
-            TRACE("Format doesn't support post-pixelshader blending.\n");
-            format_clear_flag(format, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING);
+                    case WINED3D_GL_RES_TYPE_BUFFER:
+                    case WINED3D_GL_RES_TYPE_COUNT:
+                        break;
+                }
+                checkGLcall("Post-pixelshader blending check");
+
+                a = color >> 24;
+                r = (color & 0x00ff0000) >> 16;
+
+                r_range = format->red_size < 8 ? 1 << (8 - format->red_size) : 1;
+                a_range = format->alpha_size < 8 ? 1 << (8 - format->alpha_size) : 1;
+                if (format->red_size && (r < 0x7f - r_range || r > 0x7f + r_range))
+                    match = FALSE;
+                else if (format->alpha_size > 1 && (a < 0xbf - a_range || a > 0xbf + a_range))
+                    match = FALSE;
+                if (!match)
+                {
+                    TRACE("Format %s doesn't support post-pixelshader blending, type %u.\n",
+                            debug_d3dformat(format->id), type);
+                    TRACE("Color output: %#x\n", color);
+                    format->flags[type] &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
+                }
+                else
+                {
+                    TRACE("Format %s supports post-pixelshader blending, type %u.\n",
+                            debug_d3dformat(format->id), type);
+                    TRACE("Color output: %#x\n", color);
+                    format->flags[type] |= WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
+                }
+            }
+
+            if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
+                    || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
+            {
+                gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+                gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
+                gl_info->fbo_ops.glDeleteRenderbuffers(1, &rb);
+                checkGLcall("RB cleanup");
+            }
         }
-        else
+
+        if (format->glInternal != format->glGammaInternal)
         {
-            gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
-            gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 16);
-            gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
-            gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
-            gl_info->gl_ops.gl.p_glLoadIdentity();
-            gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
-            gl_info->gl_ops.gl.p_glLoadIdentity();
-
-            gl_info->gl_ops.gl.p_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-            /* Draw a full-black quad */
-            gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
-            gl_info->gl_ops.gl.p_glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
-            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
-            gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
-            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
-            gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
-            gl_info->gl_ops.gl.p_glEnd();
+            delete_fbo_attachment(gl_info, type);
+            create_and_bind_fbo_attachment(gl_info, type, tex, format->glGammaInternal,
+                    format->glFormat, format->glType);
 
-            gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
-            /* Draw a half-transparent red quad */
-            gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
-            gl_info->gl_ops.gl.p_glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
-            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
-            gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
-            gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
-            gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
-            gl_info->gl_ops.gl.p_glEnd();
-
-            gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
-
-            /* Rebinding texture to workaround a fglrx bug. */
-            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
-            gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
-            checkGLcall("Post-pixelshader blending check");
-
-            color = readback[7 * 16 + 7];
-            a = color >> 24;
-            r = (color & 0x00ff0000) >> 16;
-
-            r_range = format->red_size < 8 ? 1 << (8 - format->red_size) : 1;
-            a_range = format->alpha_size < 8 ? 1 << (8 - format->alpha_size) : 1;
-            if (format->red_size && (r < 0x7f - r_range || r > 0x7f + r_range))
-                match = FALSE;
-            else if (format->alpha_size > 1 && (a < 0xbf - a_range || a > 0xbf + a_range))
-                match = FALSE;
-            if (!match)
+            status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+            checkGLcall("Framebuffer format check");
+
+            if (status == GL_FRAMEBUFFER_COMPLETE)
             {
-                TRACE("Format doesn't support post-pixelshader blending.\n");
-                TRACE("Color output: %#x\n", color);
-                format_clear_flag(format, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING);
+                TRACE("Format %s's sRGB format is FBO attachable, type %u.\n",
+                        debug_d3dformat(format->id), type);
+                format->flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
             }
             else
             {
-                TRACE("Format supports post-pixelshader blending.\n");
-                TRACE("Color output: %#x\n", color);
-                format_set_flag(format, WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING);
+                WARN("Format %s's sRGB format is not FBO attachable, type %u.\n",
+                        debug_d3dformat(format->id), type);
             }
         }
+        else if (status == GL_FRAMEBUFFER_COMPLETE)
+            format->flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
 
-        if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
-                || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
-        {
-            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
-            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
-            gl_info->fbo_ops.glDeleteRenderbuffers(1, &rb);
-            checkGLcall("RB cleanup");
-        }
-    }
-
-    if (format->glInternal != format->glGammaInternal)
-    {
-        gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->glGammaInternal, 16, 16, 0,
-                format->glFormat, format->glType, NULL);
-        gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
-
-        status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
-        checkGLcall("Framebuffer format check");
-
-        if (status == GL_FRAMEBUFFER_COMPLETE)
-        {
-            TRACE("Format %s's sRGB format is FBO attachable.\n", debug_d3dformat(format->id));
-            format_set_flag(format, WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB);
-        }
-        else
-        {
-            WARN("Format %s's sRGB format is not FBO attachable.\n", debug_d3dformat(format->id));
-        }
+        delete_fbo_attachment(gl_info, type);
+        gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
     }
-    else if (status == GL_FRAMEBUFFER_COMPLETE)
-        format_set_flag(format, WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB);
-
-    gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
-}
 
-static GLenum wined3d_gl_type_to_enum(enum wined3d_gl_resource_type type)
-{
-    switch (type)
+    if (fallback_fmt_used && regular_fmt_used)
     {
-        case WINED3D_GL_RES_TYPE_TEX_1D:
-            return GL_TEXTURE_1D;
-        case WINED3D_GL_RES_TYPE_TEX_2D:
-            return GL_TEXTURE_2D;
-        case WINED3D_GL_RES_TYPE_TEX_3D:
-            return GL_TEXTURE_3D;
-        case WINED3D_GL_RES_TYPE_TEX_CUBE:
-            return GL_TEXTURE_CUBE_MAP_ARB;
-        case WINED3D_GL_RES_TYPE_TEX_RECT:
-            return GL_TEXTURE_RECTANGLE_ARB;
-        case WINED3D_GL_RES_TYPE_BUFFER:
-            return GL_TEXTURE_2D; /* TODO: GL_TEXTURE_BUFFER. */
-        case WINED3D_GL_RES_TYPE_COUNT:
-            break;
+        FIXME("Format %s needs different render target formats for different resource types.\n",
+                debug_d3dformat(format->id));
+        format_clear_flag(format, WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_FBO_ATTACHABLE
+                | WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING);
     }
-    ERR("Unexpected GL resource type %u.\n", type);
-    return 0;
 }
 
 static void query_format_flag(struct wined3d_gl_info *gl_info, struct wined3d_format *format,
-- 
2.3.6




More information about the wine-patches mailing list