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 * during window resize. */ static GLboolean st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct st_context *st = st_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 = PIPE_FORMAT_NONE; struct pipe_surface surf_tmpl; struct pipe_resource templ; /* init renderbuffer fields */ strb->Base.Width = width; strb->Base.Height = height; strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); strb->defined = GL_FALSE; /* undefined contents now */ if (strb->software) { return st_renderbuffer_alloc_sw_storage(ctx, rb, internalFormat, width, height); } /* Free the old surface and texture */ pipe_surface_reference( &strb->surface, NULL ); pipe_resource_reference( &strb->texture, NULL ); /* If an sRGB framebuffer is unsupported, sRGB formats behave like linear * formats. */ if (!ctx->Extensions.EXT_framebuffer_sRGB) { internalFormat = _mesa_get_linear_internalformat(internalFormat); } /* 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; for (i = rb->NumSamples; i <= ctx->Const.MaxSamples; i++) { format = st_choose_renderbuffer_format(st, internalFormat, i); if (format != PIPE_FORMAT_NONE) { rb->NumSamples = i; break; } } } else { format = st_choose_renderbuffer_format(st, 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); if (width == 0 || height == 0) { /* if size is zero, nothing to allocate */ return GL_TRUE; } /* 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; u_surface_default_template(&surf_tmpl, strb->texture); 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; }
/** * gl_renderbuffer::AllocStorage() * This is called to allocate the original drawing surface, and * during window resize. */ static GLboolean st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct st_context *st = st_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; 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; } /* 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; } 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; } /* Setup new texture template. */ memset(&template, 0, sizeof(template));