nouveau: remove useless NOUVEAU_BO_SWIZZLED flag, copy/paste nv40 work to swizzle...
authorPatrice Mandin <pmandin@caramail.com>
Fri, 12 Dec 2008 16:22:41 +0000 (17:22 +0100)
committerPatrice Mandin <pmandin@caramail.com>
Fri, 12 Dec 2008 16:22:41 +0000 (17:22 +0100)
src/gallium/drivers/nouveau/nouveau_bo.h
src/gallium/drivers/nv30/nv30_fragtex.c
src/gallium/drivers/nv30/nv30_miptree.c
src/gallium/drivers/nv30/nv30_screen.c
src/gallium/drivers/nv30/nv30_state.h
src/gallium/drivers/nv30/nv30_state_fb.c

index 0ed3367815af22e9a755fafbced2ee571e727ba5..65b138283c48027fa208424e495670c4a9675428 100644 (file)
@@ -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 {
index 9e6f746a4208bc01fd23f89bf799ab8f61c9562e..efba8db86d8fd0d076e7fe8b9096955ca5571531 100644 (file)
@@ -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);
index 9124db03e83ae49f7dfc103f4879a28169a890b4..aa670b9a45b5f7606dfb102604be2abd1aaaeb73 100644 (file)
@@ -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];
index a595e2eb225c3602ef2219c61392be797445ea73..910a3c456dd288679b538027f80de1878eae23c0 100644 (file)
@@ -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
index e6f23bf166715c2fbcaf4e03d994212d6d74f2b9..2023278e377e00aabcfaea6ae02e6671232f1a21 100644 (file)
@@ -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;
index d93e2bb5c897ce79fc996325c6757d0b6aa15302..c549b17656e4db02a8ff987dc838128cdc5e9171 100644 (file)
@@ -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: