/** * Update the framebuffer's _DepthBuffer field using the renderbuffer * found at the given attachment index. * * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer, * create and install a depth wrapper/adaptor. * * \param fb the framebuffer whose _DepthBuffer field to update * \param attIndex indicates the renderbuffer to possibly wrap */ void _mesa_update_depth_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, GLuint attIndex) { struct gl_renderbuffer *depthRb; /* only one possiblity for now */ ASSERT(attIndex == BUFFER_DEPTH); depthRb = fb->Attachment[attIndex].Renderbuffer; if (depthRb && _mesa_is_format_packed_depth_stencil(depthRb->Format)) { /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */ if (!fb->_DepthBuffer || fb->_DepthBuffer->Wrapped != depthRb || _mesa_get_format_base_format(fb->_DepthBuffer->Format) != GL_DEPTH_COMPONENT) { /* need to update wrapper */ struct gl_renderbuffer *wrapper = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper); ASSERT(fb->_DepthBuffer->Wrapped == depthRb); } } else { /* depthRb may be null */ _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb); } }
/** * Free all the data hanging off the given gl_framebuffer, but don't free * the gl_framebuffer object itself. */ void _mesa_free_framebuffer_data(struct gl_framebuffer *fb) { GLuint i; assert(fb); assert(fb->RefCount == 0); _glthread_DESTROY_MUTEX(fb->Mutex); for (i = 0; i < BUFFER_COUNT; i++) { struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; if (att->Renderbuffer) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); } if (att->Texture) { _mesa_reference_texobj(&att->Texture, NULL); } ASSERT(!att->Renderbuffer); ASSERT(!att->Texture); att->Type = GL_NONE; } /* unbind _Depth/_StencilBuffer to decr ref counts */ _mesa_reference_renderbuffer(&fb->_DepthBuffer, NULL); _mesa_reference_renderbuffer(&fb->_StencilBuffer, NULL); }
/** * Update the framebuffer's _StencilBuffer field using the renderbuffer * found at the given attachment index. * * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer, * create and install a stencil wrapper/adaptor. * * \param fb the framebuffer whose _StencilBuffer field to update * \param attIndex indicates the renderbuffer to possibly wrap */ void _mesa_update_stencil_buffer(struct gl_context *ctx, struct gl_framebuffer *fb, GLuint attIndex) { struct gl_renderbuffer *stencilRb; ASSERT(attIndex == BUFFER_DEPTH || attIndex == BUFFER_STENCIL); stencilRb = fb->Attachment[attIndex].Renderbuffer; if (stencilRb && _mesa_is_format_packed_depth_stencil(stencilRb->Format)) { /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */ if (!fb->_StencilBuffer || fb->_StencilBuffer->Wrapped != stencilRb || _mesa_get_format_base_format(fb->_StencilBuffer->Format) != GL_STENCIL_INDEX) { /* need to update wrapper */ struct gl_renderbuffer *wrapper = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb); _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper); ASSERT(fb->_StencilBuffer->Wrapped == stencilRb); } } else { /* stencilRb may be null */ _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb); } }
static void intelFreeTextureImageData(struct gl_context * ctx, struct gl_texture_image *texImage) { struct intel_context *intel = intel_context(ctx); struct intel_texture_image *intelImage = intel_texture_image(texImage); DBG("%s\n", __FUNCTION__); if (intelImage->mt) { intel_miptree_release(intel, &intelImage->mt); } if (texImage->Data) { _mesa_free_texmemory(texImage->Data); texImage->Data = NULL; } if (intelImage->depth_rb) { _mesa_reference_renderbuffer(&intelImage->depth_rb, NULL); } if (intelImage->stencil_rb) { _mesa_reference_renderbuffer(&intelImage->stencil_rb, NULL); } }
/** * Update the framebuffer's _StencilBuffer field using the renderbuffer * found at the given attachment index. * * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer, * create and install a stencil wrapper/adaptor. * * \param fb the framebuffer whose _StencilBuffer field to update * \param attIndex indicates the renderbuffer to possibly wrap */ void _mesa_update_stencil_buffer(GLcontext *ctx, struct gl_framebuffer *fb, GLuint attIndex) { struct gl_renderbuffer *stencilRb; ASSERT(attIndex == BUFFER_DEPTH || attIndex == BUFFER_STENCIL); stencilRb = fb->Attachment[attIndex].Renderbuffer; if (stencilRb && stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) { /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */ if (!fb->_StencilBuffer || fb->_StencilBuffer->Wrapped != stencilRb || fb->_StencilBuffer->_BaseFormat != GL_STENCIL_INDEX) { /* need to update wrapper */ struct gl_renderbuffer *wrapper = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb); _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper); ASSERT(fb->_StencilBuffer->Wrapped == stencilRb); } } else { /* stencilRb may be null */ _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb); } }
static void nouveau_render_texture(struct gl_context *ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct gl_renderbuffer *rb = att->Renderbuffer; struct gl_texture_image *ti = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; /* Allocate a renderbuffer object for the texture if we * haven't already done so. */ if (!rb) { rb = nouveau_renderbuffer_new(ctx, ~0); assert(rb); rb->AllocStorage = NULL; _mesa_reference_renderbuffer(&att->Renderbuffer, rb); } /* Update the renderbuffer fields from the texture. */ set_renderbuffer_format(rb, get_tex_format(ti)); rb->Width = ti->Width; rb->Height = ti->Height; nouveau_surface_ref(&to_nouveau_teximage(ti)->surface, &to_nouveau_renderbuffer(rb)->surface); context_dirty(ctx, FRAMEBUFFER); }
/** * Attach a renderbuffer to a framebuffer. * \param bufferName one of the BUFFER_x tokens */ void _mesa_add_renderbuffer(struct gl_framebuffer *fb, gl_buffer_index bufferName, struct gl_renderbuffer *rb) { assert(fb); assert(rb); assert(bufferName < BUFFER_COUNT); /* There should be no previous renderbuffer on this attachment point, * with the exception of depth/stencil since the same renderbuffer may * be used for both. */ assert(bufferName == BUFFER_DEPTH || bufferName == BUFFER_STENCIL || fb->Attachment[bufferName].Renderbuffer == NULL); /* winsys vs. user-created buffer cross check */ if (fb->Name) { assert(rb->Name); } else { assert(!rb->Name); } fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT; fb->Attachment[bufferName].Complete = GL_TRUE; _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb); }
void GLAPIENTRY _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) { GLint i; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); FLUSH_VERTICES(ctx, _NEW_BUFFERS); for (i = 0; i < n; i++) { if (renderbuffers[i] > 0) { struct gl_renderbuffer *rb; rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]); if (rb) { /* check if deleting currently bound renderbuffer object */ if (rb == ctx->CurrentRenderbuffer) { /* bind default */ ASSERT(rb->RefCount >= 2); _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); } /* Remove from hash table immediately, to free the ID. * But the object will not be freed until it's no longer * referenced anywhere else. */ _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); if (rb != &DummyRenderbuffer) { /* no longer referenced by hash table */ _mesa_reference_renderbuffer(&rb, NULL); } } } } }
/** * Remove the named renderbuffer from the given framebuffer. * \param bufferName one of the BUFFER_x tokens */ void _mesa_remove_renderbuffer(struct gl_framebuffer *fb, gl_buffer_index bufferName) { assert(bufferName < BUFFER_COUNT); _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, NULL); }
/** * Delete a depth or stencil wrapper renderbuffer. */ static void delete_wrapper(struct gl_renderbuffer *rb) { ASSERT(rb->Format == MESA_FORMAT_S8 || rb->Format == MESA_FORMAT_X8_Z24); _mesa_reference_renderbuffer(&rb->Wrapped, NULL); free(rb); }
void brw_meta_resolve_color(struct brw_context *brw, struct intel_mipmap_tree *mt) { struct gl_context *ctx = &brw->ctx; GLuint fbo; struct gl_renderbuffer *rb; struct rect rect; brw_emit_mi_flush(brw); _mesa_meta_begin(ctx, MESA_META_ALL); _mesa_GenFramebuffers(1, &fbo); rb = brw_get_rb_for_slice(brw, mt, 0, 0, false); _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0, rb); _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0); brw_fast_clear_init(brw); use_rectlist(brw, true); brw_bind_rep_write_shader(brw, (float *) fast_clear_color); /* SKL+ also has a resolve mode for compressed render targets and thus more * bits to let us select the type of resolve. For fast clear resolves, it * turns out we can use the same value as pre-SKL though. */ if (intel_miptree_is_lossless_compressed(brw, mt)) set_fast_clear_op(brw, GEN9_PS_RENDER_TARGET_RESOLVE_FULL); else set_fast_clear_op(brw, GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE); mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED; get_resolve_rect(brw, mt, &rect); brw_draw_rectlist(brw, &rect, 1); set_fast_clear_op(brw, 0); use_rectlist(brw, false); _mesa_reference_renderbuffer(&rb, NULL); _mesa_DeleteFramebuffers(1, &fbo); _mesa_meta_end(ctx); /* We're typically called from intel_update_state() and we're supposed to * return with the state all updated to what it was before * brw_meta_resolve_color() was called. The meta rendering will have * messed up the state and we need to call _mesa_update_state() again to * get back to where we were supposed to be when resolve was called. */ if (ctx->NewState) _mesa_update_state(ctx); }
/** * Bind a renderbuffer to an attachment point. * The previous binding, if any, will be removed first. */ void _mesa_set_renderbuffer_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att, struct gl_renderbuffer *rb) { /* XXX check if re-doing same attachment, exit early */ _mesa_remove_attachment(ctx, att); att->Type = GL_RENDERBUFFER_EXT; att->Texture = NULL; /* just to be safe */ att->Complete = GL_FALSE; _mesa_reference_renderbuffer(&att->Renderbuffer, rb); }
void intel_flip_renderbuffers(struct intel_framebuffer *intel_fb) { int current_page = intel_fb->pf_current_page; int next_page = (current_page + 1) % intel_fb->pf_num_pages; struct gl_renderbuffer *tmp_rb; /* Exchange renderbuffers if necessary but make sure their reference counts * are preserved. */ if (intel_fb->color_rb[current_page] && intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer != &intel_fb->color_rb[current_page]->Base) { tmp_rb = NULL; _mesa_reference_renderbuffer(&tmp_rb, intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); tmp_rb = &intel_fb->color_rb[current_page]->Base; _mesa_reference_renderbuffer( &intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer, tmp_rb); _mesa_reference_renderbuffer(&tmp_rb, NULL); } if (intel_fb->color_rb[next_page] && intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer != &intel_fb->color_rb[next_page]->Base) { tmp_rb = NULL; _mesa_reference_renderbuffer(&tmp_rb, intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer); tmp_rb = &intel_fb->color_rb[next_page]->Base; _mesa_reference_renderbuffer( &intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer, tmp_rb); _mesa_reference_renderbuffer(&tmp_rb, NULL); } }
void GLAPIENTRY _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) { struct gl_renderbuffer *newRb; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (target != GL_RENDERBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)"); return; } FLUSH_VERTICES(ctx, _NEW_BUFFERS); /* The above doesn't fully flush the drivers in the way that a * glFlush does, but that is required here: */ if (ctx->Driver.Flush) ctx->Driver.Flush(ctx); if (renderbuffer) { newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (newRb == &DummyRenderbuffer) { /* ID was reserved, but no real renderbuffer object made yet */ newRb = NULL; } if (!newRb) { /* create new renderbuffer object */ newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer); if (!newRb) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT"); return; } ASSERT(newRb->AllocStorage); _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); newRb->RefCount = 1; /* referenced by hash table */ } } else { newRb = NULL; } ASSERT(newRb != &DummyRenderbuffer); _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb); }
/** * Destroy an Off-Screen Mesa rendering context. * * \param osmesa the context to destroy */ GLAPI void GLAPIENTRY OSMesaDestroyContext( OSMesaContext osmesa ) { if (osmesa) { if (osmesa->rb) _mesa_reference_renderbuffer(&osmesa->rb, NULL); _swsetup_DestroyContext( &osmesa->mesa ); _tnl_DestroyContext( &osmesa->mesa ); _vbo_DestroyContext( &osmesa->mesa ); _swrast_DestroyContext( &osmesa->mesa ); _mesa_destroy_visual( osmesa->gl_visual ); _mesa_unreference_framebuffer( &osmesa->gl_buffer ); _mesa_free_context_data( &osmesa->mesa ); _mesa_free( osmesa ); } }
/** * Remove any texture or renderbuffer attached to the given attachment * point. Update reference counts, etc. */ void _mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att) { if (att->Type == GL_TEXTURE) { ASSERT(att->Texture); if (ctx->Driver.FinishRenderTexture) { /* tell driver we're done rendering to this texobj */ ctx->Driver.FinishRenderTexture(ctx, att); } _mesa_reference_texobj(&att->Texture, NULL); /* unbind */ ASSERT(!att->Texture); } if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) { ASSERT(!att->Texture); _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */ ASSERT(!att->Renderbuffer); } att->Type = GL_NONE; att->Complete = GL_TRUE; }
/** * Free all the data hanging off the given gl_framebuffer, but don't free * the gl_framebuffer object itself. */ void _mesa_free_framebuffer_data(struct gl_framebuffer *fb) { GLuint i; assert(fb); assert(fb->RefCount == 0); mtx_destroy(&fb->Mutex); for (i = 0; i < BUFFER_COUNT; i++) { struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; if (att->Renderbuffer) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); } if (att->Texture) { _mesa_reference_texobj(&att->Texture, NULL); } assert(!att->Renderbuffer); assert(!att->Texture); att->Type = GL_NONE; } }
/** * This function creates a renderbuffer object which wraps a texture image. * The new renderbuffer is plugged into the given attachment point. * This allows rendering into the texture as if it were a renderbuffer. */ static void wrap_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) { struct gl_renderbuffer *rb; const GLuint name = 0; ASSERT(att->Type == GL_TEXTURE); ASSERT(att->Renderbuffer == NULL); rb = ctx->Driver.NewRenderbuffer(ctx, name); if (!rb) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture"); return; } /* init base gl_renderbuffer fields */ _mesa_init_renderbuffer(rb, name); /* plug in our texture_renderbuffer-specific functions */ rb->Delete = delete_texture_wrapper; rb->AllocStorage = NULL; /* illegal! */ /* update attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, rb); }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct intel_context *intel = intel_context(ctx); struct gl_texture_image *image = _mesa_get_attachment_teximage(att); struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int layer; (void) fb; if (att->CubeMapFace > 0) { assert(att->Zoffset == 0); layer = att->CubeMapFace; } else { layer = att->Zoffset; } if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } else if (!irb) { intel_miptree_check_level_layer(mt, att->TextureLevel, layer); irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base); } else { /* fallback to software rendering */ _swrast_render_texture(ctx, fb, att); return; } } if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n", _mesa_get_format_name(image->TexFormat), att->Texture->Name, image->Width, image->Height, irb->Base.Base.RefCount); intel_image->used_as_render_target = true; #ifndef I915 if (need_tile_offset_workaround(brw_context(ctx), irb)) { /* Original gen4 hardware couldn't draw to a non-tile-aligned * destination in a miptree unless you actually setup your * renderbuffer as a miptree and used the fragile * lod/array_index/etc. controls to select the image. So, * instead, we just make a new single-level miptree and render * into that. */ struct intel_context *intel = intel_context(ctx); struct intel_mipmap_tree *new_mt; int width, height, depth; intel_miptree_get_dimensions_for_image(image, &width, &height, &depth); new_mt = intel_miptree_create(intel, image->TexObject->Target, intel_image->base.Base.TexFormat, intel_image->base.Base.Level, intel_image->base.Base.Level, width, height, depth, true); intel_miptree_copy_teximage(intel, intel_image, new_mt); intel_renderbuffer_set_draw_offset(irb); intel_miptree_reference(&irb->mt, intel_image->mt); intel_miptree_release(&new_mt); } #endif /* update drawing region, etc */ intel_draw_buffer(ctx); }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct intel_context *intel = intel_context(ctx); struct gl_texture_image *image = _mesa_get_attachment_teximage(att); struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int layer; (void) fb; if (att->CubeMapFace > 0) { assert(att->Zoffset == 0); layer = att->CubeMapFace; } else { layer = att->Zoffset; } if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } else if (!irb) { intel_miptree_check_level_layer(mt, att->TextureLevel, layer); irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base); } else { /* fallback to software rendering */ _swrast_render_texture(ctx, fb, att); return; } } if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } irb->tex_image = image; DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n", _mesa_get_format_name(image->TexFormat), att->Texture->Name, image->Width, image->Height, irb->Base.Base.RefCount); /* update drawing region, etc */ intel_draw_buffer(ctx); }
/** * 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; }
static void radeon_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct gl_texture_image *newImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer); radeon_texture_image *radeon_image; GLuint imageOffset; radeon_print(RADEON_TEXTURE, RADEON_TRACE, "%s(%p, fb %p, rrb %p, att %p)\n", __func__, ctx, fb, rrb, att); (void) fb; ASSERT(newImage); radeon_image = (radeon_texture_image *)newImage; if (!radeon_image->mt || newImage->Border != 0) { /* Fallback on drawing to a texture without a miptree. */ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } else if (!rrb) { rrb = radeon_wrap_texture(ctx, newImage); if (rrb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base); } else { /* fallback to software rendering */ _mesa_render_texture(ctx, fb, att); return; } } if (!radeon_update_wrapper(ctx, rrb, newImage)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n", _glthread_GetID(), att->Texture->Name, newImage->Width, newImage->Height, rrb->base.RefCount); /* point the renderbufer's region to the texture image region */ if (rrb->bo != radeon_image->mt->bo) { if (rrb->bo) radeon_bo_unref(rrb->bo); rrb->bo = radeon_image->mt->bo; radeon_bo_ref(rrb->bo); } /* compute offset of the particular 2D image within the texture region */ imageOffset = radeon_miptree_image_offset(radeon_image->mt, att->CubeMapFace, att->TextureLevel); if (att->Texture->Target == GL_TEXTURE_3D) { imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride * radeon_image->mt->levels[att->TextureLevel].height * att->Zoffset; } /* store that offset in the region, along with the correct pitch for * the image we are rendering to */ rrb->draw_offset = imageOffset; rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride; /* update drawing region, etc */ radeon_draw_buffer(ctx, fb); }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(GLcontext * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct gl_texture_image *newImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image; GLuint imageOffset; (void) fb; ASSERT(newImage); if (!irb) { irb = intel_wrap_texture(ctx, newImage); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); } else { /* fallback to software rendering */ _mesa_render_texture(ctx, fb, att); return; } } if (!intel_update_wrapper(ctx, irb, newImage)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n", _glthread_GetID(), att->Texture->Name, newImage->Width, newImage->Height, irb->Base.RefCount); /* point the renderbufer's region to the texture image region */ intel_image = intel_texture_image(newImage); if (irb->region != intel_image->mt->region) { if (irb->region) intel_region_release(&irb->region); intel_region_reference(&irb->region, intel_image->mt->region); } /* compute offset of the particular 2D image within the texture region */ imageOffset = intel_miptree_image_offset(intel_image->mt, att->CubeMapFace, att->TextureLevel); if (att->Texture->Target == GL_TEXTURE_3D) { const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt, att->TextureLevel); imageOffset += offsets[att->Zoffset]; } /* store that offset in the region */ intel_image->mt->region->draw_offset = imageOffset; /* update drawing region, etc */ intel_draw_buffer(ctx, fb); }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(GLcontext * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct gl_texture_image *newImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image; GLuint dst_x, dst_y; (void) fb; ASSERT(newImage); intel_image = intel_texture_image(newImage); if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } else if (!irb) { irb = intel_wrap_texture(ctx, newImage); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); } else { /* fallback to software rendering */ _mesa_render_texture(ctx, fb, att); return; } } if (!intel_update_wrapper(ctx, irb, newImage)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n", _glthread_GetID(), att->Texture->Name, newImage->Width, newImage->Height, irb->Base.RefCount); /* point the renderbufer's region to the texture image region */ if (irb->region != intel_image->mt->region) { if (irb->region) intel_region_release(&irb->region); intel_region_reference(&irb->region, intel_image->mt->region); } /* compute offset of the particular 2D image within the texture region */ intel_miptree_get_image_offset(intel_image->mt, att->TextureLevel, att->CubeMapFace, att->Zoffset, &dst_x, &dst_y); intel_image->mt->region->draw_offset = (dst_y * intel_image->mt->pitch + dst_x) * intel_image->mt->cpp; intel_image->mt->region->draw_x = dst_x; intel_image->mt->region->draw_y = dst_y; intel_image->used_as_render_target = GL_TRUE; /* update drawing region, etc */ intel_draw_buffer(ctx, fb); }