/* * Mesa 3-D graphics library * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. * Copyright (C) 2009 VMware, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ /** * Code related to the GL_APPLE_object_purgeable extension. */ #include "glheader.h" #include "enums.h" #include "hash.h" #include "util/imports.h" #include "context.h" #include "bufferobj.h" #include "fbobject.h" #include "mtypes.h" #include "objectpurge.h" #include "texobj.h" #include "teximage.h" static GLenum buffer_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option) { struct gl_buffer_object *bufObj; GLenum retval; bufObj = _mesa_lookup_bufferobj(ctx, name); if (!bufObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glObjectPurgeable(name = 0x%x)", name); return 0; } if (!_mesa_is_bufferobj(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectPurgeable(buffer 0)" ); return 0; } if (bufObj->Purgeable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectPurgeable(name = 0x%x) is already purgeable", name); return GL_VOLATILE_APPLE; } bufObj->Purgeable = GL_TRUE; retval = GL_VOLATILE_APPLE; if (ctx->Driver.BufferObjectPurgeable) retval = ctx->Driver.BufferObjectPurgeable(ctx, bufObj, option); return retval; } static GLenum renderbuffer_purgeable(struct gl_context *ctx, GLuint name, GLenum option) { struct gl_renderbuffer *bufObj; GLenum retval; bufObj = _mesa_lookup_renderbuffer(ctx, name); if (!bufObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glObjectUnpurgeable(name = 0x%x)", name); return 0; } if (bufObj->Purgeable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectPurgeable(name = 0x%x) is already purgeable", name); return GL_VOLATILE_APPLE; } bufObj->Purgeable = GL_TRUE; retval = GL_VOLATILE_APPLE; if (ctx->Driver.RenderObjectPurgeable) retval = ctx->Driver.RenderObjectPurgeable(ctx, bufObj, option); return retval; } static GLenum texture_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option) { struct gl_texture_object *bufObj; GLenum retval; bufObj = _mesa_lookup_texture(ctx, name); if (!bufObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glObjectPurgeable(name = 0x%x)", name); return 0; } if (bufObj->Purgeable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectPurgeable(name = 0x%x) is already purgeable", name); return GL_VOLATILE_APPLE; } bufObj->Purgeable = GL_TRUE; retval = GL_VOLATILE_APPLE; if (ctx->Driver.TextureObjectPurgeable) retval = ctx->Driver.TextureObjectPurgeable(ctx, bufObj, option); return retval; } GLenum GLAPIENTRY _mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) { GLenum retval; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); if (name == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glObjectPurgeable(name = 0x%x)", name); return 0; } switch (option) { case GL_VOLATILE_APPLE: case GL_RELEASED_APPLE: /* legal */ break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glObjectPurgeable(name = 0x%x) invalid option: %d", name, option); return 0; } switch (objectType) { case GL_TEXTURE: retval = texture_object_purgeable(ctx, name, option); break; case GL_RENDERBUFFER_EXT: retval = renderbuffer_purgeable(ctx, name, option); break; case GL_BUFFER_OBJECT_APPLE: retval = buffer_object_purgeable(ctx, name, option); break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glObjectPurgeable(name = 0x%x) invalid type: %d", name, objectType); return 0; } /* In strict conformance to the spec, we must only return VOLATILE when * when passed the VOLATILE option. Madness. * * XXX First fix the spec, then fix me. */ return option == GL_VOLATILE_APPLE ? GL_VOLATILE_APPLE : retval; } static GLenum buffer_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option) { struct gl_buffer_object *bufObj; GLenum retval; bufObj = _mesa_lookup_bufferobj(ctx, name); if (!bufObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glObjectUnpurgeable(name = 0x%x)", name); return 0; } if (! bufObj->Purgeable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectUnpurgeable(name = 0x%x) object is " " already \"unpurged\"", name); return 0; } bufObj->Purgeable = GL_FALSE; retval = option; if (ctx->Driver.BufferObjectUnpurgeable) retval = ctx->Driver.BufferObjectUnpurgeable(ctx, bufObj, option); return retval; } static GLenum renderbuffer_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option) { struct gl_renderbuffer *bufObj; GLenum retval; bufObj = _mesa_lookup_renderbuffer(ctx, name); if (!bufObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glObjectUnpurgeable(name = 0x%x)", name); return 0; } if (! bufObj->Purgeable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectUnpurgeable(name = 0x%x) object is " " already \"unpurged\"", name); return 0; } bufObj->Purgeable = GL_FALSE; retval = option; if (ctx->Driver.RenderObjectUnpurgeable) retval = ctx->Driver.RenderObjectUnpurgeable(ctx, bufObj, option); return retval; } static GLenum texture_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option) { struct gl_texture_object *bufObj; GLenum retval; bufObj = _mesa_lookup_texture(ctx, name); if (!bufObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glObjectUnpurgeable(name = 0x%x)", name); return 0; } if (! bufObj->Purgeable) { _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectUnpurgeable(name = 0x%x) object is" " already \"unpurged\"", name); return 0; } bufObj->Purgeable = GL_FALSE; retval = option; if (ctx->Driver.TextureObjectUnpurgeable) retval = ctx->Driver.TextureObjectUnpurgeable(ctx, bufObj, option); return retval; } GLenum GLAPIENTRY _mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); if (name == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glObjectUnpurgeable(name = 0x%x)", name); return 0; } switch (option) { case GL_RETAINED_APPLE: case GL_UNDEFINED_APPLE: /* legal */ break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glObjectUnpurgeable(name = 0x%x) invalid option: %d", name, option); return 0; } switch (objectType) { case GL_BUFFER_OBJECT_APPLE: return buffer_object_unpurgeable(ctx, name, option); case GL_TEXTURE: return texture_object_unpurgeable(ctx, name, option); case GL_RENDERBUFFER_EXT: return renderbuffer_unpurgeable(ctx, name, option); default: _mesa_error(ctx, GL_INVALID_ENUM, "glObjectUnpurgeable(name = 0x%x) invalid type: %d", name, objectType); return 0; } } static void get_buffer_object_parameteriv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params) { struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, name); if (!bufObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectParameteriv(name = 0x%x) invalid object", name); return; } switch (pname) { case GL_PURGEABLE_APPLE: *params = bufObj->Purgeable; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", name, pname); break; } } static void get_renderbuffer_parameteriv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params) { struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name); if (!rb) { _mesa_error(ctx, GL_INVALID_VALUE, "glObjectUnpurgeable(name = 0x%x)", name); return; } switch (pname) { case GL_PURGEABLE_APPLE: *params = rb->Purgeable; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", name, pname); break; } } static void get_texture_object_parameteriv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params) { struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name); if (!texObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glObjectUnpurgeable(name = 0x%x)", name); return; } switch (pname) { case GL_PURGEABLE_APPLE: *params = texObj->Purgeable; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", name, pname); break; } } void GLAPIENTRY _mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname, GLint *params) { GET_CURRENT_CONTEXT(ctx); if (name == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectParameteriv(name = 0x%x)", name); return; } switch (objectType) { case GL_TEXTURE: get_texture_object_parameteriv(ctx, name, pname, params); break; case GL_BUFFER_OBJECT_APPLE: get_buffer_object_parameteriv(ctx, name, pname, params); break; case GL_RENDERBUFFER_EXT: get_renderbuffer_parameteriv(ctx, name, pname, params); break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetObjectParameteriv(name = 0x%x) invalid type: %d", name, objectType); } }