From: Stefan Dösinger Subject: [PATCH 1/8] wined3d: Check resource types separately in check_fbo_compat (v2). Message-Id: <1432282288-18626-1-git-send-email-stefan@codeweavers.com> Date: Fri, 22 May 2015 10:11:21 +0200 Version 2: Simplify image detaching. It seems to work according to the spec on all drivers after all. Set a viewport height of 1 for TEX_1D. --- dlls/wined3d/utils.c | 491 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 307 insertions(+), 184 deletions(-) diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 94ed858..bd9b710 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -1401,6 +1401,100 @@ 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) +{ + gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, 0, 0); +} + +/* 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 +1502,259 @@ 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()); + delete_fbo_attachment(gl_info); + create_and_bind_fbo_attachment(gl_info, type, tex, format->rtInternal, + format->glFormat, format->glType); - gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER); + checkGLcall("Framebuffer format check"); - 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); + 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; + } + } + } - gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); + 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; - status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER); - checkGLcall("Framebuffer format check"); + 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); + 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"); + } - if (status == GL_FRAMEBUFFER_COMPLETE) + 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) { - TRACE("Format %s rtInternal format is supported as FBO color attachment.\n", - debug_d3dformat(format->id)); + 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 { - FIXME("Format %s rtInternal format is not supported as FBO color attachment.\n", - debug_d3dformat(format->id)); - format_clear_flag(format, WINED3DFMT_FLAG_RENDERTARGET); - } - } - } + gl_info->gl_ops.gl.p_glDisable(GL_BLEND); + if (type == WINED3D_GL_RES_TYPE_TEX_1D) + gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1); + else + 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: + color = 0; + 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); + 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"); - } + delete_fbo_attachment(gl_info); + gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex); } - 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)); - } - } - 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