r300g: implement fake but compliant fences
This commit is contained in:
parent
e1c117d87b
commit
2c072c8f72
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue