2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Functions to implement the GL_ARB_occlusion_query extension.
39 struct occlusion_query
49 * Allocate a new occlusion query object.
50 * \param target - must be GL_SAMPLES_PASSED_ARB at this time
51 * \param id - the object's ID
52 * \return pointer to new occlusion_query object or NULL if out of memory.
54 static struct occlusion_query
*
55 new_query_object(GLenum target
, GLuint id
)
57 struct occlusion_query
*q
= MALLOC_STRUCT(occlusion_query
);
69 * Delete an occlusion query object.
72 delete_query_object(struct occlusion_query
*q
)
79 _mesa_GenQueriesARB(GLsizei n
, GLuint
*ids
)
81 GET_CURRENT_CONTEXT(ctx
);
83 ASSERT_OUTSIDE_BEGIN_END(ctx
);
86 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenQueriesARB(n < 0)");
90 if (ctx
->Occlusion
.Active
) {
91 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGenQueriesARB");
95 first
= _mesa_HashFindFreeKeyBlock(ctx
->Occlusion
.QueryObjects
, n
);
98 for (i
= 0; i
< n
; i
++) {
99 struct occlusion_query
*q
= new_query_object(GL_SAMPLES_PASSED_ARB
,
102 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGenQueriesARB");
106 _mesa_HashInsert(ctx
->Occlusion
.QueryObjects
, first
+ i
, q
);
113 _mesa_DeleteQueriesARB(GLsizei n
, const GLuint
*ids
)
115 GET_CURRENT_CONTEXT(ctx
);
117 ASSERT_OUTSIDE_BEGIN_END(ctx
);
120 _mesa_error(ctx
, GL_INVALID_VALUE
, "glDeleteQueriesARB(n < 0)");
124 if (ctx
->Occlusion
.Active
) {
125 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glDeleteQueriesARB");
129 for (i
= 0; i
< n
; i
++) {
131 struct occlusion_query
*q
= (struct occlusion_query
*)
132 _mesa_HashLookup(ctx
->Occlusion
.QueryObjects
, ids
[i
]);
134 _mesa_HashRemove(ctx
->Occlusion
.QueryObjects
, ids
[i
]);
135 delete_query_object(q
);
143 _mesa_IsQueryARB(GLuint id
)
145 GET_CURRENT_CONTEXT(ctx
);
146 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
148 if (id
&& _mesa_HashLookup(ctx
->Occlusion
.QueryObjects
, id
))
156 _mesa_BeginQueryARB(GLenum target
, GLuint id
)
158 GET_CURRENT_CONTEXT(ctx
);
159 struct occlusion_query
*q
;
160 ASSERT_OUTSIDE_BEGIN_END(ctx
);
162 FLUSH_VERTICES(ctx
, _NEW_DEPTH
);
164 if (target
!= GL_SAMPLES_PASSED_ARB
) {
165 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBeginQueryARB(target)");
170 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBeginQueryARB(id==0)");
174 if (ctx
->Occlusion
.CurrentQueryObject
) {
175 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBeginQueryARB(target)");
179 q
= (struct occlusion_query
*)
180 _mesa_HashLookup(ctx
->Occlusion
.QueryObjects
, id
);
181 if (q
&& q
->Active
) {
182 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBeginQueryARB");
186 q
= new_query_object(target
, id
);
188 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBeginQueryARB");
191 _mesa_HashInsert(ctx
->Occlusion
.QueryObjects
, id
, q
);
195 q
->PassedCounter
= 0;
196 ctx
->Occlusion
.Active
= GL_TRUE
;
197 ctx
->Occlusion
.CurrentQueryObject
= id
;
198 ctx
->Occlusion
.PassedCounter
= 0;
203 _mesa_EndQueryARB(GLenum target
)
205 GET_CURRENT_CONTEXT(ctx
);
206 struct occlusion_query
*q
= NULL
;
207 ASSERT_OUTSIDE_BEGIN_END(ctx
);
209 FLUSH_VERTICES(ctx
, _NEW_DEPTH
);
211 if (target
!= GL_SAMPLES_PASSED_ARB
) {
212 _mesa_error(ctx
, GL_INVALID_ENUM
, "glEndQueryARB(target)");
216 if (ctx
->Occlusion
.CurrentQueryObject
)
217 q
= (struct occlusion_query
*)
218 _mesa_HashLookup(ctx
->Occlusion
.QueryObjects
,
219 ctx
->Occlusion
.CurrentQueryObject
);
220 if (!q
|| !q
->Active
) {
221 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glEndQuery with no glBeginQuery");
225 q
->PassedCounter
= ctx
->Occlusion
.PassedCounter
;
226 q
->Active
= GL_FALSE
;
227 ctx
->Occlusion
.Active
= GL_FALSE
;
228 ctx
->Occlusion
.CurrentQueryObject
= 0;
233 _mesa_GetQueryivARB(GLenum target
, GLenum pname
, GLint
*params
)
235 GET_CURRENT_CONTEXT(ctx
);
236 ASSERT_OUTSIDE_BEGIN_END(ctx
);
238 if (target
!= GL_SAMPLES_PASSED_ARB
) {
239 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetQueryivARB(target)");
244 case GL_QUERY_COUNTER_BITS_ARB
:
245 *params
= 8 * sizeof(GLuint
);
247 case GL_CURRENT_QUERY_ARB
:
248 *params
= ctx
->Occlusion
.CurrentQueryObject
;
251 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetQueryivARB(pname)");
258 _mesa_GetQueryObjectivARB(GLuint id
, GLenum pname
, GLint
*params
)
260 GET_CURRENT_CONTEXT(ctx
);
261 struct occlusion_query
*q
= NULL
;
262 ASSERT_OUTSIDE_BEGIN_END(ctx
);
265 q
= (struct occlusion_query
*)
266 _mesa_HashLookup(ctx
->Occlusion
.QueryObjects
, id
);
268 if (!q
|| q
->Active
) {
269 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetQueryObjectivARB(id=%d)", id
);
274 case GL_QUERY_RESULT_ARB
:
275 *params
= q
->PassedCounter
;
277 case GL_QUERY_RESULT_AVAILABLE_ARB
:
278 /* XXX revisit when we have a hardware implementation! */
282 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetQueryObjectivARB(pname)");
289 _mesa_GetQueryObjectuivARB(GLuint id
, GLenum pname
, GLuint
*params
)
291 GET_CURRENT_CONTEXT(ctx
);
292 struct occlusion_query
*q
= NULL
;
293 ASSERT_OUTSIDE_BEGIN_END(ctx
);
296 q
= (struct occlusion_query
*)
297 _mesa_HashLookup(ctx
->Occlusion
.QueryObjects
, id
);
298 if (!q
|| q
->Active
) {
299 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetQueryObjectuivARB(id=%d", id
);
304 case GL_QUERY_RESULT_ARB
:
305 *params
= q
->PassedCounter
;
307 case GL_QUERY_RESULT_AVAILABLE_ARB
:
308 /* XXX revisit when we have a hardware implementation! */
312 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetQueryObjectuivARB(pname)");
320 * Allocate/init the context state related to occlusion query objects.
323 _mesa_init_occlude(GLcontext
*ctx
)
325 #if FEATURE_ARB_occlusion_query
326 ctx
->Occlusion
.QueryObjects
= _mesa_NewHashTable();
328 ctx
->OcclusionResult
= GL_FALSE
;
329 ctx
->OcclusionResultSaved
= GL_FALSE
;
334 * Free the context state related to occlusion query objects.
337 _mesa_free_occlude_data(GLcontext
*ctx
)
340 GLuint query
= _mesa_HashFirstEntry(ctx
->Occlusion
.QueryObjects
);
342 struct occlusion_query
*q
= (struct occlusion_query
*)
343 _mesa_HashLookup(ctx
->Occlusion
.QueryObjects
, query
);
345 delete_query_object(q
);
346 _mesa_HashRemove(ctx
->Occlusion
.QueryObjects
, query
);
352 _mesa_DeleteHashTable(ctx
->Occlusion
.QueryObjects
);