diff options
| -rw-r--r-- | src/mesa/drivers/common/driverfuncs.c | 5 | ||||
| -rw-r--r-- | src/mesa/main/dd.h | 6 | ||||
| -rw-r--r-- | src/mesa/main/mtypes.h | 9 | ||||
| -rw-r--r-- | src/mesa/main/queryobj.c | 95 | ||||
| -rw-r--r-- | src/mesa/main/queryobj.h | 14 | ||||
| -rw-r--r-- | src/mesa/pipe/failover/fo_context.c | 4 | ||||
| -rw-r--r-- | src/mesa/pipe/i915simple/i915_context.c | 21 | ||||
| -rw-r--r-- | src/mesa/pipe/p_context.h | 9 | ||||
| -rw-r--r-- | src/mesa/pipe/p_defines.h | 8 | ||||
| -rw-r--r-- | src/mesa/pipe/p_state.h | 10 | ||||
| -rw-r--r-- | src/mesa/pipe/softpipe/sp_context.c | 35 | ||||
| -rw-r--r-- | src/mesa/pipe/softpipe/sp_context.h | 7 | ||||
| -rw-r--r-- | src/mesa/pipe/softpipe/sp_quad_occlusion.c | 10 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_queryobj.c | 83 | 
14 files changed, 232 insertions, 84 deletions
| diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c index 500dbb2545..96e5037fa5 100644 --- a/src/mesa/drivers/common/driverfuncs.c +++ b/src/mesa/drivers/common/driverfuncs.c @@ -224,8 +224,9 @@ _mesa_init_driver_functions(struct dd_function_table *driver)     /* query objects */     driver->NewQueryObject = _mesa_new_query_object; -   driver->BeginQuery = NULL; -   driver->EndQuery = NULL; +   driver->BeginQuery = _mesa_begin_query; +   driver->EndQuery = _mesa_end_query; +   driver->WaitQuery = _mesa_wait_query;     /* APPLE_vertex_array_object */     driver->NewArrayObject = _mesa_new_array_object; diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index 582e0c334d..f089fcb48f 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -811,9 +811,9 @@ struct dd_function_table {      */     /*@{*/     struct gl_query_object * (*NewQueryObject)(GLcontext *ctx, GLuint id); -   void (*BeginQuery)(GLcontext *ctx, GLenum target, -                      struct gl_query_object *q); -   void (*EndQuery)(GLcontext *ctx, GLenum target, struct gl_query_object *q); +   void (*BeginQuery)(GLcontext *ctx, struct gl_query_object *q); +   void (*EndQuery)(GLcontext *ctx, struct gl_query_object *q); +   void (*WaitQuery)(GLcontext *ctx, struct gl_query_object *q);     /*@}*/ diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 0a64e0c58c..514170dbcf 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2085,10 +2085,11 @@ struct gl_ati_fragment_shader_state   */  struct gl_query_object  { -   GLuint Id; -   GLuint64EXT Result; /* the counter */ -   GLboolean Active;   /* inside Begin/EndQuery */ -   GLboolean Ready;    /* result is ready */ +   GLenum Target;      /**< The query target, when active */ +   GLuint Id;          /**< hash table ID/name */ +   GLuint64EXT Result; /**< the counter */ +   GLboolean Active;   /**< inside Begin/EndQuery */ +   GLboolean Ready;    /**< result is ready? */  }; diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c index 0e59ba615a..688d0fc7bc 100644 --- a/src/mesa/main/queryobj.c +++ b/src/mesa/main/queryobj.c @@ -1,8 +1,8 @@  /*   * Mesa 3-D graphics library - * Version:  6.5.1 + * Version:  7.1   * - * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved. + * Copyright (C) 1999-2007  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"), @@ -54,6 +54,42 @@ _mesa_new_query_object(GLcontext *ctx, GLuint id)  /** + * Begin a query.  Software driver fallback. + * Called via ctx->Driver.BeginQuery(). + */ +void +_mesa_begin_query(GLcontext *ctx, struct gl_query_object *q) +{ +   /* no-op */ +} + + +/** + * End a query.  Software driver fallback. + * Called via ctx->Driver.EndQuery(). + */ +void +_mesa_end_query(GLcontext *ctx, struct gl_query_object *q) +{ +   q->Ready = GL_TRUE; +} + + +/** + * Wait for query to complete.  Software driver fallback. + * Called via ctx->Driver.WaitQuery(). + */ +void +_mesa_wait_query(GLcontext *ctx, struct gl_query_object *q) +{ +   /* For software drivers, _mesa_end_query() should have completed the query. +    * For real hardware, implement a proper WaitQuery() driver function. +    */ +   assert(q->Ready); +} + + +/**   * Delete an occlusion query object.   * Not removed from hash table here.   * XXX maybe add Delete() method to gl_query_object class and call that instead @@ -61,7 +97,7 @@ _mesa_new_query_object(GLcontext *ctx, GLuint id)  static void  delete_query_object(struct gl_query_object *q)  { -   FREE(q); +   _mesa_free(q);  } @@ -216,6 +252,7 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)        }     } +   q->Target = target;     q->Active = GL_TRUE;     q->Result = 0;     q->Ready = GL_FALSE; @@ -229,9 +266,7 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)     }  #endif -   if (ctx->Driver.BeginQuery) { -      ctx->Driver.BeginQuery(ctx, target, q); -   } +   ctx->Driver.BeginQuery(ctx, q);  } @@ -275,13 +310,7 @@ _mesa_EndQueryARB(GLenum target)     }     q->Active = GL_FALSE; -   if (ctx->Driver.EndQuery) { -      ctx->Driver.EndQuery(ctx, target, q); -   } -   else { -      /* if we're using software rendering/querying */ -      q->Ready = GL_TRUE; -   } +   ctx->Driver.EndQuery(ctx, q);  } @@ -346,13 +375,8 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)     switch (pname) {        case GL_QUERY_RESULT_ARB: -         while (!q->Ready) { -            /* Wait for the query to finish! */ -            /* If using software rendering, the result will always be ready -             * by time we get here.  Otherwise, we must be using hardware! -             */ -            ASSERT(ctx->Driver.EndQuery); -         } +         if (!q->Ready) +            ctx->Driver.WaitQuery(ctx, q);           /* if result is too large for returned type, clamp to max value */           if (q->Result > 0x7fffffff) {              *params = 0x7fffffff; @@ -362,7 +386,6 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)           }           break;        case GL_QUERY_RESULT_AVAILABLE_ARB: -         /* XXX revisit when we have a hardware implementation! */           *params = q->Ready;           break;        default: @@ -390,13 +413,8 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)     switch (pname) {        case GL_QUERY_RESULT_ARB: -         while (!q->Ready) { -            /* Wait for the query to finish! */ -            /* If using software rendering, the result will always be ready -             * by time we get here.  Otherwise, we must be using hardware! -             */ -            ASSERT(ctx->Driver.EndQuery); -         } +         if (!q->Ready) +            ctx->Driver.WaitQuery(ctx, q);           /* if result is too large for returned type, clamp to max value */           if (q->Result > 0xffffffff) {              *params = 0xffffffff; @@ -406,7 +424,6 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)           }           break;        case GL_QUERY_RESULT_AVAILABLE_ARB: -         /* XXX revisit when we have a hardware implementation! */           *params = q->Ready;           break;        default: @@ -439,17 +456,11 @@ _mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params)     switch (pname) {        case GL_QUERY_RESULT_ARB: -         while (!q->Ready) { -            /* Wait for the query to finish! */ -            /* If using software rendering, the result will always be ready -             * by time we get here.  Otherwise, we must be using hardware! -             */ -            ASSERT(ctx->Driver.EndQuery); -         } +         if (!q->Ready) +            ctx->Driver.WaitQuery(ctx, q);           *params = q->Result;           break;        case GL_QUERY_RESULT_AVAILABLE_ARB: -         /* XXX revisit when we have a hardware implementation! */           *params = q->Ready;           break;        default: @@ -480,17 +491,11 @@ _mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params)     switch (pname) {        case GL_QUERY_RESULT_ARB: -         while (!q->Ready) { -            /* Wait for the query to finish! */ -            /* If using software rendering, the result will always be ready -             * by time we get here.  Otherwise, we must be using hardware! -             */ -            ASSERT(ctx->Driver.EndQuery); -         } +         if (!q->Ready) +            ctx->Driver.WaitQuery(ctx, q);           *params = q->Result;           break;        case GL_QUERY_RESULT_AVAILABLE_ARB: -         /* XXX revisit when we have a hardware implementation! */           *params = q->Ready;           break;        default: diff --git a/src/mesa/main/queryobj.h b/src/mesa/main/queryobj.h index ada8cf8356..d466aae652 100644 --- a/src/mesa/main/queryobj.h +++ b/src/mesa/main/queryobj.h @@ -1,8 +1,8 @@  /*   * Mesa 3-D graphics library - * Version:  6.5 + * Version:  7.1   * - * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved. + * Copyright (C) 1999-2007  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"), @@ -36,6 +36,16 @@ _mesa_init_query(GLcontext *ctx);  extern void  _mesa_free_query_data(GLcontext *ctx); +extern void +_mesa_begin_query(GLcontext *ctx, struct gl_query_object *q); + +extern void +_mesa_end_query(GLcontext *ctx, struct gl_query_object *q); + +extern void +_mesa_wait_query(GLcontext *ctx, struct gl_query_object *q); + +  extern void GLAPIENTRY  _mesa_GenQueriesARB(GLsizei n, GLuint *ids); diff --git a/src/mesa/pipe/failover/fo_context.c b/src/mesa/pipe/failover/fo_context.c index b88f1b466c..c58fc9cedc 100644 --- a/src/mesa/pipe/failover/fo_context.c +++ b/src/mesa/pipe/failover/fo_context.c @@ -129,8 +129,8 @@ struct pipe_context *failover_create( struct pipe_context *hw,      * at this point - if the hardware doesn't support it, don't      * advertise it to the application.      */ -   failover->pipe.reset_occlusion_counter = hw->reset_occlusion_counter; -   failover->pipe.get_occlusion_counter = hw->get_occlusion_counter; +   failover->pipe.begin_query = hw->begin_query; +   failover->pipe.end_query = hw->end_query;     failover_init_state_functions( failover ); diff --git a/src/mesa/pipe/i915simple/i915_context.c b/src/mesa/pipe/i915simple/i915_context.c index f4121419f7..6e48b3bd03 100644 --- a/src/mesa/pipe/i915simple/i915_context.c +++ b/src/mesa/pipe/i915simple/i915_context.c @@ -149,6 +149,22 @@ static void i915_destroy( struct pipe_context *pipe ) +static void +i915_begin_query(struct pipe_context *pipe, struct pipe_query_object *q) +{ +   /* should never be called */ +   assert(0); +} + + +static void +i915_end_query(struct pipe_context *pipe, struct pipe_query_object *q) +{ +   /* should never be called */ +   assert(0); +} + +  static boolean i915_draw_elements( struct pipe_context *pipe,                                  struct pipe_buffer_handle *indexBuffer,                                  unsigned indexSize, @@ -257,8 +273,9 @@ struct pipe_context *i915_create( struct pipe_winsys *pipe_winsys,     i915->pipe.supported_formats = i915_supported_formats;     i915->pipe.max_texture_size = i915_max_texture_size;     i915->pipe.clear = i915_clear; -   i915->pipe.reset_occlusion_counter = NULL; /* no support */ -   i915->pipe.get_occlusion_counter = NULL; + +   i915->pipe.begin_query = i915_begin_query; +   i915->pipe.end_query = i915_end_query;     i915->pipe.draw_arrays = i915_draw_arrays;     i915->pipe.draw_elements = i915_draw_elements; diff --git a/src/mesa/pipe/p_context.h b/src/mesa/pipe/p_context.h index 27a1128365..dafbef410e 100644 --- a/src/mesa/pipe/p_context.h +++ b/src/mesa/pipe/p_context.h @@ -75,11 +75,12 @@ struct pipe_context {     void (*clear)(struct pipe_context *pipe, struct pipe_surface *ps,                   unsigned clearValue); -   /** occlusion counting (XXX this may be temporary - we should probably -    * have generic query objects with begin/end methods) +   /** +    * Query objects      */ -   void (*reset_occlusion_counter)(struct pipe_context *pipe); -   unsigned (*get_occlusion_counter)(struct pipe_context *pipe); +   void (*begin_query)(struct pipe_context *pipe, struct pipe_query_object *q); +   void (*end_query)(struct pipe_context *pipe, struct pipe_query_object *q); +   void (*wait_query)(struct pipe_context *pipe, struct pipe_query_object *q);     /*      * State functions diff --git a/src/mesa/pipe/p_defines.h b/src/mesa/pipe/p_defines.h index c1164c5c08..b3ee890576 100644 --- a/src/mesa/pipe/p_defines.h +++ b/src/mesa/pipe/p_defines.h @@ -299,4 +299,12 @@  #define PIPE_PRIM_POLYGON         9 +/** + * Query object types + */ +#define PIPE_QUERY_OCCLUSION_COUNTER     0 +#define PIPE_QUERY_PRIMITIVES_GENERATED  1 +#define PIPE_QUERY_PRIMITIVES_EMITTED    2 +#define PIPE_QUERY_TYPES                 3 +  #endif diff --git a/src/mesa/pipe/p_state.h b/src/mesa/pipe/p_state.h index ccd40d39e6..b994d17ea9 100644 --- a/src/mesa/pipe/p_state.h +++ b/src/mesa/pipe/p_state.h @@ -381,4 +381,14 @@ struct pipe_feedback_buffer {  }; +/** + * Hardware queries (occlusion, transform feedback, timing, etc) + */ +struct pipe_query_object { +   uint type:3;   /**< PIPE_QUERY_x */ +   uint ready:1;  /**< is result ready? */ +   uint64 count; +}; + +  #endif diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c index 26453d9785..92357808e2 100644 --- a/src/mesa/pipe/softpipe/sp_context.c +++ b/src/mesa/pipe/softpipe/sp_context.c @@ -195,19 +195,37 @@ static void softpipe_destroy( struct pipe_context *pipe )  } -static void softpipe_reset_occlusion_counter(struct pipe_context *pipe) +static void +softpipe_begin_query(struct pipe_context *pipe, struct pipe_query_object *q)  {     struct softpipe_context *softpipe = softpipe_context( pipe ); -   softpipe->occlusion_counter = 0; +   assert(q->type < PIPE_QUERY_TYPES); +   assert(!softpipe->queries[q->type]); +   softpipe->queries[q->type] = q;  } -/* XXX pipe param should be const */ -static unsigned softpipe_get_occlusion_counter(struct pipe_context *pipe) + +static void +softpipe_end_query(struct pipe_context *pipe, struct pipe_query_object *q)  {     struct softpipe_context *softpipe = softpipe_context( pipe ); -   return softpipe->occlusion_counter; +   assert(q->type < PIPE_QUERY_TYPES); +   assert(softpipe->queries[q->type]); +   q->ready = 1;  /* software rendering is synchronous */ +   softpipe->queries[q->type] = NULL; +} + + +static void +softpipe_wait_query(struct pipe_context *pipe, struct pipe_query_object *q) +{ +   /* Should never get here since we indicated that the result was +    * ready in softpipe_end_query(). +    */ +   assert(0);  } +  static const char *softpipe_get_name( struct pipe_context *pipe )  {     return "softpipe"; @@ -260,8 +278,11 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys,     softpipe->pipe.clear = softpipe_clear;     softpipe->pipe.flush = softpipe_flush; -   softpipe->pipe.reset_occlusion_counter = softpipe_reset_occlusion_counter; -   softpipe->pipe.get_occlusion_counter = softpipe_get_occlusion_counter; + +   softpipe->pipe.begin_query = softpipe_begin_query; +   softpipe->pipe.end_query = softpipe_end_query; +   softpipe->pipe.wait_query = softpipe_wait_query; +     softpipe->pipe.get_name = softpipe_get_name;     softpipe->pipe.get_vendor = softpipe_get_vendor; diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h index 2a6b932523..13d1143c89 100644 --- a/src/mesa/pipe/softpipe/sp_context.h +++ b/src/mesa/pipe/softpipe/sp_context.h @@ -94,6 +94,11 @@ struct softpipe_context {     unsigned dirty;     /* +    * Active queries +    */ +   struct pipe_query_object *queries[PIPE_QUERY_TYPES]; + +   /*      * Mapped vertex buffers      */     ubyte *mapped_vbuffer[PIPE_ATTRIB_MAX]; @@ -120,8 +125,6 @@ struct softpipe_context {     /** Derived from scissor and surface bounds: */     struct pipe_scissor_state cliprect; -   unsigned occlusion_counter; -     unsigned line_stipple_counter;     /** Software quad rendering pipeline */ diff --git a/src/mesa/pipe/softpipe/sp_quad_occlusion.c b/src/mesa/pipe/softpipe/sp_quad_occlusion.c index 6b094a5bef..4f178f0557 100644 --- a/src/mesa/pipe/softpipe/sp_quad_occlusion.c +++ b/src/mesa/pipe/softpipe/sp_quad_occlusion.c @@ -44,11 +44,13 @@ static void  occlusion_count_quad(struct quad_stage *qs, struct quad_header *quad)  {     struct softpipe_context *softpipe = qs->softpipe; +   struct pipe_query_object *occ +      = softpipe->queries[PIPE_QUERY_OCCLUSION_COUNTER]; -   softpipe->occlusion_counter += (quad->mask     ) & 1; -   softpipe->occlusion_counter += (quad->mask >> 1) & 1; -   softpipe->occlusion_counter += (quad->mask >> 2) & 1; -   softpipe->occlusion_counter += (quad->mask >> 3) & 1; +   occ->count += (quad->mask     ) & 1; +   occ->count += (quad->mask >> 1) & 1; +   occ->count += (quad->mask >> 2) & 1; +   occ->count += (quad->mask >> 3) & 1;     if (quad->mask)        qs->next->run(qs->next, quad); diff --git a/src/mesa/state_tracker/st_cb_queryobj.c b/src/mesa/state_tracker/st_cb_queryobj.c index 3a8fbde8ab..5b95dd7fd3 100644 --- a/src/mesa/state_tracker/st_cb_queryobj.c +++ b/src/mesa/state_tracker/st_cb_queryobj.c @@ -44,33 +44,102 @@  #include "st_public.h" +struct st_query_object +{ +   struct gl_query_object base; +   struct pipe_query_object pq; +}; + + +/** + * Cast wrapper + */ +static struct st_query_object * +st_query_object(struct gl_query_object *q) +{ +   return (struct st_query_object *) q; +} + + +static struct gl_query_object * +st_NewQueryObject(GLcontext *ctx, GLuint id) +{ +   struct st_query_object *stq = CALLOC_STRUCT(st_query_object); +   if (stq) { +      stq->base.Id = id; +      stq->base.Ready = GL_TRUE; +      return &stq->base; +   } +   return NULL; +} + +  /**   * Do glReadPixels by getting rows from the framebuffer surface with   * get_tile().  Convert to requested format/type with Mesa image routines.   * Image transfer ops are done in software too.   */  static void -st_BeginQuery(GLcontext *ctx, GLenum target, struct gl_query_object *q) +st_BeginQuery(GLcontext *ctx, struct gl_query_object *q)  {     struct pipe_context *pipe = ctx->st->pipe; -   if (target == GL_SAMPLES_PASSED_ARB) { -      pipe->reset_occlusion_counter(pipe); +   struct st_query_object *stq = st_query_object(q); + +   stq->pq.count = 0; + +   switch (q->Target) { +   case GL_SAMPLES_PASSED_ARB: +      stq->pq.type = PIPE_QUERY_OCCLUSION_COUNTER; +      break; +   case GL_PRIMITIVES_GENERATED_NV: +      /* someday */ +      stq->pq.type = PIPE_QUERY_PRIMITIVES_GENERATED; +      break; +   case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV: +      /* someday */ +      stq->pq.type = PIPE_QUERY_PRIMITIVES_EMITTED; +      break; +   default: +      assert(0);     } + +   pipe->begin_query(pipe, &stq->pq);  }  static void -st_EndQuery(GLcontext *ctx, GLenum target, struct gl_query_object *q) +st_EndQuery(GLcontext *ctx, struct gl_query_object *q)  {     struct pipe_context *pipe = ctx->st->pipe; -   if (target == GL_SAMPLES_PASSED_ARB) { -      q->Result = pipe->get_occlusion_counter(pipe); -   } +   struct st_query_object *stq = st_query_object(q); + +   pipe->end_query(pipe, &stq->pq); +   stq->base.Ready = stq->pq.ready; +   if (stq->base.Ready) +      stq->base.Result = stq->pq.count; +} + + +static void +st_WaitQuery(GLcontext *ctx, struct gl_query_object *q) +{ +   struct pipe_context *pipe = ctx->st->pipe; +   struct st_query_object *stq = st_query_object(q); + +   /* this function should only be called if we don't have a ready result */ +   assert(!stq->base.Ready); + +   pipe->wait_query(pipe, &stq->pq); +   q->Ready = GL_TRUE; +   q->Result = stq->pq.count;  } +  void st_init_query_functions(struct dd_function_table *functions)  { +   functions->NewQueryObject = st_NewQueryObject;     functions->BeginQuery = st_BeginQuery;     functions->EndQuery = st_EndQuery; +   functions->WaitQuery = st_WaitQuery;  } | 
