1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26/** 27 * Code related to the GL_APPLE_object_purgeable extension. 28 */ 29 30 31#include "glheader.h" 32#include "enums.h" 33#include "hash.h" 34#include "imports.h" 35#include "context.h" 36#include "bufferobj.h" 37#include "fbobject.h" 38#include "mtypes.h" 39#include "objectpurge.h" 40#include "texobj.h" 41#include "teximage.h" 42 43 44static GLenum 45buffer_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option) 46{ 47 struct gl_buffer_object *bufObj; 48 GLenum retval; 49 50 bufObj = _mesa_lookup_bufferobj(ctx, name); 51 if (!bufObj) { 52 _mesa_error(ctx, GL_INVALID_VALUE, 53 "glObjectPurgeable(name = 0x%x)", name); 54 return 0; 55 } 56 if (!_mesa_is_bufferobj(bufObj)) { 57 _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectPurgeable(buffer 0)" ); 58 return 0; 59 } 60 61 if (bufObj->Purgeable) { 62 _mesa_error(ctx, GL_INVALID_OPERATION, 63 "glObjectPurgeable(name = 0x%x) is already purgeable", name); 64 return GL_VOLATILE_APPLE; 65 } 66 67 bufObj->Purgeable = GL_TRUE; 68 69 retval = GL_VOLATILE_APPLE; 70 if (ctx->Driver.BufferObjectPurgeable) 71 retval = ctx->Driver.BufferObjectPurgeable(ctx, bufObj, option); 72 73 return retval; 74} 75 76 77static GLenum 78renderbuffer_purgeable(struct gl_context *ctx, GLuint name, GLenum option) 79{ 80 struct gl_renderbuffer *bufObj; 81 GLenum retval; 82 83 bufObj = _mesa_lookup_renderbuffer(ctx, name); 84 if (!bufObj) { 85 _mesa_error(ctx, GL_INVALID_VALUE, 86 "glObjectUnpurgeable(name = 0x%x)", name); 87 return 0; 88 } 89 90 if (bufObj->Purgeable) { 91 _mesa_error(ctx, GL_INVALID_OPERATION, 92 "glObjectPurgeable(name = 0x%x) is already purgeable", name); 93 return GL_VOLATILE_APPLE; 94 } 95 96 bufObj->Purgeable = GL_TRUE; 97 98 retval = GL_VOLATILE_APPLE; 99 if (ctx->Driver.RenderObjectPurgeable) 100 retval = ctx->Driver.RenderObjectPurgeable(ctx, bufObj, option); 101 102 return retval; 103} 104 105 106static GLenum 107texture_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option) 108{ 109 struct gl_texture_object *bufObj; 110 GLenum retval; 111 112 bufObj = _mesa_lookup_texture(ctx, name); 113 if (!bufObj) { 114 _mesa_error(ctx, GL_INVALID_VALUE, 115 "glObjectPurgeable(name = 0x%x)", name); 116 return 0; 117 } 118 119 if (bufObj->Purgeable) { 120 _mesa_error(ctx, GL_INVALID_OPERATION, 121 "glObjectPurgeable(name = 0x%x) is already purgeable", name); 122 return GL_VOLATILE_APPLE; 123 } 124 125 bufObj->Purgeable = GL_TRUE; 126 127 retval = GL_VOLATILE_APPLE; 128 if (ctx->Driver.TextureObjectPurgeable) 129 retval = ctx->Driver.TextureObjectPurgeable(ctx, bufObj, option); 130 131 return retval; 132} 133 134 135GLenum GLAPIENTRY 136_mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) 137{ 138 GLenum retval; 139 140 GET_CURRENT_CONTEXT(ctx); 141 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); 142 143 if (name == 0) { 144 _mesa_error(ctx, GL_INVALID_VALUE, 145 "glObjectPurgeable(name = 0x%x)", name); 146 return 0; 147 } 148 149 switch (option) { 150 case GL_VOLATILE_APPLE: 151 case GL_RELEASED_APPLE: 152 /* legal */ 153 break; 154 default: 155 _mesa_error(ctx, GL_INVALID_ENUM, 156 "glObjectPurgeable(name = 0x%x) invalid option: %d", 157 name, option); 158 return 0; 159 } 160 161 switch (objectType) { 162 case GL_TEXTURE: 163 retval = texture_object_purgeable(ctx, name, option); 164 break; 165 case GL_RENDERBUFFER_EXT: 166 retval = renderbuffer_purgeable(ctx, name, option); 167 break; 168 case GL_BUFFER_OBJECT_APPLE: 169 retval = buffer_object_purgeable(ctx, name, option); 170 break; 171 default: 172 _mesa_error(ctx, GL_INVALID_ENUM, 173 "glObjectPurgeable(name = 0x%x) invalid type: %d", 174 name, objectType); 175 return 0; 176 } 177 178 /* In strict conformance to the spec, we must only return VOLATILE when 179 * when passed the VOLATILE option. Madness. 180 * 181 * XXX First fix the spec, then fix me. 182 */ 183 return option == GL_VOLATILE_APPLE ? GL_VOLATILE_APPLE : retval; 184} 185 186 187static GLenum 188buffer_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option) 189{ 190 struct gl_buffer_object *bufObj; 191 GLenum retval; 192 193 bufObj = _mesa_lookup_bufferobj(ctx, name); 194 if (!bufObj) { 195 _mesa_error(ctx, GL_INVALID_VALUE, 196 "glObjectUnpurgeable(name = 0x%x)", name); 197 return 0; 198 } 199 200 if (! bufObj->Purgeable) { 201 _mesa_error(ctx, GL_INVALID_OPERATION, 202 "glObjectUnpurgeable(name = 0x%x) object is " 203 " already \"unpurged\"", name); 204 return 0; 205 } 206 207 bufObj->Purgeable = GL_FALSE; 208 209 retval = option; 210 if (ctx->Driver.BufferObjectUnpurgeable) 211 retval = ctx->Driver.BufferObjectUnpurgeable(ctx, bufObj, option); 212 213 return retval; 214} 215 216 217static GLenum 218renderbuffer_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option) 219{ 220 struct gl_renderbuffer *bufObj; 221 GLenum retval; 222 223 bufObj = _mesa_lookup_renderbuffer(ctx, name); 224 if (!bufObj) { 225 _mesa_error(ctx, GL_INVALID_VALUE, 226 "glObjectUnpurgeable(name = 0x%x)", name); 227 return 0; 228 } 229 230 if (! bufObj->Purgeable) { 231 _mesa_error(ctx, GL_INVALID_OPERATION, 232 "glObjectUnpurgeable(name = 0x%x) object is " 233 " already \"unpurged\"", name); 234 return 0; 235 } 236 237 bufObj->Purgeable = GL_FALSE; 238 239 retval = option; 240 if (ctx->Driver.RenderObjectUnpurgeable) 241 retval = ctx->Driver.RenderObjectUnpurgeable(ctx, bufObj, option); 242 243 return retval; 244} 245 246 247static GLenum 248texture_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option) 249{ 250 struct gl_texture_object *bufObj; 251 GLenum retval; 252 253 bufObj = _mesa_lookup_texture(ctx, name); 254 if (!bufObj) { 255 _mesa_error(ctx, GL_INVALID_VALUE, 256 "glObjectUnpurgeable(name = 0x%x)", name); 257 return 0; 258 } 259 260 if (! bufObj->Purgeable) { 261 _mesa_error(ctx, GL_INVALID_OPERATION, 262 "glObjectUnpurgeable(name = 0x%x) object is" 263 " already \"unpurged\"", name); 264 return 0; 265 } 266 267 bufObj->Purgeable = GL_FALSE; 268 269 retval = option; 270 if (ctx->Driver.TextureObjectUnpurgeable) 271 retval = ctx->Driver.TextureObjectUnpurgeable(ctx, bufObj, option); 272 273 return retval; 274} 275 276 277GLenum GLAPIENTRY 278_mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) 279{ 280 GET_CURRENT_CONTEXT(ctx); 281 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); 282 283 if (name == 0) { 284 _mesa_error(ctx, GL_INVALID_VALUE, 285 "glObjectUnpurgeable(name = 0x%x)", name); 286 return 0; 287 } 288 289 switch (option) { 290 case GL_RETAINED_APPLE: 291 case GL_UNDEFINED_APPLE: 292 /* legal */ 293 break; 294 default: 295 _mesa_error(ctx, GL_INVALID_ENUM, 296 "glObjectUnpurgeable(name = 0x%x) invalid option: %d", 297 name, option); 298 return 0; 299 } 300 301 switch (objectType) { 302 case GL_BUFFER_OBJECT_APPLE: 303 return buffer_object_unpurgeable(ctx, name, option); 304 case GL_TEXTURE: 305 return texture_object_unpurgeable(ctx, name, option); 306 case GL_RENDERBUFFER_EXT: 307 return renderbuffer_unpurgeable(ctx, name, option); 308 default: 309 _mesa_error(ctx, GL_INVALID_ENUM, 310 "glObjectUnpurgeable(name = 0x%x) invalid type: %d", 311 name, objectType); 312 return 0; 313 } 314} 315 316 317static void 318get_buffer_object_parameteriv(struct gl_context *ctx, GLuint name, 319 GLenum pname, GLint *params) 320{ 321 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, name); 322 if (!bufObj) { 323 _mesa_error(ctx, GL_INVALID_VALUE, 324 "glGetObjectParameteriv(name = 0x%x) invalid object", name); 325 return; 326 } 327 328 switch (pname) { 329 case GL_PURGEABLE_APPLE: 330 *params = bufObj->Purgeable; 331 break; 332 default: 333 _mesa_error(ctx, GL_INVALID_ENUM, 334 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", 335 name, pname); 336 break; 337 } 338} 339 340 341static void 342get_renderbuffer_parameteriv(struct gl_context *ctx, GLuint name, 343 GLenum pname, GLint *params) 344{ 345 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name); 346 if (!rb) { 347 _mesa_error(ctx, GL_INVALID_VALUE, 348 "glObjectUnpurgeable(name = 0x%x)", name); 349 return; 350 } 351 352 switch (pname) { 353 case GL_PURGEABLE_APPLE: 354 *params = rb->Purgeable; 355 break; 356 default: 357 _mesa_error(ctx, GL_INVALID_ENUM, 358 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", 359 name, pname); 360 break; 361 } 362} 363 364 365static void 366get_texture_object_parameteriv(struct gl_context *ctx, GLuint name, 367 GLenum pname, GLint *params) 368{ 369 struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name); 370 if (!texObj) { 371 _mesa_error(ctx, GL_INVALID_VALUE, 372 "glObjectUnpurgeable(name = 0x%x)", name); 373 return; 374 } 375 376 switch (pname) { 377 case GL_PURGEABLE_APPLE: 378 *params = texObj->Purgeable; 379 break; 380 default: 381 _mesa_error(ctx, GL_INVALID_ENUM, 382 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", 383 name, pname); 384 break; 385 } 386} 387 388 389void GLAPIENTRY 390_mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname, 391 GLint *params) 392{ 393 GET_CURRENT_CONTEXT(ctx); 394 395 if (name == 0) { 396 _mesa_error(ctx, GL_INVALID_VALUE, 397 "glGetObjectParameteriv(name = 0x%x)", name); 398 return; 399 } 400 401 switch (objectType) { 402 case GL_TEXTURE: 403 get_texture_object_parameteriv(ctx, name, pname, params); 404 break; 405 case GL_BUFFER_OBJECT_APPLE: 406 get_buffer_object_parameteriv(ctx, name, pname, params); 407 break; 408 case GL_RENDERBUFFER_EXT: 409 get_renderbuffer_parameteriv(ctx, name, pname, params); 410 break; 411 default: 412 _mesa_error(ctx, GL_INVALID_ENUM, 413 "glGetObjectParameteriv(name = 0x%x) invalid type: %d", 414 name, objectType); 415 } 416} 417