nouveau: nv04-nv40 linear <-> swizzled conversion.
authorYounes Manton <younes.m@gmail.com>
Tue, 2 Dec 2008 03:24:19 +0000 (22:24 -0500)
committerYounes Manton <younes.m@gmail.com>
Tue, 2 Dec 2008 21:15:12 +0000 (16:15 -0500)
src/gallium/drivers/nouveau/nouveau_winsys.h
src/gallium/winsys/drm/nouveau/nv04_surface.c

index a89b056244df9c264c566cb474310af2b94fec91..5535ebb6a99587299b71633849d688896dd130fe 100644 (file)
@@ -17,6 +17,8 @@
 #define NOUVEAU_CAP_HW_VTXBUF (0xbeef0000)
 #define NOUVEAU_CAP_HW_IDXBUF (0xbeef0001)
 
+#define NOUVEAU_TEXTURE_USAGE_LINEAR (1 << 16)
+
 #define NOUVEAU_BUFFER_USAGE_TEXTURE (1 << 16)
 #define NOUVEAU_BUFFER_USAGE_ZETA    (1 << 17)
 
index d08955de718f4c677a5303f35e982aa1d3834956..4f37af792723e389eec5eb0422808a9a60e45c30 100644 (file)
@@ -37,7 +37,11 @@ nv04_surface_format(enum pipe_format format)
                return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
        case PIPE_FORMAT_R5G6B5_UNORM:
                return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
+       case PIPE_FORMAT_R16_SNORM:
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_Y16;
+       case PIPE_FORMAT_X8R8G8B8_UNORM:
        case PIPE_FORMAT_A8R8G8B8_UNORM:
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
        case PIPE_FORMAT_Z24S8_UNORM:
                return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
        default:
@@ -61,6 +65,69 @@ nv04_rect_format(enum pipe_format format)
        }
 }
 
+static INLINE int
+nv04_scaled_image_format(enum pipe_format format)
+{
+       switch (format) {
+       case PIPE_FORMAT_A1R5G5B5_UNORM:
+               return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5;
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+               return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
+       case PIPE_FORMAT_X8R8G8B8_UNORM:
+               return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
+       case PIPE_FORMAT_R5G6B5_UNORM:
+       case PIPE_FORMAT_R16_SNORM:
+               return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
+       default:
+               return -1;
+       }
+}
+
+static void
+nv04_surface_copy_swizzle(struct nouveau_context *nv, unsigned dx, unsigned dy,
+                      unsigned sx, unsigned sy, unsigned w, unsigned h)
+{
+       struct nouveau_channel *chan = nv->nvc->channel;
+       struct pipe_surface *dst = nv->surf_dst;
+       struct pipe_surface *src = nv->surf_src;
+
+       BEGIN_RING(chan, nv->nvc->NvSwzSurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1);
+       OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
+                        NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+       BEGIN_RING(chan, nv->nvc->NvSwzSurf, NV04_SWIZZLED_SURFACE_FORMAT, 2);
+       OUT_RING  (chan, nv04_surface_format(dst->format) |
+                        log2i(w) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT |
+                        log2i(h) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT);
+       OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset,
+                        NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+       BEGIN_RING(chan, nv->nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
+       OUT_RELOCo(chan, nouveau_buffer(src->buffer)->bo,
+                        NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+       BEGIN_RING(chan, nv->nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
+       OUT_RING  (chan, nv->nvc->NvSwzSurf->handle);
+
+       BEGIN_RING(chan, nv->nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9);
+       OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
+       OUT_RING  (chan, nv04_scaled_image_format(src->format));
+       OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, h << 16 | w);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, h << 16 | w);
+       OUT_RING  (chan, 1 << 20);
+       OUT_RING  (chan, 1 << 20);
+       BEGIN_RING(chan, nv->nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
+       OUT_RING  (chan, h << 16 | w);
+       OUT_RING  (chan, src->stride |
+                        NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
+                        NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
+       OUT_RELOCl(chan, nouveau_buffer(src->buffer)->bo, src->offset,
+                        NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+       OUT_RING  (chan, 0);
+}
+
 static void
 nv04_surface_copy_m2mf(struct nouveau_context *nv, unsigned dx, unsigned dy,
                       unsigned sx, unsigned sy, unsigned w, unsigned h)
@@ -107,56 +174,6 @@ nv04_surface_copy_blit(struct nouveau_context *nv, unsigned dx, unsigned dy,
        OUT_RING  (chan, ( h << 16) |  w);
 }
 
-static int
-nv04_surface_copy_prep_swizzled(struct nouveau_context *nv,
-                               struct pipe_surface *dst,
-                               struct pipe_surface *src)
-{
-       struct nouveau_channel *chan = nv->nvc->channel;
-
-       BEGIN_RING(chan, nv->nvc->NvSwzSurf,
-                  NV04_SWIZZLED_SURFACE_FORMAT, 2);
-       /* FIXME: read destination format from somewhere */
-       OUT_RING  (chan,
-               NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8
-               | (log2i(dst->width)<<NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT)
-               | (log2i(dst->height)<<NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT) );
-       OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
-                  NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-
-       BEGIN_RING(chan, nv->nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 13);
-       OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
-       /* FIXME: read source format from somewhere */
-       OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8);
-       OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
-       OUT_RING  (chan, 0);
-       OUT_RING  (chan, (src->height<<16) | src->width);
-       OUT_RING  (chan, 0);
-       OUT_RING  (chan, (src->height<<16) | src->width);
-       OUT_RING  (chan, 1<<20);
-       OUT_RING  (chan, 1<<20);
-       OUT_RING  (chan, (src->height<<16) | src->width);
-       OUT_RING  (chan,
-               src->stride
-               | NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER
-               | NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
-       OUT_RELOCo(chan, nouveau_buffer(src->buffer)->bo,
-                  NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-       OUT_RING  (chan, 0);
-
-       BEGIN_RING(chan, nv->nvc->NvM2MF,
-                  NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
-       OUT_RELOCo(chan, nouveau_buffer(src->buffer)->bo,
-                  NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
-       OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
-                  NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-
-       nv->surface_copy = nv04_surface_copy_m2mf;
-       nv->surf_dst = dst;
-       nv->surf_src = src;
-       return 0;
-}
-
 static int
 nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst,
                       struct pipe_surface *src)
@@ -169,9 +186,17 @@ nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst,
 
        /* Setup transfer to swizzle the texture to vram if needed */
        /* FIXME/TODO: check proper limits of this operation */
-       if (nouveau_buffer(dst->buffer)->bo->flags & NOUVEAU_BO_SWIZZLED) {
-               /* FIXME: Disable it for the moment */
-               /*return nv04_surface_copy_prep_swizzled(nv, dst, src);*/
+       if (src->texture && dst->texture) {
+               unsigned int src_linear = src->texture->tex_usage &
+                                         NOUVEAU_TEXTURE_USAGE_LINEAR;
+               unsigned int dst_linear = dst->texture->tex_usage &
+                                         NOUVEAU_TEXTURE_USAGE_LINEAR;
+               if (src_linear ^ dst_linear) {
+                       nv->surface_copy = nv04_surface_copy_swizzle;
+                       nv->surf_dst = dst;
+                       nv->surf_src = src;
+                       return 0;
+               }
        }
 
        /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
@@ -359,10 +384,6 @@ nouveau_surface_channel_create_nv04(struct nouveau_channel_context *nvc)
        }
 
        BIND_RING (chan, nvc->NvSwzSurf, nvc->next_subchannel++);
-       BEGIN_RING(chan, nvc->NvSwzSurf, NV04_SWIZZLED_SURFACE_DMA_NOTIFY, 1);
-       OUT_RING  (chan, nvc->sync_notifier->handle);
-       BEGIN_RING(chan, nvc->NvSwzSurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1);
-       OUT_RING  (chan, nvc->channel->vram->handle);
 
        if (chipset < 0x10) {
                class = NV04_SCALED_IMAGE_FROM_MEMORY;
@@ -381,22 +402,6 @@ nouveau_surface_channel_create_nv04(struct nouveau_channel_context *nvc)
        }
 
        BIND_RING (chan, nvc->NvSIFM, nvc->next_subchannel++);
-       BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY, 1);
-       OUT_RING  (chan, 0);
-       BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
-       OUT_RING  (chan, nvc->channel->vram->handle);
-       BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
-       OUT_RING  (chan, nvc->NvSwzSurf->handle);
-       BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_PATTERN, 1);
-       OUT_RING  (chan, 0);
-       BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_ROP, 1);
-       OUT_RING  (chan, 0);
-       BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_BETA1, 1);
-       OUT_RING  (chan, 0);
-       BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_BETA4, 1);
-       OUT_RING  (chan, 0);
-       BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION, 1);
-       OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
 
        return 0;
 }