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 */
|
/* query objects */
|
||||||
driver->NewQueryObject = _mesa_new_query_object;
|
driver->NewQueryObject = _mesa_new_query_object;
|
||||||
driver->BeginQuery = NULL;
|
driver->BeginQuery = _mesa_begin_query;
|
||||||
driver->EndQuery = NULL;
|
driver->EndQuery = _mesa_end_query;
|
||||||
|
driver->WaitQuery = _mesa_wait_query;
|
||||||
|
|
||||||
/* APPLE_vertex_array_object */
|
/* APPLE_vertex_array_object */
|
||||||
driver->NewArrayObject = _mesa_new_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);
|
struct gl_query_object * (*NewQueryObject)(GLcontext *ctx, GLuint id);
|
||||||
void (*BeginQuery)(GLcontext *ctx, GLenum target,
|
void (*BeginQuery)(GLcontext *ctx, struct gl_query_object *q);
|
||||||
struct gl_query_object *q);
|
void (*EndQuery)(GLcontext *ctx, struct gl_query_object *q);
|
||||||
void (*EndQuery)(GLcontext *ctx, GLenum target, 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
|
struct gl_query_object
|
||||||
{
|
{
|
||||||
GLuint Id;
|
GLenum Target; /**< The query target, when active */
|
||||||
GLuint64EXT Result; /* the counter */
|
GLuint Id; /**< hash table ID/name */
|
||||||
GLboolean Active; /* inside Begin/EndQuery */
|
GLuint64EXT Result; /**< the counter */
|
||||||
GLboolean Ready; /* result is ready */
|
GLboolean Active; /**< inside Begin/EndQuery */
|
||||||
|
GLboolean Ready; /**< result is ready? */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Mesa 3-D graphics library
|
* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* 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.
|
* Delete an occlusion query object.
|
||||||
* Not removed from hash table here.
|
* Not removed from hash table here.
|
||||||
@@ -61,7 +97,7 @@ _mesa_new_query_object(GLcontext *ctx, GLuint id)
|
|||||||
static void
|
static void
|
||||||
delete_query_object(struct gl_query_object *q)
|
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->Active = GL_TRUE;
|
||||||
q->Result = 0;
|
q->Result = 0;
|
||||||
q->Ready = GL_FALSE;
|
q->Ready = GL_FALSE;
|
||||||
@@ -229,9 +266,7 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ctx->Driver.BeginQuery) {
|
ctx->Driver.BeginQuery(ctx, q);
|
||||||
ctx->Driver.BeginQuery(ctx, target, q);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -275,13 +310,7 @@ _mesa_EndQueryARB(GLenum target)
|
|||||||
}
|
}
|
||||||
|
|
||||||
q->Active = GL_FALSE;
|
q->Active = GL_FALSE;
|
||||||
if (ctx->Driver.EndQuery) {
|
ctx->Driver.EndQuery(ctx, q);
|
||||||
ctx->Driver.EndQuery(ctx, target, q);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* if we're using software rendering/querying */
|
|
||||||
q->Ready = GL_TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -346,13 +375,8 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)
|
|||||||
|
|
||||||
switch (pname) {
|
switch (pname) {
|
||||||
case GL_QUERY_RESULT_ARB:
|
case GL_QUERY_RESULT_ARB:
|
||||||
while (!q->Ready) {
|
if (!q->Ready)
|
||||||
/* Wait for the query to finish! */
|
ctx->Driver.WaitQuery(ctx, q);
|
||||||
/* 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 result is too large for returned type, clamp to max value */
|
/* if result is too large for returned type, clamp to max value */
|
||||||
if (q->Result > 0x7fffffff) {
|
if (q->Result > 0x7fffffff) {
|
||||||
*params = 0x7fffffff;
|
*params = 0x7fffffff;
|
||||||
@@ -362,7 +386,6 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_QUERY_RESULT_AVAILABLE_ARB:
|
case GL_QUERY_RESULT_AVAILABLE_ARB:
|
||||||
/* XXX revisit when we have a hardware implementation! */
|
|
||||||
*params = q->Ready;
|
*params = q->Ready;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -390,13 +413,8 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)
|
|||||||
|
|
||||||
switch (pname) {
|
switch (pname) {
|
||||||
case GL_QUERY_RESULT_ARB:
|
case GL_QUERY_RESULT_ARB:
|
||||||
while (!q->Ready) {
|
if (!q->Ready)
|
||||||
/* Wait for the query to finish! */
|
ctx->Driver.WaitQuery(ctx, q);
|
||||||
/* 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 result is too large for returned type, clamp to max value */
|
/* if result is too large for returned type, clamp to max value */
|
||||||
if (q->Result > 0xffffffff) {
|
if (q->Result > 0xffffffff) {
|
||||||
*params = 0xffffffff;
|
*params = 0xffffffff;
|
||||||
@@ -406,7 +424,6 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_QUERY_RESULT_AVAILABLE_ARB:
|
case GL_QUERY_RESULT_AVAILABLE_ARB:
|
||||||
/* XXX revisit when we have a hardware implementation! */
|
|
||||||
*params = q->Ready;
|
*params = q->Ready;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -439,17 +456,11 @@ _mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params)
|
|||||||
|
|
||||||
switch (pname) {
|
switch (pname) {
|
||||||
case GL_QUERY_RESULT_ARB:
|
case GL_QUERY_RESULT_ARB:
|
||||||
while (!q->Ready) {
|
if (!q->Ready)
|
||||||
/* Wait for the query to finish! */
|
ctx->Driver.WaitQuery(ctx, q);
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
*params = q->Result;
|
*params = q->Result;
|
||||||
break;
|
break;
|
||||||
case GL_QUERY_RESULT_AVAILABLE_ARB:
|
case GL_QUERY_RESULT_AVAILABLE_ARB:
|
||||||
/* XXX revisit when we have a hardware implementation! */
|
|
||||||
*params = q->Ready;
|
*params = q->Ready;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -480,17 +491,11 @@ _mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params)
|
|||||||
|
|
||||||
switch (pname) {
|
switch (pname) {
|
||||||
case GL_QUERY_RESULT_ARB:
|
case GL_QUERY_RESULT_ARB:
|
||||||
while (!q->Ready) {
|
if (!q->Ready)
|
||||||
/* Wait for the query to finish! */
|
ctx->Driver.WaitQuery(ctx, q);
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
*params = q->Result;
|
*params = q->Result;
|
||||||
break;
|
break;
|
||||||
case GL_QUERY_RESULT_AVAILABLE_ARB:
|
case GL_QUERY_RESULT_AVAILABLE_ARB:
|
||||||
/* XXX revisit when we have a hardware implementation! */
|
|
||||||
*params = q->Ready;
|
*params = q->Ready;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Mesa 3-D graphics library
|
* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -36,6 +36,16 @@ _mesa_init_query(GLcontext *ctx);
|
|||||||
extern void
|
extern void
|
||||||
_mesa_free_query_data(GLcontext *ctx);
|
_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
|
extern void GLAPIENTRY
|
||||||
_mesa_GenQueriesARB(GLsizei n, GLuint *ids);
|
_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
|
* at this point - if the hardware doesn't support it, don't
|
||||||
* advertise it to the application.
|
* advertise it to the application.
|
||||||
*/
|
*/
|
||||||
failover->pipe.reset_occlusion_counter = hw->reset_occlusion_counter;
|
failover->pipe.begin_query = hw->begin_query;
|
||||||
failover->pipe.get_occlusion_counter = hw->get_occlusion_counter;
|
failover->pipe.end_query = hw->end_query;
|
||||||
|
|
||||||
failover_init_state_functions( failover );
|
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,
|
static boolean i915_draw_elements( struct pipe_context *pipe,
|
||||||
struct pipe_buffer_handle *indexBuffer,
|
struct pipe_buffer_handle *indexBuffer,
|
||||||
unsigned indexSize,
|
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.supported_formats = i915_supported_formats;
|
||||||
i915->pipe.max_texture_size = i915_max_texture_size;
|
i915->pipe.max_texture_size = i915_max_texture_size;
|
||||||
i915->pipe.clear = i915_clear;
|
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_arrays = i915_draw_arrays;
|
||||||
i915->pipe.draw_elements = i915_draw_elements;
|
i915->pipe.draw_elements = i915_draw_elements;
|
||||||
|
@@ -75,11 +75,12 @@ struct pipe_context {
|
|||||||
void (*clear)(struct pipe_context *pipe, struct pipe_surface *ps,
|
void (*clear)(struct pipe_context *pipe, struct pipe_surface *ps,
|
||||||
unsigned clearValue);
|
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);
|
void (*begin_query)(struct pipe_context *pipe, struct pipe_query_object *q);
|
||||||
unsigned (*get_occlusion_counter)(struct pipe_context *pipe);
|
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
|
* State functions
|
||||||
|
@@ -299,4 +299,12 @@
|
|||||||
#define PIPE_PRIM_POLYGON 9
|
#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
|
#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
|
#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 );
|
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 );
|
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 )
|
static const char *softpipe_get_name( struct pipe_context *pipe )
|
||||||
{
|
{
|
||||||
return "softpipe";
|
return "softpipe";
|
||||||
@@ -260,8 +278,11 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys,
|
|||||||
|
|
||||||
softpipe->pipe.clear = softpipe_clear;
|
softpipe->pipe.clear = softpipe_clear;
|
||||||
softpipe->pipe.flush = softpipe_flush;
|
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_name = softpipe_get_name;
|
||||||
softpipe->pipe.get_vendor = softpipe_get_vendor;
|
softpipe->pipe.get_vendor = softpipe_get_vendor;
|
||||||
|
|
||||||
|
@@ -93,6 +93,11 @@ struct softpipe_context {
|
|||||||
struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX];
|
struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX];
|
||||||
unsigned dirty;
|
unsigned dirty;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Active queries
|
||||||
|
*/
|
||||||
|
struct pipe_query_object *queries[PIPE_QUERY_TYPES];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mapped vertex buffers
|
* Mapped vertex buffers
|
||||||
*/
|
*/
|
||||||
@@ -120,8 +125,6 @@ struct softpipe_context {
|
|||||||
/** Derived from scissor and surface bounds: */
|
/** Derived from scissor and surface bounds: */
|
||||||
struct pipe_scissor_state cliprect;
|
struct pipe_scissor_state cliprect;
|
||||||
|
|
||||||
unsigned occlusion_counter;
|
|
||||||
|
|
||||||
unsigned line_stipple_counter;
|
unsigned line_stipple_counter;
|
||||||
|
|
||||||
/** Software quad rendering pipeline */
|
/** Software quad rendering pipeline */
|
||||||
|
@@ -44,11 +44,13 @@ static void
|
|||||||
occlusion_count_quad(struct quad_stage *qs, struct quad_header *quad)
|
occlusion_count_quad(struct quad_stage *qs, struct quad_header *quad)
|
||||||
{
|
{
|
||||||
struct softpipe_context *softpipe = qs->softpipe;
|
struct softpipe_context *softpipe = qs->softpipe;
|
||||||
|
struct pipe_query_object *occ
|
||||||
|
= softpipe->queries[PIPE_QUERY_OCCLUSION_COUNTER];
|
||||||
|
|
||||||
softpipe->occlusion_counter += (quad->mask ) & 1;
|
occ->count += (quad->mask ) & 1;
|
||||||
softpipe->occlusion_counter += (quad->mask >> 1) & 1;
|
occ->count += (quad->mask >> 1) & 1;
|
||||||
softpipe->occlusion_counter += (quad->mask >> 2) & 1;
|
occ->count += (quad->mask >> 2) & 1;
|
||||||
softpipe->occlusion_counter += (quad->mask >> 3) & 1;
|
occ->count += (quad->mask >> 3) & 1;
|
||||||
|
|
||||||
if (quad->mask)
|
if (quad->mask)
|
||||||
qs->next->run(qs->next, quad);
|
qs->next->run(qs->next, quad);
|
||||||
|
@@ -44,33 +44,102 @@
|
|||||||
#include "st_public.h"
|
#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
|
* Do glReadPixels by getting rows from the framebuffer surface with
|
||||||
* get_tile(). Convert to requested format/type with Mesa image routines.
|
* get_tile(). Convert to requested format/type with Mesa image routines.
|
||||||
* Image transfer ops are done in software too.
|
* Image transfer ops are done in software too.
|
||||||
*/
|
*/
|
||||||
static void
|
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;
|
struct pipe_context *pipe = ctx->st->pipe;
|
||||||
if (target == GL_SAMPLES_PASSED_ARB) {
|
struct st_query_object *stq = st_query_object(q);
|
||||||
pipe->reset_occlusion_counter(pipe);
|
|
||||||
|
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
|
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;
|
struct pipe_context *pipe = ctx->st->pipe;
|
||||||
if (target == GL_SAMPLES_PASSED_ARB) {
|
struct st_query_object *stq = st_query_object(q);
|
||||||
q->Result = pipe->get_occlusion_counter(pipe);
|
|
||||||
}
|
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)
|
void st_init_query_functions(struct dd_function_table *functions)
|
||||||
{
|
{
|
||||||
|
functions->NewQueryObject = st_NewQueryObject;
|
||||||
functions->BeginQuery = st_BeginQuery;
|
functions->BeginQuery = st_BeginQuery;
|
||||||
functions->EndQuery = st_EndQuery;
|
functions->EndQuery = st_EndQuery;
|
||||||
|
functions->WaitQuery = st_WaitQuery;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user