diff options
Diffstat (limited to 'mesalib/src/mesa/state_tracker/st_cb_fbo.c')
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_cb_fbo.c | 204 |
1 files changed, 128 insertions, 76 deletions
diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c index 953295c0e..aeb5ac7fb 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c @@ -57,6 +57,47 @@ #include "util/u_surface.h" +static GLboolean +st_renderbuffer_alloc_sw_storage(struct gl_context * ctx, + struct gl_renderbuffer *rb, + GLenum internalFormat, + GLuint width, GLuint height) +{ + struct pipe_screen *screen = st_context(ctx)->pipe->screen; + struct st_renderbuffer *strb = st_renderbuffer(rb); + enum pipe_format format; + size_t size; + + free(strb->data); + strb->data = NULL; + + if (internalFormat == GL_RGBA16_SNORM) { + /* Special case for software accum buffers. Otherwise, if the + * call to st_choose_renderbuffer_format() fails (because the + * driver doesn't support signed 16-bit/channel colors) we'd + * just return without allocating the software accum buffer. + */ + format = PIPE_FORMAT_R16G16B16A16_SNORM; + } + else { + format = st_choose_renderbuffer_format(screen, internalFormat, 0); + + /* Not setting gl_renderbuffer::Format here will cause + * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called. + */ + if (format == PIPE_FORMAT_NONE) { + return GL_TRUE; + } + } + + strb->Base.Format = st_pipe_format_to_mesa_format(format); + + size = _mesa_format_image_size(strb->Base.Format, width, height, 1); + strb->data = malloc(size); + return strb->data != NULL; +} + + /** * gl_renderbuffer::AllocStorage() * This is called to allocate the original drawing surface, and @@ -72,100 +113,111 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = st->pipe->screen; struct st_renderbuffer *strb = st_renderbuffer(rb); - enum pipe_format format; + enum pipe_format format = PIPE_FORMAT_NONE; struct pipe_surface surf_tmpl; - - if (internalFormat == GL_RGBA16_SNORM && strb->software) { - /* Special case for software accum buffers. Otherwise, if the - * call to st_choose_renderbuffer_format() fails (because the - * driver doesn't support signed 16-bit/channel colors) we'd - * just return without allocating the software accum buffer. - */ - format = PIPE_FORMAT_R16G16B16A16_SNORM; - } - else { - format = st_choose_renderbuffer_format(screen, internalFormat, - rb->NumSamples); - } - - if (format == PIPE_FORMAT_NONE) { - return FALSE; - } + struct pipe_resource templ; /* init renderbuffer fields */ strb->Base.Width = width; strb->Base.Height = height; - strb->Base.Format = st_pipe_format_to_mesa_format(format); strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); - strb->defined = GL_FALSE; /* undefined contents now */ if (strb->software) { - size_t size; - - free(strb->data); - - size = _mesa_format_image_size(strb->Base.Format, width, height, 1); - - strb->data = malloc(size); - - return strb->data != NULL; + return st_renderbuffer_alloc_sw_storage(ctx, rb, internalFormat, + width, height); } - else { - struct pipe_resource template; - - /* Free the old surface and texture - */ - pipe_surface_reference( &strb->surface, NULL ); - pipe_resource_reference( &strb->texture, NULL ); - if (width == 0 || height == 0) { - /* if size is zero, nothing to allocate */ - return GL_TRUE; - } + /* Free the old surface and texture + */ + pipe_surface_reference( &strb->surface, NULL ); + pipe_resource_reference( &strb->texture, NULL ); + + /* Handle multisample renderbuffers first. + * + * From ARB_framebuffer_object: + * If <samples> is zero, then RENDERBUFFER_SAMPLES is set to zero. + * Otherwise <samples> represents a request for a desired minimum + * number of samples. Since different implementations may support + * different sample counts for multisampled rendering, the actual + * number of samples allocated for the renderbuffer image is + * implementation dependent. However, the resulting value for + * RENDERBUFFER_SAMPLES is guaranteed to be greater than or equal + * to <samples> and no more than the next larger sample count supported + * by the implementation. + * + * So let's find the supported number of samples closest to NumSamples. + * (NumSamples == 1) is treated the same as (NumSamples == 0). + */ + if (rb->NumSamples > 1) { + unsigned i; - /* Setup new texture template. - */ - memset(&template, 0, sizeof(template)); - template.target = st->internal_target; - template.format = format; - template.width0 = width; - template.height0 = height; - template.depth0 = 1; - template.array_size = 1; - template.last_level = 0; - template.nr_samples = rb->NumSamples; - if (util_format_is_depth_or_stencil(format)) { - template.bind = PIPE_BIND_DEPTH_STENCIL; - } - else if (strb->Base.Name != 0) { - /* this is a user-created renderbuffer */ - template.bind = PIPE_BIND_RENDER_TARGET; - } - else { - /* this is a window-system buffer */ - template.bind = (PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_RENDER_TARGET); + for (i = rb->NumSamples; i <= ctx->Const.MaxSamples; i++) { + format = st_choose_renderbuffer_format(screen, internalFormat, i); + + if (format != PIPE_FORMAT_NONE) { + rb->NumSamples = i; + break; + } } + } else { + format = st_choose_renderbuffer_format(screen, internalFormat, 0); + } + + /* Not setting gl_renderbuffer::Format here will cause + * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called. + */ + if (format == PIPE_FORMAT_NONE) { + return GL_TRUE; + } - strb->texture = screen->resource_create(screen, &template); + strb->Base.Format = st_pipe_format_to_mesa_format(format); - if (!strb->texture) - return FALSE; + if (width == 0 || height == 0) { + /* if size is zero, nothing to allocate */ + return GL_TRUE; + } - u_surface_default_template(&surf_tmpl, strb->texture, template.bind); - strb->surface = pipe->create_surface(pipe, - strb->texture, - &surf_tmpl); - if (strb->surface) { - assert(strb->surface->texture); - assert(strb->surface->format); - assert(strb->surface->width == width); - assert(strb->surface->height == height); - } + /* Setup new texture template. + */ + memset(&templ, 0, sizeof(templ)); + templ.target = st->internal_target; + templ.format = format; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + templ.nr_samples = rb->NumSamples; + if (util_format_is_depth_or_stencil(format)) { + templ.bind = PIPE_BIND_DEPTH_STENCIL; + } + else if (strb->Base.Name != 0) { + /* this is a user-created renderbuffer */ + templ.bind = PIPE_BIND_RENDER_TARGET; + } + else { + /* this is a window-system buffer */ + templ.bind = (PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_RENDER_TARGET); + } + + strb->texture = screen->resource_create(screen, &templ); + + if (!strb->texture) + return FALSE; - return strb->surface != NULL; + u_surface_default_template(&surf_tmpl, strb->texture, templ.bind); + strb->surface = pipe->create_surface(pipe, + strb->texture, + &surf_tmpl); + if (strb->surface) { + assert(strb->surface->texture); + assert(strb->surface->format); + assert(strb->surface->width == width); + assert(strb->surface->height == height); } + + return strb->surface != NULL; } |