/** * Reference a framebuffer. */ static void st_framebuffer_reference(struct st_framebuffer **ptr, struct st_framebuffer *stfb) { struct gl_framebuffer *fb = &stfb->Base; _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb); }
static void intelDestroyBuffer(__DRIdrawable * driDrawPriv) { struct gl_framebuffer *fb = driDrawPriv->driverPrivate; _mesa_reference_framebuffer(&fb, NULL); }
/** * Remove buffer from linked list, delete if no longer referenced. */ static void xmesa_free_buffer(XMesaBuffer buffer) { XMesaBuffer prev = NULL, b; for (b = XMesaBufferList; b; b = b->Next) { if (b == buffer) { struct gl_framebuffer *fb = &buffer->mesa_buffer; /* unlink buffer from list */ if (prev) prev->Next = buffer->Next; else XMesaBufferList = buffer->Next; /* mark as delete pending */ fb->DeletePending = GL_TRUE; /* Since the X window for the XMesaBuffer is going away, we don't * want to dereference this pointer in the future. */ b->frontxrb->drawable = 0; /* Unreference. If count = zero we'll really delete the buffer */ _mesa_reference_framebuffer(&fb, NULL); return; } /* continue search */ prev = b; } /* buffer not found in XMesaBufferList */ _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n"); }
void radeonDestroyBuffer(__DRIdrawable *driDrawPriv) { struct radeon_framebuffer *rfb; if (!driDrawPriv) return; rfb = (void*)driDrawPriv->driverPrivate; if (!rfb) return; radeon_cleanup_renderbuffers(rfb); _mesa_reference_framebuffer((struct gl_framebuffer **)(&(driDrawPriv->driverPrivate)), NULL); }
void _mesa_meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx, struct gen_mipmap_state *mipmap) { if (mipmap->VAO == 0) return; _mesa_DeleteVertexArrays(1, &mipmap->VAO); mipmap->VAO = 0; _mesa_reference_buffer_object(ctx, &mipmap->buf_obj, NULL); _mesa_reference_sampler_object(ctx, &mipmap->samp_obj, NULL); _mesa_reference_framebuffer(&mipmap->fb, NULL); _mesa_meta_blit_shader_table_cleanup(ctx, &mipmap->shaders); }
void glFBDevDestroyBuffer( GLFBDevBufferPtr buffer ) { if (buffer) { /* check if destroying the current buffer */ GLFBDevBufferPtr curDraw = glFBDevGetCurrentDrawBuffer(); GLFBDevBufferPtr curRead = glFBDevGetCurrentReadBuffer(); if (buffer == curDraw || buffer == curRead) { glFBDevMakeCurrent( NULL, NULL, NULL); } { struct gl_framebuffer *fb = &buffer->glframebuffer; _mesa_reference_framebuffer(&fb, NULL); } } }
static void dri_destroy_buffer(__DRIdrawable * dPriv) { TRACE; if (dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); struct gl_framebuffer *fb; free(drawable->row); fb = &drawable->Base; fb->DeletePending = GL_TRUE; _mesa_reference_framebuffer(&fb, NULL); } }
/** * Destroy an Off-Screen Mesa rendering context. * * \param osmesa the context to destroy */ GLAPI void GLAPIENTRY OSMesaDestroyContext( OSMesaContext osmesa ) { if (osmesa) { if (osmesa->srb) _mesa_reference_renderbuffer((struct gl_renderbuffer **) &osmesa->srb, NULL); _mesa_meta_free( &osmesa->mesa ); _swsetup_DestroyContext( &osmesa->mesa ); _tnl_DestroyContext( &osmesa->mesa ); _vbo_DestroyContext( &osmesa->mesa ); _swrast_DestroyContext( &osmesa->mesa ); _mesa_destroy_visual( osmesa->gl_visual ); _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL ); _mesa_free_context_data( &osmesa->mesa ); free( osmesa ); } }
/** * Free the data associated with the given context. * * But doesn't free the GLcontext struct itself. * * \sa _mesa_initialize_context() and init_attrib_groups(). */ void _mesa_free_context_data( GLcontext *ctx ) { GLint RefCount; if (!_mesa_get_current_context()){ /* No current context, but we may need one in order to delete * texture objs, etc. So temporarily bind the context now. */ _mesa_make_current(ctx, NULL, NULL); } /* unreference WinSysDraw/Read buffers */ _mesa_reference_framebuffer(&ctx->WinSysDrawBuffer, NULL); _mesa_reference_framebuffer(&ctx->WinSysReadBuffer, NULL); _mesa_reference_framebuffer(&ctx->DrawBuffer, NULL); _mesa_reference_framebuffer(&ctx->ReadBuffer, NULL); _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL); _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); _mesa_free_attrib_data(ctx); _mesa_free_lighting_data( ctx ); _mesa_free_eval_data( ctx ); _mesa_free_texture_data( ctx ); _mesa_free_matrix_data( ctx ); _mesa_free_viewport_data( ctx ); _mesa_free_colortables_data( ctx ); _mesa_free_program_data(ctx); _mesa_free_shader_state(ctx); _mesa_free_queryobj_data(ctx); #if FEATURE_ARB_sync _mesa_free_sync_data(ctx); #endif _mesa_free_varray_data(ctx); _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj); #if FEATURE_ARB_pixel_buffer_object _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL); _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL); #endif #if FEATURE_ARB_vertex_buffer_object _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL); _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL); #endif /* free dispatch tables */ _mesa_free(ctx->Exec); _mesa_free(ctx->Save); /* Shared context state (display lists, textures, etc) */ _glthread_LOCK_MUTEX(ctx->Shared->Mutex); RefCount = --ctx->Shared->RefCount; _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); assert(RefCount >= 0); if (RefCount == 0) { /* free shared state */ _mesa_free_shared_state( ctx, ctx->Shared ); } /* needs to be after freeing shared state */ _mesa_free_display_list_data(ctx); if (ctx->Extensions.String) _mesa_free((void *) ctx->Extensions.String); /* unbind the context if it's currently bound */ if (ctx == _mesa_get_current_context()) { _mesa_make_current(NULL, NULL, NULL); } }
/** * Bind the given context to the given drawBuffer and readBuffer and * make it the current context for the calling thread. * We'll render into the drawBuffer and read pixels from the * readBuffer (i.e. glRead/CopyPixels, glCopyTexImage, etc). * * We check that the context's and framebuffer's visuals are compatible * and return immediately if they're not. * * \param newCtx the new GL context. If NULL then there will be no current GL * context. * \param drawBuffer the drawing framebuffer * \param readBuffer the reading framebuffer */ GLboolean _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, GLframebuffer *readBuffer ) { if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(newCtx, "_mesa_make_current()\n"); /* Check that the context's and framebuffer's visuals are compatible. */ if (newCtx && drawBuffer && newCtx->WinSysDrawBuffer != drawBuffer) { if (!check_compatible(newCtx, drawBuffer)) { _mesa_warning(newCtx, "MakeCurrent: incompatible visuals for context and drawbuffer"); return GL_FALSE; } } if (newCtx && readBuffer && newCtx->WinSysReadBuffer != readBuffer) { if (!check_compatible(newCtx, readBuffer)) { _mesa_warning(newCtx, "MakeCurrent: incompatible visuals for context and readbuffer"); return GL_FALSE; } } /* We used to call _glapi_check_multithread() here. Now do it in drivers */ _glapi_set_context((void *) newCtx); ASSERT(_mesa_get_current_context() == newCtx); if (!newCtx) { _glapi_set_dispatch(NULL); /* none current */ } else { _glapi_set_dispatch(newCtx->CurrentDispatch); if (drawBuffer && readBuffer) { /* TODO: check if newCtx and buffer's visual match??? */ ASSERT(drawBuffer->Name == 0); ASSERT(readBuffer->Name == 0); _mesa_reference_framebuffer(&newCtx->WinSysDrawBuffer, drawBuffer); _mesa_reference_framebuffer(&newCtx->WinSysReadBuffer, readBuffer); /* * Only set the context's Draw/ReadBuffer fields if they're NULL * or not bound to a user-created FBO. */ if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) { /* KW: merge conflict here, revisit. */ /* fix up the fb fields - these will end up wrong otherwise * if the DRIdrawable changes, and everything relies on them. * This is a bit messy (same as needed in _mesa_BindFramebufferEXT) */ unsigned int i; GLenum buffers[MAX_DRAW_BUFFERS]; _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer); for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) { buffers[i] = newCtx->Color.DrawBuffer[i]; } _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL); } if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) { _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer); } /* XXX only set this flag if we're really changing the draw/read * framebuffer bindings. */ newCtx->NewState |= _NEW_BUFFERS; #if 1 /* We want to get rid of these lines: */ #if _HAVE_FULL_GL if (!drawBuffer->Initialized) { initialize_framebuffer_size(newCtx, drawBuffer); } if (readBuffer != drawBuffer && !readBuffer->Initialized) { initialize_framebuffer_size(newCtx, readBuffer); } _mesa_resizebuffers(newCtx); #endif #else /* We want the drawBuffer and readBuffer to be initialized by * the driver. * This generally means the Width and Height match the actual * window size and the renderbuffers (both hardware and software * based) are allocated to match. The later can generally be * done with a call to _mesa_resize_framebuffer(). * * It's theoretically possible for a buffer to have zero width * or height, but for now, assert check that the driver did what's * expected of it. */ ASSERT(drawBuffer->Width > 0); ASSERT(drawBuffer->Height > 0); #endif if (drawBuffer) { _mesa_check_init_viewport(newCtx, drawBuffer->Width, drawBuffer->Height); } } if (newCtx->FirstTimeCurrent) { check_context_limits(newCtx); /* We can use this to help debug user's problems. Tell them to set * the MESA_INFO env variable before running their app. Then the * first time each context is made current we'll print some useful * information. */ if (_mesa_getenv("MESA_INFO")) { _mesa_print_info(); } newCtx->FirstTimeCurrent = GL_FALSE; } } return GL_TRUE; }
static void nouveau_destroy_buffer(__DRIdrawable *drawable) { _mesa_reference_framebuffer( (struct gl_framebuffer **)&drawable->driverPrivate, NULL); }
/** A partial implementation of glCopyImageSubData * * This is a partial implementation of glCopyImageSubData that works only * if both textures are uncompressed and the destination texture is * renderable. It uses a slight abuse of a texture view (see make_view) to * turn the source texture into the destination texture type and then uses * _mesa_meta_BlitFramebuffers to do the copy. */ bool _mesa_meta_CopyImageSubData_uncompressed(struct gl_context *ctx, struct gl_texture_image *src_tex_image, struct gl_renderbuffer *src_renderbuffer, int src_x, int src_y, int src_z, struct gl_texture_image *dst_tex_image, struct gl_renderbuffer *dst_renderbuffer, int dst_x, int dst_y, int dst_z, int src_width, int src_height) { mesa_format src_format, dst_format; GLint src_internal_format, dst_internal_format; GLuint src_view_texture = 0; struct gl_texture_image *src_view_tex_image; struct gl_framebuffer *readFb; struct gl_framebuffer *drawFb = NULL; bool success = false; GLbitfield mask; GLenum status, attachment; if (src_renderbuffer) { src_format = src_renderbuffer->Format; src_internal_format = src_renderbuffer->InternalFormat; } else { assert(src_tex_image); src_format = src_tex_image->TexFormat; src_internal_format = src_tex_image->InternalFormat; } if (dst_renderbuffer) { dst_format = dst_renderbuffer->Format; dst_internal_format = dst_renderbuffer->InternalFormat; } else { assert(dst_tex_image); dst_format = dst_tex_image->TexFormat; dst_internal_format = dst_tex_image->InternalFormat; } if (_mesa_is_format_compressed(src_format)) return false; if (_mesa_is_format_compressed(dst_format)) return false; if (src_internal_format == dst_internal_format) { src_view_tex_image = src_tex_image; } else { if (src_renderbuffer) { assert(src_tex_image == NULL); src_tex_image = wrap_renderbuffer(ctx, src_renderbuffer); } if (!make_view(ctx, src_tex_image, &src_view_tex_image, &src_view_texture, dst_internal_format)) goto cleanup; } /* We really only need to stash the bound framebuffers and scissor. */ _mesa_meta_begin(ctx, MESA_META_SCISSOR); readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); if (readFb == NULL) goto meta_end; drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); if (drawFb == NULL) goto meta_end; _mesa_bind_framebuffers(ctx, drawFb, readFb); switch (_mesa_get_format_base_format(src_format)) { case GL_DEPTH_COMPONENT: attachment = GL_DEPTH_ATTACHMENT; mask = GL_DEPTH_BUFFER_BIT; break; case GL_DEPTH_STENCIL: attachment = GL_DEPTH_STENCIL_ATTACHMENT; mask = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; break; case GL_STENCIL_INDEX: attachment = GL_STENCIL_ATTACHMENT; mask = GL_STENCIL_BUFFER_BIT; break; default: attachment = GL_COLOR_ATTACHMENT0; mask = GL_COLOR_BUFFER_BIT; _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0); _mesa_ReadBuffer(GL_COLOR_ATTACHMENT0); } if (src_view_tex_image) { /* Prefer the tex image because, even if we have a renderbuffer, we may * have had to wrap it in a texture view. */ _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer, attachment, src_view_tex_image, src_z); } else { _mesa_framebuffer_renderbuffer(ctx, ctx->ReadBuffer, attachment, src_renderbuffer); } status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer); if (status != GL_FRAMEBUFFER_COMPLETE) goto meta_end; if (dst_renderbuffer) { _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, attachment, dst_renderbuffer); } else { _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, attachment, dst_tex_image, dst_z); } status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer); if (status != GL_FRAMEBUFFER_COMPLETE) goto meta_end; /* Explicitly disable sRGB encoding */ ctx->DrawBuffer->Visual.sRGBCapable = false; /* Since we've bound a new draw framebuffer, we need to update its * derived state -- _Xmin, etc -- for BlitFramebuffer's clipping to * be correct. */ _mesa_update_state(ctx); /* We skip the core BlitFramebuffer checks for format consistency. * We have already created views to ensure that the texture formats * match. */ ctx->Driver.BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, src_x, src_y, src_x + src_width, src_y + src_height, dst_x, dst_y, dst_x + src_width, dst_y + src_height, mask, GL_NEAREST); success = true; meta_end: _mesa_reference_framebuffer(&readFb, NULL); _mesa_reference_framebuffer(&drawFb, NULL); _mesa_meta_end(ctx); cleanup: _mesa_DeleteTextures(1, &src_view_texture); /* If we got a renderbuffer source, delete the temporary texture */ if (src_renderbuffer && src_tex_image) ctx->Driver.DeleteTexture(ctx, src_tex_image->TexObject); return success; }
void GLAPIENTRY _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) { struct gl_framebuffer *newFb, *newFbread; GLboolean bindReadBuf, bindDrawBuf; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (!ctx->Extensions.EXT_framebuffer_object) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebufferEXT(unsupported)"); return; } switch (target) { #if FEATURE_EXT_framebuffer_blit case GL_DRAW_FRAMEBUFFER_EXT: if (!ctx->Extensions.EXT_framebuffer_blit) { _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); return; } bindDrawBuf = GL_TRUE; bindReadBuf = GL_FALSE; break; case GL_READ_FRAMEBUFFER_EXT: if (!ctx->Extensions.EXT_framebuffer_blit) { _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); return; } bindDrawBuf = GL_FALSE; bindReadBuf = GL_TRUE; break; #endif case GL_FRAMEBUFFER_EXT: bindDrawBuf = GL_TRUE; bindReadBuf = GL_TRUE; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); return; } FLUSH_VERTICES(ctx, _NEW_BUFFERS); if (ctx->Driver.Flush) { ctx->Driver.Flush(ctx); } if (framebuffer) { /* Binding a user-created framebuffer object */ newFb = _mesa_lookup_framebuffer(ctx, framebuffer); if (newFb == &DummyFramebuffer) { /* ID was reserved, but no real framebuffer object made yet */ newFb = NULL; } if (!newFb) { /* create new framebuffer object */ newFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); if (!newFb) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT"); return; } _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb); } newFbread = newFb; } else { /* Binding the window system framebuffer (which was originally set * with MakeCurrent). */ newFb = ctx->WinSysDrawBuffer; newFbread = ctx->WinSysReadBuffer; } ASSERT(newFb); ASSERT(newFb != &DummyFramebuffer); /* * XXX check if re-binding same buffer and skip some of this code. */ if (bindReadBuf) { _mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread); } if (bindDrawBuf) { /* check if old FB had any texture attachments */ check_end_texture_render(ctx, ctx->DrawBuffer); /* check if time to delete this framebuffer */ _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb); if (newFb->Name != 0) { /* check if newly bound framebuffer has any texture attachments */ check_begin_texture_render(ctx, newFb); } } if (ctx->Driver.BindFramebuffer) { ctx->Driver.BindFramebuffer(ctx, target, newFb, newFbread); } }
bool _mesa_meta_pbo_GetTexSubImage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *tex_image, int xoffset, int yoffset, int zoffset, int width, int height, int depth, GLenum format, GLenum type, const void *pixels, const struct gl_pixelstore_attrib *packing) { struct gl_buffer_object *pbo = NULL; GLuint pbo_tex = 0; struct gl_framebuffer *readFb; struct gl_framebuffer *drawFb; int image_height; struct gl_texture_image *pbo_tex_image; struct gl_renderbuffer *rb = NULL; GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format); GLenum status, src_base_format; bool success = false, clear_channels_to_zero = false; float save_clear_color[4]; int z; if (!_mesa_is_bufferobj(packing->BufferObj)) return false; if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL || format == GL_STENCIL_INDEX || format == GL_COLOR_INDEX) return false; /* Don't use meta path for readpixels in below conditions. */ if (!tex_image) { rb = ctx->ReadBuffer->_ColorReadBuffer; /* _mesa_get_readpixels_transfer_ops() includes the cases of read * color clamping along with the ctx->_ImageTransferState. */ if (_mesa_get_readpixels_transfer_ops(ctx, rb->Format, format, type, GL_FALSE)) return false; if (_mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat, dstBaseFormat)) return false; /* This function rely on BlitFramebuffer to fill in the pixel data for * ReadPixels. But, BlitFrameBuffer doesn't support signed to unsigned * or unsigned to signed integer conversions. OpenGL spec expects an * invalid operation in that case. */ if (need_signed_unsigned_int_conversion(rb->Format, format, type)) return false; } else { if (need_signed_unsigned_int_conversion(tex_image->TexFormat, format, type)) return false; } /* For arrays, use a tall (height * depth) 2D texture but taking into * account the inter-image padding specified with the image height packing * property. */ image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight; _mesa_meta_begin(ctx, ~(MESA_META_PIXEL_TRANSFER | MESA_META_PIXEL_STORE)); pbo_tex_image = create_texture_for_pbo(ctx, false, GL_PIXEL_PACK_BUFFER, dims, width, height, depth, format, type, pixels, packing, &pbo, &pbo_tex); if (!pbo_tex_image) { _mesa_meta_end(ctx); return false; } /* GL_CLAMP_FRAGMENT_COLOR doesn't affect ReadPixels and GettexImage */ if (ctx->Extensions.ARB_color_buffer_float) _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); if (readFb == NULL) goto fail; drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); if (drawFb == NULL) goto fail; if (tex_image && tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) { assert(depth == 1); assert(zoffset == 0); depth = height; height = 1; image_height = 1; zoffset = yoffset; yoffset = 0; } /* If we were given a texture, bind it to the read framebuffer. If not, * we're doing a ReadPixels and we should just use whatever framebuffer * the client has bound. */ _mesa_bind_framebuffers(ctx, drawFb, tex_image ? readFb : ctx->ReadBuffer); if (tex_image) { _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer, GL_COLOR_ATTACHMENT0, tex_image, zoffset); /* If this passes on the first layer it should pass on the others */ status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer); if (status != GL_FRAMEBUFFER_COMPLETE) goto fail; } else { assert(depth == 1); } _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0, pbo_tex_image, 0); /* If this passes on the first layer it should pass on the others */ status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer); if (status != GL_FRAMEBUFFER_COMPLETE) goto fail; /* Explicitly disable sRGB encoding */ ctx->DrawBuffer->Visual.sRGBCapable = false; _mesa_update_state(ctx); if (_mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, xoffset, yoffset, xoffset + width, yoffset + height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST)) goto fail; src_base_format = tex_image ? tex_image->_BaseFormat : ctx->ReadBuffer->_ColorReadBuffer->_BaseFormat; /* Depending on the base formats involved we might need to rebase some * values. For example if we download from a Luminance format to RGBA * format, we want G=0 and B=0. */ clear_channels_to_zero = _mesa_need_luminance_to_rgb_conversion(src_base_format, pbo_tex_image->_BaseFormat); if (clear_channels_to_zero) { memcpy(save_clear_color, ctx->Color.ClearColor.f, 4 * sizeof(float)); /* Clear the Green, Blue channels. */ _mesa_ColorMask(GL_FALSE, GL_TRUE, GL_TRUE, src_base_format != GL_LUMINANCE_ALPHA); _mesa_ClearColor(0.0, 0.0, 0.0, 1.0); _mesa_Clear(GL_COLOR_BUFFER_BIT); } for (z = 1; z < depth; z++) { _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer, GL_COLOR_ATTACHMENT0, tex_image, zoffset + z); _mesa_update_state(ctx); _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, xoffset, yoffset, xoffset + width, yoffset + height, 0, z * image_height, width, z * image_height + height, GL_COLOR_BUFFER_BIT, GL_NEAREST); if (clear_channels_to_zero) _mesa_Clear(GL_COLOR_BUFFER_BIT); } /* Unmask the color channels and restore the saved clear color values. */ if (clear_channels_to_zero) { _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); _mesa_ClearColor(save_clear_color[0], save_clear_color[1], save_clear_color[2], save_clear_color[3]); } success = true; fail: _mesa_reference_framebuffer(&drawFb, NULL); _mesa_reference_framebuffer(&readFb, NULL); _mesa_DeleteTextures(1, &pbo_tex); _mesa_reference_buffer_object(ctx, &pbo, NULL); _mesa_meta_end(ctx); return success; }
bool _mesa_meta_pbo_TexSubImage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *tex_image, int xoffset, int yoffset, int zoffset, int width, int height, int depth, GLenum format, GLenum type, const void *pixels, bool create_pbo, const struct gl_pixelstore_attrib *packing) { struct gl_buffer_object *pbo = NULL; GLuint pbo_tex = 0; struct gl_framebuffer *readFb = NULL; struct gl_framebuffer *drawFb = NULL; int image_height; struct gl_texture_image *pbo_tex_image; GLenum status; bool success = false; int z; if (!_mesa_is_bufferobj(packing->BufferObj) && (!create_pbo || pixels == NULL)) return false; if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL || format == GL_STENCIL_INDEX || format == GL_COLOR_INDEX) return false; if (ctx->_ImageTransferState) return false; /* This function rely on BlitFramebuffer to fill in the pixel data for * glTex[Sub]Image*D. But, BlitFrameBuffer doesn't support signed to * unsigned or unsigned to signed integer conversions. */ if (need_signed_unsigned_int_conversion(tex_image->TexFormat, format, type)) return false; /* For arrays, use a tall (height * depth) 2D texture but taking into * account the inter-image padding specified with the image height packing * property. */ image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight; _mesa_meta_begin(ctx, ~(MESA_META_PIXEL_TRANSFER | MESA_META_PIXEL_STORE)); pbo_tex_image = create_texture_for_pbo(ctx, create_pbo, GL_PIXEL_UNPACK_BUFFER, dims, width, height, depth, format, type, pixels, packing, &pbo, &pbo_tex); if (!pbo_tex_image) { _mesa_meta_end(ctx); return false; } readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); if (readFb == NULL) goto fail; drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); if (drawFb == NULL) goto fail; _mesa_bind_framebuffers(ctx, drawFb, tex_image ? readFb : ctx->ReadBuffer); if (tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) { assert(depth == 1); assert(zoffset == 0); depth = height; height = 1; image_height = 1; zoffset = yoffset; yoffset = 0; } _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer, GL_COLOR_ATTACHMENT0, pbo_tex_image, 0); /* If this passes on the first layer it should pass on the others */ status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer); if (status != GL_FRAMEBUFFER_COMPLETE) goto fail; _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0, tex_image, zoffset); /* If this passes on the first layer it should pass on the others */ status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer); if (status != GL_FRAMEBUFFER_COMPLETE) goto fail; /* Explicitly disable sRGB encoding */ ctx->DrawBuffer->Visual.sRGBCapable = false; _mesa_update_state(ctx); if (_mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, 0, 0, width, height, xoffset, yoffset, xoffset + width, yoffset + height, GL_COLOR_BUFFER_BIT, GL_NEAREST)) goto fail; for (z = 1; z < depth; z++) { _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0, tex_image, zoffset + z); _mesa_update_state(ctx); _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, 0, z * image_height, width, z * image_height + height, xoffset, yoffset, xoffset + width, yoffset + height, GL_COLOR_BUFFER_BIT, GL_NEAREST); } success = true; fail: _mesa_reference_framebuffer(&readFb, NULL); _mesa_reference_framebuffer(&drawFb, NULL); _mesa_DeleteTextures(1, &pbo_tex); _mesa_reference_buffer_object(ctx, &pbo, NULL); _mesa_meta_end(ctx); return success; }
void brw_meta_resolve_color(struct brw_context *brw, struct intel_mipmap_tree *mt) { struct gl_context *ctx = &brw->ctx; struct gl_framebuffer *drawFb; struct gl_renderbuffer *rb; struct rect rect; brw_emit_mi_flush(brw); drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); if (drawFb == NULL) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "in %s", __func__); return; } _mesa_meta_begin(ctx, MESA_META_ALL); rb = brw_get_rb_for_slice(brw, mt, 0, 0, false); _mesa_bind_framebuffers(ctx, drawFb, ctx->ReadBuffer); _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_reference_framebuffer(&drawFb, NULL); _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); }