summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nv40/nv40_screen.c
diff options
context:
space:
mode:
authorYounes Manton <younes.m@gmail.com>2008-12-01 23:48:29 -0500
committerYounes Manton <younes.m@gmail.com>2008-12-02 16:15:12 -0500
commit6b4776df35c46892d7701072b8c03cb1cf2d6f01 (patch)
tree019c35f691c5c1002ffd67f6f8e15bfec26665f3 /src/gallium/drivers/nv40/nv40_screen.c
parenta6b7c0bcbebb7532b6728500a868b7c985e3f822 (diff)
nouveau: Use swizzled textures & render targets on nv40 when possible.
Diffstat (limited to 'src/gallium/drivers/nv40/nv40_screen.c')
-rw-r--r--src/gallium/drivers/nv40/nv40_screen.c63
1 files changed, 57 insertions, 6 deletions
diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c
index ada0238511..25c7868296 100644
--- a/src/gallium/drivers/nv40/nv40_screen.c
+++ b/src/gallium/drivers/nv40/nv40_screen.c
@@ -137,22 +137,73 @@ static void *
nv40_surface_map(struct pipe_screen *screen, struct pipe_surface *surface,
unsigned flags )
{
- struct pipe_winsys *ws = screen->winsys;
- void *map;
+ struct pipe_winsys *ws = screen->winsys;
+ struct pipe_surface *surface_to_map;
+ void *map;
+
+ if (!(surface->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
+ struct nv40_miptree *mt = (struct nv40_miptree *)surface->texture;
+
+ if (!mt->shadow_tex) {
+ unsigned old_tex_usage = surface->texture->tex_usage;
+ surface->texture->tex_usage = NOUVEAU_TEXTURE_USAGE_LINEAR;
+ mt->shadow_tex = screen->texture_create(screen, surface->texture);
+ surface->texture->tex_usage = old_tex_usage;
+
+ assert(mt->shadow_tex->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR);
+ mt->shadow_surface = screen->get_tex_surface
+ (
+ screen, mt->shadow_tex,
+ surface->face, surface->level, surface->zslice,
+ surface->usage
+ );
+ }
+
+ surface_to_map = mt->shadow_surface;
+ }
+ else
+ surface_to_map = surface;
- map = ws->buffer_map(ws, surface->buffer, flags);
+ assert(surface_to_map);
+
+ map = ws->buffer_map(ws, surface_to_map->buffer, flags);
if (!map)
return NULL;
- return map + surface->offset;
+ return map + surface_to_map->offset;
}
static void
nv40_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface)
{
- struct pipe_winsys *ws = screen->winsys;
+ struct pipe_winsys *ws = screen->winsys;
+ struct pipe_surface *surface_to_unmap;
+
+ /* TODO: Copy from shadow just before push buffer is flushed instead.
+ There are probably some programs that map/unmap excessively
+ before rendering. */
+ if (!(surface->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
+ struct nv40_miptree *mt = (struct nv40_miptree *)surface->texture;
+
+ assert(mt->shadow_tex);
- ws->buffer_unmap(ws, surface->buffer);
+ surface_to_unmap = mt->shadow_surface;
+ }
+ else
+ surface_to_unmap = surface;
+
+ assert(surface_to_unmap);
+
+ ws->buffer_unmap(ws, surface_to_unmap->buffer);
+
+ if (surface_to_unmap != surface) {
+ struct nv40_screen *nvscreen = nv40_screen(screen);
+
+ nvscreen->nvws->surface_copy(nvscreen->nvws,
+ surface, 0, 0,
+ surface_to_unmap, 0, 0,
+ surface->width, surface->height);
+ }
}
static void