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