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, \
(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 {
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),
{},
};
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;
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);
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);
}
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 *
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];
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