diff options
-rw-r--r-- | src/gallium/drivers/nouveau/nouveau_bo.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nv30/nv30_fragtex.c | 46 | ||||
-rw-r--r-- | src/gallium/drivers/nv30/nv30_miptree.c | 57 | ||||
-rw-r--r-- | src/gallium/drivers/nv30/nv30_screen.c | 63 | ||||
-rw-r--r-- | src/gallium/drivers/nv30/nv30_state.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/nv30/nv30_state_fb.c | 39 |
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: |