summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nv50/nv50_surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nv50/nv50_surface.c')
-rw-r--r--src/gallium/drivers/nv50/nv50_surface.c169
1 files changed, 106 insertions, 63 deletions
diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c
index 3e61203adf..f70c138fe1 100644
--- a/src/gallium/drivers/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nv50/nv50_surface.c
@@ -52,48 +52,26 @@ nv50_2d_format_faithful(enum pipe_format format)
}
}
-static INLINE int
-nv50_format(enum pipe_format format)
+static INLINE uint8_t
+nv50_2d_format(enum pipe_format format)
{
- switch (format) {
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM;
- case PIPE_FORMAT_B8G8R8X8_UNORM:
- return NV50_2D_DST_FORMAT_X8R8G8B8_UNORM;
- case PIPE_FORMAT_B8G8R8A8_SRGB:
- return NV50_2D_DST_FORMAT_A8R8G8B8_SRGB;
- case PIPE_FORMAT_B8G8R8X8_SRGB:
- return NV50_2D_DST_FORMAT_X8R8G8B8_SRGB;
- case PIPE_FORMAT_B5G6R5_UNORM:
- return NV50_2D_DST_FORMAT_R5G6B5_UNORM;
- case PIPE_FORMAT_B5G5R5A1_UNORM:
- return NV50_2D_DST_FORMAT_A1R5G5B5_UNORM;
- case PIPE_FORMAT_B10G10R10A2_UNORM:
- return NV50_2D_DST_FORMAT_A2R10G10B10_UNORM;
- case PIPE_FORMAT_A8_UNORM:
- case PIPE_FORMAT_I8_UNORM:
- case PIPE_FORMAT_L8_UNORM:
- case PIPE_FORMAT_R8_UNORM:
+ uint8_t id = nv50_format_table[format].rt;
+
+ /* Hardware values for color formats range from 0xc0 to 0xff,
+ * but the 2D engine doesn't support all of them.
+ */
+ if ((id >= 0xc0) && (0xff0843e080608409ULL & (1ULL << (id - 0xc0))))
+ return id;
+
+ switch (util_format_get_blocksize(format)) {
+ case 1:
return NV50_2D_DST_FORMAT_R8_UNORM;
- case PIPE_FORMAT_R32G32B32A32_FLOAT:
- return NV50_2D_DST_FORMAT_R32G32B32A32_FLOAT;
- case PIPE_FORMAT_R32G32B32_FLOAT:
- return NV50_2D_DST_FORMAT_R32G32B32X32_FLOAT;
- case PIPE_FORMAT_Z32_FLOAT:
- return NV50_2D_DST_FORMAT_R32_FLOAT;
-
- /* only because we require src format == dst format: */
- case PIPE_FORMAT_R16G16_SNORM:
- case PIPE_FORMAT_R16G16_UNORM:
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM;
- case PIPE_FORMAT_L8A8_UNORM:
- case PIPE_FORMAT_B4G4R4A4_UNORM:
+ case 2:
return NV50_2D_DST_FORMAT_R16_UNORM;
-
+ case 4:
+ return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM;
default:
- return -1;
+ return 0;
}
}
@@ -107,14 +85,14 @@ nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst)
int format, mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT;
int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD);
- format = nv50_format(ps->format);
- if (format < 0) {
+ format = nv50_2d_format(ps->format);
+ if (!format) {
NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
util_format_name(ps->format));
return 1;
}
- if (!bo->tile_flags) {
+ if (!nouveau_bo_tile_layout(bo)) {
BEGIN_RING(chan, eng2d, mthd, 2);
OUT_RING (chan, format);
OUT_RING (chan, 1);
@@ -221,7 +199,6 @@ nv50_surface_copy(struct pipe_context *pipe,
nv50_miptree_surface_del(ps_dst);
}
-/* XXX this should probably look more along the lines of nv50_clear */
static void
nv50_clear_render_target(struct pipe_context *pipe,
struct pipe_surface *dst,
@@ -231,34 +208,99 @@ nv50_clear_render_target(struct pipe_context *pipe,
{
struct nv50_context *nv50 = nv50_context(pipe);
struct nv50_screen *screen = nv50->screen;
- struct nouveau_channel *chan = screen->eng2d->channel;
- struct nouveau_grobj *eng2d = screen->eng2d;
- int format, ret;
- union util_color uc;
- util_pack_color(rgba, dst->format, &uc);
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *tesla = screen->tesla;
+ struct nv50_miptree *mt = nv50_miptree(dst->texture);
+ struct nouveau_bo *bo = mt->base.bo;
- format = nv50_format(dst->format);
- if (format < 0)
- return;
+ BEGIN_RING(chan, tesla, NV50TCL_CLEAR_COLOR(0), 4);
+ OUT_RINGf (chan, rgba[0]);
+ OUT_RINGf (chan, rgba[1]);
+ OUT_RINGf (chan, rgba[2]);
+ OUT_RINGf (chan, rgba[3]);
- ret = MARK_RING (chan, 16 + 32, 2);
- if (ret)
+ if (MARK_RING(chan, 18, 2))
return;
- ret = nv50_surface_set(screen, dst, 1);
- if (ret)
+ BEGIN_RING(chan, tesla, NV50TCL_RT_CONTROL, 1);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, tesla, NV50TCL_RT_ADDRESS_HIGH(0), 5);
+ OUT_RELOCh(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RING (chan, nv50_format_table[dst->format].rt);
+ OUT_RING (chan, mt->level[dst->level].tile_mode << 4);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, tesla, NV50TCL_RT_HORIZ(0), 2);
+ OUT_RING (chan, dst->width);
+ OUT_RING (chan, dst->height);
+ BEGIN_RING(chan, tesla, NV50TCL_RT_ARRAY_MODE, 1);
+ OUT_RING (chan, 1);
+
+ /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */
+
+ BEGIN_RING(chan, tesla, NV50TCL_VIEWPORT_HORIZ(0), 2);
+ OUT_RING (chan, (width << 16) | dstx);
+ OUT_RING (chan, (height << 16) | dsty);
+
+ BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1);
+ OUT_RING (chan, 0x3c);
+
+ nv50->dirty |= NV50_NEW_FRAMEBUFFER;
+}
+
+static void
+nv50_clear_depth_stencil(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned clear_flags,
+ double depth,
+ unsigned stencil,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nv50_screen *screen = nv50->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *tesla = screen->tesla;
+ struct nv50_miptree *mt = nv50_miptree(dst->texture);
+ struct nouveau_bo *bo = mt->base.bo;
+ uint32_t mode = 0;
+
+ if (clear_flags & PIPE_CLEAR_DEPTH) {
+ BEGIN_RING(chan, tesla, NV50TCL_CLEAR_DEPTH, 1);
+ OUT_RINGf (chan, depth);
+ mode |= NV50TCL_CLEAR_BUFFERS_Z;
+ }
+
+ if (clear_flags & PIPE_CLEAR_STENCIL) {
+ BEGIN_RING(chan, tesla, NV50TCL_CLEAR_STENCIL, 1);
+ OUT_RING (chan, stencil & 0xff);
+ mode |= NV50TCL_CLEAR_BUFFERS_S;
+ }
+
+ if (MARK_RING(chan, 17, 2))
return;
- BEGIN_RING(chan, eng2d, NV50_2D_DRAW_SHAPE, 3);
- OUT_RING (chan, NV50_2D_DRAW_SHAPE_RECTANGLES);
- OUT_RING (chan, format);
- OUT_RING (chan, uc.ui);
- BEGIN_RING(chan, eng2d, NV50_2D_DRAW_POINT32_X(0), 4);
- OUT_RING (chan, dstx);
- OUT_RING (chan, dsty);
- OUT_RING (chan, width);
- OUT_RING (chan, height);
+ BEGIN_RING(chan, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5);
+ OUT_RELOCh(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RING (chan, nv50_format_table[dst->format].rt);
+ OUT_RING (chan, mt->level[dst->level].tile_mode << 4);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, tesla, NV50TCL_ZETA_ENABLE, 1);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, tesla, NV50TCL_ZETA_HORIZ, 3);
+ OUT_RING (chan, dst->width);
+ OUT_RING (chan, dst->height);
+ OUT_RING (chan, (1 << 16) | 1);
+
+ BEGIN_RING(chan, tesla, NV50TCL_VIEWPORT_HORIZ(0), 2);
+ OUT_RING (chan, (width << 16) | dstx);
+ OUT_RING (chan, (height << 16) | dsty);
+
+ BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1);
+ OUT_RING (chan, mode);
+ nv50->dirty |= NV50_NEW_FRAMEBUFFER;
}
void
@@ -266,6 +308,7 @@ nv50_init_surface_functions(struct nv50_context *nv50)
{
nv50->pipe.resource_copy_region = nv50_surface_copy;
nv50->pipe.clear_render_target = nv50_clear_render_target;
+ nv50->pipe.clear_depth_stencil = nv50_clear_depth_stencil;
}