void _mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target, struct fb_tex_blit_state *blit) { /* Restore texture object state, the texture binding will * be restored by _mesa_meta_end(). */ if (target != GL_TEXTURE_RECTANGLE_ARB) { _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, blit->baseLevelSave); _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, blit->maxLevelSave); if (ctx->Extensions.ARB_stencil_texturing) { const struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target); if (texObj->StencilSampling != blit->stencilSamplingSave) _mesa_TexParameteri(target, GL_DEPTH_STENCIL_TEXTURE_MODE, blit->stencilSamplingSave ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT); } } _mesa_BindSampler(ctx->Texture.CurrentUnit, blit->samplerSave); _mesa_DeleteSamplers(1, &blit->sampler); if (blit->tempTex) _mesa_DeleteTextures(1, &blit->tempTex); }
void GLAPIENTRY _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (getcompressedteximage_error_check(ctx, target, level, img)) { return; } if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) { /* not an error, do nothing */ return; } texObj = _mesa_get_current_tex_object(ctx, target); texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { _mesa_debug(ctx, "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n", texObj->Name, _mesa_get_format_name(texImage->TexFormat), texImage->Width, texImage->Height); } _mesa_lock_texture(ctx, texObj); { ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj, texImage); } _mesa_unlock_texture(ctx, texObj); }
void intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint texture_format, __DRIdrawable *dPriv) { struct gl_framebuffer *fb = dPriv->driverPrivate; struct brw_context *brw = pDRICtx->driverPrivate; struct gl_context *ctx = &brw->ctx; struct intel_renderbuffer *rb; struct gl_texture_object *texObj; struct gl_texture_image *texImage; int level = 0, internalFormat = 0; mesa_format texFormat = MESA_FORMAT_NONE; texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) return; if (dPriv->lastStamp != dPriv->dri2.stamp || !pDRICtx->driScreenPriv->dri2.useInvalidate) intel_update_renderbuffers(pDRICtx, dPriv); rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); /* If the miptree isn't set, then intel_update_renderbuffers was unable * to get the BO for the drawable from the window system. */ if (!rb || !rb->mt) return; if (rb->mt->cpp == 4) { if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { internalFormat = GL_RGB; texFormat = MESA_FORMAT_B8G8R8X8_UNORM; } else { internalFormat = GL_RGBA; texFormat = MESA_FORMAT_B8G8R8A8_UNORM; } } else if (rb->mt->cpp == 2) { internalFormat = GL_RGB; texFormat = MESA_FORMAT_B5G6R5_UNORM; } _mesa_lock_texture(&brw->ctx, texObj); texImage = _mesa_get_tex_image(ctx, texObj, target, level); intel_miptree_make_shareable(brw, rb->mt); intel_set_texture_image_bo(ctx, texImage, rb->mt->bo, target, internalFormat, texFormat, 0, rb->Base.Base.Width, rb->Base.Base.Height, rb->mt->pitch, 0, 0, 0); _mesa_unlock_texture(&brw->ctx, texObj); }
void intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint texture_format, __DRIdrawable *dPriv) { struct gl_framebuffer *fb = dPriv->driverPrivate; struct intel_context *intel = pDRICtx->driverPrivate; struct gl_context *ctx = &intel->ctx; struct intel_texture_object *intelObj; struct intel_renderbuffer *rb; struct gl_texture_object *texObj; struct gl_texture_image *texImage; int level = 0, internalFormat = 0; gl_format texFormat = MESA_FORMAT_NONE; texObj = _mesa_get_current_tex_object(ctx, target); intelObj = intel_texture_object(texObj); if (!intelObj) return; if (dPriv->lastStamp != dPriv->dri2.stamp || !pDRICtx->driScreenPriv->dri2.useInvalidate) intel_update_renderbuffers(pDRICtx, dPriv); rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); /* If the region isn't set, then intel_update_renderbuffers was unable * to get the buffers for the drawable. */ if (!rb || !rb->mt) return; if (rb->mt->cpp == 4) { if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { internalFormat = GL_RGB; texFormat = MESA_FORMAT_XRGB8888; } else { internalFormat = GL_RGBA; texFormat = MESA_FORMAT_ARGB8888; } } else if (rb->mt->cpp == 2) { internalFormat = GL_RGB; texFormat = MESA_FORMAT_RGB565; } _mesa_lock_texture(&intel->ctx, texObj); texImage = _mesa_get_tex_image(ctx, texObj, target, level); intel_set_texture_image_region(ctx, texImage, rb->mt->region, target, internalFormat, texFormat, 0, rb->mt->region->width, rb->mt->region->height, 0, 0); _mesa_unlock_texture(&intel->ctx, texObj); }
static GLboolean st_TestProxyTexImage(struct gl_context *ctx, GLenum target, GLint level, gl_format format, GLint width, GLint height, GLint depth, GLint border) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; if (width == 0 || height == 0 || depth == 0) { /* zero-sized images are legal, and always fit! */ return GL_TRUE; } if (pipe->screen->can_create_resource) { /* Ask the gallium driver if the texture is too large */ struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target); struct pipe_resource pt; /* Setup the pipe_resource object */ memset(&pt, 0, sizeof(pt)); pt.target = gl_target_to_pipe(target); pt.format = st_mesa_format_to_pipe_format(format); st_gl_texture_dims_to_pipe_dims(target, width, height, depth, &pt.width0, &pt.height0, &pt.depth0, &pt.array_size); if (level == 0 && (texObj->Sampler.MinFilter == GL_LINEAR || texObj->Sampler.MinFilter == GL_NEAREST)) { /* assume just one mipmap level */ pt.last_level = 0; } else { /* assume a full set of mipmaps */ pt.last_level = _mesa_logbase2(MAX3(width, height, depth)); } return pipe->screen->can_create_resource(pipe->screen, &pt); } else { /* Use core Mesa fallback */ return _mesa_test_proxy_teximage(ctx, target, level, format, width, height, depth, border); } }
void glGetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize, GLvoid *img) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) return; texImage = _mesa_select_tex_image(texObj, target, level); if (!texImage) return; _mesa_get_compressed_texture_image(ctx, texObj, texImage, target, level, bufSize, img, false); }
/** * Get texture image. Called by glGetTexImage. * * \param target texture target. * \param level image level. * \param format pixel data format for returned image. * \param type pixel data type for returned image. * \param bufSize size of the pixels data buffer. * \param pixels returned pixel data. */ void GLAPIENTRY _mesa_GetnTexImageARB( GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid *pixels ) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); if (getteximage_error_check(ctx, target, level, format, type, bufSize, pixels)) { return; } if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { /* not an error, do nothing */ return; } texObj = _mesa_get_current_tex_object(ctx, target); texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (_mesa_is_zero_size_texture(texImage)) return; if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d," " dstFmt=0x%x, dstType=0x%x\n", texObj->Name, _mesa_get_format_name(texImage->TexFormat), texImage->Width, texImage->Height, format, type); } _mesa_lock_texture(ctx, texObj); { ctx->Driver.GetTexImage(ctx, format, type, pixels, texImage); } _mesa_unlock_texture(ctx, texObj); }
/** * Get texture image. Called by glGetTexImage. * * \param target texture target. * \param level image level. * \param format pixel data format for returned image. * \param type pixel data type for returned image. * \param bufSize size of the pixels data buffer. * \param pixels returned pixel data. */ void glGetnTexImageARB(GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, GLvoid *pixels) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; GLenum err; GET_CURRENT_CONTEXT(ctx); /* * This has been moved here because a format/type mismatch can cause a NULL * texImage object, which in turn causes the mismatch error to be * ignored. */ err = _mesa_error_check_format_and_type(ctx, format, type); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glGetnTexImage(format/type)"); return; } /* * Legal target checking has been moved here to prevent exiting with a NULL * texImage object. */ if (!legal_getteximage_target(ctx, target, false)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetnTexImage(target=0x%x)", target); return; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) return; texImage = _mesa_select_tex_image(texObj, target, level); if (!texImage) return; _mesa_get_texture_image(ctx, texObj, texImage, target, level, format, type, bufSize, pixels, false); }
/** * Helper used by _mesa_TexStorage1/2/3D(). */ static void texstorage(GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { struct gl_texture_object *texObj; GLboolean error; GET_CURRENT_CONTEXT(ctx); texObj = _mesa_get_current_tex_object(ctx, target); error = tex_storage_error_check(ctx, dims, target, levels, internalformat, width, height, depth); if (!error) { setup_texstorage(ctx, texObj, dims, levels, internalformat, width, height, depth); } else if (_mesa_is_proxy_texture(target)) { /* clear all image fields for [levels] */ clear_image_fields(ctx, dims, texObj); } }
/** * Helper used by _mesa_TexStorage1/2/3D(). */ static void texstorage(GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, const char *caller) { struct gl_texture_object *texObj; GET_CURRENT_CONTEXT(ctx); /* Check target. This is done here so that texture_storage * can receive unsized formats. */ if (!legal_texobj_target(ctx, dims, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(illegal target=%s)", caller, _mesa_enum_to_string(target)); return; } if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) _mesa_debug(ctx, "%s %s %d %s %d %d %d\n", caller, _mesa_enum_to_string(target), levels, _mesa_enum_to_string(internalformat), width, height, depth); /* Check the format to make sure it is sized. */ if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalformat = %s)", caller, _mesa_enum_to_string(internalformat)); return; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) return; texture_storage(ctx, dims, texObj, target, levels, internalformat, width, height, depth, false); }
static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint texture_format, __DRIdrawable *dPriv) { struct dri_context *dri_ctx; int x, y, w, h; __DRIscreen *sPriv = dPriv->driScreenPriv; struct gl_texture_object *texObj; struct gl_texture_image *texImage; struct swrast_texture_image *swImage; uint32_t internalFormat; mesa_format texFormat; dri_ctx = pDRICtx->driverPrivate; internalFormat = (texture_format == __DRI_TEXTURE_FORMAT_RGB ? 3 : 4); texObj = _mesa_get_current_tex_object(&dri_ctx->Base, target); texImage = _mesa_get_tex_image(&dri_ctx->Base, texObj, target, 0); swImage = swrast_texture_image(texImage); _mesa_lock_texture(&dri_ctx->Base, texObj); sPriv->swrast_loader->getDrawableInfo(dPriv, &x, &y, &w, &h, dPriv->loaderPrivate); if (texture_format == __DRI_TEXTURE_FORMAT_RGB) texFormat = MESA_FORMAT_B8G8R8X8_UNORM; else texFormat = MESA_FORMAT_B8G8R8A8_UNORM; _mesa_init_teximage_fields(&dri_ctx->Base, texImage, w, h, 1, 0, internalFormat, texFormat); sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)swImage->Buffer, dPriv->loaderPrivate); _mesa_unlock_texture(&dri_ctx->Base, texObj); }
void _mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target, struct fb_tex_blit_state *blit) { struct gl_texture_object *const texObj = _mesa_get_current_tex_object(ctx, target); /* Restore texture object state, the texture binding will * be restored by _mesa_meta_end(). */ if (target != GL_TEXTURE_RECTANGLE_ARB) { _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL, &blit->baseLevelSave, false); _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, &blit->maxLevelSave, false); } /* If ARB_stencil_texturing is not supported, the mode won't have changed. */ if (texObj->StencilSampling != blit->stencilSamplingSave) { /* GLint so the compiler won't complain about type signedness mismatch * in the call to _mesa_texture_parameteriv below. */ const GLint param = blit->stencilSamplingSave ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT; _mesa_texture_parameteriv(ctx, texObj, GL_DEPTH_STENCIL_TEXTURE_MODE, ¶m, false); } _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, blit->samp_obj_save); _mesa_reference_sampler_object(ctx, &blit->samp_obj_save, NULL); _mesa_reference_sampler_object(ctx, &blit->samp_obj, NULL); if (blit->tempTex) _mesa_DeleteTextures(1, &blit->tempTex); }
/** * Do error checking for a glGetCompressedTexImage() call. * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, GLsizei clientMemSize, GLvoid *img) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLint maxLevels = _mesa_max_texture_levels(ctx, target); GLuint compressedSize; if (!legal_getteximage_target(ctx, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)", target); return GL_TRUE; } assert(maxLevels != 0); if (level < 0 || level >= maxLevels) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(bad level = %d)", level); return GL_TRUE; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); return GL_TRUE; } texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (!texImage) { /* probably invalid mipmap level */ _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); return GL_TRUE; } if (!_mesa_is_format_compressed(texImage->TexFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB(texture is not compressed)"); return GL_TRUE; } compressedSize = _mesa_format_image_size(texImage->TexFormat, texImage->Width, texImage->Height, texImage->Depth); if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* do bounds checking on writing to client memory */ if (clientMemSize < compressedSize) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetnCompressedTexImageARB(out of bounds access:" " bufSize (%d) is too small)", clientMemSize); return GL_TRUE; } } else { /* do bounds checking on PBO write */ if ((const GLubyte *) img + compressedSize > (const GLubyte *) ctx->Pack.BufferObj->Size) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImage(out of bounds PBO access)"); return GL_TRUE; } /* make sure PBO is not mapped */ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImage(PBO is mapped)"); return GL_TRUE; } } return GL_FALSE; }
static boolean st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type tex_type, int level, enum pipe_format pipe_format, struct pipe_resource *tex, boolean mipmap) { struct st_context *st = (struct st_context *) stctxi; struct gl_context *ctx = st->ctx; struct gl_texture_object *texObj; struct gl_texture_image *texImage; struct st_texture_object *stObj; struct st_texture_image *stImage; GLenum internalFormat; GLuint width, height, depth; GLenum target; switch (tex_type) { case ST_TEXTURE_1D: target = GL_TEXTURE_1D; break; case ST_TEXTURE_2D: target = GL_TEXTURE_2D; break; case ST_TEXTURE_3D: target = GL_TEXTURE_3D; break; case ST_TEXTURE_RECT: target = GL_TEXTURE_RECTANGLE_ARB; break; default: return FALSE; } texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); stObj = st_texture_object(texObj); /* switch to surface based */ if (!stObj->surface_based) { _mesa_clear_texture_object(ctx, texObj); stObj->surface_based = GL_TRUE; } texImage = _mesa_get_tex_image(ctx, texObj, target, level); stImage = st_texture_image(texImage); if (tex) { mesa_format texFormat = st_pipe_format_to_mesa_format(pipe_format); if (util_format_has_alpha(tex->format)) internalFormat = GL_RGBA; else internalFormat = GL_RGB; _mesa_init_teximage_fields(ctx, texImage, tex->width0, tex->height0, 1, 0, internalFormat, texFormat); width = tex->width0; height = tex->height0; depth = tex->depth0; /* grow the image size until we hit level = 0 */ while (level > 0) { if (width != 1) width <<= 1; if (height != 1) height <<= 1; if (depth != 1) depth <<= 1; level--; } } else { _mesa_clear_texture_image(ctx, texImage); width = height = depth = 0; } pipe_resource_reference(&stImage->pt, tex); stObj->width0 = width; stObj->height0 = height; stObj->depth0 = depth; stObj->surface_format = pipe_format; _mesa_dirty_texobj(ctx, texObj); _mesa_unlock_texture(ctx, texObj); return TRUE; }
/** * Do error checking for calls to glTexStorage1/2/3D(). * If an error is found, record it with _mesa_error(), unless the target * is a proxy texture. * \return GL_TRUE if any error, GL_FALSE otherwise. */ static GLboolean tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { const GLboolean isProxy = _mesa_is_proxy_texture(target); struct gl_texture_object *texObj; GLuint maxDim; /* size check */ if (width < 1 || height < 1 || depth < 1) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(width, height or depth < 1)", dims); } return GL_TRUE; } /* levels check */ if (levels < 1 || height < 1 || depth < 1) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)", dims); } return GL_TRUE; } /* target check */ if (!legal_texobj_target(ctx, dims, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(illegal target=%s)", dims, _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } /* check levels against maximum */ if (levels > _mesa_max_texture_levels(ctx, target)) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(levels too large)", dims); } return GL_TRUE; } /* check levels against width/height/depth */ maxDim = MAX3(width, height, depth); if (levels > _mesa_logbase2(maxDim) + 1) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(too many levels for max texture dimension)", dims); } return GL_TRUE; } /* non-default texture object check */ texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj || (texObj->Name == 0 && !isProxy)) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(texture object 0)", dims); } return GL_TRUE; } /* Check if texObj->Immutable is set */ if (texObj->Immutable) { if (!isProxy) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(immutable)", dims); } return GL_TRUE; } return GL_FALSE; }
/** * Do error checking for a glGetTexImage() call. * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean getteximage_error_check(GLcontext *ctx, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels ) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLuint maxLevels = _mesa_max_texture_levels(ctx, target); GLenum baseFormat; if (maxLevels == 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target); return GL_TRUE; } if (level < 0 || level >= maxLevels) { _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); return GL_TRUE; } if (_mesa_sizeof_packed_type(type) <= 0) { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); return GL_TRUE; } if (_mesa_components_in_format(format) <= 0 || format == GL_STENCIL_INDEX) { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); return GL_TRUE; } if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); return GL_TRUE; } if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); return GL_TRUE; } if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); return GL_TRUE; } if (!ctx->Extensions.EXT_packed_depth_stencil && _mesa_is_depthstencil_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); return GL_TRUE; } if (!ctx->Extensions.ATI_envmap_bumpmap && _mesa_is_dudv_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); return GL_TRUE; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj || _mesa_is_proxy_texture(target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); return GL_TRUE; } texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (!texImage) { /* out of memory */ return GL_TRUE; } baseFormat = _mesa_get_format_base_format(texImage->TexFormat); /* Make sure the requested image format is compatible with the * texture's format. Note that a color index texture can be converted * to RGBA so that combo is allowed. */ if (_mesa_is_color_format(format) && !_mesa_is_color_format(baseFormat) && !_mesa_is_index_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_index_format(format) && !_mesa_is_index_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_depth_format(format) && !_mesa_is_depth_format(baseFormat) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_ycbcr_format(format) && !_mesa_is_ycbcr_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_depthstencil_format(format) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_dudv_format(format) && !_mesa_is_dudv_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* packing texture image into a PBO */ const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, texImage->Height, texImage->Depth, format, type, pixels)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(out of bounds PBO write)"); return GL_TRUE; } /* PBO should not be mapped */ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(PBO is mapped)"); return GL_TRUE; } } return GL_FALSE; }
/** * Do error checking for a glGetCompressedTexImage() call. * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean getcompressedteximage_error_check(GLcontext *ctx, GLenum target, GLint level, GLvoid *img) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLuint maxLevels = _mesa_max_texture_levels(ctx, target); if (maxLevels == 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)", target); return GL_TRUE; } if (level < 0 || level >= maxLevels) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(bad level = %d)", level); return GL_TRUE; } if (_mesa_is_proxy_texture(target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(bad target = %s)", _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); return GL_TRUE; } texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (!texImage) { /* probably invalid mipmap level */ _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); return GL_TRUE; } if (!_mesa_is_format_compressed(texImage->TexFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB(texture is not compressed)"); return GL_TRUE; } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { GLuint compressedSize; /* make sure PBO is not mapped */ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImage(PBO is mapped)"); return GL_TRUE; } compressedSize = _mesa_format_image_size(texImage->TexFormat, texImage->Width, texImage->Height, texImage->Depth); /* do bounds checking on PBO write */ if ((const GLubyte *) img + compressedSize > (const GLubyte *) ctx->Pack.BufferObj->Size) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImage(out of bounds PBO write)"); return GL_TRUE; } } return GL_FALSE; }
/** * Do error checking for a glGetTexImage() call. * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, GLenum format, GLenum type, GLsizei clientMemSize, GLvoid *pixels ) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLint maxLevels = _mesa_max_texture_levels(ctx, target); const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; GLenum baseFormat, err; if (!legal_getteximage_target(ctx, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target); return GL_TRUE; } assert(maxLevels != 0); if (level < 0 || level >= maxLevels) { _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); return GL_TRUE; } err = _mesa_error_check_format_and_type(ctx, format, type); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glGetTexImage(format/type)"); return GL_TRUE; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); return GL_TRUE; } texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (!texImage) { /* non-existant texture image */ return GL_TRUE; } baseFormat = _mesa_get_format_base_format(texImage->TexFormat); /* Make sure the requested image format is compatible with the * texture's format. */ if (_mesa_is_color_format(format) && !_mesa_is_color_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_depth_format(format) && !_mesa_is_depth_format(baseFormat) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_ycbcr_format(format) && !_mesa_is_ycbcr_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_depthstencil_format(format) && !_mesa_is_depthstencil_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } else if (_mesa_is_dudv_format(format) && !_mesa_is_dudv_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, texImage->Height, texImage->Depth, format, type, clientMemSize, pixels)) { if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(out of bounds PBO access)"); } else { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetnTexImageARB(out of bounds access:" " bufSize (%d) is too small)", clientMemSize); } return GL_TRUE; } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* PBO should not be mapped */ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(PBO is mapped)"); return GL_TRUE; } } return GL_FALSE; }
/** * Helper used by _mesa_TexStorage1/2/3D(). */ static void texstorage(GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { struct gl_texture_object *texObj; GLboolean sizeOK, dimensionsOK; gl_format texFormat; GET_CURRENT_CONTEXT(ctx); if (tex_storage_error_check(ctx, dims, target, levels, internalformat, width, height, depth)) { return; /* error was recorded */ } texObj = _mesa_get_current_tex_object(ctx, target); assert(texObj); texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, internalformat, GL_NONE, GL_NONE); assert(texFormat != MESA_FORMAT_NONE); /* check that width, height, depth are legal for the mipmap level */ dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, width, height, depth, 0); sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 0, texFormat, width, height, depth, 0); if (_mesa_is_proxy_texture(texObj->Target)) { if (dimensionsOK && sizeOK) { initialize_texture_fields(ctx, texObj, levels, width, height, depth, internalformat, texFormat); } else { /* clear all image fields for [levels] */ clear_texture_fields(ctx, texObj); } } else { if (!dimensionsOK) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(invalid width, height or depth)", dims); return; } if (!sizeOK) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage%uD(texture too large)", dims); } assert(levels > 0); assert(width > 0); assert(height > 0); assert(depth > 0); if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth, internalformat, texFormat)) { return; } /* Do actual texture memory allocation */ if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels, width, height, depth)) { /* Reset the texture images' info to zeros. * Strictly speaking, we probably don't have to do this since * generating GL_OUT_OF_MEMORY can leave things in an undefined * state but this puts things in a consistent state. */ clear_texture_fields(ctx, texObj); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage%uD", dims); return; } texObj->Immutable = GL_TRUE; texObj->ImmutableLevels = levels; } }
/** * Do error checking for calls to glTexStorage1/2/3D(). * If an error is found, record it with _mesa_error(), unless the target * is a proxy texture. * \return GL_TRUE if any error, GL_FALSE otherwise. */ static GLboolean tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { struct gl_texture_object *texObj; GLboolean legalFormat; /* check internal format - note that only sized formats are allowed */ switch (internalformat) { case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_INTENSITY: case GL_RED: case GL_RG: case GL_RGB: case GL_RGBA: case GL_BGRA: case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL: case GL_COMPRESSED_ALPHA: case GL_COMPRESSED_LUMINANCE_ALPHA: case GL_COMPRESSED_LUMINANCE: case GL_COMPRESSED_INTENSITY: case GL_COMPRESSED_RGB: case GL_COMPRESSED_RGBA: case GL_COMPRESSED_SRGB: case GL_COMPRESSED_SRGB_ALPHA: case GL_COMPRESSED_SLUMINANCE: case GL_COMPRESSED_SLUMINANCE_ALPHA: case GL_RED_INTEGER: case GL_GREEN_INTEGER: case GL_BLUE_INTEGER: case GL_ALPHA_INTEGER: case GL_RGB_INTEGER: case GL_RGBA_INTEGER: case GL_BGR_INTEGER: case GL_BGRA_INTEGER: case GL_LUMINANCE_INTEGER_EXT: case GL_LUMINANCE_ALPHA_INTEGER_EXT: /* these unsized formats are illegal */ legalFormat = GL_FALSE; break; default: legalFormat = _mesa_base_tex_format(ctx, internalformat) > 0; } if (!legalFormat) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(internalformat = %s)", dims, _mesa_lookup_enum_by_nr(internalformat)); return GL_TRUE; } /* size check */ if (width < 1 || height < 1 || depth < 1) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(width, height or depth < 1)", dims); return GL_TRUE; } /* target check */ if (!legal_texobj_target(ctx, dims, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(illegal target=%s)", dims, _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } /* levels check */ if (levels < 1) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)", dims); return GL_TRUE; } /* check levels against maximum (note different error than above) */ if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(levels too large)", dims); return GL_TRUE; } /* check levels against width/height/depth */ if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(too many levels for max texture dimension)", dims); return GL_TRUE; } /* non-default texture object check */ texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj || (texObj->Name == 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(texture object 0)", dims); return GL_TRUE; } /* Check if texObj->Immutable is set */ if (texObj->Immutable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(immutable)", dims); return GL_TRUE; } return GL_FALSE; }
/** * Generate all the mipmap levels below the base level. * Note: this GL function would be more useful if one could specify a * cube face, a set of array slices, etc. */ void GLAPIENTRY _mesa_GenerateMipmap(GLenum target) { struct gl_texture_image *srcImage; struct gl_texture_object *texObj; GLboolean error; GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); switch (target) { case GL_TEXTURE_1D: error = _mesa_is_gles(ctx); break; case GL_TEXTURE_2D: error = GL_FALSE; break; case GL_TEXTURE_3D: error = ctx->API == API_OPENGLES; break; case GL_TEXTURE_CUBE_MAP: error = !ctx->Extensions.ARB_texture_cube_map; break; case GL_TEXTURE_1D_ARRAY: error = _mesa_is_gles(ctx) || !ctx->Extensions.EXT_texture_array; break; case GL_TEXTURE_2D_ARRAY: error = (_mesa_is_gles(ctx) && ctx->Version < 30) || !ctx->Extensions.EXT_texture_array; break; case GL_TEXTURE_CUBE_MAP_ARRAY: error = _mesa_is_gles(ctx) || !ctx->Extensions.ARB_texture_cube_map_array; break; default: error = GL_TRUE; } if (error) { _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)", _mesa_lookup_enum_by_nr(target)); return; } texObj = _mesa_get_current_tex_object(ctx, target); if (texObj->BaseLevel >= texObj->MaxLevel) { /* nothing to do */ return; } if (texObj->Target == GL_TEXTURE_CUBE_MAP && !_mesa_cube_complete(texObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGenerateMipmap(incomplete cube map)"); return; } _mesa_lock_texture(ctx, texObj); srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel); if (!srcImage) { _mesa_unlock_texture(ctx, texObj); _mesa_error(ctx, GL_INVALID_OPERATION, "glGenerateMipmap(zero size base image)"); return; } if (_mesa_is_enum_format_integer(srcImage->InternalFormat) || _mesa_is_depthstencil_format(srcImage->InternalFormat) || _mesa_is_stencil_format(srcImage->InternalFormat)) { _mesa_unlock_texture(ctx, texObj); _mesa_error(ctx, GL_INVALID_OPERATION, "glGenerateMipmap(invalid internal format)"); return; } if (target == GL_TEXTURE_CUBE_MAP) { GLuint face; for (face = 0; face < 6; face++) ctx->Driver.GenerateMipmap(ctx, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face, texObj); } else { ctx->Driver.GenerateMipmap(ctx, target, texObj); } _mesa_unlock_texture(ctx, texObj); }
/** * Do error checking for calls to glTexStorage1/2/3D(). * If an error is found, record it with _mesa_error(), unless the target * is a proxy texture. * \return GL_TRUE if any error, GL_FALSE otherwise. */ static GLboolean tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { struct gl_texture_object *texObj; if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(internalformat = %s)", dims, _mesa_lookup_enum_by_nr(internalformat)); return GL_TRUE; } /* size check */ if (width < 1 || height < 1 || depth < 1) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(width, height or depth < 1)", dims); return GL_TRUE; } /* target check */ if (!legal_texobj_target(ctx, dims, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(illegal target=%s)", dims, _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec: * * "The ETC2/EAC texture compression algorithm supports only * two-dimensional images. If internalformat is an ETC2/EAC format, * CompressedTexImage3D will generate an INVALID_OPERATION error if * target is not TEXTURE_2D_ARRAY." * * This should also be applicable for glTexStorage3D(). */ if (_mesa_is_compressed_format(ctx, internalformat) && !_mesa_target_can_be_compressed(ctx, target, internalformat)) { _mesa_error(ctx, _mesa_is_desktop_gl(ctx)? GL_INVALID_ENUM : GL_INVALID_OPERATION, "glTexStorage3D(internalformat = %s)", _mesa_lookup_enum_by_nr(internalformat)); } /* levels check */ if (levels < 1) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexStorage%uD(levels < 1)", dims); return GL_TRUE; } /* check levels against maximum (note different error than above) */ if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(levels too large)", dims); return GL_TRUE; } /* check levels against width/height/depth */ if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(too many levels for max texture dimension)", dims); return GL_TRUE; } /* non-default texture object check */ texObj = _mesa_get_current_tex_object(ctx, target); if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(texture object 0)", dims); return GL_TRUE; } /* Check if texObj->Immutable is set */ if (!_mesa_is_proxy_texture(target) && texObj->Immutable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexStorage%uD(immutable)", dims); return GL_TRUE; } /* additional checks for depth textures */ if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat, dims, "glTexStorage")) return GL_TRUE; return GL_FALSE; }