[PATCH 3/8] wined3d: Keep track of renderbuffer capabilities.

Stefan Dösinger stefan at codeweavers.com
Fri May 22 03:11:23 CDT 2015


According to EXT_framebuffer_object we don't have to explicitly detach
images attached to the currently bound framebuffer before destroying
them. The same language is used in ARB_framebuffer_object.
---
 dlls/wined3d/arb_program_shader.c |  8 ++++
 dlls/wined3d/directx.c            |  4 +-
 dlls/wined3d/glsl_shader.c        |  8 ++++
 dlls/wined3d/texture.c            | 17 ++++++--
 dlls/wined3d/utils.c              | 92 +++++++++++++++++++++++++++++----------
 dlls/wined3d/wined3d_private.h    |  3 +-
 6 files changed, 102 insertions(+), 30 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 1e8784e..0a73b40 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -3390,6 +3390,10 @@ static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_i
         "TEX R0.x, fragment.texcoord[0], texture[0], RECT;\n"
         "MOV result.depth.z, R0.x;\n"
         "END\n",
+        /* WINED3D_GL_RES_TYPE_BUFFER */
+        NULL,
+        /* WINED3D_GL_RES_TYPE_RB */
+        NULL,
     };
 
     static const char * const blt_fprograms_masked[WINED3D_GL_RES_TYPE_COUNT] =
@@ -3428,6 +3432,10 @@ static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_i
         "TEX R0.x, fragment.texcoord[0], texture[0], RECT;\n"
         "MOV result.depth.z, R0.x;\n"
         "END\n",
+        /* WINED3D_GL_RES_TYPE_BUFFER */
+        NULL,
+        /* WINED3D_GL_RES_TYPE_RB */
+        NULL,
     };
 
     fprogram = masked ? blt_fprograms_masked[tex_type] : blt_fprograms_full[tex_type];
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index eb749ea..af3251c 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -4384,6 +4384,8 @@ static BOOL CheckSurfaceCapability(const struct wined3d_adapter *adapter,
     /* All depth stencil formats are supported on surfaces */
     if (CheckDepthStencilCapability(adapter, adapter_format, check_format, WINED3D_GL_RES_TYPE_TEX_2D))
         return TRUE;
+    if (CheckDepthStencilCapability(adapter, adapter_format, check_format, WINED3D_GL_RES_TYPE_RB))
+        return TRUE;
 
     /* If opengl can't process the format natively, the blitter may be able to convert it */
     if (adapter->blitter->blit_supported(&adapter->gl_info, &adapter->d3d_info,
@@ -4456,7 +4458,7 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad
             allowed_usage = WINED3DUSAGE_DEPTHSTENCIL
                     | WINED3DUSAGE_RENDERTARGET
                     | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
-            gl_type = WINED3D_GL_RES_TYPE_TEX_2D;
+            gl_type = WINED3D_GL_RES_TYPE_RB;
             break;
 
         case WINED3D_RTYPE_TEXTURE:
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index c85508c..b17306b 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -6856,6 +6856,10 @@ static GLuint create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, enum
         "{\n"
         "    gl_FragDepth = texture2DRect(sampler, gl_TexCoord[0].xy).x;\n"
         "}\n",
+        /* WINED3D_GL_RES_TYPE_BUFFER */
+        NULL,
+        /* WINED3D_GL_RES_TYPE_RB */
+        NULL,
     };
 
     static const char * const blt_pshaders_masked[WINED3D_GL_RES_TYPE_COUNT] =
@@ -6892,6 +6896,10 @@ static GLuint create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, enum
         "    if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n"
         "    gl_FragDepth = texture2DRect(sampler, gl_TexCoord[0].xy).x;\n"
         "}\n",
+        /* WINED3D_GL_RES_TYPE_BUFFER */
+        NULL,
+        /* WINED3D_GL_RES_TYPE_RB */
+        NULL,
     };
 
     blt_pshader = masked ? blt_pshaders_masked[tex_type] : blt_pshaders_full[tex_type];
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 916bcb2..8184e6d 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -1067,6 +1067,12 @@ static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wi
     return WINED3D_OK;
 }
 
+static BOOL check_ds_support(const struct wined3d_format *format, unsigned int type, DWORD d3d_usage)
+{
+    return !(d3d_usage & WINED3DUSAGE_DEPTHSTENCIL)
+            || (format->flags[type] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL));
+}
+
 static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc,
         UINT levels, DWORD surface_flags, struct wined3d_device *device, void *parent,
         const struct wined3d_parent_ops *parent_ops)
@@ -1077,7 +1083,7 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
     unsigned int i;
     HRESULT hr;
     enum wined3d_gl_resource_type gl_type;
-    unsigned int required_flags = 0, ds_flags = WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL;
+    unsigned int required_flags = 0;
     const struct wined3d_format *format;
 
     /* TODO: It should only be possible to create textures for formats
@@ -1145,18 +1151,21 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
     /* WINED3DUSAGE_DEPTHSTENCIL needs WINED3DFMT_FLAG_DEPTH or WINED3DFMT_FLAG_STENCIL, not both. */
 
     if ((format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & required_flags) == required_flags
-            && (!(desc->usage & WINED3DUSAGE_DEPTHSTENCIL) || (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & ds_flags))
+            && check_ds_support(format, WINED3D_GL_RES_TYPE_TEX_2D, desc->usage)
             && (gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT]
             || (desc->width == pow2_width && desc->height == pow2_height)))
         gl_type = WINED3D_GL_RES_TYPE_TEX_2D;
     else if ((format->flags[WINED3D_GL_RES_TYPE_TEX_RECT] & required_flags) == required_flags
-            && (!(desc->usage & WINED3DUSAGE_DEPTHSTENCIL) || (format->flags[WINED3D_GL_RES_TYPE_TEX_RECT] & ds_flags)))
+            && check_ds_support(format, WINED3D_GL_RES_TYPE_TEX_RECT, desc->usage))
         gl_type = WINED3D_GL_RES_TYPE_TEX_RECT;
+    else if ((format->flags[WINED3D_GL_RES_TYPE_RB] & required_flags) == required_flags
+            && check_ds_support(format, WINED3D_GL_RES_TYPE_RB, desc->usage))
+        gl_type = WINED3D_GL_RES_TYPE_RB;
     else
         gl_type = WINED3D_GL_RES_TYPE_TEX_2D; /* No error, may be SCRATCH pool or emulated conditional np2. */
 
     if (FAILED(hr = wined3d_texture_init(texture, &texture2d_ops, 1, levels, desc,
-            surface_flags, WINED3D_GL_RES_TYPE_TEX_2D, device, parent, parent_ops, &texture_resource_ops)))
+            surface_flags, gl_type, device, parent, parent_ops, &texture_resource_ops)))
     {
         WARN("Failed to initialize texture, returning %#x.\n", hr);
         return hr;
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index bd9b710..106a88e 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -1417,6 +1417,8 @@ static GLenum wined3d_gl_type_to_enum(enum wined3d_gl_resource_type type)
             return GL_TEXTURE_RECTANGLE_ARB;
         case WINED3D_GL_RES_TYPE_BUFFER:
             return GL_TEXTURE_2D; /* TODO: GL_TEXTURE_BUFFER. */
+        case WINED3D_GL_RES_TYPE_RB:
+            return GL_RENDERBUFFER;
         case WINED3D_GL_RES_TYPE_COUNT:
             break;
     }
@@ -1424,52 +1426,74 @@ static GLenum wined3d_gl_type_to_enum(enum wined3d_gl_resource_type type)
     return 0;
 }
 
-static void delete_fbo_attachment(const struct wined3d_gl_info *gl_info)
+static void delete_fbo_attachment(const struct wined3d_gl_info *gl_info,
+        enum wined3d_gl_resource_type d3d_type, GLuint *object)
 {
-    gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-            GL_TEXTURE_2D, 0, 0);
+    switch (d3d_type)
+    {
+        case WINED3D_GL_RES_TYPE_TEX_1D:
+        case WINED3D_GL_RES_TYPE_TEX_2D:
+        case WINED3D_GL_RES_TYPE_TEX_RECT:
+        case WINED3D_GL_RES_TYPE_TEX_3D:
+        case WINED3D_GL_RES_TYPE_TEX_CUBE:
+            gl_info->gl_ops.gl.p_glDeleteTextures(1, object);
+            break;
+
+        case WINED3D_GL_RES_TYPE_RB:
+            gl_info->fbo_ops.glDeleteRenderbuffers(1, object);
+            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)
+        enum wined3d_gl_resource_type d3d_type, GLuint *object, 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_glGenTextures(1, object);
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, *object);
             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);
+            gl_info->fbo_ops.glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_1D,
+                    *object, 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_glGenTextures(1, object);
+            gl_info->gl_ops.gl.p_glBindTexture(wined3d_gl_type_to_enum(d3d_type), *object);
             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);
+                    wined3d_gl_type_to_enum(d3d_type), *object, 0);
             break;
 
         case WINED3D_GL_RES_TYPE_TEX_3D:
-            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, tex);
+            gl_info->gl_ops.gl.p_glGenTextures(1, object);
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, *object);
             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);
+                    GL_TEXTURE_3D, *object, 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_glGenTextures(1, object);
+            gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, *object);
             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,
@@ -1486,7 +1510,15 @@ static void create_and_bind_fbo_attachment(const struct wined3d_gl_info *gl_info
             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);
+                    GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, *object, 0);
+            break;
+
+        case WINED3D_GL_RES_TYPE_RB:
+            gl_info->fbo_ops.glGenRenderbuffers(1, object);
+            gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, *object);
+            gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, internal, 16, 16);
+            gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+                    *object);
             break;
 
         case WINED3D_GL_RES_TYPE_BUFFER:
@@ -1503,7 +1535,7 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
      *
      * Try to stick to the standard format if possible, this limits precision differences. */
     GLenum status, rt_internal = format->rtInternal;
-    GLuint tex;
+    GLuint object;
     enum wined3d_gl_resource_type type;
     BOOL fallback_fmt_used = FALSE, regular_fmt_used = FALSE;
 
@@ -1520,8 +1552,7 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
          * format never has WINED3DFMT_FLAG_TEXTURE set. Instead, swallow GL
          * errors generated by invalid formats. */
 
-        gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
-        create_and_bind_fbo_attachment(gl_info, type, tex, format->glInternal,
+        create_and_bind_fbo_attachment(gl_info, type, &object, format->glInternal,
                 format->glFormat, format->glType);
         while (gl_info->gl_ops.gl.p_glGetError());
 
@@ -1560,8 +1591,8 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
 
                 while (gl_info->gl_ops.gl.p_glGetError());
 
-                delete_fbo_attachment(gl_info);
-                create_and_bind_fbo_attachment(gl_info, type, tex, format->rtInternal,
+                delete_fbo_attachment(gl_info, type, &object);
+                create_and_bind_fbo_attachment(gl_info, type, &object, format->rtInternal,
                         format->glFormat, format->glType);
 
                 status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -1654,12 +1685,12 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
 
                 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,
+                        /* Rebinding texture to workaround a fglrx bug. */
+                        gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, object);
+                        gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_1D, 0, GL_BGRA,
                                 GL_UNSIGNED_INT_8_8_8_8_REV, readback);
                         color = readback[7];
                         break;
@@ -1667,17 +1698,27 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
                     case WINED3D_GL_RES_TYPE_TEX_2D:
                     case WINED3D_GL_RES_TYPE_TEX_3D:
                     case WINED3D_GL_RES_TYPE_TEX_RECT:
+                        /* Rebinding texture to workaround a fglrx bug. */
+                        gl_info->gl_ops.gl.p_glBindTexture(wined3d_gl_type_to_enum(type), object);
                         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;
 
                     case WINED3D_GL_RES_TYPE_TEX_CUBE:
+                        /* Rebinding texture to workaround a fglrx bug. */
+                        gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, object);
                         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;
 
+                    case WINED3D_GL_RES_TYPE_RB:
+                        gl_info->gl_ops.gl.p_glReadPixels(0, 0, 16, 16,
+                                GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
+                        color = readback[7 * 16 + 7];
+                        break;
+
                     case WINED3D_GL_RES_TYPE_BUFFER:
                     case WINED3D_GL_RES_TYPE_COUNT:
                         color = 0;
@@ -1722,8 +1763,8 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
 
         if (format->glInternal != format->glGammaInternal)
         {
-            delete_fbo_attachment(gl_info);
-            create_and_bind_fbo_attachment(gl_info, type, tex, format->glGammaInternal,
+            delete_fbo_attachment(gl_info, type, &object);
+            create_and_bind_fbo_attachment(gl_info, type, &object, format->glGammaInternal,
                     format->glFormat, format->glType);
 
             status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -1744,8 +1785,8 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
         else if (status == GL_FRAMEBUFFER_COMPLETE)
             format->flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
 
-        delete_fbo_attachment(gl_info);
-        gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
+        delete_fbo_attachment(gl_info, type, &object);
+        checkGLcall("Framebuffer format check cleaup");
     }
 
     if (fallback_fmt_used && regular_fmt_used)
@@ -1994,6 +2035,9 @@ static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct win
         if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
             format->flags[WINED3D_GL_RES_TYPE_TEX_RECT] |= format_texture_info[i].flags;
 
+        format->flags[WINED3D_GL_RES_TYPE_RB] |= format_texture_info[i].flags;
+        format->flags[WINED3D_GL_RES_TYPE_RB] &= ~WINED3DFMT_FLAG_TEXTURE;
+
         if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
         {
             query_format_flag(gl_info, format, format->glInternal, GL_VERTEX_TEXTURE,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 8215eac..1804bd1 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -783,7 +783,8 @@ enum wined3d_gl_resource_type
     WINED3D_GL_RES_TYPE_TEX_CUBE        = 3,
     WINED3D_GL_RES_TYPE_TEX_RECT        = 4,
     WINED3D_GL_RES_TYPE_BUFFER          = 5,
-    WINED3D_GL_RES_TYPE_COUNT           = 6,
+    WINED3D_GL_RES_TYPE_RB              = 6,
+    WINED3D_GL_RES_TYPE_COUNT           = 7,
 };
 
 enum vertexprocessing_mode {
-- 
2.3.6




More information about the wine-patches mailing list