From 9b0add0be4a3ba7fc72779daf8361d8cd98d9f64 Mon Sep 17 00:00:00 2001
From: Ben Skeggs <skeggsb@gmail.com>
Date: Fri, 11 Jul 2008 22:45:11 +1000
Subject: nv50: quick hack to get textures untiled on map, and tiled on unmap

progs/fp/tri-tex is all good now rather than all scrambled :)
---
 src/gallium/drivers/nv50/nv50_context.h | 11 ++++++++++
 src/gallium/drivers/nv50/nv50_miptree.c | 18 +++++++++++------
 src/gallium/drivers/nv50/nv50_surface.c | 36 ++++++++++++++++++++++++++++-----
 3 files changed, 54 insertions(+), 11 deletions(-)

(limited to 'src/gallium/drivers/nv50')

diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index cb51fb02eb..1c069f1625 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -74,6 +74,17 @@ nv50_miptree(struct pipe_texture *pt)
 	return (struct nv50_miptree *)pt;
 }
 
+struct nv50_surface {
+	struct pipe_surface base;
+	struct pipe_buffer *untiled;
+};
+
+static INLINE struct nv50_surface *
+nv50_surface(struct pipe_surface *pt)
+{
+	return (struct nv50_surface *)pt;
+}
+
 struct nv50_state {
 	unsigned dirty;
 
diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c
index 8b61ca2a1f..a02ad41885 100644
--- a/src/gallium/drivers/nv50/nv50_miptree.c
+++ b/src/gallium/drivers/nv50/nv50_miptree.c
@@ -82,9 +82,14 @@ nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
 {
 	struct pipe_winsys *ws = pscreen->winsys;
 	struct nv50_miptree *mt = nv50_miptree(pt);
+	struct nv50_surface *s;
 	struct pipe_surface *ps;
 
-	ps = CALLOC_STRUCT(pipe_surface);
+	s = CALLOC_STRUCT(nv50_surface);
+	if (!s)
+		return NULL;
+	ps = &s->base;
+
 	ps->refcount = 1;
 	ps->winsys = ws;
 	ps->format = pt->format;
@@ -109,14 +114,15 @@ nv50_miptree_surface_del(struct pipe_screen *pscreen,
 			 struct pipe_surface **psurface)
 {
 	struct pipe_winsys *ws = pscreen->winsys;
-	struct pipe_surface *surf = *psurface;
+	struct pipe_surface *ps = *psurface;
+	struct nv50_surface *s = nv50_surface(ps);
 
 	*psurface = NULL;
 
-	if (--surf->refcount <= 0) {
-		pipe_texture_reference(&surf->texture, NULL);
-		pipe_buffer_reference(ws, &surf->buffer, NULL);
-		FREE(surf);
+	if (--ps->refcount <= 0) {
+		pipe_texture_reference(&ps->texture, NULL);
+		pipe_buffer_reference(ws, &ps->buffer, NULL);
+		FREE(s);
 	}
 }
 
diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c
index 6229b63626..8d3f1edcfe 100644
--- a/src/gallium/drivers/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nv50/nv50_surface.c
@@ -52,25 +52,51 @@ nv50_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
 }
 
 static void *
-nv50_surface_map(struct pipe_screen *screen, struct pipe_surface *surface,
+nv50_surface_map(struct pipe_screen *screen, struct pipe_surface *ps,
 		 unsigned flags )
 {
+	struct nouveau_winsys *nvws = nv50_screen(screen)->nvws;
 	struct pipe_winsys *ws = screen->winsys;
+	struct nv50_surface *s = nv50_surface(ps);
+	struct nv50_surface m = *s;
 	void *map;
 
-	map = ws->buffer_map(ws, surface->buffer, flags);
+	if (!s->untiled) {
+		s->untiled = ws->buffer_create(ws, 0, 0, ps->buffer->size);
+
+		m.base.buffer = s->untiled;
+		nvws->surface_copy(nvws, &m.base, 0, 0, &s->base, 0, 0,
+					 ps->width, ps->height);
+	}
+
+	/* Map original tiled surface to disallow it being validated while
+	 * untiled mirror is mapped.
+	 */
+	ws->buffer_map(ws, ps->buffer, flags);
+
+	map = ws->buffer_map(ws, s->untiled, flags);
 	if (!map)
 		return NULL;
 
-	return map + surface->offset;
+	return map;
 }
 
 static void
-nv50_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface)
+nv50_surface_unmap(struct pipe_screen *screen, struct pipe_surface *ps)
 {
+	struct nouveau_winsys *nvws = nv50_screen(screen)->nvws;
 	struct pipe_winsys *ws = screen->winsys;
+	struct nv50_surface *s = nv50_surface(ps);
+	struct nv50_surface m = *s;
+
+	ws->buffer_unmap(ws, s->untiled);
+	ws->buffer_unmap(ws, ps->buffer);
+
+	m.base.buffer = s->untiled;
+	nvws->surface_copy(nvws, &s->base, 0, 0, &m.base, 0, 0,
+				 ps->width, ps->height);
 
-	ws->buffer_unmap(ws, surface->buffer);
+	pipe_buffer_reference(ws, &s->untiled, NULL);
 }
 
 void
-- 
cgit v1.2.3