diff options
author | Younes Manton <[email protected]> | 2009-02-25 12:55:26 -0500 |
---|---|---|
committer | Younes Manton <[email protected]> | 2009-02-25 12:56:00 -0500 |
commit | a0dc286b5fecec1ede014cb5702368a60cbb22bc (patch) | |
tree | 7def0bcb025d1495cf41ea7aa54fca763ae60e10 /src/gallium/drivers/nv10 | |
parent | 5726a5afa56e18b1662a8b03cf36c77e2d8b3114 (diff) |
nouveau: nv04-nv40 texture transfer.
Diffstat (limited to 'src/gallium/drivers/nv10')
-rw-r--r-- | src/gallium/drivers/nv10/Makefile | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_miptree.c | 33 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_screen.c | 28 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_screen.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_state_emit.c | 14 | ||||
-rw-r--r-- | src/gallium/drivers/nv10/nv10_transfer.c | 201 |
6 files changed, 231 insertions, 50 deletions
diff --git a/src/gallium/drivers/nv10/Makefile b/src/gallium/drivers/nv10/Makefile index 2b5fbd4f5a6..62677f5194a 100644 --- a/src/gallium/drivers/nv10/Makefile +++ b/src/gallium/drivers/nv10/Makefile @@ -14,6 +14,7 @@ C_SOURCES = \ nv10_state.c \ nv10_state_emit.c \ nv10_surface.c \ + nv10_transfer.c \ nv10_vbo.c include ../../Makefile.template diff --git a/src/gallium/drivers/nv10/nv10_miptree.c b/src/gallium/drivers/nv10/nv10_miptree.c index 96161354617..4747868a508 100644 --- a/src/gallium/drivers/nv10/nv10_miptree.c +++ b/src/gallium/drivers/nv10/nv10_miptree.c @@ -131,30 +131,31 @@ nv10_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags) { - struct pipe_winsys *ws = screen->winsys; struct nv10_miptree *nv10mt = (struct nv10_miptree *)pt; - struct pipe_surface *ps; + struct nv04_surface *ns; - ps = CALLOC_STRUCT(pipe_surface); - if (!ps) + ns = CALLOC_STRUCT(nv04_surface); + if (!ns) return NULL; - pipe_texture_reference(&ps->texture, pt); - ps->format = pt->format; - ps->width = pt->width[level]; - ps->height = pt->height[level]; - ps->block = pt->block; - ps->nblocksx = pt->nblocksx[level]; - ps->nblocksy = pt->nblocksy[level]; - ps->stride = nv10mt->level[level].pitch; - ps->refcount = 1; + pipe_texture_reference(&ns->base.texture, pt); + ns->base.format = pt->format; + ns->base.width = pt->width[level]; + ns->base.height = pt->height[level]; + ns->base.usage = flags; + ns->base.status = PIPE_SURFACE_STATUS_DEFINED; + ns->base.refcount = 1; + ns->base.face = face; + ns->base.level = level; + ns->base.zslice = zslice; + ns->pitch = nv10mt->level[level].pitch; if (pt->target == PIPE_TEXTURE_CUBE) { - ps->offset = nv10mt->level[level].image_offset[face]; + ns->base.offset = nv10mt->level[level].image_offset[face]; } else { - ps->offset = nv10mt->level[level].image_offset[0]; + ns->base.offset = nv10mt->level[level].image_offset[0]; } - return ps; + return &ns->base; } static void diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c index f417b06c944..6532a93c7ba 100644 --- a/src/gallium/drivers/nv10/nv10_screen.c +++ b/src/gallium/drivers/nv10/nv10_screen.c @@ -116,30 +116,6 @@ nv10_screen_is_format_supported(struct pipe_screen *screen, return FALSE; } -static void * -nv10_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, - unsigned flags ) -{ - struct pipe_winsys *ws = screen->winsys; - void *map; - struct nv10_miptree *nv10mt = (struct nv10_miptree *)surface->texture; - - map = ws->buffer_map(ws, nv10mt->buffer, flags); - if (!map) - return NULL; - - return map + surface->offset; -} - -static void -nv10_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) -{ - struct pipe_winsys *ws = screen->winsys; - struct nv10_miptree *nv10mt = (struct nv10_miptree *)surface->texture; - - ws->buffer_unmap(ws, nv10mt->buffer); -} - static void nv10_screen_destroy(struct pipe_screen *pscreen) { @@ -215,10 +191,8 @@ nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) screen->pipe.is_format_supported = nv10_screen_is_format_supported; - screen->pipe.surface_map = nv10_surface_map; - screen->pipe.surface_unmap = nv10_surface_unmap; - nv10_screen_init_miptree_functions(&screen->pipe); + nv10_screen_init_transfer_functions(&screen->pipe); u_simple_screen_init(&screen->pipe); return &screen->pipe; diff --git a/src/gallium/drivers/nv10/nv10_screen.h b/src/gallium/drivers/nv10/nv10_screen.h index 60102a369a9..ad829ee3fd4 100644 --- a/src/gallium/drivers/nv10/nv10_screen.h +++ b/src/gallium/drivers/nv10/nv10_screen.h @@ -21,4 +21,8 @@ nv10_screen(struct pipe_screen *screen) return (struct nv10_screen *)screen; } + +void +nv10_screen_init_transfer_functions(struct pipe_screen *pscreen); + #endif diff --git a/src/gallium/drivers/nv10/nv10_state_emit.c b/src/gallium/drivers/nv10/nv10_state_emit.c index 5dec618b933..d8691ef9c67 100644 --- a/src/gallium/drivers/nv10/nv10_state_emit.c +++ b/src/gallium/drivers/nv10/nv10_state_emit.c @@ -103,7 +103,7 @@ static void nv10_state_emit_scissor(struct nv10_context* nv10) static void nv10_state_emit_framebuffer(struct nv10_context* nv10) { struct pipe_framebuffer_state* fb = nv10->framebuffer; - struct pipe_surface *rt, *zeta = NULL; + struct nv04_surface *rt, *zeta = NULL; uint32_t rt_format, w, h; int colour_format = 0, zeta_format = 0; struct nv10_miptree *nv10mt = 0; @@ -111,7 +111,7 @@ static void nv10_state_emit_framebuffer(struct nv10_context* nv10) w = fb->cbufs[0]->width; h = fb->cbufs[0]->height; colour_format = fb->cbufs[0]->format; - rt = fb->cbufs[0]; + rt = (struct nv04_surface *)fb->cbufs[0]; if (fb->zsbuf) { if (colour_format) { @@ -123,7 +123,7 @@ static void nv10_state_emit_framebuffer(struct nv10_context* nv10) } zeta_format = fb->zsbuf->format; - zeta = fb->zsbuf; + zeta = (struct nv04_surface *)fb->zsbuf; } rt_format = NV10TCL_RT_FORMAT_TYPE_LINEAR; @@ -142,18 +142,18 @@ static void nv10_state_emit_framebuffer(struct nv10_context* nv10) if (zeta) { BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1); - OUT_RING (rt->stride | (zeta->stride << 16)); + OUT_RING (rt->pitch | (zeta->pitch << 16)); } else { BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1); - OUT_RING (rt->stride | (rt->stride << 16)); + OUT_RING (rt->pitch | (rt->pitch << 16)); } - nv10mt = (struct nv10_miptree *)rt->texture; + nv10mt = (struct nv10_miptree *)rt->base.texture; nv10->rt[0] = nv10mt->buffer; if (zeta_format) { - nv10mt = (struct nv10_miptree *)zeta->texture; + nv10mt = (struct nv10_miptree *)zeta->base.texture; nv10->zeta = nv10mt->buffer; } diff --git a/src/gallium/drivers/nv10/nv10_transfer.c b/src/gallium/drivers/nv10/nv10_transfer.c new file mode 100644 index 00000000000..967e2cc20ce --- /dev/null +++ b/src/gallium/drivers/nv10/nv10_transfer.c @@ -0,0 +1,201 @@ +#include <pipe/p_state.h> +#include <pipe/p_defines.h> +#include <pipe/p_inlines.h> +#include <util/u_memory.h> +#include <nouveau/nouveau_winsys.h> +#include "nv10_context.h" +#include "nv10_screen.h" +#include "nv10_state.h" + +struct nv10_transfer { + struct pipe_transfer base; + struct pipe_surface *surface; + bool direct; +}; + +static unsigned nv10_usage_tx_to_buf(unsigned tx_usage) +{ + switch (tx_usage) { + case PIPE_TRANSFER_READ: + return PIPE_BUFFER_USAGE_CPU_READ; + case PIPE_TRANSFER_WRITE: + return PIPE_BUFFER_USAGE_CPU_WRITE; + case PIPE_TRANSFER_READ_WRITE: + return PIPE_BUFFER_USAGE_CPU_READ_WRITE; + default: + assert(0); + } + + return -1; +} + +static void +nv10_compatible_transfer_tex(struct pipe_texture *pt, unsigned level, + struct pipe_texture *template) +{ + memset(template, 0, sizeof(struct pipe_texture)); + template->target = pt->target; + template->format = pt->format; + template->width[0] = pt->width[level]; + template->height[0] = pt->height[level]; + template->depth[0] = 1; + template->block = pt->block; + template->nblocksx[0] = pt->nblocksx[level]; + template->nblocksy[0] = pt->nblocksx[level]; + template->last_level = 0; + template->compressed = pt->compressed; + template->nr_samples = pt->nr_samples; + + template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | + NOUVEAU_TEXTURE_USAGE_LINEAR; +} + +static struct pipe_transfer * +nv10_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct nv10_miptree *mt = (struct nv10_miptree *)pt; + struct nv10_transfer *tx; + struct pipe_texture tx_tex_template, *tx_tex; + + tx = CALLOC_STRUCT(nv10_transfer); + if (!tx) + return NULL; + + tx->base.refcount = 1; + pipe_texture_reference(&tx->base.texture, pt); + tx->base.format = pt->format; + tx->base.x = x; + tx->base.y = y; + tx->base.width = w; + tx->base.height = h; + tx->base.block = pt->block; + tx->base.nblocksx = pt->nblocksx[level]; + tx->base.nblocksy = pt->nblocksy[level]; + tx->base.stride = mt->level[level].pitch; + tx->base.usage = usage; + tx->base.face = face; + tx->base.level = level; + tx->base.zslice = zslice; + + /* Direct access to texture */ + if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || + debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && + pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) + { + tx->direct = true; + tx->surface = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + nv10_usage_tx_to_buf(usage)); + return &tx->base; + } + + tx->direct = false; + + nv10_compatible_transfer_tex(pt, level, &tx_tex_template); + + tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); + if (!tx_tex) + { + FREE(tx); + return NULL; + } + + tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, + face, level, zslice, + nv10_usage_tx_to_buf(usage)); + + pipe_texture_reference(&tx_tex, NULL); + + if (!tx->surface) + { + pipe_surface_reference(&tx->surface, NULL); + FREE(tx); + return NULL; + } + + if (usage != PIPE_TRANSFER_WRITE) { + struct nv10_screen *nvscreen = nv10_screen(pscreen); + struct pipe_surface *src; + + src = pscreen->get_tex_surface(pscreen, pt, + face, level, zslice, + PIPE_BUFFER_USAGE_GPU_READ); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + /* TODO: Check if SIFM can un-swizzle */ + nvscreen->eng2d->copy(nvscreen->eng2d, + tx->surface, 0, 0, + src, 0, 0, + src->width, src->height); + + pipe_surface_reference(&src, NULL); + } + + return &tx->base; +} + +static void +nv10_transfer_del(struct pipe_screen *pscreen, struct pipe_transfer **pptx) +{ + struct pipe_transfer *ptx = *pptx; + struct nv10_transfer *tx = (struct nv10_transfer *)ptx; + + if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) { + struct nv10_screen *nvscreen = nv10_screen(pscreen); + struct pipe_surface *dst; + + dst = pscreen->get_tex_surface(pscreen, ptx->texture, + ptx->face, ptx->level, ptx->zslice, + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + nvscreen->eng2d->copy(nvscreen->eng2d, + dst, 0, 0, + tx->surface, 0, 0, + dst->width, dst->height); + + pipe_surface_reference(&dst, NULL); + } + + *pptx = NULL; + if (--ptx->refcount) + return; + + pipe_surface_reference(&tx->surface, NULL); + pipe_texture_reference(&ptx->texture, NULL); + FREE(ptx); +} + +static void * +nv10_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv10_transfer *tx = (struct nv10_transfer *)ptx; + struct nv04_surface *ns = (struct nv04_surface *)tx->surface; + struct nv10_miptree *mt = (struct nv10_miptree *)tx->surface->texture; + void *map = pipe_buffer_map(pscreen, mt->buffer, + nv10_usage_tx_to_buf(ptx->usage)); + + return map + ns->base.offset + + ptx->y * ns->pitch + ptx->x * ptx->block.size; +} + +static void +nv10_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv10_transfer *tx = (struct nv10_transfer *)ptx; + struct nv10_miptree *mt = (struct nv10_miptree *)tx->surface->texture; + + pipe_buffer_unmap(pscreen, mt->buffer); +} + +void +nv10_screen_init_transfer_functions(struct pipe_screen *pscreen) +{ + pscreen->get_tex_transfer = nv10_transfer_new; + pscreen->tex_transfer_release = nv10_transfer_del; + pscreen->transfer_map = nv10_transfer_map; + pscreen->transfer_unmap = nv10_transfer_unmap; +} |