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 
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    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 
77 static GLenum
renderbuffer_purgeable(struct gl_context * ctx,GLuint name,GLenum option)78 renderbuffer_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 
106 static GLenum
texture_object_purgeable(struct gl_context * ctx,GLuint name,GLenum option)107 texture_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 
135 GLenum GLAPIENTRY
_mesa_ObjectPurgeableAPPLE(GLenum objectType,GLuint name,GLenum option)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 
187 static GLenum
buffer_object_unpurgeable(struct gl_context * ctx,GLuint name,GLenum option)188 buffer_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 
217 static GLenum
renderbuffer_unpurgeable(struct gl_context * ctx,GLuint name,GLenum option)218 renderbuffer_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 
247 static GLenum
texture_object_unpurgeable(struct gl_context * ctx,GLuint name,GLenum option)248 texture_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 
277 GLenum GLAPIENTRY
_mesa_ObjectUnpurgeableAPPLE(GLenum objectType,GLuint name,GLenum option)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 
317 static void
get_buffer_object_parameteriv(struct gl_context * ctx,GLuint name,GLenum pname,GLint * params)318 get_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 
341 static void
get_renderbuffer_parameteriv(struct gl_context * ctx,GLuint name,GLenum pname,GLint * params)342 get_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 
365 static void
get_texture_object_parameteriv(struct gl_context * ctx,GLuint name,GLenum pname,GLint * params)366 get_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 
389 void GLAPIENTRY
_mesa_GetObjectParameterivAPPLE(GLenum objectType,GLuint name,GLenum pname,GLint * params)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