diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/nv50/nv50_context.h | 11 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_miptree.c | 18 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/nv50_surface.c | 36 |
3 files changed, 54 insertions, 11 deletions
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 |