r300g: implement fake but compliant fences

This commit is contained in:
Marek Olšák 2010-05-26 01:23:07 +02:00
parent e1c117d87b
commit 2c072c8f72
4 changed files with 63 additions and 35 deletions

View File

@ -235,3 +235,29 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
FREE(r300);
return NULL;
}
void r300_finish(struct r300_context *r300)
{
struct pipe_framebuffer_state *fb;
unsigned i;
/* This is a preliminary implementation of glFinish.
*
* The ideal implementation should use something like EmitIrqLocked and
* WaitIrq, or better, real fences.
*/
if (r300->fb_state.state) {
fb = r300->fb_state.state;
for (i = 0; i < fb->nr_cbufs; i++) {
if (fb->cbufs[i]->texture) {
r300->rws->buffer_wait(r300->rws,
r300_texture(fb->cbufs[i]->texture)->buffer);
}
if (fb->zsbuf) {
r300->rws->buffer_wait(r300->rws,
r300_texture(fb->zsbuf->texture)->buffer);
}
}
}
}

View File

@ -252,6 +252,22 @@ struct r300_query {
struct r300_query* next;
};
/* Fence object.
*
* This is a fake fence. Instead of syncing with the fence, we sync
* with the context, which is inefficient but compliant.
*
* This is not a subclass of pipe_fence_handle because pipe_fence_handle is
* never actually fully defined. So, rather than have it as a member, and do
* subclass-style casting, we treat pipe_query as an opaque, and just
* trust that our state tracker does not ever mess up query objects.
*/
struct r300_fence {
struct pipe_reference reference;
struct r300_context *ctx;
boolean signalled;
};
struct r300_texture {
/* Parent class */
struct u_resource b;
@ -474,6 +490,7 @@ void r300_init_render_functions(struct r300_context *r300);
void r300_init_state_functions(struct r300_context* r300);
void r300_init_resource_functions(struct r300_context* r300);
void r300_finish(struct r300_context *r300);
void r500_dump_rs_block(struct r300_rs_block *rs);
static INLINE boolean CTX_DBG_ON(struct r300_context * ctx, unsigned flags)

View File

@ -37,8 +37,7 @@ static void r300_flush(struct pipe_context* pipe,
struct r300_context *r300 = r300_context(pipe);
struct r300_query *query;
struct r300_atom *atom;
struct pipe_framebuffer_state *fb;
unsigned i;
struct r300_fence **rfence = (struct r300_fence**)fence;
CS_LOCALS(r300);
(void) cs_count;
@ -75,37 +74,10 @@ static void r300_flush(struct pipe_context* pipe,
query->flushed = TRUE;
}
/* XXX
*
* This is a preliminary implementation of glFinish. Note that st/mesa
* uses a non-null fence when glFinish is called and then waits for
* the fence. Instead of returning the actual fence, we do the sync
* directly.
*
* The ideal implementation should use something like EmitIrqLocked and
* WaitIrq, or better, real fences.
*
* This feature degrades performance to the level of r300c for games that
* use glFinish a lot, even openarena does. Ideally we wouldn't need
* glFinish at all if we had proper throttling in swapbuffers so that
* the CPU wouldn't outrun the GPU by several frames, so this is basically
* a temporary fix for the input lag. Once swap&sync works with DRI2,
* I'll be happy to remove this code.
*
* - M. */
if (fence && r300->fb_state.state) {
fb = r300->fb_state.state;
for (i = 0; i < fb->nr_cbufs; i++) {
if (fb->cbufs[i]->texture) {
r300->rws->buffer_wait(r300->rws,
r300_texture(fb->cbufs[i]->texture)->buffer);
}
if (fb->zsbuf) {
r300->rws->buffer_wait(r300->rws,
r300_texture(fb->zsbuf->texture)->buffer);
}
}
/* Create a new fence. */
if (rfence) {
*rfence = CALLOC_STRUCT(r300_fence);
(*rfence)->ctx = r300;
}
}

View File

@ -319,20 +319,33 @@ static void r300_fence_reference(struct pipe_screen *screen,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *fence)
{
struct r300_fence **oldf = (struct r300_fence**)ptr;
struct r300_fence *newf = (struct r300_fence*)fence;
if (pipe_reference(&(*oldf)->reference, &newf->reference))
FREE(*oldf);
*ptr = fence;
}
static int r300_fence_signalled(struct pipe_screen *screen,
struct pipe_fence_handle *fence,
unsigned flags)
{
return 0;
struct r300_fence *rfence = (struct r300_fence*)fence;
return rfence->signalled ? 0 : 1; /* 0 == success */
}
static int r300_fence_finish(struct pipe_screen *screen,
struct pipe_fence_handle *fence,
unsigned flags)
{
return 0;
struct r300_fence *rfence = (struct r300_fence*)fence;
r300_finish(rfence->ctx);
rfence->signalled = TRUE;
return 0; /* 0 == success */
}
struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws)