[mesa patch v3 2/3] dri/nouveau: Use event driven buffer validation.

Francisco Jerez currojerez at riseup.net
Fri Jan 22 06:30:57 PST 2010


---
 src/mesa/drivers/dri/nouveau/nouveau_context.c  |   49 ++++++++++++++++-------
 src/mesa/drivers/dri/nouveau/nouveau_context.h  |    7 +++
 src/mesa/drivers/dri/nouveau/nouveau_driver.c   |    3 +
 src/mesa/drivers/dri/nouveau/nouveau_render_t.c |    2 +
 src/mesa/drivers/dri/nouveau/nouveau_screen.c   |   20 +++++++++
 src/mesa/drivers/dri/nouveau/nouveau_state.c    |    2 -
 src/mesa/drivers/dri/nouveau/nv10_context.c     |    2 +
 7 files changed, 68 insertions(+), 17 deletions(-)

diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
index 9312ec7..e526b6d 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c
@@ -127,7 +127,8 @@ nouveau_context_destroy(__DRIcontext *dri_ctx)
 }
 
 static void
-nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
+nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
+			     unsigned int *stamp)
 {
 	struct nouveau_context *nctx = context->driverPrivate;
 	GLcontext *ctx = &nctx->base;
@@ -137,6 +138,8 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
 	__DRIbuffer *buffers = NULL;
 	int i = 0, count, ret;
 
+	*stamp = *drawable->pStamp;
+
 	attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
 	if (fb->Visual.doubleBufferMode)
 		attachments[i++] = __DRI_BUFFER_BACK_LEFT;
@@ -217,15 +220,18 @@ nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *dri_draw,
 		struct nouveau_context *nctx = dri_ctx->driverPrivate;
 		GLcontext *ctx = &nctx->base;
 
-		if (nctx->screen->context != nctx) {
-			nctx->screen->context = nctx;
-			nctx->dirty = ~0;
-		}
+		if (nctx->screen->context == nctx)
+			return GL_TRUE;
+
+		nctx->screen->context = nctx;
+		nctx->dirty = ~0;
 
 		/* Ask the X server for new renderbuffers. */
-		nouveau_update_renderbuffers(dri_ctx, dri_draw);
+		nouveau_update_renderbuffers(dri_ctx, dri_draw,
+					     &nctx->drawable.d_stamp);
 		if (dri_draw != dri_read)
-			nouveau_update_renderbuffers(dri_ctx, dri_read);
+			nouveau_update_renderbuffers(dri_ctx, dri_read,
+						     &nctx->drawable.r_stamp);
 
 		/* Pass it down to mesa. */
 		_mesa_make_current(ctx, dri_draw->driverPrivate,
@@ -260,17 +266,30 @@ nouveau_fallback(GLcontext *ctx, enum nouveau_fallback mode)
 void
 nouveau_validate_framebuffer(GLcontext *ctx)
 {
+	struct nouveau_context *nctx = to_nouveau_context(ctx);
 	__DRIcontext *dri_ctx = to_nouveau_context(ctx)->dri_context;
+	__DRIdrawable *dri_draw = dri_ctx->driDrawablePriv;
+	__DRIdrawable *dri_read = dri_ctx->driReadablePriv;
 
-	if (ctx->DrawBuffer->Name)
-		return;
+	if ((ctx->DrawBuffer->Name == 0 &&
+	     nctx->drawable.d_stamp != *dri_draw->pStamp) ||
+	    (dri_draw != dri_read &&
+	     ctx->ReadBuffer->Name == 0 &&
+	     nctx->drawable.r_stamp != *dri_read->pStamp)) {
+		if (nctx->drawable.dirty)
+			ctx->Driver.Flush(ctx);
 
-	ctx->Driver.Flush(ctx);
+		/* Ask the X server for new renderbuffers. */
+		nouveau_update_renderbuffers(dri_ctx, dri_draw,
+					     &nctx->drawable.d_stamp);
+		if (dri_draw != dri_read)
+			nouveau_update_renderbuffers(dri_ctx, dri_read,
+						     &nctx->drawable.r_stamp);
 
-	/* Make sure our renderbuffers are up-to-date. */
-	nouveau_update_renderbuffers(dri_ctx, dri_ctx->driDrawablePriv);
-	if (dri_ctx->driDrawablePriv != dri_ctx->driReadablePriv)
-		nouveau_update_renderbuffers(dri_ctx, dri_ctx->driReadablePriv);
+		if (nctx->dirty)
+			FIRE_RING(context_chan(ctx));
+	}
 
-	FIRE_RING(context_chan(ctx));
+	/* Someone's planning to draw something really soon. */
+	nctx->drawable.dirty = GL_TRUE;
 }
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h
index 4171249..891fca0 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h
@@ -38,6 +38,12 @@ enum nouveau_fallback {
 	SWRAST,
 };
 
+struct nouveau_drawable_state {
+	GLboolean dirty;
+	unsigned int d_stamp;
+	unsigned int r_stamp;
+};
+
 struct nouveau_context {
 	GLcontext base;
 	__DRIcontext *dri_context;
@@ -48,6 +54,7 @@ struct nouveau_context {
 
 	struct nouveau_bo_state bo;
 	struct nouveau_render_state render;
+	struct nouveau_drawable_state drawable;
 };
 
 #define to_nouveau_context(ctx)	((struct nouveau_context *)(ctx))
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.c b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
index 12df30a..bf0e20c 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_driver.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
@@ -67,6 +67,8 @@ nouveau_flush(GLcontext *ctx)
 
 		dri2->flushFrontBuffer(drawable, drawable->loaderPrivate);
 	}
+
+	nctx->drawable.dirty = GL_FALSE;
 }
 
 static void
@@ -82,6 +84,7 @@ nouveau_clear(GLcontext *ctx, GLbitfield buffers)
 	int x, y, w, h;
 	int i, buf;
 
+	nouveau_validate_framebuffer(ctx);
 	get_scissors(fb, &x, &y, &w, &h);
 
 	for (i = 0; i < BUFFER_COUNT; i++) {
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_render_t.c b/src/mesa/drivers/dri/nouveau/nouveau_render_t.c
index 8c551de..6fc2668 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_render_t.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_render_t.c
@@ -218,6 +218,8 @@ render_prims(GLcontext *ctx, const struct gl_client_array **arrays,
 {
 	struct nouveau_context *nctx = to_nouveau_context(ctx);
 
+	nouveau_validate_framebuffer(ctx);
+
 	if (nctx->fallback == HWTNL)
 		TAG(vbo_render_prims)(ctx, arrays, prims, nr_prims, ib,
 				      index_bounds_valid, min_index, max_index);
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
index fbb0d75..9a19144 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_screen.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
@@ -35,6 +35,8 @@
 #include "main/framebuffer.h"
 #include "main/renderbuffer.h"
 
+static const __DRIextension *nouveau_screen_extensions[];
+
 static void
 nouveau_destroy_screen(__DRIscreen *dri_screen);
 
@@ -104,6 +106,7 @@ nouveau_init_screen2(__DRIscreen *dri_screen)
 		return NULL;
 
 	dri_screen->private = screen;
+	dri_screen->extensions = nouveau_screen_extensions;
 	screen->dri_screen = dri_screen;
 
 	/* Open the DRM device. */
@@ -243,6 +246,23 @@ nouveau_destroy_buffer(__DRIdrawable *drawable)
 		(struct gl_framebuffer **)&drawable->driverPrivate, NULL);
 }
 
+static void
+nouveau_drawable_flush(__DRIdrawable *draw)
+{
+}
+
+static const struct __DRI2flushExtensionRec nouveau_flush_extension = {
+    { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
+    nouveau_drawable_flush,
+    NULL,
+    dri2InvalidateDrawable,
+};
+
+static const __DRIextension *nouveau_screen_extensions[] = {
+    &nouveau_flush_extension.base,
+    NULL
+};
+
 const struct __DriverAPIRec driDriverAPI = {
 	.InitScreen2     = nouveau_init_screen2,
 	.DestroyScreen   = nouveau_destroy_screen,
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.c b/src/mesa/drivers/dri/nouveau/nouveau_state.c
index 01f924c..7c5f7f2 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_state.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_state.c
@@ -366,8 +366,6 @@ nouveau_update_state(GLcontext *ctx, GLbitfield new_state)
 		context_dirty(ctx, PROJECTION);
 	if (new_state & _NEW_MODELVIEW)
 		context_dirty(ctx, MODELVIEW);
-	if (new_state & _NEW_VIEWPORT)
-		nouveau_validate_framebuffer(ctx);
 
 	_swrast_InvalidateState(ctx, new_state);
 	_tnl_InvalidateState(ctx, new_state);
diff --git a/src/mesa/drivers/dri/nouveau/nv10_context.c b/src/mesa/drivers/dri/nouveau/nv10_context.c
index b2ef800..d1afa87 100644
--- a/src/mesa/drivers/dri/nouveau/nv10_context.c
+++ b/src/mesa/drivers/dri/nouveau/nv10_context.c
@@ -39,6 +39,8 @@ nv10_clear(GLcontext *ctx, GLbitfield buffers)
 	struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(
 		ctx->DrawBuffer);
 
+	nouveau_validate_framebuffer(ctx);
+
 	/* Clear the LMA depth buffer, if present. */
 	if ((buffers & BUFFER_BIT_DEPTH) && ctx->Depth.Mask &&
 	    nfb->lma_bo) {
-- 
1.6.4.4



More information about the xorg-devel mailing list