/** * Add a color renderbuffer on demand. */ boolean st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *fb, gl_buffer_index idx) { struct st_framebuffer *stfb = st_ws_framebuffer(fb); /* FBO */ if (!stfb) return FALSE; if (stfb->Base.Attachment[idx].Renderbuffer) return TRUE; switch (idx) { case BUFFER_FRONT_LEFT: case BUFFER_BACK_LEFT: case BUFFER_FRONT_RIGHT: case BUFFER_BACK_RIGHT: break; default: return FALSE; break; } if (!st_framebuffer_add_renderbuffer(stfb, idx)) return FALSE; st_framebuffer_update_attachments(stfb); st_invalidate_state(st->ctx, _NEW_BUFFERS); return TRUE; }
/** * Called via ctx->Driver.FinishRenderTexture. */ static void st_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb) { struct st_renderbuffer *strb = st_renderbuffer(rb); if (!strb) return; strb->is_rtt = FALSE; /* restore previous framebuffer state */ st_invalidate_state(ctx, _NEW_BUFFERS); }
/** * Called via ctx->Driver.FinishRenderTexture. */ static void st_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) { struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer); if (!strb) return; strb->rtt = NULL; /* restore previous framebuffer state */ st_invalidate_state(ctx, _NEW_BUFFERS); }
/** * Called by ctx->Driver.RenderTexture */ static void st_render_texture(struct gl_context *ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct gl_renderbuffer *rb = att->Renderbuffer; struct st_renderbuffer *strb = st_renderbuffer(rb); struct pipe_resource *pt; if (!st_finalize_texture(ctx, pipe, att->Texture)) return; pt = st_get_texobj_resource(att->Texture); assert(pt); /* point renderbuffer at texobject */ strb->is_rtt = TRUE; strb->rtt_face = att->CubeMapFace; strb->rtt_slice = att->Zoffset; strb->rtt_layered = att->Layered; pipe_resource_reference(&strb->texture, pt); pipe_surface_release(pipe, &strb->surface); st_update_renderbuffer_surface(st, strb); strb->Base.Format = st_pipe_format_to_mesa_format(pt->format); /* Invalidate buffer state so that the pipe's framebuffer state * gets updated. * 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); /* Need to trigger a call to update_framebuffer() since we just * attached a new renderbuffer. */ ctx->NewState |= _NEW_BUFFERS; }
/** * Add a color renderbuffer on demand. */ boolean st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *fb, gl_buffer_index idx) { struct st_framebuffer *stfb = st_ws_framebuffer(fb); /* FBO */ if (!stfb) return FALSE; if (stfb->Base.Attachment[idx].Renderbuffer) return TRUE; switch (idx) { case BUFFER_FRONT_LEFT: case BUFFER_BACK_LEFT: case BUFFER_FRONT_RIGHT: case BUFFER_BACK_RIGHT: break; default: return FALSE; break; } if (!st_framebuffer_add_renderbuffer(stfb, idx)) return FALSE; st_framebuffer_update_attachments(stfb); /* * Force a call to the state tracker manager to validate the * new renderbuffer. It might be that there is a window system * renderbuffer available. */ if(stfb->iface) stfb->iface_stamp = p_atomic_read(&stfb->iface->stamp) - 1; st_invalidate_state(st->ctx, _NEW_BUFFERS); return TRUE; }
/** * Called by ctx->Driver.RenderTexture */ static void st_render_texture(struct gl_context *ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_renderbuffer *strb; struct gl_renderbuffer *rb; struct pipe_resource *pt; struct st_texture_object *stObj; const struct gl_texture_image *texImage; struct pipe_surface surf_tmpl; if (!st_finalize_texture(ctx, pipe, att->Texture)) return; pt = st_get_texobj_resource(att->Texture); assert(pt); /* get pointer to texture image we're rendeing to */ texImage = _mesa_get_attachment_teximage(att); /* create new renderbuffer which wraps the texture image. * Use the texture's name as the renderbuffer's name so that we have * something that's non-zero (to determine vertical orientation) and * possibly helpful for debugging. */ rb = st_new_renderbuffer(ctx, att->Texture->Name); if (!rb) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()"); return; } _mesa_reference_renderbuffer(&att->Renderbuffer, rb); assert(rb->RefCount == 1); rb->AllocStorage = NULL; /* should not get called */ strb = st_renderbuffer(rb); assert(strb->Base.RefCount > 0); /* get the texture for the texture object */ stObj = st_texture_object(att->Texture); /* point renderbuffer at texobject */ strb->rtt = stObj; strb->rtt_level = att->TextureLevel; strb->rtt_face = att->CubeMapFace; strb->rtt_slice = att->Zoffset; rb->Width = texImage->Width2; rb->Height = texImage->Height2; rb->_BaseFormat = texImage->_BaseFormat; rb->InternalFormat = texImage->InternalFormat; pipe_resource_reference( &strb->texture, pt ); pipe_surface_release(pipe, &strb->surface); assert(strb->rtt_level <= strb->texture->last_level); /* new surface for rendering into the texture */ memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format); surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; surf_tmpl.u.tex.level = strb->rtt_level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; strb->surface = pipe->create_surface(pipe, strb->texture, &surf_tmpl); strb->Base.Format = st_pipe_format_to_mesa_format(pt->format); /* Invalidate buffer state so that the pipe's framebuffer state * gets updated. * 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); /* Need to trigger a call to update_framebuffer() since we just * attached a new renderbuffer. */ ctx->NewState |= _NEW_BUFFERS; }
/** * Called by ctx->Driver.RenderTexture */ static void st_render_texture(struct gl_context *ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct gl_renderbuffer *rb = att->Renderbuffer; struct st_renderbuffer *strb = st_renderbuffer(rb); struct pipe_resource *pt; struct st_texture_object *stObj; const struct gl_texture_image *texImage; struct pipe_surface surf_tmpl; if (!st_finalize_texture(ctx, pipe, att->Texture)) return; pt = st_get_texobj_resource(att->Texture); assert(pt); /* get pointer to texture image we're rendeing to */ texImage = _mesa_get_attachment_teximage(att); /* get the texture for the texture object */ stObj = st_texture_object(att->Texture); /* point renderbuffer at texobject */ strb->rtt = stObj; strb->rtt_level = att->TextureLevel; strb->rtt_face = att->CubeMapFace; strb->rtt_slice = att->Zoffset; pipe_resource_reference( &strb->texture, pt ); pipe_surface_release(pipe, &strb->surface); assert(strb->rtt_level <= strb->texture->last_level); /* new surface for rendering into the texture */ memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format); surf_tmpl.u.tex.level = strb->rtt_level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; strb->surface = pipe->create_surface(pipe, strb->texture, &surf_tmpl); strb->Base.Format = st_pipe_format_to_mesa_format(pt->format); /* Invalidate buffer state so that the pipe's framebuffer state * gets updated. * 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); /* Need to trigger a call to update_framebuffer() since we just * attached a new renderbuffer. */ ctx->NewState |= _NEW_BUFFERS; }