Mesa (master): nv50: use CLEAR_BUFFERS for surface fills

Christoph Bumiller chrisbmr at kemper.freedesktop.org
Sat Sep 25 17:37:24 UTC 2010


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

Author: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
Date:   Fri Sep 24 22:46:51 2010 +0200

nv50: use CLEAR_BUFFERS for surface fills

The 2D engine's fill doesn't seem suited for RGBA32F or ZS buffers.

---

 src/gallium/drivers/nv50/nv50_reg.h     |    3 +
 src/gallium/drivers/nv50/nv50_screen.c  |    3 +
 src/gallium/drivers/nv50/nv50_surface.c |  110 ++++++++++++++++++++++++------
 3 files changed, 94 insertions(+), 22 deletions(-)

diff --git a/src/gallium/drivers/nv50/nv50_reg.h b/src/gallium/drivers/nv50/nv50_reg.h
index 365576f..949838b 100644
--- a/src/gallium/drivers/nv50/nv50_reg.h
+++ b/src/gallium/drivers/nv50/nv50_reg.h
@@ -1018,6 +1018,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define  NV50TCL_FP_START_ID								0x00001414
 #define  NV50TCL_GP_VERTEX_OUTPUT_COUNT							0x00001420
 #define  NV50TCL_VB_ELEMENT_BASE							0x00001434
+#define  NV50TCL_CLEAR_FLAGS								0x0000143c
+#define   NV50TCL_CLEAR_FLAGS_OGL							(1 <<  0)
+#define   NV50TCL_CLEAR_FLAGS_D3D							(1 <<  4)
 #define  NV50TCL_INSTANCE_BASE								0x00001438
 #define  NV50TCL_CODE_CB_FLUSH								0x00001440
 #define  NV50TCL_BIND_TSC(x)								(0x00001444+((x)*8))
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index 7c9342b..c511537 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -457,6 +457,9 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
 	BEGIN_RING(chan, screen->tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
 	OUT_RING  (chan, 8);
 
+	BEGIN_RING(chan, screen->tesla, NV50TCL_CLEAR_FLAGS, 1);
+	OUT_RING  (chan, NV50TCL_CLEAR_FLAGS_D3D);
+
 	/* constant buffers for immediates and VP/FP parameters */
 	ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (32 * 4) * 4,
 			     &screen->constbuf_misc[0]);
diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c
index 623024c..3f31662 100644
--- a/src/gallium/drivers/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nv50/nv50_surface.c
@@ -199,7 +199,6 @@ nv50_surface_copy(struct pipe_context *pipe,
 	nv50_miptree_surface_del(ps_dst);
 }
 
-/* XXX this should probably look more along the lines of nv50_clear */
 static void
 nv50_clear_render_target(struct pipe_context *pipe,
 			 struct pipe_surface *dst,
@@ -209,33 +208,99 @@ nv50_clear_render_target(struct pipe_context *pipe,
 {
 	struct nv50_context *nv50 = nv50_context(pipe);
 	struct nv50_screen *screen = nv50->screen;
-	struct nouveau_channel *chan = screen->eng2d->channel;
-	struct nouveau_grobj *eng2d = screen->eng2d;
-	int format, ret;
-	union util_color uc;
-	util_pack_color(rgba, dst->format, &uc);
+	struct nouveau_channel *chan = screen->base.channel;
+	struct nouveau_grobj *tesla = screen->tesla;
+	struct nv50_miptree *mt = nv50_miptree(dst->texture);
+	struct nouveau_bo *bo = mt->base.bo;
 
-	format = nv50_2d_format(dst->format);
-	if (!format)
-		return;
+	BEGIN_RING(chan, tesla, NV50TCL_CLEAR_COLOR(0), 4);
+	OUT_RINGf (chan, rgba[0]);
+	OUT_RINGf (chan, rgba[1]);
+	OUT_RINGf (chan, rgba[2]);
+	OUT_RINGf (chan, rgba[3]);
 
-	ret = MARK_RING (chan, 16 + 32, 2);
-	if (ret)
+	if (MARK_RING(chan, 18, 2))
 		return;
 
-	ret = nv50_surface_set(screen, dst, 1);
-	if (ret)
+	BEGIN_RING(chan, tesla, NV50TCL_RT_CONTROL, 1);
+	OUT_RING  (chan, 1);
+	BEGIN_RING(chan, tesla, NV50TCL_RT_ADDRESS_HIGH(0), 5);
+	OUT_RELOCh(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RELOCl(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RING  (chan, nv50_format_table[dst->format].rt);
+	OUT_RING  (chan, mt->level[dst->level].tile_mode << 4);
+	OUT_RING  (chan, 0);
+	BEGIN_RING(chan, tesla, NV50TCL_RT_HORIZ(0), 2);
+	OUT_RING  (chan, dst->width);
+	OUT_RING  (chan, dst->height);
+	BEGIN_RING(chan, tesla, NV50TCL_RT_ARRAY_MODE, 1);
+	OUT_RING  (chan, 1);
+
+	/* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */
+
+	BEGIN_RING(chan, tesla, NV50TCL_VIEWPORT_HORIZ(0), 2);
+	OUT_RING  (chan, (width << 16) | dstx);
+	OUT_RING  (chan, (height << 16) | dsty);
+
+	BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1);
+	OUT_RING  (chan, 0x3c);
+
+	nv50->dirty |= NV50_NEW_FRAMEBUFFER;
+}
+
+static void
+nv50_clear_depth_stencil(struct pipe_context *pipe,
+			 struct pipe_surface *dst,
+			 unsigned clear_flags,
+			 double depth,
+			 unsigned stencil,
+			 unsigned dstx, unsigned dsty,
+			 unsigned width, unsigned height)
+{
+	struct nv50_context *nv50 = nv50_context(pipe);
+	struct nv50_screen *screen = nv50->screen;
+	struct nouveau_channel *chan = screen->base.channel;
+	struct nouveau_grobj *tesla = screen->tesla;
+	struct nv50_miptree *mt = nv50_miptree(dst->texture);
+	struct nouveau_bo *bo = mt->base.bo;
+	uint32_t mode = 0;
+
+	if (clear_flags & PIPE_CLEAR_DEPTH) {
+		BEGIN_RING(chan, tesla, NV50TCL_CLEAR_DEPTH, 1);
+		OUT_RINGf (chan, depth);
+		mode |= NV50TCL_CLEAR_BUFFERS_Z;
+	}
+
+	if (clear_flags & PIPE_CLEAR_STENCIL) {
+		BEGIN_RING(chan, tesla, NV50TCL_CLEAR_STENCIL, 1);
+		OUT_RING  (chan, stencil & 0xff);
+		mode |= NV50TCL_CLEAR_BUFFERS_S;
+	}
+
+	if (MARK_RING(chan, 17, 2))
 		return;
 
-	BEGIN_RING(chan, eng2d, NV50_2D_DRAW_SHAPE, 3);
-	OUT_RING  (chan, NV50_2D_DRAW_SHAPE_RECTANGLES);
-	OUT_RING  (chan, format);
-	OUT_RING  (chan, uc.ui);
-	BEGIN_RING(chan, eng2d, NV50_2D_DRAW_POINT32_X(0), 4);
-	OUT_RING  (chan, dstx);
-	OUT_RING  (chan, dsty);
-	OUT_RING  (chan, width);
-	OUT_RING  (chan, height);
+	BEGIN_RING(chan, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5);
+	OUT_RELOCh(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RELOCl(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RING  (chan, nv50_format_table[dst->format].rt);
+	OUT_RING  (chan, mt->level[dst->level].tile_mode << 4);
+	OUT_RING  (chan, 0);
+	BEGIN_RING(chan, tesla, NV50TCL_ZETA_ENABLE, 1);
+	OUT_RING  (chan, 1);
+	BEGIN_RING(chan, tesla, NV50TCL_ZETA_HORIZ, 3);
+	OUT_RING  (chan, dst->width);
+	OUT_RING  (chan, dst->height);
+	OUT_RING  (chan, (1 << 16) | 1);
+
+	BEGIN_RING(chan, tesla, NV50TCL_VIEWPORT_HORIZ(0), 2);
+	OUT_RING  (chan, (width << 16) | dstx);
+	OUT_RING  (chan, (height << 16) | dsty);
+
+	BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1);
+	OUT_RING  (chan, mode);
+
+	nv50->dirty |= NV50_NEW_FRAMEBUFFER;
 }
 
 void
@@ -243,6 +308,7 @@ nv50_init_surface_functions(struct nv50_context *nv50)
 {
 	nv50->pipe.resource_copy_region = nv50_surface_copy;
 	nv50->pipe.clear_render_target = nv50_clear_render_target;
+	nv50->pipe.clear_depth_stencil = nv50_clear_depth_stencil;
 }
 
 




More information about the mesa-commit mailing list