Implement query object interface.
This replaces the temporary occlusion counter functions we had before. Added new ctx->Driver.WaitQuery() function which should block until the result is ready. Sketch out some code for vertex transformation feedback counters.
This commit is contained in:
@@ -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;
|
||||
|
@@ -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);
|
||||
/*@}*/
|
||||
|
||||
|
||||
|
@@ -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? */
|
||||
};
|
||||
|
||||
|
||||
|
@@ -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"),
|
||||
@@ -53,6 +53,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.
|
||||
@@ -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:
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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 );
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -93,6 +93,11 @@ struct softpipe_context {
|
||||
struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX];
|
||||
unsigned dirty;
|
||||
|
||||
/*
|
||||
* Active queries
|
||||
*/
|
||||
struct pipe_query_object *queries[PIPE_QUERY_TYPES];
|
||||
|
||||
/*
|
||||
* Mapped vertex buffers
|
||||
*/
|
||||
@@ -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 */
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user