gallium: move border color to be a color union
[mesa.git] / src / gallium / drivers / nvfx / nv04_2d.c
index bc6012f013d110c3eeab37e0b587efbcd61dd93e..e2fadd33e1c7d81c624b57a915260d333efef9dd 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
-#include <nouveau/nouveau_class.h>
 #include <nouveau/nouveau_device.h>
-#include <nouveau/nouveau_pushbuf.h>
 #include <nouveau/nouveau_channel.h>
 #include <nouveau/nouveau_bo.h>
 #include <nouveau/nouveau_notifier.h>
 #include <nouveau/nouveau_grobj.h>
+#include <nouveau/nv04_pushbuf.h>
 #include "nv04_2d.h"
 
+#include "nouveau/nv_object.xml.h"
+#include "nouveau/nv_m2mf.xml.h"
+#include "nv01_2d.xml.h"
+
 /* avoid depending on Mesa/Gallium */
 #ifdef __GNUC__
 #define likely(x) __builtin_expect(!!(x), 1)
@@ -725,15 +728,58 @@ ms:
        nouveau_bo_unmap(dst->bo);
 }
 
+static inline int
+nv04_region_cs2d_format(struct nv04_region* rgn)
+{
+       switch(rgn->bpps) {
+       case 0:
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
+       case 1:
+               if(rgn->one_bits >= 1)
+                       return NV04_CONTEXT_SURFACES_2D_FORMAT_X1R5G5B5_X1R5G5B5;
+               else
+                       return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
+       case 2:
+               if(rgn->one_bits >= 8)
+                       return NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_X8R8G8B8;
+               else
+                       return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
+       default:
+               return -1;
+       }
+}
+
+static inline int
+nv04_region_sifm_format(struct nv04_region* rgn)
+{
+       switch(rgn->bpps) {
+       case 0:
+               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8;
+       case 1:
+               if(rgn->one_bits >= 1)
+                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X1R5G5B5;
+               else
+                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
+       case 2:
+               if(rgn->one_bits >= 8)
+                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
+               else
+                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
+       default:
+               return -1;
+       }
+}
 static void
 nv04_region_copy_swizzle(struct nv04_2d_context *ctx,
                          struct nv04_region* dst,
                          struct nv04_region* src,
-                         int w, int h, int cs2d_format, int sifm_format)
+                         int w, int h)
 {
        struct nouveau_channel *chan = ctx->swzsurf->channel;
        struct nouveau_grobj *swzsurf = ctx->swzsurf;
        struct nouveau_grobj *sifm = ctx->sifm;
+       int cs2d_format = nv04_region_cs2d_format(dst);
+       int sifm_format = nv04_region_sifm_format(src);
        /* Max width & height may not be the same on all HW, but must be POT */
        unsigned max_shift = 10;
        unsigned cw = 1 << max_shift;
@@ -770,8 +816,8 @@ nv04_region_copy_swizzle(struct nv04_2d_context *ctx,
 
        BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_FORMAT, 1);
        OUT_RING  (chan, cs2d_format |
-                        log2i(cw) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT |
-                        log2i(ch) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT);
+                        log2i(cw) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U__SHIFT |
+                        log2i(ch) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V__SHIFT);
 
        BEGIN_RING(chan, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
        OUT_RELOCo(chan, src->bo,
@@ -798,19 +844,19 @@ nv04_region_copy_swizzle(struct nv04_2d_context *ctx,
            OUT_RELOCl(chan, dst->bo, dst_offset,
                            NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
 
-           BEGIN_RING(chan, sifm, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9);
-           OUT_RING  (chan, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
+           BEGIN_RING(chan, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9);
+           OUT_RING  (chan, NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
            OUT_RING  (chan, sifm_format);
            OUT_RING  (chan, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
-           OUT_RING  (chan, rx | (ry << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_SHIFT));
-           OUT_RING  (chan, rh << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_SHIFT | rw);
-           OUT_RING  (chan, rx | (ry << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y_SHIFT));
-           OUT_RING  (chan, rh << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H_SHIFT | rw);
+           OUT_RING  (chan, rx | (ry << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y__SHIFT));
+           OUT_RING  (chan, rh << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H__SHIFT | rw);
+           OUT_RING  (chan, rx | (ry << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y__SHIFT));
+           OUT_RING  (chan, rh << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H__SHIFT | rw);
            OUT_RING  (chan, 1 << 20);
            OUT_RING  (chan, 1 << 20);
 
            BEGIN_RING(chan, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
-           OUT_RING  (chan, rh << NV03_SCALED_IMAGE_FROM_MEMORY_SIZE_H_SHIFT | align(rw, 8));
+           OUT_RING  (chan, rh << NV03_SCALED_IMAGE_FROM_MEMORY_SIZE_H__SHIFT | align(rw, 8));
            OUT_RING  (chan, src->pitch |
                             NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
                             NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
@@ -830,7 +876,7 @@ nv04_copy_m2mf_begin(struct nv04_2d_context *ctx, struct nouveau_bo* dstbo, stru
        struct nouveau_channel *chan = ctx->m2mf->channel;
        struct nouveau_grobj *m2mf = ctx->m2mf;
        MARK_RING (chan, 3 + commands * 9, 2 + commands * 2);
-       BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
+       BEGIN_RING(chan, m2mf, NV04_M2MF_DMA_BUFFER_IN, 2);
        OUT_RELOCo(chan, srcbo,
                   NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
        OUT_RELOCo(chan, dstbo,
@@ -847,7 +893,7 @@ nv04_copy_m2mf_body(struct nv04_2d_context *ctx, struct nouveau_bo* dstbo, int*
        fprintf(stderr, "\t\t\tCOPY_M2MF_BODY [%i, %i] <%i[%u]> lin %u <- <%i[%u]> lin %u\n", size, lines, dstbo->handle, *pdstoff, dstpitch, srcbo->handle, *psrcoff, srcpitch);
 #endif
 
-       BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+       BEGIN_RING(chan, m2mf, NV04_M2MF_OFFSET_IN, 8);
        OUT_RELOCl(chan, srcbo, *psrcoff,
                   NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
        OUT_RELOCl(chan, dstbo, *pdstoff,
@@ -951,11 +997,12 @@ nv04_region_copy_m2mf(struct nv04_2d_context *ctx, struct nv04_region *dst, stru
 }
 
 static inline void
-nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, struct nv04_region* src, int w, int h, int format)
+nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, struct nv04_region* src, int w, int h)
 {
        struct nouveau_channel *chan = ctx->surf2d->channel;
        struct nouveau_grobj *surf2d = ctx->surf2d;
        struct nouveau_grobj *blit = ctx->blit;
+       int cs2d_format = nv04_region_cs2d_format(dst);
 
 #ifdef NV04_REGION_DEBUG
        fprintf(stderr, "\tRGN_COPY_BLIT [%i, %i: %i] ", w, h, dst->bpps);
@@ -976,7 +1023,7 @@ nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, stru
        OUT_RELOCo(chan, src->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
        OUT_RELOCo(chan, dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
        BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
-       OUT_RING  (chan, format);
+       OUT_RING  (chan, cs2d_format);
        OUT_RING  (chan, (dst->pitch << 16) | src->pitch);
        OUT_RELOCl(chan, src->bo, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
        OUT_RELOCl(chan, dst->bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
@@ -1003,12 +1050,12 @@ nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, stru
 // dst and src may be modified, and the possibly modified version should be passed to nv04_region_cpu if necessary
 int
 nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct nv04_region* src,
-               int w, int h, int cs2d_format, int sifm_format, int dst_to_gpu, int src_on_gpu)
+               int w, int h, int dst_to_gpu, int src_on_gpu)
 {
        assert(src->bpps == dst->bpps);
 
 #ifdef NV04_REGION_DEBUG
-       fprintf(stderr, "RGN_COPY%s [%i, %i: %i] ", (cs2d_format >= 0) ? "_2D" : "_NO2D", w, h, dst->bpps);
+       fprintf(stderr, "RGN_COPY [%i, %i: %i] ", w, h, dst->bpps);
        for(int i = 0; i < 2; ++i)
        {
                int gpu = i ? src_on_gpu : dst_to_gpu;
@@ -1061,7 +1108,7 @@ nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct
        {
                if (!dst->pitch)
                {
-                       if(cs2d_format < 0 || sifm_format < 0 || !dst_to_gpu)
+                       if(!dst_to_gpu)
                        {
 #ifdef NV04_REGION_DEBUG
                                fprintf(stderr, "\tCOPY_ENG3D\n");
@@ -1072,25 +1119,29 @@ nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct
                        {
                                assert(!nv04_region_align(dst, w, h, 6));
 
-                               nv04_region_copy_swizzle(ctx, dst, src, w, h, cs2d_format, sifm_format);
+                               nv04_region_copy_swizzle(ctx, dst, src, w, h);
                                return 0;
                        }
                }
                else
                {
                        /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
-                        * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
+                        * to NV_M2MF in this case.
                         * TODO: is this also true for the source? possibly not
+                        * TODO: should we just always use m2mf?
+                        * TODO: if not, add support for multiple operations to copy_blit
                         */
 
-                       if ((cs2d_format < 0)
-                               || !dst_to_gpu
+                       if (!dst_to_gpu
+                               || w > 2047
+                               || h > 2047
+                               || (w & 1)
                                || nv04_region_align(src, w, h, 6)
                                || nv04_region_align(dst, w, h, 6)
                                )
                                nv04_region_copy_m2mf(ctx, dst, src, w, h);
                        else
-                               nv04_region_copy_blit(ctx, dst, src, w, h, cs2d_format);
+                               nv04_region_copy_blit(ctx, dst, src, w, h);
 
                        return 0;
                }
@@ -1112,26 +1163,25 @@ nv04_region_fill_gdirect(struct nv04_2d_context *ctx, struct nv04_region* dst, i
        assert(!(dst->pitch & 63) && dst->pitch);
        nv04_region_assert(dst, w, h);
 
-       if(dst->bpps == 0)
+       switch(dst->bpps)
        {
+       case 0:
                gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
                cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
-       }
-       else if(dst->bpps == 1)
-       {
+               break;
+       case 1:
                gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
                cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y16;
-       }
-       else if(dst->bpps == 2)
-       {
+               break;
+       case 2:
                gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
                cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
-       }
-       else
-       {
+               break;
+       default:
                assert(0);
                gdirect_format = 0;
                cs2d_format = 0;
+               break;
        }
 
        MARK_RING (chan, 15, 4);
@@ -1227,7 +1277,7 @@ nv04_2d_context_init(struct nouveau_channel* chan)
                return NULL;
        }
 
-       BEGIN_RING(chan, ctx->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
+       BEGIN_RING(chan, ctx->m2mf, NV04_M2MF_DMA_NOTIFY, 1);
        OUT_RING  (chan, ctx->ntfy->handle);
 
        if (chan->device->chipset < 0x10)
@@ -1249,7 +1299,7 @@ nv04_2d_context_init(struct nouveau_channel* chan)
        if (chan->device->chipset < 0x10)
                class = NV04_IMAGE_BLIT;
        else
-               class = NV12_IMAGE_BLIT;
+               class = NV11_IMAGE_BLIT;
 
        ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->blit);
        if (ret) {
@@ -1259,7 +1309,7 @@ nv04_2d_context_init(struct nouveau_channel* chan)
 
        BEGIN_RING(chan, ctx->blit, NV01_IMAGE_BLIT_DMA_NOTIFY, 1);
        OUT_RING  (chan, ctx->ntfy->handle);
-       BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_SURFACE, 1);
+       BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_SURFACES, 1);
        OUT_RING  (chan, ctx->surf2d->handle);
        BEGIN_RING(chan, ctx->blit, NV01_IMAGE_BLIT_OPERATION, 1);
        OUT_RING  (chan, NV01_IMAGE_BLIT_OPERATION_SRCCOPY);
@@ -1287,7 +1337,7 @@ nv04_2d_context_init(struct nouveau_channel* chan)
                class = NV04_SWIZZLED_SURFACE;
                break;
        case 0x20:
-               class = NV20_SWIZZLED_SURFACE;
+               class = NV11_SWIZZLED_SURFACE;
                break;
        case 0x30:
                class = NV30_SWIZZLED_SURFACE;