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/nv40 | |
parent | 5726a5afa56e18b1662a8b03cf36c77e2d8b3114 (diff) |
nouveau: nv04-nv40 texture transfer.
Diffstat (limited to 'src/gallium/drivers/nv40')
-rw-r--r-- | src/gallium/drivers/nv40/Makefile | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nv40/nv40_miptree.c | 47 | ||||
-rw-r--r-- | src/gallium/drivers/nv40/nv40_screen.c | 83 | ||||
-rw-r--r-- | src/gallium/drivers/nv40/nv40_screen.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/nv40/nv40_state.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/nv40/nv40_state_fb.c | 40 | ||||
-rw-r--r-- | src/gallium/drivers/nv40/nv40_transfer.c | 201 |
7 files changed, 245 insertions, 133 deletions
diff --git a/src/gallium/drivers/nv40/Makefile b/src/gallium/drivers/nv40/Makefile index 8c738aefa6a..0ecae2b4913 100644 --- a/src/gallium/drivers/nv40/Makefile +++ b/src/gallium/drivers/nv40/Makefile @@ -22,6 +22,7 @@ C_SOURCES = \ nv40_state_viewport.c \ nv40_state_zsa.c \ nv40_surface.c \ + nv40_transfer.c \ nv40_vbo.c \ nv40_vertprog.c diff --git a/src/gallium/drivers/nv40/nv40_miptree.c b/src/gallium/drivers/nv40/nv40_miptree.c index e38b1e7f5ca..638d279aa5a 100644 --- a/src/gallium/drivers/nv40/nv40_miptree.c +++ b/src/gallium/drivers/nv40/nv40_miptree.c @@ -78,8 +78,6 @@ nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) mt->base = *pt; mt->base.refcount = 1; mt->base.screen = pscreen; - mt->shadow_tex = NULL; - mt->shadow_surface = NULL; /* Swizzled textures must be POT */ if (pt->width[0] & (pt->width[0] - 1) || @@ -165,12 +163,6 @@ nv40_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **ppt) FREE(mt->level[l].image_offset); } - if (mt->shadow_tex) { - if (mt->shadow_surface) - pscreen->tex_surface_release(pscreen, &mt->shadow_surface); - nv40_miptree_release(pscreen, &mt->shadow_tex); - } - FREE(mt); } @@ -180,36 +172,33 @@ nv40_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, unsigned flags) { struct nv40_miptree *mt = (struct nv40_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 = mt->level[level].pitch; - ps->usage = flags; - ps->status = PIPE_SURFACE_STATUS_DEFINED; - ps->refcount = 1; - ps->face = face; - ps->level = level; - ps->zslice = zslice; + 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 = mt->level[level].pitch; if (pt->target == PIPE_TEXTURE_CUBE) { - ps->offset = mt->level[level].image_offset[face]; + ns->base.offset = mt->level[level].image_offset[face]; } else if (pt->target == PIPE_TEXTURE_3D) { - ps->offset = mt->level[level].image_offset[zslice]; + ns->base.offset = mt->level[level].image_offset[zslice]; } else { - ps->offset = mt->level[level].image_offset[0]; + ns->base.offset = mt->level[level].image_offset[0]; } - return ps; + return &ns->base; } static void diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c index 2372bc84410..0d4baefaea3 100644 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -144,81 +144,6 @@ nv40_surface_buffer(struct pipe_surface *surf) return mt->buffer; } -static void * -nv40_surface_map(struct pipe_screen *screen, struct pipe_surface *surface, - unsigned flags ) -{ - 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 | - PIPE_TEXTURE_USAGE_DYNAMIC; - 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; - - assert(surface_to_map); - map = ws->buffer_map(ws, nv40_surface_buffer(surface_to_map), flags); - if (!map) - return NULL; - - 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_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); - - surface_to_unmap = mt->shadow_surface; - } - else - surface_to_unmap = surface; - - assert(surface_to_unmap); - - ws->buffer_unmap(ws, nv40_surface_buffer(surface_to_unmap)); - - if (surface_to_unmap != surface) { - struct nv40_screen *nvscreen = nv40_screen(screen); - - nvscreen->eng2d->copy(nvscreen->eng2d, surface, 0, 0, - surface_to_unmap, 0, 0, - surface->width, surface->height); - - screen->tex_surface_release(screen, &surface_to_unmap); - } -} - static void nv40_screen_destroy(struct pipe_screen *pscreen) { @@ -240,7 +165,7 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) { struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen); struct nouveau_stateobj *so; - unsigned curie_class; + unsigned curie_class = 0; unsigned chipset = nvws->channel->device->chipset; int ret; @@ -265,8 +190,6 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) if (NV6X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) curie_class = NV44TCL; break; - default: - break; } if (!curie_class) { @@ -372,10 +295,8 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) screen->pipe.is_format_supported = nv40_screen_surface_format_supported; - screen->pipe.surface_map = nv40_surface_map; - screen->pipe.surface_unmap = nv40_surface_unmap; - nv40_screen_init_miptree_functions(&screen->pipe); + nv40_screen_init_transfer_functions(&screen->pipe); u_simple_screen_init(&screen->pipe); return &screen->pipe; diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h index 4500aa0e5cc..7b503bd207d 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -34,4 +34,7 @@ nv40_screen(struct pipe_screen *screen) return (struct nv40_screen *)screen; } +void +nv40_screen_init_transfer_functions(struct pipe_screen *pscreen); + #endif diff --git a/src/gallium/drivers/nv40/nv40_state.h b/src/gallium/drivers/nv40/nv40_state.h index 9c55903ae30..8a9d8c8fdf6 100644 --- a/src/gallium/drivers/nv40/nv40_state.h +++ b/src/gallium/drivers/nv40/nv40_state.h @@ -79,9 +79,6 @@ struct nv40_miptree { struct pipe_buffer *buffer; uint total_size; - struct pipe_texture *shadow_tex; - struct pipe_surface *shadow_surface; - struct { uint pitch; uint *image_offset; diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c index 454abad31f4..5ebd3a1a56b 100644 --- a/src/gallium/drivers/nv40/nv40_state_fb.c +++ b/src/gallium/drivers/nv40/nv40_state_fb.c @@ -12,7 +12,7 @@ static boolean nv40_state_framebuffer_validate(struct nv40_context *nv40) { struct pipe_framebuffer_state *fb = &nv40->framebuffer; - struct pipe_surface *rt[4], *zeta; + struct nv04_surface *rt[4], *zeta; uint32_t rt_enable, rt_format; int i, colour_format = 0, zeta_format = 0; struct nouveau_stateobj *so = so_new(64, 10); @@ -27,7 +27,7 @@ nv40_state_framebuffer_validate(struct nv40_context *nv40) } else { colour_format = fb->cbufs[i]->format; rt_enable |= (NV40TCL_RT_ENABLE_COLOR0 << i); - rt[i] = fb->cbufs[i]; + rt[i] = (struct nv04_surface *)fb->cbufs[i]; } } @@ -37,13 +37,13 @@ nv40_state_framebuffer_validate(struct nv40_context *nv40) if (fb->zsbuf) { zeta_format = fb->zsbuf->format; - zeta = fb->zsbuf; + zeta = (struct nv04_surface *)fb->zsbuf; } - if (!(rt[0]->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { + if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); for (i = 1; i < fb->nr_cbufs; i++) - assert(!(rt[i]->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); + assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); rt_format = NV40TCL_RT_FORMAT_TYPE_SWIZZLED | log2i(fb->width) << NV40TCL_RT_FORMAT_LOG2_WIDTH_SHIFT | @@ -78,60 +78,60 @@ nv40_state_framebuffer_validate(struct nv40_context *nv40) if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) { so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR0, 1); - so_reloc (so, nv40_surface_buffer(rt[0]), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nv40_surface_buffer(&rt[0]->base), 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); so_method(so, nv40->screen->curie, NV40TCL_COLOR0_PITCH, 2); - so_data (so, rt[0]->stride); - so_reloc (so, nv40_surface_buffer(rt[0]), rt[0]->offset, rt_flags | + so_data (so, rt[0]->pitch); + so_reloc (so, nv40_surface_buffer(&rt[0]->base), rt[0]->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) { so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR1, 1); - so_reloc (so, nv40_surface_buffer(rt[1]), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nv40_surface_buffer(&rt[1]->base), 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); so_method(so, nv40->screen->curie, NV40TCL_COLOR1_OFFSET, 2); - so_reloc (so, nv40_surface_buffer(rt[1]), rt[1]->offset, rt_flags | + so_reloc (so, nv40_surface_buffer(&rt[1]->base), rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); - so_data (so, rt[1]->stride); + so_data (so, rt[1]->pitch); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) { so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR2, 1); - so_reloc (so, nv40_surface_buffer(rt[2]), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nv40_surface_buffer(&rt[2]->base), 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); so_method(so, nv40->screen->curie, NV40TCL_COLOR2_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(rt[2]), rt[2]->offset, rt_flags | + so_reloc (so, nv40_surface_buffer(&rt[2]->base), rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); so_method(so, nv40->screen->curie, NV40TCL_COLOR2_PITCH, 1); - so_data (so, rt[2]->stride); + so_data (so, rt[2]->pitch); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) { so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR3, 1); - so_reloc (so, nv40_surface_buffer(rt[3]), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nv40_surface_buffer(&rt[3]->base), 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); so_method(so, nv40->screen->curie, NV40TCL_COLOR3_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(rt[3]), rt[3]->offset, rt_flags | + so_reloc (so, nv40_surface_buffer(&rt[3]->base), rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); so_method(so, nv40->screen->curie, NV40TCL_COLOR3_PITCH, 1); - so_data (so, rt[3]->stride); + so_data (so, rt[3]->pitch); } if (zeta_format) { so_method(so, nv40->screen->curie, NV40TCL_DMA_ZETA, 1); - so_reloc (so, nv40_surface_buffer(zeta), 0, rt_flags | NOUVEAU_BO_OR, + so_reloc (so, nv40_surface_buffer(&zeta->base), 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); so_method(so, nv40->screen->curie, NV40TCL_ZETA_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(zeta), zeta->offset, rt_flags | + so_reloc (so, nv40_surface_buffer(&zeta->base), zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); so_method(so, nv40->screen->curie, NV40TCL_ZETA_PITCH, 1); - so_data (so, zeta->stride); + so_data (so, zeta->pitch); } so_method(so, nv40->screen->curie, NV40TCL_RT_ENABLE, 1); diff --git a/src/gallium/drivers/nv40/nv40_transfer.c b/src/gallium/drivers/nv40/nv40_transfer.c new file mode 100644 index 00000000000..b090f2238e4 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_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 "nv40_context.h" +#include "nv40_screen.h" +#include "nv40_state.h" + +struct nv40_transfer { + struct pipe_transfer base; + struct pipe_surface *surface; + bool direct; +}; + +static unsigned nv40_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 +nv40_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 * +nv40_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 nv40_miptree *mt = (struct nv40_miptree *)pt; + struct nv40_transfer *tx; + struct pipe_texture tx_tex_template, *tx_tex; + + tx = CALLOC_STRUCT(nv40_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, + nv40_usage_tx_to_buf(usage)); + return &tx->base; + } + + tx->direct = false; + + nv40_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, + nv40_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 nv40_screen *nvscreen = nv40_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 +nv40_transfer_del(struct pipe_screen *pscreen, struct pipe_transfer **pptx) +{ + struct pipe_transfer *ptx = *pptx; + struct nv40_transfer *tx = (struct nv40_transfer *)ptx; + + if (!tx->direct && ptx->usage != PIPE_TRANSFER_READ) { + struct nv40_screen *nvscreen = nv40_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 * +nv40_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv40_transfer *tx = (struct nv40_transfer *)ptx; + struct nv04_surface *ns = (struct nv04_surface *)tx->surface; + struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture; + void *map = pipe_buffer_map(pscreen, mt->buffer, + nv40_usage_tx_to_buf(ptx->usage)); + + return map + ns->base.offset + + ptx->y * ns->pitch + ptx->x * ptx->block.size; +} + +static void +nv40_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +{ + struct nv40_transfer *tx = (struct nv40_transfer *)ptx; + struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture; + + pipe_buffer_unmap(pscreen, mt->buffer); +} + +void +nv40_screen_init_transfer_functions(struct pipe_screen *pscreen) +{ + pscreen->get_tex_transfer = nv40_transfer_new; + pscreen->tex_transfer_release = nv40_transfer_del; + pscreen->transfer_map = nv40_transfer_map; + pscreen->transfer_unmap = nv40_transfer_unmap; +} |