summaryrefslogtreecommitdiff
path: root/src/gallium/winsys/dri/nouveau/nv50_surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/winsys/dri/nouveau/nv50_surface.c')
-rw-r--r--src/gallium/winsys/dri/nouveau/nv50_surface.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/gallium/winsys/dri/nouveau/nv50_surface.c b/src/gallium/winsys/dri/nouveau/nv50_surface.c
new file mode 100644
index 0000000000..15a1002861
--- /dev/null
+++ b/src/gallium/winsys/dri/nouveau/nv50_surface.c
@@ -0,0 +1,160 @@
+#include "pipe/p_context.h"
+
+#include "nouveau_context.h"
+
+static INLINE int
+nv50_format(int cpp)
+{
+ switch (cpp) {
+ case 4: return NV50_2D_DST_FORMAT_32BPP;
+ case 3: return NV50_2D_DST_FORMAT_24BPP;
+ case 2: return NV50_2D_DST_FORMAT_16BPP;
+ case 1: return NV50_2D_DST_FORMAT_8BPP;
+ default:
+ return -1;
+ }
+}
+
+static int
+nv50_surface_copy_prep(struct nouveau_context *nv,
+ struct pipe_surface *dst, struct pipe_surface *src)
+{
+ int surf_format;
+
+ assert(src->cpp == dst->cpp);
+
+ surf_format = nv50_format(dst->cpp);
+ assert(surf_format >= 0);
+
+ BEGIN_RING(Nv2D, NV50_2D_DMA_IN_MEMORY0, 2);
+ OUT_RELOCo(src->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ BEGIN_RING(Nv2D, NV50_2D_DST_FORMAT, 2);
+ OUT_RING (surf_format);
+ OUT_RING (1);
+ BEGIN_RING(Nv2D, NV50_2D_DST_PITCH, 5);
+ OUT_RING (dst->pitch * dst->cpp);
+ OUT_RING (dst->pitch);
+ OUT_RING (dst->height);
+ OUT_RELOCh(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(Nv2D, NV50_2D_CLIP_X, 4);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (dst->pitch);
+ OUT_RING (dst->height);
+
+ BEGIN_RING(Nv2D, NV50_2D_SRC_FORMAT, 2);
+ OUT_RING (surf_format);
+ OUT_RING (1);
+ BEGIN_RING(Nv2D, NV50_2D_SRC_PITCH, 5);
+ OUT_RING (src->pitch * src->cpp);
+ OUT_RING (src->pitch);
+ OUT_RING (src->height);
+ OUT_RELOCh(src->buffer, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ OUT_RELOCl(src->buffer, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+
+ return 0;
+}
+
+static void
+nv50_surface_copy(struct nouveau_context *nv, unsigned dx, unsigned dy,
+ unsigned sx, unsigned sy, unsigned w, unsigned h)
+{
+ BEGIN_RING(Nv2D, 0x0110, 1);
+ OUT_RING (0);
+ BEGIN_RING(Nv2D, NV50_2D_BLIT_DST_X, 12);
+ OUT_RING (dx);
+ OUT_RING (dy);
+ OUT_RING (w);
+ OUT_RING (h);
+ OUT_RING (0);
+ OUT_RING (1);
+ OUT_RING (0);
+ OUT_RING (1);
+ OUT_RING (0);
+ OUT_RING (sx);
+ OUT_RING (0);
+ OUT_RING (sy);
+}
+
+static void
+nv50_surface_copy_done(struct nouveau_context *nv)
+{
+ FIRE_RING();
+}
+
+static int
+nv50_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
+ unsigned dx, unsigned dy, unsigned w, unsigned h,
+ unsigned value)
+{
+ int surf_format, rect_format;
+
+ surf_format = nv50_format(dst->cpp);
+ if (surf_format < 0)
+ return 1;
+
+ rect_format = nv50_format(dst->cpp);
+ if (rect_format < 0)
+ return 1;
+
+ BEGIN_RING(Nv2D, NV50_2D_DMA_IN_MEMORY1, 1);
+ OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(Nv2D, NV50_2D_DST_FORMAT, 2);
+ OUT_RING (surf_format);
+ OUT_RING (1);
+ BEGIN_RING(Nv2D, NV50_2D_DST_PITCH, 5);
+ OUT_RING (dst->pitch * dst->cpp);
+ OUT_RING (dst->pitch);
+ OUT_RING (dst->height);
+ OUT_RELOCh(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(Nv2D, NV50_2D_CLIP_X, 4);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (dst->pitch);
+ OUT_RING (dst->height);
+
+ BEGIN_RING(Nv2D, 0x0580, 3);
+ OUT_RING (4);
+ OUT_RING (rect_format);
+ OUT_RING (value);
+
+ BEGIN_RING(Nv2D, NV50_2D_RECT_X1, 4);
+ OUT_RING (dx);
+ OUT_RING (dy);
+ OUT_RING (dx + w);
+ OUT_RING (dy + h);
+
+ FIRE_RING();
+
+ return 0;
+}
+
+int
+nouveau_surface_init_nv50(struct nouveau_context *nv)
+{
+ int ret;
+
+ ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, NV50_2D,
+ &nv->Nv2D);
+ if (ret)
+ return ret;
+ BIND_RING (Nv2D, 0);
+ BEGIN_RING(Nv2D, NV50_2D_DMA_NOTIFY, 1);
+ OUT_RING (nv->sync_notifier->handle);
+ BEGIN_RING(Nv2D, NV50_2D_DMA_IN_MEMORY0, 2);
+ OUT_RING (nv->channel->vram->handle);
+ OUT_RING (nv->channel->vram->handle);
+ BEGIN_RING(Nv2D, NV50_2D_OPERATION, 1);
+ OUT_RING (NV50_2D_OPERATION_SRCCOPY);
+
+ nv->surface_copy_prep = nv50_surface_copy_prep;
+ nv->surface_copy = nv50_surface_copy;
+ nv->surface_copy_done = nv50_surface_copy_done;
+ nv->surface_fill = nv50_surface_fill;
+ return 0;
+}
+