summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/nouveau/nouveau_bo.h1
-rw-r--r--src/gallium/drivers/nv30/nv30_fragtex.c46
-rw-r--r--src/gallium/drivers/nv30/nv30_miptree.c57
-rw-r--r--src/gallium/drivers/nv30/nv30_screen.c63
-rw-r--r--src/gallium/drivers/nv30/nv30_state.h3
-rw-r--r--src/gallium/drivers/nv30/nv30_state_fb.c39
6 files changed, 167 insertions, 42 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_bo.h b/src/gallium/drivers/nouveau/nouveau_bo.h
index 0ed3367815a..65b138283c4 100644
--- a/src/gallium/drivers/nouveau/nouveau_bo.h
+++ b/src/gallium/drivers/nouveau/nouveau_bo.h
@@ -37,7 +37,6 @@
#define NOUVEAU_BO_LOCAL (1 << 9)
#define NOUVEAU_BO_TILED (1 << 10)
#define NOUVEAU_BO_ZTILE (1 << 11)
-#define NOUVEAU_BO_SWIZZLED (1 << 12)
#define NOUVEAU_BO_DUMMY (1 << 31)
struct nouveau_bo {
diff --git a/src/gallium/drivers/nv30/nv30_fragtex.c b/src/gallium/drivers/nv30/nv30_fragtex.c
index 9e6f746a420..efba8db86d8 100644
--- a/src/gallium/drivers/nv30/nv30_fragtex.c
+++ b/src/gallium/drivers/nv30/nv30_fragtex.c
@@ -26,7 +26,7 @@ static INLINE int log2i(int i)
return r;
}
-#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,swsurf) \
+#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w) \
{ \
TRUE, \
PIPE_FORMAT_##m, \
@@ -34,8 +34,7 @@ static INLINE int log2i(int i)
(NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y | \
NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w | \
NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y | \
- NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w), \
- swsurf \
+ NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w) \
}
struct nv30_texture_format {
@@ -43,25 +42,24 @@ struct nv30_texture_format {
uint pipe;
int format;
int swizzle;
- int swizzled_surface;
};
static struct nv30_texture_format
nv30_texture_formats[] = {
- _(A8R8G8B8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W, 1),
- _(A1R5G5B5_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W, 1),
- _(A4R4G4B4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W, 1),
- _(R5G6B5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W, 1),
- _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X, 1),
- _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X, 1),
- _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X, 1),
- _(A8L8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y, 1),
-// _(Z16_UNORM , Z16 , S1, S1, S1, ONE, X, X, X, X, 0),
-// _(Z24S8_UNORM , Z24 , S1, S1, S1, ONE, X, X, X, X, 0),
- _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W, 0),
- _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W, 0),
- _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W, 0),
- _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W, 0),
+ _(A8R8G8B8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W),
+ _(A1R5G5B5_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W),
+ _(A4R4G4B4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W),
+ _(R5G6B5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W),
+ _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X),
+ _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X),
+ _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X),
+ _(A8L8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y),
+// _(Z16_UNORM , Z16 , S1, S1, S1, ONE, X, X, X, X),
+// _(Z24S8_UNORM , Z24 , S1, S1, S1, ONE, X, X, X, X),
+ _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W),
+ _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W),
+ _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W),
+ _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W),
{},
};
@@ -90,16 +88,13 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit)
struct pipe_texture *pt = &nv30mt->base;
struct nv30_texture_format *tf;
struct nouveau_stateobj *so;
- uint32_t txf, txs /*, txp*/;
- /*int swizzled = 0;*/ /*XXX: implement in region code? */
+ uint32_t txf, txs , txp;
unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
tf = nv30_fragtex_format(pt->format);
if (!tf)
assert(0);
- tex_flags |= (tf->swizzled_surface ? NOUVEAU_BO_SWIZZLED : 0);
-
txf = tf->format;
txf |= ((pt->last_level>0) ? NV34TCL_TX_FORMAT_MIPMAP : 0);
txf |= log2i(pt->width[0]) << 20;
@@ -125,6 +120,13 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit)
return NULL;
}
+ if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
+ txp = 0;
+ } else {
+ txp = nv30mt->level[0].pitch;
+ txf |= (1<<13) /*FIXME: NV34TCL_TX_FORMAT_LINEAR ? */;
+ }
+
txs = tf->swizzle;
so = so_new(16, 2);
diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c
index 9124db03e83..aa670b9a45b 100644
--- a/src/gallium/drivers/nv30/nv30_miptree.c
+++ b/src/gallium/drivers/nv30/nv30_miptree.c
@@ -65,6 +65,29 @@ nv30_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) ||
+ pt->height[0] & (pt->height[0] - 1))
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ else
+ if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY |
+ PIPE_TEXTURE_USAGE_DISPLAY_TARGET))
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ else {
+ switch (pt->format) {
+ /* TODO: Figure out which formats can be swizzled */
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_X8R8G8B8_UNORM:
+ /* XXX: Re-enable when SIFM size limits are fixed */
+ /*case PIPE_FORMAT_R16_SNORM:*/
+ break;
+ default:
+ mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR;
+ }
+ }
nv30_miptree_layout(mt);
@@ -81,22 +104,29 @@ nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt)
}
static void
-nv30_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **pt)
+nv30_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **ppt)
{
- struct pipe_texture *mt = *pt;
+ struct pipe_texture *pt = *ppt;
+ struct nv30_miptree *mt = (struct nv30_miptree *)pt;
+ int l;
- *pt = NULL;
- if (--mt->refcount <= 0) {
- struct nv30_miptree *nv30mt = (struct nv30_miptree *)mt;
- int l;
+ *ppt = NULL;
+ if (--pt->refcount)
+ return;
- pipe_buffer_reference(pscreen, &nv30mt->buffer, NULL);
- for (l = 0; l <= mt->last_level; l++) {
- if (nv30mt->level[l].image_offset)
- FREE(nv30mt->level[l].image_offset);
- }
- FREE(nv30mt);
+ pipe_buffer_reference(pscreen, &mt->buffer, NULL);
+ for (l = 0; l <= pt->last_level; l++) {
+ if (mt->level[l].image_offset)
+ FREE(mt->level[l].image_offset);
+ }
+
+ if (mt->shadow_tex) {
+ assert(mt->shadow_surface);
+ pscreen->tex_surface_release(pscreen, &mt->shadow_surface);
+ nv30_miptree_release(pscreen, &mt->shadow_tex);
}
+
+ FREE(mt);
}
static struct pipe_surface *
@@ -123,6 +153,9 @@ nv30_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
ps->status = PIPE_SURFACE_STATUS_DEFINED;
ps->refcount = 1;
ps->winsys = pscreen->winsys;
+ ps->face = face;
+ ps->level = level;
+ ps->zslice = zslice;
if (pt->target == PIPE_TEXTURE_CUBE) {
ps->offset = nv30mt->level[level].image_offset[face];
diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c
index a595e2eb225..910a3c456dd 100644
--- a/src/gallium/drivers/nv30/nv30_screen.c
+++ b/src/gallium/drivers/nv30/nv30_screen.c
@@ -128,22 +128,73 @@ static void *
nv30_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 nv30_miptree *mt = (struct nv30_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
nv30_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 nv30_miptree *mt = (struct nv30_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 nv30_screen *nvscreen = nv30_screen(screen);
+
+ nvscreen->nvws->surface_copy(nvscreen->nvws,
+ surface, 0, 0,
+ surface_to_unmap, 0, 0,
+ surface->width, surface->height);
+ }
}
static void
diff --git a/src/gallium/drivers/nv30/nv30_state.h b/src/gallium/drivers/nv30/nv30_state.h
index e6f23bf1667..2023278e377 100644
--- a/src/gallium/drivers/nv30/nv30_state.h
+++ b/src/gallium/drivers/nv30/nv30_state.h
@@ -76,6 +76,9 @@ struct nv30_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/nv30/nv30_state_fb.c b/src/gallium/drivers/nv30/nv30_state_fb.c
index d93e2bb5c89..c549b17656e 100644
--- a/src/gallium/drivers/nv30/nv30_state_fb.c
+++ b/src/gallium/drivers/nv30/nv30_state_fb.c
@@ -1,5 +1,31 @@
#include "nv30_context.h"
+static INLINE int log2i(int i)
+{
+ int r = 0;
+
+ if (i & 0xffff0000) {
+ i >>= 16;
+ r += 16;
+ }
+ if (i & 0x0000ff00) {
+ i >>= 8;
+ r += 8;
+ }
+ if (i & 0x000000f0) {
+ i >>= 4;
+ r += 4;
+ }
+ if (i & 0x0000000c) {
+ i >>= 2;
+ r += 2;
+ }
+ if (i & 0x00000002) {
+ r += 1;
+ }
+ return r;
+}
+
static boolean
nv30_state_framebuffer_validate(struct nv30_context *nv30)
{
@@ -31,7 +57,18 @@ nv30_state_framebuffer_validate(struct nv30_context *nv30)
zeta = fb->zsbuf;
}
- rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR;
+ if (!(rt[0]->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
+ assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1)));
+ for (i = 1; i < fb->num_cbufs; i++)
+ assert(!(rt[i]->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR));
+
+ /* FIXME: NV34TCL_RT_FORMAT_LOG2_[WIDTH/HEIGHT] */
+ rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED |
+ log2i(fb->width) << 16 /*NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT*/ |
+ log2i(fb->height) << 24 /*NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT*/;
+ }
+ else
+ rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR;
switch (colour_format) {
case PIPE_FORMAT_A8R8G8B8_UNORM: