From e9b12fe20ee1354959f27f24883676e1f1073e45 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 21 Dec 2021 15:43:45 +1000 Subject: [PATCH] mesa/st: move validate/discard framebuffer into mesa Reviewed-by: Kristian H. Kristensen Part-of: --- src/mesa/main/fbobject.c | 167 +++++++++++++++++++++++++++- src/mesa/state_tracker/st_cb_fbo.c | 169 ----------------------------- src/mesa/state_tracker/st_cb_fbo.h | 3 - 3 files changed, 165 insertions(+), 174 deletions(-) diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 48c64ae1386..036fbc7729d 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -56,6 +56,7 @@ #include "state_tracker/st_cb_fbo.h" #include "state_tracker/st_cb_eglimage.h" #include "state_tracker/st_context.h" +#include "state_tracker/st_format.h" /** * Notes: @@ -1145,6 +1146,149 @@ test_attachment_completeness(const struct gl_context *ctx, GLenum format, } } +/** Debug helper */ +static void +fbo_invalid(const char *reason) +{ + if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) { + _mesa_debug(NULL, "Invalid FBO: %s\n", reason); + } +} + + +/** + * Validate a renderbuffer attachment for a particular set of bindings. + */ +static GLboolean +do_validate_attachment(struct gl_context *ctx, + struct pipe_screen *screen, + const struct gl_renderbuffer_attachment *att, + unsigned bindings) +{ + const struct gl_texture_object *stObj = att->Texture; + enum pipe_format format; + mesa_format texFormat; + GLboolean valid; + + /* Sanity check: we must be binding the surface as a (color) render target + * or depth/stencil target. + */ + assert(bindings == PIPE_BIND_RENDER_TARGET || + bindings == PIPE_BIND_DEPTH_STENCIL); + + /* 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 || !stObj->pt) + return GL_FALSE; + + format = stObj->pt->format; + texFormat = att->Renderbuffer->TexImage->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_sRGB && _mesa_is_format_srgb(texFormat)) { + const mesa_format linearFormat = _mesa_get_srgb_format_linear(texFormat); + format = st_mesa_format_to_pipe_format(st_context(ctx), linearFormat); + } + + valid = screen->is_format_supported(screen, format, + PIPE_TEXTURE_2D, + stObj->pt->nr_samples, + stObj->pt->nr_storage_samples, + bindings); + if (!valid) { + 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 +do_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + struct pipe_screen *screen = ctx->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) { + 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) { + 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; + fbo_invalid("Different Depth/Stencil textures"); + return; + } + + if (!do_validate_attachment(ctx, screen, depth, PIPE_BIND_DEPTH_STENCIL)) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + fbo_invalid("Invalid depth attachment"); + return; + } + if (!do_validate_attachment(ctx, screen, stencil, PIPE_BIND_DEPTH_STENCIL)) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + fbo_invalid("Invalid stencil attachment"); + return; + } + for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { + struct gl_renderbuffer_attachment *att = + &fb->Attachment[BUFFER_COLOR0 + i]; + enum pipe_format format; + + if (!do_validate_attachment(ctx, screen, att, PIPE_BIND_RENDER_TARGET)) { + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; + fbo_invalid("Invalid color attachment"); + return; + } + + if (!mixed_formats) { + /* Disallow mixed formats. */ + if (att->Type != GL_NONE) { + format = 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; + fbo_invalid("Mixed color formats"); + return; + } + } + } +} + /** * Test if the given framebuffer object is complete and update its @@ -1588,7 +1732,7 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED * if anything. */ - st_validate_framebuffer(ctx, fb); + do_validate_framebuffer(ctx, fb); if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { fbo_incomplete(ctx, "driver marked FBO as incomplete", -1); return; @@ -5219,6 +5363,25 @@ get_fb_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, } } +static void +do_discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb, + struct gl_renderbuffer_attachment *att) +{ + struct pipe_resource *prsc; + + if (!att->Renderbuffer || !att->Complete) + return; + + prsc = att->Renderbuffer->surface->texture; + + /* using invalidate_resource will only work for simple 2D resources */ + if (prsc->depth0 != 1 || prsc->array_size != 1 || prsc->last_level != 0) + return; + + if (ctx->pipe->invalidate_resource) + ctx->pipe->invalidate_resource(ctx->pipe, prsc); +} + static void discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb, GLsizei numAttachments, const GLenum *attachments) @@ -5254,7 +5417,7 @@ discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb, continue; } - st_discard_framebuffer(ctx, fb, att); + do_discard_framebuffer(ctx, fb, att); } } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index 213219728fc..936417bfc95 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -536,175 +536,6 @@ st_update_renderbuffer_surface(struct st_context *st, rb->surface = *psurf; } -/** Debug helper */ -static void -st_fbo_invalid(const char *reason) -{ - if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) { - _mesa_debug(NULL, "Invalid FBO: %s\n", reason); - } -} - - -/** - * 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 gl_texture_object *stObj = att->Texture; - enum pipe_format format; - mesa_format texFormat; - GLboolean valid; - - /* Sanity check: we must be binding the surface as a (color) render target - * or depth/stencil target. - */ - assert(bindings == PIPE_BIND_RENDER_TARGET || - bindings == PIPE_BIND_DEPTH_STENCIL); - - /* 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 || !stObj->pt) - return GL_FALSE; - - format = stObj->pt->format; - texFormat = att->Renderbuffer->TexImage->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_sRGB && _mesa_is_format_srgb(texFormat)) { - const mesa_format linearFormat = _mesa_get_srgb_format_linear(texFormat); - format = st_mesa_format_to_pipe_format(st_context(ctx), linearFormat); - } - - valid = screen->is_format_supported(screen, format, - PIPE_TEXTURE_2D, - stObj->pt->nr_samples, - stObj->pt->nr_storage_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. - */ -void -st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) -{ - struct st_context *st = st_context(ctx); - struct pipe_screen *screen = st->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; - st_fbo_invalid("Invalid depth attachment"); - return; - } - if (!st_validate_attachment(ctx, screen, stencil, PIPE_BIND_DEPTH_STENCIL)) { - fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; - st_fbo_invalid("Invalid stencil attachment"); - 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; - st_fbo_invalid("Invalid color attachment"); - return; - } - - if (!mixed_formats) { - /* Disallow mixed formats. */ - if (att->Type != GL_NONE) { - format = 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; - } - } - } -} - - -/** - * Called by ctx->Driver.DiscardFramebuffer - */ -void -st_discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb, - struct gl_renderbuffer_attachment *att) -{ - struct st_context *st = st_context(ctx); - struct pipe_resource *prsc; - - if (!att->Renderbuffer || !att->Complete) - return; - - prsc = att->Renderbuffer->surface->texture; - - /* using invalidate_resource will only work for simple 2D resources */ - if (prsc->depth0 != 1 || prsc->array_size != 1 || prsc->last_level != 0) - return; - - if (st->pipe->invalidate_resource) - st->pipe->invalidate_resource(st->pipe, prsc); -} - - /** * Called via glDrawBuffer. We only provide this driver function so that we * can check if we need to allocate a new renderbuffer. Specifically, we diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h index f3b40a26a47..da1a1dacbd6 100644 --- a/src/mesa/state_tracker/st_cb_fbo.h +++ b/src/mesa/state_tracker/st_cb_fbo.h @@ -78,9 +78,6 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height); -void st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb); -void st_discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb, - struct gl_renderbuffer_attachment *att); void st_DrawBufferAllocate(struct gl_context *ctx); void st_ReadBuffer(struct gl_context *ctx, GLenum buffer);