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
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
44 static GLenum
buffer_object_purgeable(struct gl_context * ctx,GLuint name,GLenum option)45 buffer_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
57 if (bufObj->Purgeable) {
58 _mesa_error(ctx, GL_INVALID_OPERATION,
59 "glObjectPurgeable(name = 0x%x) is already purgeable", name);
60 return GL_VOLATILE_APPLE;
61 }
62
63 bufObj->Purgeable = GL_TRUE;
64
65 retval = GL_VOLATILE_APPLE;
66 if (ctx->Driver.BufferObjectPurgeable)
67 retval = ctx->Driver.BufferObjectPurgeable(ctx, bufObj, option);
68
69 return retval;
70 }
71
72
73 static GLenum
renderbuffer_purgeable(struct gl_context * ctx,GLuint name,GLenum option)74 renderbuffer_purgeable(struct gl_context *ctx, GLuint name, GLenum option)
75 {
76 struct gl_renderbuffer *bufObj;
77 GLenum retval;
78
79 bufObj = _mesa_lookup_renderbuffer(ctx, name);
80 if (!bufObj) {
81 _mesa_error(ctx, GL_INVALID_VALUE,
82 "glObjectUnpurgeable(name = 0x%x)", name);
83 return 0;
84 }
85
86 if (bufObj->Purgeable) {
87 _mesa_error(ctx, GL_INVALID_OPERATION,
88 "glObjectPurgeable(name = 0x%x) is already purgeable", name);
89 return GL_VOLATILE_APPLE;
90 }
91
92 bufObj->Purgeable = GL_TRUE;
93
94 retval = GL_VOLATILE_APPLE;
95 if (ctx->Driver.RenderObjectPurgeable)
96 retval = ctx->Driver.RenderObjectPurgeable(ctx, bufObj, option);
97
98 return retval;
99 }
100
101
102 static GLenum
texture_object_purgeable(struct gl_context * ctx,GLuint name,GLenum option)103 texture_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option)
104 {
105 struct gl_texture_object *bufObj;
106 GLenum retval;
107
108 bufObj = _mesa_lookup_texture(ctx, name);
109 if (!bufObj) {
110 _mesa_error(ctx, GL_INVALID_VALUE,
111 "glObjectPurgeable(name = 0x%x)", name);
112 return 0;
113 }
114
115 if (bufObj->Purgeable) {
116 _mesa_error(ctx, GL_INVALID_OPERATION,
117 "glObjectPurgeable(name = 0x%x) is already purgeable", name);
118 return GL_VOLATILE_APPLE;
119 }
120
121 bufObj->Purgeable = GL_TRUE;
122
123 retval = GL_VOLATILE_APPLE;
124 if (ctx->Driver.TextureObjectPurgeable)
125 retval = ctx->Driver.TextureObjectPurgeable(ctx, bufObj, option);
126
127 return retval;
128 }
129
130
131 GLenum GLAPIENTRY
_mesa_ObjectPurgeableAPPLE(GLenum objectType,GLuint name,GLenum option)132 _mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option)
133 {
134 GLenum retval;
135
136 GET_CURRENT_CONTEXT(ctx);
137 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
138
139 if (name == 0) {
140 _mesa_error(ctx, GL_INVALID_VALUE,
141 "glObjectPurgeable(name = 0x%x)", name);
142 return 0;
143 }
144
145 switch (option) {
146 case GL_VOLATILE_APPLE:
147 case GL_RELEASED_APPLE:
148 /* legal */
149 break;
150 default:
151 _mesa_error(ctx, GL_INVALID_ENUM,
152 "glObjectPurgeable(name = 0x%x) invalid option: %d",
153 name, option);
154 return 0;
155 }
156
157 switch (objectType) {
158 case GL_TEXTURE:
159 retval = texture_object_purgeable(ctx, name, option);
160 break;
161 case GL_RENDERBUFFER_EXT:
162 retval = renderbuffer_purgeable(ctx, name, option);
163 break;
164 case GL_BUFFER_OBJECT_APPLE:
165 retval = buffer_object_purgeable(ctx, name, option);
166 break;
167 default:
168 _mesa_error(ctx, GL_INVALID_ENUM,
169 "glObjectPurgeable(name = 0x%x) invalid type: %d",
170 name, objectType);
171 return 0;
172 }
173
174 /* In strict conformance to the spec, we must only return VOLATILE when
175 * when passed the VOLATILE option. Madness.
176 *
177 * XXX First fix the spec, then fix me.
178 */
179 return option == GL_VOLATILE_APPLE ? GL_VOLATILE_APPLE : retval;
180 }
181
182
183 static GLenum
buffer_object_unpurgeable(struct gl_context * ctx,GLuint name,GLenum option)184 buffer_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
185 {
186 struct gl_buffer_object *bufObj;
187 GLenum retval;
188
189 bufObj = _mesa_lookup_bufferobj(ctx, name);
190 if (!bufObj) {
191 _mesa_error(ctx, GL_INVALID_VALUE,
192 "glObjectUnpurgeable(name = 0x%x)", name);
193 return 0;
194 }
195
196 if (! bufObj->Purgeable) {
197 _mesa_error(ctx, GL_INVALID_OPERATION,
198 "glObjectUnpurgeable(name = 0x%x) object is "
199 " already \"unpurged\"", name);
200 return 0;
201 }
202
203 bufObj->Purgeable = GL_FALSE;
204
205 retval = option;
206 if (ctx->Driver.BufferObjectUnpurgeable)
207 retval = ctx->Driver.BufferObjectUnpurgeable(ctx, bufObj, option);
208
209 return retval;
210 }
211
212
213 static GLenum
renderbuffer_unpurgeable(struct gl_context * ctx,GLuint name,GLenum option)214 renderbuffer_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
215 {
216 struct gl_renderbuffer *bufObj;
217 GLenum retval;
218
219 bufObj = _mesa_lookup_renderbuffer(ctx, name);
220 if (!bufObj) {
221 _mesa_error(ctx, GL_INVALID_VALUE,
222 "glObjectUnpurgeable(name = 0x%x)", name);
223 return 0;
224 }
225
226 if (! bufObj->Purgeable) {
227 _mesa_error(ctx, GL_INVALID_OPERATION,
228 "glObjectUnpurgeable(name = 0x%x) object is "
229 " already \"unpurged\"", name);
230 return 0;
231 }
232
233 bufObj->Purgeable = GL_FALSE;
234
235 retval = option;
236 if (ctx->Driver.RenderObjectUnpurgeable)
237 retval = ctx->Driver.RenderObjectUnpurgeable(ctx, bufObj, option);
238
239 return retval;
240 }
241
242
243 static GLenum
texture_object_unpurgeable(struct gl_context * ctx,GLuint name,GLenum option)244 texture_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
245 {
246 struct gl_texture_object *bufObj;
247 GLenum retval;
248
249 bufObj = _mesa_lookup_texture(ctx, name);
250 if (!bufObj) {
251 _mesa_error(ctx, GL_INVALID_VALUE,
252 "glObjectUnpurgeable(name = 0x%x)", name);
253 return 0;
254 }
255
256 if (! bufObj->Purgeable) {
257 _mesa_error(ctx, GL_INVALID_OPERATION,
258 "glObjectUnpurgeable(name = 0x%x) object is"
259 " already \"unpurged\"", name);
260 return 0;
261 }
262
263 bufObj->Purgeable = GL_FALSE;
264
265 retval = option;
266 if (ctx->Driver.TextureObjectUnpurgeable)
267 retval = ctx->Driver.TextureObjectUnpurgeable(ctx, bufObj, option);
268
269 return retval;
270 }
271
272
273 GLenum GLAPIENTRY
_mesa_ObjectUnpurgeableAPPLE(GLenum objectType,GLuint name,GLenum option)274 _mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option)
275 {
276 GET_CURRENT_CONTEXT(ctx);
277 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
278
279 if (name == 0) {
280 _mesa_error(ctx, GL_INVALID_VALUE,
281 "glObjectUnpurgeable(name = 0x%x)", name);
282 return 0;
283 }
284
285 switch (option) {
286 case GL_RETAINED_APPLE:
287 case GL_UNDEFINED_APPLE:
288 /* legal */
289 break;
290 default:
291 _mesa_error(ctx, GL_INVALID_ENUM,
292 "glObjectUnpurgeable(name = 0x%x) invalid option: %d",
293 name, option);
294 return 0;
295 }
296
297 switch (objectType) {
298 case GL_BUFFER_OBJECT_APPLE:
299 return buffer_object_unpurgeable(ctx, name, option);
300 case GL_TEXTURE:
301 return texture_object_unpurgeable(ctx, name, option);
302 case GL_RENDERBUFFER_EXT:
303 return renderbuffer_unpurgeable(ctx, name, option);
304 default:
305 _mesa_error(ctx, GL_INVALID_ENUM,
306 "glObjectUnpurgeable(name = 0x%x) invalid type: %d",
307 name, objectType);
308 return 0;
309 }
310 }
311
312
313 static void
get_buffer_object_parameteriv(struct gl_context * ctx,GLuint name,GLenum pname,GLint * params)314 get_buffer_object_parameteriv(struct gl_context *ctx, GLuint name,
315 GLenum pname, GLint *params)
316 {
317 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, name);
318 if (!bufObj) {
319 _mesa_error(ctx, GL_INVALID_VALUE,
320 "glGetObjectParameteriv(name = 0x%x) invalid object", name);
321 return;
322 }
323
324 switch (pname) {
325 case GL_PURGEABLE_APPLE:
326 *params = bufObj->Purgeable;
327 break;
328 default:
329 _mesa_error(ctx, GL_INVALID_ENUM,
330 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
331 name, pname);
332 break;
333 }
334 }
335
336
337 static void
get_renderbuffer_parameteriv(struct gl_context * ctx,GLuint name,GLenum pname,GLint * params)338 get_renderbuffer_parameteriv(struct gl_context *ctx, GLuint name,
339 GLenum pname, GLint *params)
340 {
341 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name);
342 if (!rb) {
343 _mesa_error(ctx, GL_INVALID_VALUE,
344 "glObjectUnpurgeable(name = 0x%x)", name);
345 return;
346 }
347
348 switch (pname) {
349 case GL_PURGEABLE_APPLE:
350 *params = rb->Purgeable;
351 break;
352 default:
353 _mesa_error(ctx, GL_INVALID_ENUM,
354 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
355 name, pname);
356 break;
357 }
358 }
359
360
361 static void
get_texture_object_parameteriv(struct gl_context * ctx,GLuint name,GLenum pname,GLint * params)362 get_texture_object_parameteriv(struct gl_context *ctx, GLuint name,
363 GLenum pname, GLint *params)
364 {
365 struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
366 if (!texObj) {
367 _mesa_error(ctx, GL_INVALID_VALUE,
368 "glObjectUnpurgeable(name = 0x%x)", name);
369 return;
370 }
371
372 switch (pname) {
373 case GL_PURGEABLE_APPLE:
374 *params = texObj->Purgeable;
375 break;
376 default:
377 _mesa_error(ctx, GL_INVALID_ENUM,
378 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
379 name, pname);
380 break;
381 }
382 }
383
384
385 void GLAPIENTRY
_mesa_GetObjectParameterivAPPLE(GLenum objectType,GLuint name,GLenum pname,GLint * params)386 _mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname,
387 GLint *params)
388 {
389 GET_CURRENT_CONTEXT(ctx);
390
391 if (name == 0) {
392 _mesa_error(ctx, GL_INVALID_VALUE,
393 "glGetObjectParameteriv(name = 0x%x)", name);
394 return;
395 }
396
397 switch (objectType) {
398 case GL_TEXTURE:
399 get_texture_object_parameteriv(ctx, name, pname, params);
400 break;
401 case GL_BUFFER_OBJECT_APPLE:
402 get_buffer_object_parameteriv(ctx, name, pname, params);
403 break;
404 case GL_RENDERBUFFER_EXT:
405 get_renderbuffer_parameteriv(ctx, name, pname, params);
406 break;
407 default:
408 _mesa_error(ctx, GL_INVALID_ENUM,
409 "glGetObjectParameteriv(name = 0x%x) invalid type: %d",
410 name, objectType);
411 }
412 }
413