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);
+ }
+ }
+ }
+}
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;
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)
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;
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;
}
}
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)