#include "main/glformats.h"
#include "main/macros.h"
#include "main/renderbuffer.h"
+#include "main/state.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
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 */
/* Free the old surface and texture
*/
- pipe_surface_reference( &strb->surface, NULL );
+ pipe_surface_reference(&strb->surface_srgb, NULL);
+ pipe_surface_reference(&strb->surface_linear, NULL);
+ strb->surface = NULL;
pipe_resource_reference( &strb->texture, NULL );
/* If an sRGB framebuffer is unsupported, sRGB formats behave like linear
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);
- }
-
+ st_update_renderbuffer_surface(st, strb);
return strb->surface != NULL;
}
struct st_renderbuffer *strb = st_renderbuffer(rb);
if (ctx) {
struct st_context *st = st_context(ctx);
- pipe_surface_release(st->pipe, &strb->surface);
+ pipe_surface_release(st->pipe, &strb->surface_srgb);
+ pipe_surface_release(st->pipe, &strb->surface_linear);
+ strb->surface = NULL;
}
pipe_resource_reference(&strb->texture, NULL);
free(strb->data);
/**
- * Allocate a renderbuffer for a an on-screen window (not a user-created
+ * Allocate a renderbuffer for an on-screen window (not a user-created
* renderbuffer). The window system code determines the format.
*/
struct gl_renderbuffer *
{
struct pipe_context *pipe = st->pipe;
struct pipe_resource *resource = strb->texture;
- struct st_texture_object *stTexObj = NULL;
+ const struct st_texture_object *stTexObj = NULL;
unsigned rtt_width = strb->Base.Width;
unsigned rtt_height = strb->Base.Height;
unsigned rtt_depth = strb->Base.Depth;
+
/*
* For winsys fbo, it is possible that the renderbuffer is sRGB-capable but
* the format of strb->texture is linear (because we have no control over
* the format). Check strb->Base.Format instead of strb->texture->format
* to determine if the rb is sRGB-capable.
*/
- boolean enable_srgb = (st->ctx->Color.sRGBEnabled &&
- _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB);
+ boolean enable_srgb = st->ctx->Color.sRGBEnabled &&
+ _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB;
enum pipe_format format = resource->format;
if (strb->is_rtt) {
format = stTexObj->surface_format;
}
- format = (enable_srgb) ?
- util_format_srgb(format) :
- util_format_linear(format);
-
- unsigned first_layer, last_layer, level;
+ format = enable_srgb ? util_format_srgb(format) : util_format_linear(format);
if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
rtt_depth = rtt_height;
}
/* find matching mipmap level size */
+ unsigned level;
for (level = 0; level <= resource->last_level; level++) {
if (u_minify(resource->width0, level) == rtt_width &&
u_minify(resource->height0, level) == rtt_height &&
assert(level <= resource->last_level);
/* determine the layer bounds */
+ unsigned first_layer, last_layer;
if (strb->rtt_layered) {
first_layer = 0;
last_layer = util_max_layer(strb->texture, level);
/* Adjust for texture views */
if (strb->is_rtt && resource->array_size > 1 &&
stTexObj->base.Immutable) {
- struct gl_texture_object *tex = &stTexObj->base;
+ const struct gl_texture_object *tex = &stTexObj->base;
first_layer += tex->MinLayer;
if (!strb->rtt_layered)
last_layer += tex->MinLayer;
last_layer = MIN2(first_layer + tex->NumLayers - 1, last_layer);
}
- if (!strb->surface ||
- strb->surface->texture->nr_samples != strb->Base.NumSamples ||
- strb->surface->format != format ||
- strb->surface->texture != resource ||
- strb->surface->width != rtt_width ||
- strb->surface->height != rtt_height ||
- strb->surface->u.tex.level != level ||
- strb->surface->u.tex.first_layer != first_layer ||
- strb->surface->u.tex.last_layer != last_layer) {
+ struct pipe_surface **psurf =
+ enable_srgb ? &strb->surface_srgb : &strb->surface_linear;
+ struct pipe_surface *surf = *psurf;
+
+ if (!surf ||
+ surf->texture->nr_samples != strb->Base.NumSamples ||
+ surf->format != format ||
+ surf->texture != resource ||
+ surf->width != rtt_width ||
+ surf->height != rtt_height ||
+ surf->u.tex.level != level ||
+ surf->u.tex.first_layer != first_layer ||
+ surf->u.tex.last_layer != last_layer) {
/* create a new pipe_surface */
struct pipe_surface surf_tmpl;
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
surf_tmpl.u.tex.first_layer = first_layer;
surf_tmpl.u.tex.last_layer = last_layer;
- pipe_surface_release(pipe, &strb->surface);
+ pipe_surface_release(pipe, psurf);
- strb->surface = pipe->create_surface(pipe, resource, &surf_tmpl);
+ *psurf = pipe->create_surface(pipe, resource, &surf_tmpl);
}
+ strb->surface = *psurf;
}
/**
struct st_renderbuffer *strb = st_renderbuffer(rb);
struct pipe_resource *pt;
- if (!st_finalize_texture(ctx, pipe, att->Texture))
+ if (!st_finalize_texture(ctx, pipe, att->Texture, att->CubeMapFace))
return;
pt = st_get_texobj_resource(att->Texture);
* That's where the new renderbuffer (which we just created) gets
* passed to the pipe as a (color/depth) render target.
*/
- st_invalidate_state(ctx, _NEW_BUFFERS);
+ st_invalidate_buffers(st);
/* Need to trigger a call to update_framebuffer() since we just
static void
st_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
+ struct st_context *st = st_context(ctx);
struct st_renderbuffer *strb = st_renderbuffer(rb);
if (!strb)
strb->is_rtt = FALSE;
/* restore previous framebuffer state */
- st_invalidate_state(ctx, _NEW_BUFFERS);
+ st_invalidate_buffers(st);
}
depth,
PIPE_BIND_DEPTH_STENCIL)) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ st_fbo_invalid("Invalid depth attachment");
return;
}
if (!st_validate_attachment(ctx,
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++) {
att,
PIPE_BIND_RENDER_TARGET)) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ st_fbo_invalid("Invalid color attachment");
return;
}
/**
- * Called via glDrawBuffer.
+ * Called via glDrawBuffer. We only provide this driver function so that we
+ * can check if we need to allocate a new renderbuffer. Specifically, we
+ * don't usually allocate a front color buffer when using a double-buffered
+ * visual. But if the app calls glDrawBuffer(GL_FRONT) we need to allocate
+ * that buffer. Note, this is only for window system buffers, not user-
+ * created FBOs.
*/
static void
st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers)
{
struct st_context *st = st_context(ctx);
struct gl_framebuffer *fb = ctx->DrawBuffer;
- GLuint i;
(void) count;
(void) buffers;
- /* add the renderbuffers on demand */
- for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
- gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
+ if (_mesa_is_winsys_fbo(fb)) {
+ GLuint i;
+ /* add the renderbuffers on demand */
+ for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ GLint idx = fb->_ColorDrawBufferIndexes[i];
- if (idx >= 0) {
- st_manager_add_color_renderbuffer(st, fb, idx);
+ if (idx >= 0) {
+ st_manager_add_color_renderbuffer(st, fb, idx);
+ }
}
}
}
/**
- * Called via glReadBuffer.
+ * Called via glReadBuffer. As with st_DrawBuffers, we use this function
+ * to check if we need to allocate a renderbuffer on demand.
*/
static void
st_ReadBuffer(struct gl_context *ctx, GLenum buffer)
if ((fb->_ColorReadBufferIndex == BUFFER_FRONT_LEFT ||
fb->_ColorReadBufferIndex == BUFFER_FRONT_RIGHT) &&
fb->Attachment[fb->_ColorReadBufferIndex].Type == GL_NONE) {
+ assert(_mesa_is_winsys_fbo(fb));
/* add the buffer */
st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex);
- st_validate_state(st, ST_PIPELINE_RENDER);
+ _mesa_update_state(ctx);
+ st_validate_state(st, ST_PIPELINE_UPDATE_FRAMEBUFFER);
}
}