summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv10
diff options
context:
space:
mode:
authorYounes Manton <[email protected]>2009-02-25 12:55:26 -0500
committerYounes Manton <[email protected]>2009-02-25 12:56:00 -0500
commita0dc286b5fecec1ede014cb5702368a60cbb22bc (patch)
tree7def0bcb025d1495cf41ea7aa54fca763ae60e10 /src/gallium/drivers/nv10
parent5726a5afa56e18b1662a8b03cf36c77e2d8b3114 (diff)
nouveau: nv04-nv40 texture transfer.
Diffstat (limited to 'src/gallium/drivers/nv10')
-rw-r--r--src/gallium/drivers/nv10/Makefile1
-rw-r--r--src/gallium/drivers/nv10/nv10_miptree.c33
-rw-r--r--src/gallium/drivers/nv10/nv10_screen.c28
-rw-r--r--src/gallium/drivers/nv10/nv10_screen.h4
-rw-r--r--src/gallium/drivers/nv10/nv10_state_emit.c14
-rw-r--r--src/gallium/drivers/nv10/nv10_transfer.c201
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;
+}