Mesa (master): dri/nouveau: Implement EXT_texture_from_pixmap.

Francisco Jerez currojerez at kemper.freedesktop.org
Thu Feb 25 18:33:39 UTC 2010


Module: Mesa
Branch: master
Commit: 4a7e9b5df453055ed6eedce1ea5c1d4a2f810fa7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4a7e9b5df453055ed6eedce1ea5c1d4a2f810fa7

Author: Francisco Jerez <currojerez at riseup.net>
Date:   Sun Feb 21 14:23:40 2010 +0100

dri/nouveau: Implement EXT_texture_from_pixmap.

---

 src/mesa/drivers/dri/nouveau/nouveau_context.c |   91 ++++++++++++------------
 src/mesa/drivers/dri/nouveau/nouveau_context.h |   13 +---
 src/mesa/drivers/dri/nouveau/nouveau_driver.c  |    2 -
 src/mesa/drivers/dri/nouveau/nouveau_fbo.c     |    1 -
 src/mesa/drivers/dri/nouveau/nouveau_screen.c  |    8 ++
 src/mesa/drivers/dri/nouveau/nouveau_texture.c |   53 ++++++++++++++
 src/mesa/drivers/dri/nouveau/nouveau_texture.h |    5 ++
 7 files changed, 116 insertions(+), 57 deletions(-)

diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
index b1b0e81..2629733 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c
@@ -168,19 +168,19 @@ nouveau_context_destroy(__DRIcontext *dri_ctx)
 	context_drv(ctx)->context_destroy(ctx);
 }
 
-static void
-nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
-			     unsigned int *stamp)
+void
+nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw)
 {
-	struct nouveau_context *nctx = context->driverPrivate;
-	GLcontext *ctx = &nctx->base;
-	__DRIscreen *screen = context->driScreenPriv;
-	struct gl_framebuffer *fb = drawable->driverPrivate;
+	GLcontext *ctx = dri_ctx->driverPrivate;
+	__DRIscreen *screen = dri_ctx->driScreenPriv;
+	struct gl_framebuffer *fb = draw->driverPrivate;
 	unsigned int attachments[10];
 	__DRIbuffer *buffers = NULL;
 	int i = 0, count, ret;
 
-	*stamp = *drawable->pStamp;
+	if (draw->lastStamp == *draw->pStamp)
+		return;
+	draw->lastStamp = *draw->pStamp;
 
 	attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
 	if (fb->Visual.doubleBufferMode)
@@ -192,10 +192,9 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
 	else if (fb->Visual.haveStencilBuffer)
 		attachments[i++] = __DRI_BUFFER_STENCIL;
 
-	buffers = (*screen->dri2.loader->getBuffers)(drawable,
-						     &drawable->w, &drawable->h,
+	buffers = (*screen->dri2.loader->getBuffers)(draw, &draw->w, &draw->h,
 						     attachments, i, &count,
-						     drawable->loaderPrivate);
+						     draw->loaderPrivate);
 	if (buffers == NULL)
 		return;
 
@@ -227,8 +226,8 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
 		rb = fb->Attachment[index].Renderbuffer;
 		s = &to_nouveau_renderbuffer(rb)->surface;
 
-		s->width = drawable->w;
-		s->height = drawable->h;
+		s->width = draw->w;
+		s->height = draw->h;
 		s->pitch = buffers[i].pitch;
 		s->cpp = buffers[i].cpp;
 
@@ -244,12 +243,25 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
 			ret = nouveau_bo_handle_ref(context_dev(ctx),
 						    buffers[i].name, &s->bo);
 			assert(!ret);
-
-			context_dirty(ctx, FRAMEBUFFER);
 		}
 	}
 
-	_mesa_resize_framebuffer(ctx, fb, drawable->w, drawable->h);
+	_mesa_resize_framebuffer(NULL, fb, draw->w, draw->h);
+}
+
+static void
+update_framebuffer(__DRIcontext *dri_ctx, __DRIdrawable *draw,
+		   int *stamp)
+{
+	GLcontext *ctx = dri_ctx->driverPrivate;
+	struct gl_framebuffer *fb = draw->driverPrivate;
+
+	*stamp = *draw->pStamp;
+
+	nouveau_update_renderbuffers(dri_ctx, draw);
+	_mesa_resize_framebuffer(ctx, fb, draw->w, draw->h);
+
+	context_dirty(ctx, FRAMEBUFFER);
 }
 
 GLboolean
@@ -260,16 +272,15 @@ nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *dri_draw,
 		struct nouveau_context *nctx = dri_ctx->driverPrivate;
 		GLcontext *ctx = &nctx->base;
 
-		if (dri_draw->driverPrivate == ctx->WinSysDrawBuffer &&
-		    dri_read->driverPrivate == ctx->WinSysReadBuffer)
-			return GL_TRUE;
-
 		/* 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);
+		if (dri_draw->driverPrivate != ctx->WinSysDrawBuffer)
+			update_framebuffer(dri_ctx, dri_draw,
+					   &dri_ctx->dri2.draw_stamp);
+
+		if (dri_draw != dri_read &&
+		    dri_read->driverPrivate != ctx->WinSysReadBuffer)
+			update_framebuffer(dri_ctx, dri_read,
+					   &dri_ctx->dri2.read_stamp);
 
 		/* Pass it down to mesa. */
 		_mesa_make_current(ctx, dri_draw->driverPrivate,
@@ -307,30 +318,20 @@ 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 == 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);
+	if (ctx->DrawBuffer->Name == 0 &&
+	    dri_ctx->dri2.draw_stamp != *dri_draw->pStamp)
+		update_framebuffer(dri_ctx, dri_draw,
+				   &dri_ctx->dri2.draw_stamp);
 
-		/* 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);
-
-		if (nouveau_next_dirty_state(ctx) >= 0)
-			FIRE_RING(context_chan(ctx));
-	}
+	if (ctx->ReadBuffer->Name == 0 && dri_draw != dri_read &&
+	    dri_ctx->dri2.read_stamp != *dri_read->pStamp)
+		update_framebuffer(dri_ctx, dri_read,
+				   &dri_ctx->dri2.read_stamp);
 
-	/* Someone's planning to draw something really soon. */
-	nctx->drawable.dirty = GL_TRUE;
+	if (nouveau_next_dirty_state(ctx) >= 0)
+		FIRE_RING(context_chan(ctx));
 }
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h
index efe3e51..682f8a4 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h
@@ -56,12 +56,6 @@ struct nouveau_hw_state {
 	struct nouveau_grobj *sifm;
 };
 
-struct nouveau_drawable_state {
-	GLboolean dirty;
-	unsigned int d_stamp;
-	unsigned int r_stamp;
-};
-
 struct nouveau_context {
 	GLcontext base;
 	__DRIcontext *dri_context;
@@ -73,7 +67,6 @@ struct nouveau_context {
 	struct nouveau_hw_state hw;
 	struct nouveau_bo_state bo;
 	struct nouveau_render_state render;
-	struct nouveau_drawable_state drawable;
 };
 
 #define to_nouveau_context(ctx)	((struct nouveau_context *)(ctx))
@@ -107,9 +100,11 @@ nouveau_context_deinit(GLcontext *ctx);
 void
 nouveau_context_destroy(__DRIcontext *dri_ctx);
 
+void
+nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw);
+
 GLboolean
-nouveau_context_make_current(__DRIcontext *dri_ctx,
-			     __DRIdrawable *ddraw,
+nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *ddraw,
 			     __DRIdrawable *rdraw);
 
 GLboolean
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.c b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
index afaa8de..1d12f43 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_driver.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
@@ -67,8 +67,6 @@ nouveau_flush(GLcontext *ctx)
 
 		dri2->flushFrontBuffer(drawable, drawable->loaderPrivate);
 	}
-
-	nctx->drawable.dirty = GL_FALSE;
 }
 
 static void
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fbo.c b/src/mesa/drivers/dri/nouveau/nouveau_fbo.c
index c5fb015..1db8c5d 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_fbo.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_fbo.c
@@ -142,7 +142,6 @@ nouveau_renderbuffer_dri_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
 	rb->Width = width;
 	rb->Height = height;
 
-	context_dirty(ctx, FRAMEBUFFER);
 	return GL_TRUE;
 }
 
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
index 71e57e1..18db12f 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_screen.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
@@ -27,6 +27,7 @@
 #include "nouveau_driver.h"
 #include "nouveau_context.h"
 #include "nouveau_fbo.h"
+#include "nouveau_texture.h"
 #include "nouveau_drmif.h"
 #include "nv04_driver.h"
 #include "nv10_driver.h"
@@ -226,8 +227,15 @@ static const struct __DRI2flushExtensionRec nouveau_flush_extension = {
     dri2InvalidateDrawable,
 };
 
+static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = {
+    { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
+    NULL,
+    nouveau_set_texbuffer,
+};
+
 static const __DRIextension *nouveau_screen_extensions[] = {
     &nouveau_flush_extension.base,
+    &nouveau_texbuffer_extension.base,
     NULL
 };
 
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_texture.c b/src/mesa/drivers/dri/nouveau/nouveau_texture.c
index 840bd6f..c1b0dda 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_texture.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_texture.c
@@ -27,6 +27,7 @@
 #include "nouveau_driver.h"
 #include "nouveau_context.h"
 #include "nouveau_texture.h"
+#include "nouveau_fbo.h"
 #include "nouveau_util.h"
 
 #include "main/texobj.h"
@@ -36,6 +37,7 @@
 #include "main/texgetimage.h"
 #include "main/mipmap.h"
 #include "main/texfetch.h"
+#include "main/teximage.h"
 
 static struct gl_texture_object *
 nouveau_texture_new(GLcontext *ctx, GLuint name, GLenum target)
@@ -489,6 +491,57 @@ nouveau_bind_texture(GLcontext *ctx, GLenum target,
 	context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
 }
 
+static gl_format
+get_texbuffer_format(struct gl_renderbuffer *rb, GLint format)
+{
+	struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
+
+	if (s->cpp < 4)
+		return s->format;
+	else if (format == __DRI_TEXTURE_FORMAT_RGBA)
+		return MESA_FORMAT_ARGB8888;
+	else
+		return MESA_FORMAT_XRGB8888;
+}
+
+void
+nouveau_set_texbuffer(__DRIcontext *dri_ctx,
+		      GLint target, GLint format,
+		      __DRIdrawable *draw)
+{
+	struct nouveau_context *nctx = dri_ctx->driverPrivate;
+	GLcontext *ctx = &nctx->base;
+	struct gl_framebuffer *fb = draw->driverPrivate;
+	struct gl_renderbuffer *rb =
+		fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+	struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target);
+	struct gl_texture_image *ti;
+	struct nouveau_surface *s;
+
+	_mesa_lock_texture(ctx, t);
+	ti = _mesa_get_tex_image(ctx, t, target, 0);
+	s = &to_nouveau_teximage(ti)->surface;
+
+	/* Update the texture surface with the given drawable. */
+	nouveau_update_renderbuffers(dri_ctx, draw);
+	nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s);
+
+	/* Update the image fields. */
+	_mesa_init_teximage_fields(ctx, target, ti, s->width, s->height,
+				   1, 0, s->cpp);
+	ti->RowStride = s->pitch / s->cpp;
+	ti->TexFormat = s->format = get_texbuffer_format(rb, format);
+
+	/* Try to validate it. */
+	if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1))
+		nouveau_texture_reallocate(ctx, t);
+
+	context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
+	context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
+
+	_mesa_unlock_texture(ctx, t);
+}
+
 static void
 nouveau_texture_map(GLcontext *ctx, struct gl_texture_object *t)
 {
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_texture.h b/src/mesa/drivers/dri/nouveau/nouveau_texture.h
index 75d8190..b91facb 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_texture.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_texture.h
@@ -43,6 +43,11 @@ struct nouveau_texture {
 #define texture_dirty(t) \
 	to_nouveau_texture(t)->dirty = GL_TRUE;
 
+void
+nouveau_set_texbuffer(__DRIcontext *dri_ctx,
+		      GLint target, GLint format,
+		      __DRIdrawable *draw);
+
 GLboolean
 nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t);
 




More information about the mesa-commit mailing list