/** * Validate a renderbuffer attachment for a particular set of bindings. */ static GLboolean st_validate_attachment(struct gl_context *ctx, struct pipe_screen *screen, const struct gl_renderbuffer_attachment *att, unsigned bindings) { const struct st_texture_object *stObj = st_texture_object(att->Texture); enum pipe_format format; gl_format texFormat; GLboolean valid; /* Only validate texture attachments for now, since * st_renderbuffer_alloc_storage makes sure that * the format is supported. */ if (att->Type != GL_TEXTURE) return GL_TRUE; if (!stObj) return GL_FALSE; format = stObj->pt->format; texFormat = _mesa_get_attachment_teximage_const(att)->TexFormat; /* If the encoding is sRGB and sRGB rendering cannot be enabled, * check for linear format support instead. * Later when we create a surface, we change the format to a linear one. */ if (!ctx->Extensions.EXT_framebuffer_sRGB && _mesa_get_format_color_encoding(texFormat) == GL_SRGB) { const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat); format = st_mesa_format_to_pipe_format(linearFormat); } valid = screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, stObj->pt->nr_samples, bindings); if (!valid) { st_fbo_invalid("Invalid format"); } return valid; }
/** * Check that the framebuffer configuration is valid in terms of what * the driver can support. * * For Gallium we only supports combined Z+stencil, not separate buffers. */ static void st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) { struct st_context *st = st_context(ctx); struct pipe_screen *screen = st->pipe->screen; const struct gl_renderbuffer_attachment *depth = &fb->Attachment[BUFFER_DEPTH]; const struct gl_renderbuffer_attachment *stencil = &fb->Attachment[BUFFER_STENCIL]; GLuint i; enum pipe_format first_format = PIPE_FORMAT_NONE; boolean mixed_formats = screen->get_param(screen, PIPE_CAP_MIXED_COLORBUFFER_FORMATS) != 0; if (depth->Type && stencil->Type && depth->Type != stencil->Type) { st_fbo_invalid("Different Depth/Stencil buffer formats"); fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; return; } if (depth->Type == GL_RENDERBUFFER_EXT && stencil->Type == GL_RENDERBUFFER_EXT && depth->Renderbuffer != stencil->Renderbuffer) { st_fbo_invalid("Separate Depth/Stencil buffers"); fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; return; } if (depth->Type == GL_TEXTURE && stencil->Type == GL_TEXTURE && depth->Texture != stencil->Texture) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; st_fbo_invalid("Different Depth/Stencil textures"); return; } if (!st_validate_attachment(ctx, screen, depth, PIPE_BIND_DEPTH_STENCIL)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; return; } if (!st_validate_attachment(ctx, screen, stencil, PIPE_BIND_DEPTH_STENCIL)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; return; } for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { struct gl_renderbuffer_attachment *att = &fb->Attachment[BUFFER_COLOR0 + i]; enum pipe_format format; if (!st_validate_attachment(ctx, screen, att, PIPE_BIND_RENDER_TARGET)) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; return; } if (!mixed_formats) { /* Disallow mixed formats. */ if (att->Type != GL_NONE) { format = st_renderbuffer(att->Renderbuffer)->surface->format; } else { continue; } if (first_format == PIPE_FORMAT_NONE) { first_format = format; } else if (format != first_format) { fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; st_fbo_invalid("Mixed color formats"); return; } } } }