/** * Undo the pairing/interleaving between depth and stencil buffers. * irb should be a depth/stencil or stencil renderbuffer. */ void intel_unpair_depth_stencil(GLcontext * ctx, struct intel_renderbuffer *irb) { if (irb->PairedStencil) { /* irb is a depth/stencil buffer */ struct gl_renderbuffer *stencilRb; struct intel_renderbuffer *stencilIrb; ASSERT(irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil); stencilIrb = intel_renderbuffer(stencilRb); if (stencilIrb) { /* need to extract stencil values from the depth buffer */ ASSERT(stencilIrb->PairedDepth == irb->Base.Name); map_regions(ctx, irb, stencilIrb); _mesa_extract_stencil(ctx, &irb->Base, &stencilIrb->Base); unmap_regions(ctx, irb, stencilIrb); stencilIrb->PairedDepth = 0; } irb->PairedStencil = 0; } else if (irb->PairedDepth) { /* irb is a stencil buffer */ struct gl_renderbuffer *depthRb; struct intel_renderbuffer *depthIrb; ASSERT(irb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT || irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth); depthIrb = intel_renderbuffer(depthRb); if (depthIrb) { /* need to extract stencil values from the depth buffer */ ASSERT(depthIrb->PairedStencil == irb->Base.Name); map_regions(ctx, depthIrb, irb); _mesa_extract_stencil(ctx, &depthIrb->Base, &irb->Base); unmap_regions(ctx, depthIrb, irb); depthIrb->PairedStencil = 0; } irb->PairedDepth = 0; } else { _mesa_problem(ctx, "Problem in undo_depth_stencil_pairing"); } ASSERT(irb->PairedStencil == 0); ASSERT(irb->PairedDepth == 0); }
static __DRIimage * intel_create_image_from_renderbuffer(__DRIcontext *context, int renderbuffer, void *loaderPrivate) { __DRIimage *image; struct intel_context *intel = context->driverPrivate; struct gl_renderbuffer *rb; struct intel_renderbuffer *irb; rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer); if (!rb) { _mesa_error(&intel->ctx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); return NULL; } irb = intel_renderbuffer(rb); image = calloc(1, sizeof *image); if (image == NULL) return NULL; image->internal_format = rb->InternalFormat; image->format = rb->Format; image->offset = 0; image->data = loaderPrivate; intel_region_reference(&image->region, irb->mt->region); intel_setup_image_from_dimensions(image); image->dri_format = intel_dri_format(image->format); rb->NeedsFinishRenderTexture = true; return image; }
static __DRIimage * radeon_create_image_from_renderbuffer(__DRIcontext *context, int renderbuffer, void *loaderPrivate) { __DRIimage *image; radeonContextPtr radeon = context->driverPrivate; struct gl_renderbuffer *rb; struct radeon_renderbuffer *rrb; rb = _mesa_lookup_renderbuffer(&radeon->glCtx, renderbuffer); if (!rb) { _mesa_error(&radeon->glCtx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); return NULL; } rrb = radeon_renderbuffer(rb); image = calloc(1, sizeof *image); if (image == NULL) return NULL; image->internal_format = rb->InternalFormat; image->format = rb->Format; image->cpp = rrb->cpp; image->data_type = GL_UNSIGNED_BYTE; image->data = loaderPrivate; radeon_bo_ref(rrb->bo); image->bo = rrb->bo; image->width = rb->Width; image->height = rb->Height; image->pitch = rrb->pitch / image->cpp; return image; }
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); } } } } }
GLboolean GLAPIENTRY _mesa_IsRenderbufferEXT(GLuint renderbuffer) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); if (renderbuffer) { struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (rb != NULL && rb != &DummyRenderbuffer) return GL_TRUE; } return GL_FALSE; }
static __DRIimage * intel_create_image_from_renderbuffer(__DRIcontext *context, int renderbuffer, void *loaderPrivate) { __DRIimage *image; struct intel_context *intel = context->driverPrivate; struct gl_renderbuffer *rb; struct intel_renderbuffer *irb; rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer); if (!rb) { _mesa_error(&intel->ctx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); return NULL; } irb = intel_renderbuffer(rb); image = calloc(1, sizeof *image); if (image == NULL) return NULL; image->internal_format = rb->InternalFormat; image->format = rb->Format; image->offset = 0; image->data = loaderPrivate; intel_region_reference(&image->region, irb->mt->region); switch (image->format) { case MESA_FORMAT_RGB565: image->dri_format = __DRI_IMAGE_FORMAT_RGB565; break; case MESA_FORMAT_XRGB8888: image->dri_format = __DRI_IMAGE_FORMAT_XRGB8888; break; case MESA_FORMAT_ARGB8888: image->dri_format = __DRI_IMAGE_FORMAT_ARGB8888; break; case MESA_FORMAT_RGBA8888_REV: image->dri_format = __DRI_IMAGE_FORMAT_ABGR8888; break; case MESA_FORMAT_R8: image->dri_format = __DRI_IMAGE_FORMAT_R8; break; case MESA_FORMAT_RG88: image->dri_format = __DRI_IMAGE_FORMAT_GR88; break; } rb->NeedsFinishRenderTexture = true; return image; }
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); }
static __DRIimage * intel_create_image_from_renderbuffer(__DRIcontext *context, int renderbuffer, void *loaderPrivate) { __DRIimage *image; struct brw_context *brw = context->driverPrivate; struct gl_context *ctx = &brw->ctx; struct gl_renderbuffer *rb; struct intel_renderbuffer *irb; rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (!rb) { _mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); return NULL; } irb = intel_renderbuffer(rb); intel_miptree_make_shareable(brw, irb->mt); image = calloc(1, sizeof *image); if (image == NULL) return NULL; image->internal_format = rb->InternalFormat; image->format = rb->Format; image->offset = 0; image->data = loaderPrivate; drm_intel_bo_unreference(image->bo); image->bo = irb->mt->bo; drm_intel_bo_reference(irb->mt->bo); image->width = rb->Width; image->height = rb->Height; image->pitch = irb->mt->pitch; image->dri_format = driGLFormatToImageFormat(image->format); image->has_depthstencil = irb->mt->stencil_mt? true : false; rb->NeedsFinishRenderTexture = true; return image; }
/** * Prepare the source or destination resource, including: * - Error checking * - Creating texture wrappers for renderbuffers * \param name the texture or renderbuffer name * \param target GL_TEXTURE target or GL_RENDERBUFFER. For the later, will * be changed to a compatible GL_TEXTURE target. * \param level mipmap level * \param tex_obj returns a pointer to a texture object * \param tex_image returns a pointer to a texture image * \param tmp_tex returns temporary texture object name * \return true if success, false if error */ static bool prepare_target(struct gl_context *ctx, GLuint name, GLenum *target, int level, struct gl_texture_object **tex_obj, struct gl_texture_image **tex_image, GLuint *tmp_tex, const char *dbg_prefix) { if (name == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sName = %d)", dbg_prefix, name); return false; } /* * INVALID_ENUM is generated * * if either <srcTarget> or <dstTarget> * - is not RENDERBUFFER or a valid non-proxy texture target * - is TEXTURE_BUFFER, or * - is one of the cubemap face selectors described in table 3.17, */ switch (*target) { case GL_RENDERBUFFER: /* Not a texture target, but valid */ case GL_TEXTURE_1D: case GL_TEXTURE_1D_ARRAY: case GL_TEXTURE_2D: case GL_TEXTURE_3D: case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_RECTANGLE: case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: /* These are all valid */ break; case GL_TEXTURE_EXTERNAL_OES: /* Only exists in ES */ case GL_TEXTURE_BUFFER: default: _mesa_error(ctx, GL_INVALID_ENUM, "glCopyImageSubData(%sTarget = %s)", dbg_prefix, _mesa_lookup_enum_by_nr(*target)); return false; } if (*target == GL_RENDERBUFFER) { struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name); if (!rb) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sName = %u)", dbg_prefix, name); return false; } if (!rb->Name) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyImageSubData(%sName incomplete)", dbg_prefix); return false; } if (level != 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level); return false; } if (rb->NumSamples > 1) *target = GL_TEXTURE_2D_MULTISAMPLE; else *target = GL_TEXTURE_2D; *tmp_tex = 0; _mesa_GenTextures(1, tmp_tex); if (*tmp_tex == 0) return false; /* Error already set by GenTextures */ _mesa_BindTexture(*target, *tmp_tex); *tex_obj = _mesa_lookup_texture(ctx, *tmp_tex); *tex_image = _mesa_get_tex_image(ctx, *tex_obj, *target, 0); if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, *tex_image)) { _mesa_problem(ctx, "Failed to create texture from renderbuffer"); return false; } if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) { rb->NeedsFinishRenderTexture = true; ctx->Driver.FinishRenderTexture(ctx, rb); } } else { *tex_obj = _mesa_lookup_texture(ctx, name); if (!*tex_obj) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sName = %u)", dbg_prefix, name); return false; } _mesa_test_texobj_completeness(ctx, *tex_obj); if (!(*tex_obj)->_BaseComplete || (level != 0 && !(*tex_obj)->_MipmapComplete)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyImageSubData(%sName incomplete)", dbg_prefix); return false; } if ((*tex_obj)->Target != *target) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyImageSubData(%sTarget = %s)", dbg_prefix, _mesa_lookup_enum_by_nr(*target)); return false; } if (level < 0 || level >= MAX_TEXTURE_LEVELS) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sLevel = %d)", dbg_prefix, level); return false; } *tex_image = _mesa_select_tex_image(*tex_obj, *target, level); if (!*tex_image) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level); return false; } } return true; }
void GLAPIENTRY _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbufferTarget, GLuint renderbuffer) { struct gl_renderbuffer_attachment *att; struct gl_framebuffer *fb; struct gl_renderbuffer *rb; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); switch (target) { #if FEATURE_EXT_framebuffer_blit case GL_DRAW_FRAMEBUFFER_EXT: if (!ctx->Extensions.EXT_framebuffer_blit) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)"); return; } fb = ctx->DrawBuffer; break; case GL_READ_FRAMEBUFFER_EXT: if (!ctx->Extensions.EXT_framebuffer_blit) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)"); return; } fb = ctx->ReadBuffer; break; #endif case GL_FRAMEBUFFER_EXT: fb = ctx->DrawBuffer; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)"); return; } if (renderbufferTarget != GL_RENDERBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(renderbufferTarget)"); return; } if (fb->Name == 0) { /* Can't attach new renderbuffers to a window system framebuffer */ _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT"); return; } att = _mesa_get_attachment(ctx, fb, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(attachment)"); return; } if (renderbuffer) { rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); if (!rb) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT(renderbuffer)"); return; } } else { /* remove renderbuffer attachment */ rb = NULL; } 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); assert(ctx->Driver.FramebufferRenderbuffer); ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb); /* Some subsequent GL commands may depend on the framebuffer's visual * after the binding is updated. Update visual info now. */ _mesa_update_framebuffer_visual(fb); }
/** * Prepare the source or destination resource. This involves error * checking and returning the relevant gl_texture_image or gl_renderbuffer. * Note that one of the resulting tex_image or renderbuffer pointers will be * NULL and the other will be non-null. * * \param name the texture or renderbuffer name * \param target One of GL_TEXTURE_x target or GL_RENDERBUFFER * \param level mipmap level * \param z src or dest Z * \param depth number of slices/faces/layers to copy * \param tex_image returns a pointer to a texture image * \param renderbuffer returns a pointer to a renderbuffer * \return true if success, false if error */ static bool prepare_target(struct gl_context *ctx, GLuint name, GLenum target, int level, int z, int depth, struct gl_texture_image **tex_image, struct gl_renderbuffer **renderbuffer, mesa_format *format, GLenum *internalFormat, GLuint *width, GLuint *height, GLuint *num_samples, const char *dbg_prefix) { if (name == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sName = %d)", dbg_prefix, name); return false; } /* * INVALID_ENUM is generated * * if either <srcTarget> or <dstTarget> * - is not RENDERBUFFER or a valid non-proxy texture target * - is TEXTURE_BUFFER, or * - is one of the cubemap face selectors described in table 3.17, */ switch (target) { case GL_RENDERBUFFER: /* Not a texture target, but valid */ case GL_TEXTURE_1D: case GL_TEXTURE_1D_ARRAY: case GL_TEXTURE_2D: case GL_TEXTURE_3D: case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_RECTANGLE: case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: /* These are all valid */ break; case GL_TEXTURE_EXTERNAL_OES: /* Only exists in ES */ case GL_TEXTURE_BUFFER: default: _mesa_error(ctx, GL_INVALID_ENUM, "glCopyImageSubData(%sTarget = %s)", dbg_prefix, _mesa_enum_to_string(target)); return false; } if (target == GL_RENDERBUFFER) { struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name); if (!rb) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sName = %u)", dbg_prefix, name); return false; } if (!rb->Name) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyImageSubData(%sName incomplete)", dbg_prefix); return false; } if (level != 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level); return false; } *renderbuffer = rb; *format = rb->Format; *internalFormat = rb->InternalFormat; *width = rb->Width; *height = rb->Height; *num_samples = rb->NumSamples; *tex_image = NULL; } else { struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name); if (!texObj) { /* * From GL_ARB_copy_image specification: * "INVALID_VALUE is generated if either <srcName> or <dstName> does * not correspond to a valid renderbuffer or texture object according * to the corresponding target parameter." */ _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sName = %u)", dbg_prefix, name); return false; } _mesa_test_texobj_completeness(ctx, texObj); if (!texObj->_BaseComplete || (level != 0 && !texObj->_MipmapComplete)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyImageSubData(%sName incomplete)", dbg_prefix); return false; } /* Note that target will not be a cube face name */ if (texObj->Target != target) { /* * From GL_ARB_copy_image_specification: * "INVALID_ENUM is generated if the target does not match the type * of the object." */ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyImageSubData(%sTarget = %s)", dbg_prefix, _mesa_enum_to_string(target)); return false; } if (level < 0 || level >= MAX_TEXTURE_LEVELS) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sLevel = %d)", dbg_prefix, level); return false; } if (target == GL_TEXTURE_CUBE_MAP) { int i; assert(z < MAX_FACES); /* should have been caught earlier */ /* make sure all the cube faces are present */ for (i = 0; i < depth; i++) { if (!texObj->Image[z+i][level]) { /* missing cube face */ _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(missing cube face)"); return false; } } *tex_image = texObj->Image[z][level]; } else { *tex_image = _mesa_select_tex_image(texObj, target, level); } if (!*tex_image) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level); return false; } *renderbuffer = NULL; *format = (*tex_image)->TexFormat; *internalFormat = (*tex_image)->InternalFormat; *width = (*tex_image)->Width; *height = (*tex_image)->Height; *num_samples = (*tex_image)->NumSamples; } return true; }