From b17a722ca3989e8563ee04cb2939f4835f8a171e Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 13 Jun 2003 02:37:27 +0000 Subject: Implemented GL_ARB_occlusion_query (not 100% finalized). --- docs/RELNOTES-5.1 | 3 + docs/VERSIONS | 1 + include/GL/gl.h | 33 +++++ src/mesa/Makefile.X11 | 1 + src/mesa/glapi/APIspec | 63 ++++++++- src/mesa/glapi/glapioffsets.h | 8 ++ src/mesa/glapi/glapitable.h | 8 ++ src/mesa/glapi/glapitemp.h | 48 +++++++ src/mesa/glapi/glprocs.h | 8 ++ src/mesa/main/config.h | 1 + src/mesa/main/context.c | 4 + src/mesa/main/extensions.c | 4 + src/mesa/main/mtypes.h | 15 ++ src/mesa/main/occlude.c | 314 ++++++++++++++++++++++++++++++++++++++++++ src/mesa/main/occlude.h | 55 ++++++++ src/mesa/main/state.c | 14 ++ src/mesa/sparc/glapi_sparc.S | 168 ++++++++++++++++++++++ src/mesa/swrast/s_context.c | 2 +- src/mesa/swrast/s_span.c | 24 ++++ src/mesa/swrast/s_triangle.c | 14 +- src/mesa/x86/glapi_x86.S | 48 +++++++ 21 files changed, 829 insertions(+), 7 deletions(-) create mode 100644 src/mesa/main/occlude.c create mode 100644 src/mesa/main/occlude.h diff --git a/docs/RELNOTES-5.1 b/docs/RELNOTES-5.1 index 0a38006752..d0619916cc 100644 --- a/docs/RELNOTES-5.1 +++ b/docs/RELNOTES-5.1 @@ -60,6 +60,9 @@ GL_NV_light_max_exponent GL_EXT_texture_rectangle Identical to GL_NV_texture_rectangle +GL_ARB_occlusion_query + Useful for visibility-based culling. + Build System Changes diff --git a/docs/VERSIONS b/docs/VERSIONS index 0a35cb518f..7d48f3f325 100644 --- a/docs/VERSIONS +++ b/docs/VERSIONS @@ -1126,6 +1126,7 @@ Mesa Version History - GL_NV_fragment_program extension - GL_NV_light_max_exponent - GL_EXT_texture_rectangle (identical to GL_NV_texture_rectangle) + - GL_ARB_occlusion_query - new X86 feature detection code (Petr Sebor) - less memory used for display lists and vertex buffers - demo of per-pixel lighting with a fragment program (demos/fplight.c) diff --git a/include/GL/gl.h b/include/GL/gl.h index f7456ef99a..260b59ac38 100644 --- a/include/GL/gl.h +++ b/include/GL/gl.h @@ -2640,6 +2640,39 @@ typedef void (APIENTRY * PFNGLDEPTHBOUNDSEXTPROC)(GLclampd zmin, GLclampd zmax); +/* XXX temporary until glext.h is updated! */ +#ifndef GL_ARB_occlusion_query +#define GL_ARB_occlusion_query 1 + +#define GL_SAMPLES_PASSED_ARB 0x8914 +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 + +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void GLAPIENTRY glGenQueriesARB(GLsizei n, GLuint *ids); +GLAPI void GLAPIENTRY glDeleteQueriesARB(GLsizei n, const GLuint *ids); +GLAPI GLboolean GLAPIENTRY glIsQueryARB(GLuint id); +GLAPI void GLAPIENTRY glBeginQueryARB(GLenum target, GLuint id); +GLAPI void GLAPIENTRY glEndQueryARB(GLenum target); +GLAPI void GLAPIENTRY glGetQueryivARB(GLenum target, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetQueryObjectivARB(GLuint id, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params); +#endif + +typedef void (APIENTRY * PFNGLGENQUERIESARBPROC)(GLsizei n, GLuint *ids); +typedef void (APIENTRY * PFNGLDELETEQUERIESARBPROC)(GLsizei n, const GLuint *ids); +typedef GLboolean (APIENTRY * PFNGLISQUERYARBPROC)(GLuint id); +typedef void (APIENTRY * PFNGLBEGINQUERYARBPROC)(GLenum target, GLuint id); +typedef void (APIENTRY * PFNGLENDQUERYARBPROC)(GLenum target); +typedef void (APIENTRY * PFNGLGETQUERYIVARBPROC)(GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETQUERYOBJECTIVARBPROC)(GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETQUERYOBJECTUIVARBPROC)(GLuint id, GLenum pname, GLuint *params); + +#endif /* GL_ARB_occlusion_query */ + + /********************************************************************** * Begin system-specific stuff */ diff --git a/src/mesa/Makefile.X11 b/src/mesa/Makefile.X11 index ae9f89cc8c..30ab3bd4b8 100644 --- a/src/mesa/Makefile.X11 +++ b/src/mesa/Makefile.X11 @@ -58,6 +58,7 @@ MAIN_SOURCES = \ main/nvfragparse.c \ main/nvvertexec.c \ main/nvvertparse.c \ + main/occlude.c \ main/pixel.c \ main/points.c \ main/polygon.c \ diff --git a/src/mesa/glapi/APIspec b/src/mesa/glapi/APIspec index 5075eaf035..eba696346c 100644 --- a/src/mesa/glapi/APIspec +++ b/src/mesa/glapi/APIspec @@ -1,4 +1,4 @@ -# $Id: APIspec,v 1.17 2003/05/10 04:35:36 brianp Exp $ +# $Id: APIspec,v 1.18 2003/06/13 02:37:28 brianp Exp $ # This file describes all the OpenGL functions. # We use a number of Python scripts to parse this file and @@ -8346,6 +8346,67 @@ offset 699 +# GL_ARB_occlusion_query + +name GenQueriesARB +return void +param n GLsizei +param ids GLuint * +category GL_ARB_occlusion_query +offset 700 + +name DeleteQueriesARB +return void +param n GLsizei +param ids const GLuint * +category GL_ARB_occlusion_query +offset 701 + +name IsQueryARB +return GLboolean +param id GLuint +category GL_ARB_occlusion_query +offset 702 + +name BeginQueryARB +return void +param target GLenum +param id GLuint +category GL_ARB_occlusion_query +offset 703 + +name EndQueryARB +return void +param target GLenum +category GL_ARB_occlusion_query +offset 704 + +name GetQueryivARB +return void +param target GLenum +param pname GLenum +param params GLint * +category GL_ARB_occlusion_query +offset 705 + +name GetQueryObjectivARB +return void +param id GLuint +param pname GLenum +param params GLint * +category GL_ARB_occlusion_query +offset 706 + +name GetQueryObjectuivARB +return void +param id GLuint +param pname GLenum +param params GLuint * +category GL_ARB_occlusion_query +offset 707 + + + # end of file sentinal name dummy diff --git a/src/mesa/glapi/glapioffsets.h b/src/mesa/glapi/glapioffsets.h index ccc05daee1..0dc699f5c2 100644 --- a/src/mesa/glapi/glapioffsets.h +++ b/src/mesa/glapi/glapioffsets.h @@ -702,5 +702,13 @@ #define _gloffset_MapBufferARB 697 #define _gloffset_UnmapBufferARB 698 #define _gloffset_DepthBoundsEXT 699 +#define _gloffset_GenQueriesARB 700 +#define _gloffset_DeleteQueriesARB 701 +#define _gloffset_IsQueryARB 702 +#define _gloffset_BeginQueryARB 703 +#define _gloffset_EndQueryARB 704 +#define _gloffset_GetQueryivARB 705 +#define _gloffset_GetQueryObjectivARB 706 +#define _gloffset_GetQueryObjectuivARB 707 #endif diff --git a/src/mesa/glapi/glapitable.h b/src/mesa/glapi/glapitable.h index 2bb31e2e0d..42f8408480 100644 --- a/src/mesa/glapi/glapitable.h +++ b/src/mesa/glapi/glapitable.h @@ -706,6 +706,14 @@ struct _glapi_table void * (*MapBufferARB)(GLenum target, GLenum access); /* 697 */ GLboolean (*UnmapBufferARB)(GLenum target); /* 698 */ void (*DepthBoundsEXT)(GLclampd zmin, GLclampd zmax); /* 699 */ + void (*GenQueriesARB)(GLsizei n, GLuint * ids); /* 700 */ + void (*DeleteQueriesARB)(GLsizei n, const GLuint * ids); /* 701 */ + GLboolean (*IsQueryARB)(GLuint id); /* 702 */ + void (*BeginQueryARB)(GLenum target, GLuint id); /* 703 */ + void (*EndQueryARB)(GLenum target); /* 704 */ + void (*GetQueryivARB)(GLenum target, GLenum pname, GLint * params); /* 705 */ + void (*GetQueryObjectivARB)(GLuint id, GLenum pname, GLint * params); /* 706 */ + void (*GetQueryObjectuivARB)(GLuint id, GLenum pname, GLuint * params); /* 707 */ }; #endif diff --git a/src/mesa/glapi/glapitemp.h b/src/mesa/glapi/glapitemp.h index 707333043d..4d373933d4 100644 --- a/src/mesa/glapi/glapitemp.h +++ b/src/mesa/glapi/glapitemp.h @@ -4624,6 +4624,46 @@ KEYWORD1 void KEYWORD2 NAME(DepthBoundsEXT)(GLclampd zmin, GLclampd zmax) DISPATCH(DepthBoundsEXT, (zmin, zmax), (F, "glDepthBoundsEXT(%f, %f);\n", zmin, zmax)); } +KEYWORD1 void KEYWORD2 NAME(GenQueriesARB)(GLsizei n, GLuint * ids) +{ + DISPATCH(GenQueriesARB, (n, ids), (F, "glGenQueriesARB(%d, %p);\n", n, (const void *) ids)); +} + +KEYWORD1 void KEYWORD2 NAME(DeleteQueriesARB)(GLsizei n, const GLuint * ids) +{ + DISPATCH(DeleteQueriesARB, (n, ids), (F, "glDeleteQueriesARB(%d, %p);\n", n, (const void *) ids)); +} + +KEYWORD1 GLboolean KEYWORD2 NAME(IsQueryARB)(GLuint id) +{ + RETURN_DISPATCH(IsQueryARB, (id), (F, "glIsQueryARB(%d);\n", id)); +} + +KEYWORD1 void KEYWORD2 NAME(BeginQueryARB)(GLenum target, GLuint id) +{ + DISPATCH(BeginQueryARB, (target, id), (F, "glBeginQueryARB(0x%x, %d);\n", target, id)); +} + +KEYWORD1 void KEYWORD2 NAME(EndQueryARB)(GLenum target) +{ + DISPATCH(EndQueryARB, (target), (F, "glEndQueryARB(0x%x);\n", target)); +} + +KEYWORD1 void KEYWORD2 NAME(GetQueryivARB)(GLenum target, GLenum pname, GLint * params) +{ + DISPATCH(GetQueryivARB, (target, pname, params), (F, "glGetQueryivARB(0x%x, 0x%x, %p);\n", target, pname, (const void *) params)); +} + +KEYWORD1 void KEYWORD2 NAME(GetQueryObjectivARB)(GLuint id, GLenum pname, GLint * params) +{ + DISPATCH(GetQueryObjectivARB, (id, pname, params), (F, "glGetQueryObjectivARB(%d, 0x%x, %p);\n", id, pname, (const void *) params)); +} + +KEYWORD1 void KEYWORD2 NAME(GetQueryObjectuivARB)(GLuint id, GLenum pname, GLuint * params) +{ + DISPATCH(GetQueryObjectuivARB, (id, pname, params), (F, "glGetQueryObjectuivARB(%d, 0x%x, %p);\n", id, pname, (const void *) params)); +} + /* @@ -5337,6 +5377,14 @@ void *DISPATCH_TABLE_NAME[] = { TABLE_ENTRY(MapBufferARB), TABLE_ENTRY(UnmapBufferARB), TABLE_ENTRY(DepthBoundsEXT), + TABLE_ENTRY(GenQueriesARB), + TABLE_ENTRY(DeleteQueriesARB), + TABLE_ENTRY(IsQueryARB), + TABLE_ENTRY(BeginQueryARB), + TABLE_ENTRY(EndQueryARB), + TABLE_ENTRY(GetQueryivARB), + TABLE_ENTRY(GetQueryObjectivARB), + TABLE_ENTRY(GetQueryObjectuivARB), /* A whole bunch of no-op functions. These might be called * when someone tries to call a dynamically-registered * extension function without a current rendering context. diff --git a/src/mesa/glapi/glprocs.h b/src/mesa/glapi/glprocs.h index ea18fdfc69..70bac5623b 100644 --- a/src/mesa/glapi/glprocs.h +++ b/src/mesa/glapi/glprocs.h @@ -890,5 +890,13 @@ static struct name_address_offset static_functions[] = { { "glMapBufferARB", (GLvoid *) glMapBufferARB, _gloffset_MapBufferARB }, { "glUnmapBufferARB", (GLvoid *) glUnmapBufferARB, _gloffset_UnmapBufferARB }, { "glDepthBoundsEXT", (GLvoid *) glDepthBoundsEXT, _gloffset_DepthBoundsEXT }, + { "glGenQueriesARB", (GLvoid *) glGenQueriesARB, _gloffset_GenQueriesARB }, + { "glDeleteQueriesARB", (GLvoid *) glDeleteQueriesARB, _gloffset_DeleteQueriesARB }, + { "glIsQueryARB", (GLvoid *) glIsQueryARB, _gloffset_IsQueryARB }, + { "glBeginQueryARB", (GLvoid *) glBeginQueryARB, _gloffset_BeginQueryARB }, + { "glEndQueryARB", (GLvoid *) glEndQueryARB, _gloffset_EndQueryARB }, + { "glGetQueryivARB", (GLvoid *) glGetQueryivARB, _gloffset_GetQueryivARB }, + { "glGetQueryObjectivARB", (GLvoid *) glGetQueryObjectivARB, _gloffset_GetQueryObjectivARB }, + { "glGetQueryObjectuivARB", (GLvoid *) glGetQueryObjectuivARB, _gloffset_GetQueryObjectuivARB }, { NULL, NULL } /* end of list marker */ }; diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h index f35f100205..4b4b3ef10a 100644 --- a/src/mesa/main/config.h +++ b/src/mesa/main/config.h @@ -243,5 +243,6 @@ #define FEATURE_ARB_fragment_program 1 +#define FEATURE_ARB_occlusion_query 1 #endif /* CONFIG_H */ diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index ae030bce84..666e3403a2 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1562,6 +1562,10 @@ init_attrib_groups( GLcontext *ctx ) ctx->FragmentProgram.Current->Base.RefCount++; #endif +#if FEATURE_ARB_occlusion_query + ctx->Occlusion.QueryObjects = _mesa_NewHashTable(); +#endif + /* Miscellaneous */ ctx->NewState = _NEW_ALL; ctx->RenderMode = GL_RENDER; diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index 50769fed31..3b7c21a162 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -54,6 +54,7 @@ static const struct { { OFF, "GL_ARB_imaging", F(ARB_imaging) }, { OFF, "GL_ARB_multisample", F(ARB_multisample) }, { OFF, "GL_ARB_multitexture", F(ARB_multitexture) }, + { OFF, "GL_ARB_occlusion_query", F(ARB_occlusion_query) }, { OFF, "GL_ARB_point_parameters", F(EXT_point_parameters) }, { OFF, "GL_ARB_shadow", F(ARB_shadow) }, { OFF, "GL_ARB_shadow_ambient", F(SGIX_shadow_ambient) }, @@ -163,6 +164,9 @@ _mesa_enable_sw_extensions(GLcontext *ctx) #endif "GL_ARB_imaging", "GL_ARB_multitexture", +#if FEATURE_ARB_occlusion_query + "GL_ARB_occlusion_query", +#endif "GL_ARB_point_parameters", "GL_ARB_shadow", "GL_ARB_shadow_ambient", diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index dd660fa3ab..59a75da8c8 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1314,6 +1314,18 @@ struct fragment_program_state }; +/* + * State for GL_ARB_occlusion_query + */ +struct occlusion_state +{ + GLboolean Active; + GLuint CurrentQueryObject; + GLuint PassedCounter; + struct _mesa_HashTable *QueryObjects; +}; + + /* * State which can be shared by multiple contexts: */ @@ -1449,6 +1461,7 @@ struct gl_extensions { GLboolean ARB_imaging; GLboolean ARB_multisample; GLboolean ARB_multitexture; + GLboolean ARB_occlusion_query; GLboolean ARB_shadow; GLboolean ARB_texture_border_clamp; GLboolean ARB_texture_compression; @@ -1827,6 +1840,8 @@ struct __GLcontextRec { struct vertex_program_state VertexProgram; /* GL_NV_vertex_program */ struct fragment_program_state FragmentProgram; /* GL_NV_fragment_program */ + struct occlusion_state Occlusion; /* GL_ARB_occlusion_query */ + GLenum ErrorValue; /* Last error code */ GLenum RenderMode; /* either GL_RENDER, GL_SELECT, GL_FEEDBACK */ GLuint NewState; /* bitwise-or of _NEW_* flags */ diff --git a/src/mesa/main/occlude.c b/src/mesa/main/occlude.c new file mode 100644 index 0000000000..029e5d0894 --- /dev/null +++ b/src/mesa/main/occlude.c @@ -0,0 +1,314 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * \brief Functions to implement the GL_ARB_occlusion_query extension. + */ + + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "occlude.h" +#include "mtypes.h" + +#ifndef GL_SAMPLES_PASSED_ARB +#define GL_SAMPLES_PASSED_ARB 0x8914 +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 +#endif + + +struct occlusion_query +{ + GLenum Target; + GLuint Id; + GLuint PassedCounter; + GLboolean Active; +}; + + +/** + * Allocate a new occlusion query object. + * \param target - must be GL_SAMPLES_PASSED_ARB at this time + * \param id - the object's ID + * \return pointer to new occlusion_query object or NULL if out of memory. + */ +static struct occlusion_query * +new_query_object(GLenum target, GLuint id) +{ + struct occlusion_query *q = MALLOC_STRUCT(occlusion_query); + if (q) { + q->Target = target; + q->Id = id; + q->PassedCounter = 0; + q->Active = GL_FALSE; + } + return q; +} + + +/** + * Delete an occlusion query object. + */ +static void +delete_query_object(struct occlusion_query *q) +{ + FREE(q); +} + + +void +_mesa_GenQueriesARB(GLsizei n, GLuint *ids) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint first; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); + return; + } + + if (ctx->Occlusion.Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB"); + return; + } + + first = _mesa_HashFindFreeKeyBlock(ctx->Occlusion.QueryObjects, n); + if (first) { + GLuint i; + for (i = 0; i < n; i++) { + struct occlusion_query *q = new_query_object(GL_SAMPLES_PASSED_ARB, + first + i); + if (!q) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB"); + return; + } + ids[i] = first + i; + _mesa_HashInsert(ctx->Occlusion.QueryObjects, first + i, q); + } + } +} + + +void +_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)"); + return; + } + + if (ctx->Occlusion.Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB"); + return; + } + + for (i = 0; i < n; i++) { + if (ids[i] > 0) { + struct occlusion_query *q = (struct occlusion_query *) + _mesa_HashLookup(ctx->Occlusion.QueryObjects, ids[i]); + if (q) { + _mesa_HashRemove(ctx->Occlusion.QueryObjects, ids[i]); + delete_query_object(q); + } + } + } +} + + +GLboolean +_mesa_IsQueryARB(GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (id && _mesa_HashLookup(ctx->Occlusion.QueryObjects, id)) + return GL_TRUE; + else + return GL_FALSE; +} + + +void +_mesa_BeginQueryARB(GLenum target, GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + struct occlusion_query *q; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + + if (target != GL_SAMPLES_PASSED_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); + return; + } + + if (ctx->Occlusion.CurrentQueryObject) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(target)"); + return; + } + + q = (struct occlusion_query *) + _mesa_HashLookup(ctx->Occlusion.QueryObjects, id); + if (q && q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB"); + return; + } + else if (!q) { + q = new_query_object(target, id); + if (!q) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB"); + return; + } + _mesa_HashInsert(ctx->Occlusion.QueryObjects, id, q); + } + + q->Active = GL_TRUE; + q->PassedCounter = 0; + ctx->Occlusion.Active = GL_TRUE; + ctx->Occlusion.CurrentQueryObject = id; + ctx->Occlusion.PassedCounter = 0; +} + + +void +_mesa_EndQueryARB(GLenum target) +{ + GET_CURRENT_CONTEXT(ctx); + struct occlusion_query *q; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + + if (target != GL_SAMPLES_PASSED_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); + return; + } + + q = (struct occlusion_query *) + _mesa_HashLookup(ctx->Occlusion.QueryObjects, + ctx->Occlusion.CurrentQueryObject); + if (!q || !q->Active) { + _mesa_problem(ctx, "bad query object in glEndQueryARB"); + return; + } + + q->PassedCounter = ctx->Occlusion.PassedCounter; + q->Active = GL_FALSE; + ctx->Occlusion.Active = GL_FALSE; + ctx->Occlusion.CurrentQueryObject = 0; +} + + +void +_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_SAMPLES_PASSED_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(target)"); + return; + } + + switch (pname) { + case GL_QUERY_COUNTER_BITS_ARB: + *params = 8 * sizeof(GLuint); + break; + case GL_CURRENT_QUERY_ARB: + *params = ctx->Occlusion.CurrentQueryObject; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)"); + return; + } +} + + +void +_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct occlusion_query *q; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + q = (struct occlusion_query *) + _mesa_HashLookup(ctx->Occlusion.QueryObjects, id); + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryObjectivARB"); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + *params = q->PassedCounter; + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + /* XXX revisit when we have a hardware implementation! */ + *params = GL_TRUE; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)"); + return; + } +} + + +void +_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct occlusion_query *q; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + q = (struct occlusion_query *) + _mesa_HashLookup(ctx->Occlusion.QueryObjects, id); + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryObjectuivARB"); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + *params = q->PassedCounter; + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + /* XXX revisit when we have a hardware implementation! */ + *params = GL_TRUE; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)"); + return; + } +} diff --git a/src/mesa/main/occlude.h b/src/mesa/main/occlude.h new file mode 100644 index 0000000000..cc3786772b --- /dev/null +++ b/src/mesa/main/occlude.h @@ -0,0 +1,55 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef OCCLUDE_H +#define OCCLUDE_H + + +extern void +_mesa_GenQueriesARB(GLsizei n, GLuint *ids); + +extern void +_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids); + +extern GLboolean +_mesa_IsQueryARB(GLuint id); + +extern void +_mesa_BeginQueryARB(GLenum target, GLuint id); + +extern void +_mesa_EndQueryARB(GLenum target); + +extern void +_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params); + +extern void +_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params); + +extern void +_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params); + + +#endif /* OCCLUDE_H */ diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 63c8bc4abd..2851b8e083 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -59,6 +59,9 @@ #include "light.h" #include "lines.h" #include "matrix.h" +#if FEATURE_ARB_occlusion_query +#include "occlude.h" +#endif #include "pixel.h" #include "points.h" #include "polygon.h" @@ -644,6 +647,17 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize) exec->MapBufferARB = _mesa_MapBufferARB; exec->UnmapBufferARB = _mesa_UnmapBufferARB; #endif + +#if FEATURE_ARB_occlusion_query + exec->GenQueriesARB = _mesa_GenQueriesARB; + exec->DeleteQueriesARB = _mesa_DeleteQueriesARB; + exec->IsQueryARB = _mesa_IsQueryARB; + exec->BeginQueryARB = _mesa_BeginQueryARB; + exec->EndQueryARB = _mesa_EndQueryARB; + exec->GetQueryivARB = _mesa_GetQueryivARB; + exec->GetQueryObjectivARB = _mesa_GetQueryObjectivARB; + exec->GetQueryObjectuivARB = _mesa_GetQueryObjectuivARB; +#endif } diff --git a/src/mesa/sparc/glapi_sparc.S b/src/mesa/sparc/glapi_sparc.S index 6c12304077..b44ab68c3b 100644 --- a/src/mesa/sparc/glapi_sparc.S +++ b/src/mesa/sparc/glapi_sparc.S @@ -18623,6 +18623,174 @@ glDepthBoundsEXT: sethi %hi(0x00000000), %g1 ld [%g1 + %lo(0x00000000)], %g1 ld [%g1 + (4 * _gloffset_DepthBoundsEXT)], %g3 +#endif + jmpl %g3, %g0 + nop + +.globl glGenQueriesARB +.type glGenQueriesARB,#function +glGenQueriesARB: +#ifdef __sparc_v9__ + sethi %hi(0x00000000), %g2 + sethi %hi(0x00000000), %g1 + or %g2, %lo(0x00000000), %g2 + or %g1, %lo(0x00000000), %g1 + sllx %g2, 32, %g2 + ldx [%g1 + %g2], %g1 + sethi %hi(8 * _gloffset_GenQueriesARB), %g2 + or %g2, %lo(8 * _gloffset_GenQueriesARB), %g2 + ldx [%g1 + %g2], %g3 +#else + sethi %hi(0x00000000), %g1 + ld [%g1 + %lo(0x00000000)], %g1 + ld [%g1 + (4 * _gloffset_GenQueriesARB)], %g3 +#endif + jmpl %g3, %g0 + nop + +.globl glDeleteQueriesARB +.type glDeleteQueriesARB,#function +glDeleteQueriesARB: +#ifdef __sparc_v9__ + sethi %hi(0x00000000), %g2 + sethi %hi(0x00000000), %g1 + or %g2, %lo(0x00000000), %g2 + or %g1, %lo(0x00000000), %g1 + sllx %g2, 32, %g2 + ldx [%g1 + %g2], %g1 + sethi %hi(8 * _gloffset_DeleteQueriesARB), %g2 + or %g2, %lo(8 * _gloffset_DeleteQueriesARB), %g2 + ldx [%g1 + %g2], %g3 +#else + sethi %hi(0x00000000), %g1 + ld [%g1 + %lo(0x00000000)], %g1 + ld [%g1 + (4 * _gloffset_DeleteQueriesARB)], %g3 +#endif + jmpl %g3, %g0 + nop + +.globl glIsQueryARB +.type glIsQueryARB,#function +glIsQueryARB: +#ifdef __sparc_v9__ + sethi %hi(0x00000000), %g2 + sethi %hi(0x00000000), %g1 + or %g2, %lo(0x00000000), %g2 + or %g1, %lo(0x00000000), %g1 + sllx %g2, 32, %g2 + ldx [%g1 + %g2], %g1 + sethi %hi(8 * _gloffset_IsQueryARB), %g2 + or %g2, %lo(8 * _gloffset_IsQueryARB), %g2 + ldx [%g1 + %g2], %g3 +#else + sethi %hi(0x00000000), %g1 + ld [%g1 + %lo(0x00000000)], %g1 + ld [%g1 + (4 * _gloffset_IsQueryARB)], %g3 +#endif + jmpl %g3, %g0 + nop + +.globl glBeginQueryARB +.type glBeginQueryARB,#function +glBeginQueryARB: +#ifdef __sparc_v9__ + sethi %hi(0x00000000), %g2 + sethi %hi(0x00000000), %g1 + or %g2, %lo(0x00000000), %g2 + or %g1, %lo(0x00000000), %g1 + sllx %g2, 32, %g2 + ldx [%g1 + %g2], %g1 + sethi %hi(8 * _gloffset_BeginQueryARB), %g2 + or %g2, %lo(8 * _gloffset_BeginQueryARB), %g2 + ldx [%g1 + %g2], %g3 +#else + sethi %hi(0x00000000), %g1 + ld [%g1 + %lo(0x00000000)], %g1 + ld [%g1 + (4 * _gloffset_BeginQueryARB)], %g3 +#endif + jmpl %g3, %g0 + nop + +.globl glEndQueryARB +.type glEndQueryARB,#function +glEndQueryARB: +#ifdef __sparc_v9__ + sethi %hi(0x00000000), %g2 + sethi %hi(0x00000000), %g1 + or %g2, %lo(0x00000000), %g2 + or %g1, %lo(0x00000000), %g1 + sllx %g2, 32, %g2 + ldx [%g1 + %g2], %g1 + sethi %hi(8 * _gloffset_EndQueryARB), %g2 + or %g2, %lo(8 * _gloffset_EndQueryARB), %g2 + ldx [%g1 + %g2], %g3 +#else + sethi %hi(0x00000000), %g1 + ld [%g1 + %lo(0x00000000)], %g1 + ld [%g1 + (4 * _gloffset_EndQueryARB)], %g3 +#endif + jmpl %g3, %g0 + nop + +.globl glGetQueryivARB +.type glGetQueryivARB,#function +glGetQueryivARB: +#ifdef __sparc_v9__ + sethi %hi(0x00000000), %g2 + sethi %hi(0x00000000), %g1 + or %g2, %lo(0x00000000), %g2 + or %g1, %lo(0x00000000), %g1 + sllx %g2, 32, %g2 + ldx [%g1 + %g2], %g1 + sethi %hi(8 * _gloffset_GetQueryivARB), %g2 + or %g2, %lo(8 * _gloffset_GetQueryivARB), %g2 + ldx [%g1 + %g2], %g3 +#else + sethi %hi(0x00000000), %g1 + ld [%g1 + %lo(0x00000000)], %g1 + ld [%g1 + (4 * _gloffset_GetQueryivARB)], %g3 +#endif + jmpl %g3, %g0 + nop + +.globl glGetQueryObjectivARB +.type glGetQueryObjectivARB,#function +glGetQueryObjectivARB: +#ifdef __sparc_v9__ + sethi %hi(0x00000000), %g2 + sethi %hi(0x00000000), %g1 + or %g2, %lo(0x00000000), %g2 + or %g1, %lo(0x00000000), %g1 + sllx %g2, 32, %g2 + ldx [%g1 + %g2], %g1 + sethi %hi(8 * _gloffset_GetQueryObjectivARB), %g2 + or %g2, %lo(8 * _gloffset_GetQueryObjectivARB), %g2 + ldx [%g1 + %g2], %g3 +#else + sethi %hi(0x00000000), %g1 + ld [%g1 + %lo(0x00000000)], %g1 + ld [%g1 + (4 * _gloffset_GetQueryObjectivARB)], %g3 +#endif + jmpl %g3, %g0 + nop + +.globl glGetQueryObjectuivARB +.type glGetQueryObjectuivARB,#function +glGetQueryObjectuivARB: +#ifdef __sparc_v9__ + sethi %hi(0x00000000), %g2 + sethi %hi(0x00000000), %g1 + or %g2, %lo(0x00000000), %g2 + or %g1, %lo(0x00000000), %g1 + sllx %g2, 32, %g2 + ldx [%g1 + %g2], %g1 + sethi %hi(8 * _gloffset_GetQueryObjectuivARB), %g2 + or %g2, %lo(8 * _gloffset_GetQueryObjectuivARB), %g2 + ldx [%g1 + %g2], %g3 +#else + sethi %hi(0x00000000), %g1 + ld [%g1 + %lo(0x00000000)], %g1 + ld [%g1 + (4 * _gloffset_GetQueryObjectuivARB)], %g3 #endif jmpl %g3, %g0 nop diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c index 5160e810cd..6a25be68f5 100644 --- a/src/mesa/swrast/s_context.c +++ b/src/mesa/swrast/s_context.c @@ -79,7 +79,7 @@ _swrast_update_rasterflags( GLcontext *ctx ) RasterMask |= CLIP_BIT; } - if (ctx->Depth.OcclusionTest) + if (ctx->Depth.OcclusionTest || ctx->Occlusion.Active) RasterMask |= OCCLUSION_BIT; diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c index cce69b8c43..59e89252a0 100644 --- a/src/mesa/swrast/s_span.c +++ b/src/mesa/swrast/s_span.c @@ -841,6 +841,14 @@ _swrast_write_index_span( GLcontext *ctx, struct sw_span *span) /* if we get here, something passed the depth test */ ctx->OcclusionResult = GL_TRUE; +#if FEATURE_ARB_occlusion_query + if (ctx->Occlusion.Active) { + GLuint i; + for (i = 0; i < span->end; i++) + ctx->Occlusion.PassedCounter += span->array->mask[i]; + } +#endif + /* we have to wait until after occlusion to do this test */ if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) { /* write no pixels */ @@ -1046,6 +1054,14 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) /* if we get here, something passed the depth test */ ctx->OcclusionResult = GL_TRUE; +#if FEATURE_ARB_occlusion_query + if (ctx->Occlusion.Active) { + GLuint i; + for (i = 0; i < span->end; i++) + ctx->Occlusion.PassedCounter += span->array->mask[i]; + } +#endif + /* can't abort span-writing until after occlusion testing */ if (colorMask == 0x0) { span->interpMask = origInterpMask; @@ -1288,6 +1304,14 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span) /* if we get here, some fragments passed the depth test */ ctx->OcclusionResult = GL_TRUE; +#if FEATURE_ARB_occlusion_query + if (ctx->Occlusion.Active) { + GLuint i; + for (i = 0; i < span->end; i++) + ctx->Occlusion.PassedCounter += span->array->mask[i]; + } +#endif + /* We had to wait until now to check for glColorMask(F,F,F,F) because of * the occlusion test. */ diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c index 43c131a6e7..0ce3459d54 100644 --- a/src/mesa/swrast/s_triangle.c +++ b/src/mesa/swrast/s_triangle.c @@ -899,13 +899,16 @@ fast_persp_span(GLcontext *ctx, struct sw_span *span, +/* + * Special tri function for occlusion testing + */ #define NAME occlusion_zless_triangle #define DO_OCCLUSION_TEST #define INTERP_Z 1 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE -#define SETUP_CODE \ - if (ctx->OcclusionResult) { \ - return; \ +#define SETUP_CODE \ + if (ctx->OcclusionResult && !ctx->Occlusion.Active) { \ + return; \ } #define RENDER_SPAN( span ) \ GLuint i; \ @@ -913,7 +916,7 @@ fast_persp_span(GLcontext *ctx, struct sw_span *span, GLdepth z = FixedToDepth(span.z); \ if (z < zRow[i]) { \ ctx->OcclusionResult = GL_TRUE; \ - return; \ + ctx->Occlusion.PassedCounter++; \ } \ span.z += span.zStep; \ } @@ -1034,7 +1037,8 @@ _swrast_choose_triangle( GLcontext *ctx ) return; } - if (ctx->Depth.OcclusionTest && + /* special case for occlusion testing */ + if ((ctx->Depth.OcclusionTest || ctx->Occlusion.Active) && ctx->Depth.Test && ctx->Depth.Mask == GL_FALSE && ctx->Depth.Func == GL_LESS && diff --git a/src/mesa/x86/glapi_x86.S b/src/mesa/x86/glapi_x86.S index a515818e4b..a574c63bca 100644 --- a/src/mesa/x86/glapi_x86.S +++ b/src/mesa/x86/glapi_x86.S @@ -5337,5 +5337,53 @@ GL_PREFIX(DepthBoundsEXT): MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) JMP(GL_OFFSET(_gloffset_DepthBoundsEXT)) +ALIGNTEXT16 +GLOBL_FN(GL_PREFIX(GenQueriesARB)) +GL_PREFIX(GenQueriesARB): + MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) + JMP(GL_OFFSET(_gloffset_GenQueriesARB)) + +ALIGNTEXT16 +GLOBL_FN(GL_PREFIX(DeleteQueriesARB)) +GL_PREFIX(DeleteQueriesARB): + MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) + JMP(GL_OFFSET(_gloffset_DeleteQueriesARB)) + +ALIGNTEXT16 +GLOBL_FN(GL_PREFIX(IsQueryARB)) +GL_PREFIX(IsQueryARB): + MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) + JMP(GL_OFFSET(_gloffset_IsQueryARB)) + +ALIGNTEXT16 +GLOBL_FN(GL_PREFIX(BeginQueryARB)) +GL_PREFIX(BeginQueryARB): + MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) + JMP(GL_OFFSET(_gloffset_BeginQueryARB)) + +ALIGNTEXT16 +GLOBL_FN(GL_PREFIX(EndQueryARB)) +GL_PREFIX(EndQueryARB): + MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) + JMP(GL_OFFSET(_gloffset_EndQueryARB)) + +ALIGNTEXT16 +GLOBL_FN(GL_PREFIX(GetQueryivARB)) +GL_PREFIX(GetQueryivARB): + MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) + JMP(GL_OFFSET(_gloffset_GetQueryivARB)) + +ALIGNTEXT16 +GLOBL_FN(GL_PREFIX(GetQueryObjectivARB)) +GL_PREFIX(GetQueryObjectivARB): + MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) + JMP(GL_OFFSET(_gloffset_GetQueryObjectivARB)) + +ALIGNTEXT16 +GLOBL_FN(GL_PREFIX(GetQueryObjectuivARB)) +GL_PREFIX(GetQueryObjectuivARB): + MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) + JMP(GL_OFFSET(_gloffset_GetQueryObjectuivARB)) + #endif /* __WIN32__ */ -- cgit v1.2.3