summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2010-05-26 01:23:07 +0200
committerMarek Olšák <maraeo@gmail.com>2010-05-26 01:23:11 +0200
commit2c072c8f72647a3b32e9855f7635b37ba399f5be (patch)
tree861a0b424ed1e4e17b6ca9f0f0503b8daa8ea161
parente1c117d87bd1c77c6093a7a77b7994a8313b084e (diff)
r300g: implement fake but compliant fences
-rw-r--r--src/gallium/drivers/r300/r300_context.c26
-rw-r--r--src/gallium/drivers/r300/r300_context.h17
-rw-r--r--src/gallium/drivers/r300/r300_flush.c38
-rw-r--r--src/gallium/drivers/r300/r300_screen.c17
4 files changed, 63 insertions, 35 deletions
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index 505970ffb8..4721b7d5dc 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -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);
+ }
+ }
+ }
+}
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 0933d6b833..82183cfcb8 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -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)
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index f629e57c5a..9cda940c85 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -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;
}
}
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index ef0255066b..4859db523a 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -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)