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