summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv50/nv50_surface.c
diff options
context:
space:
mode:
authorChristian König <[email protected]>2011-03-04 17:15:43 +0100
committerChristian König <[email protected]>2011-03-04 17:15:43 +0100
commit54f11a27a1ec28fcf9734f4454dee870bc0113f8 (patch)
tree2dc71d95b1ad5d2ca966bbb6726fba45b4cfbac1 /src/gallium/drivers/nv50/nv50_surface.c
parent0eccb1038a620bc76ba45ac00c293b3e88427510 (diff)
parent6838c9ce74f16c765474c0d2b4ae1469dd4a64d5 (diff)
Merge remote branch 'origin/master' into pipe-video
Diffstat (limited to 'src/gallium/drivers/nv50/nv50_surface.c')
-rw-r--r--src/gallium/drivers/nv50/nv50_surface.c570
1 files changed, 313 insertions, 257 deletions
diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c
index a99df76cee3..dc9e2880f0f 100644
--- a/src/gallium/drivers/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nv50/nv50_surface.c
@@ -20,306 +20,362 @@
* SOFTWARE.
*/
-#define __NOUVEAU_PUSH_H__
#include <stdint.h>
-#include "nouveau/nv04_pushbuf.h"
-#include "nv50_context.h"
-#include "nv50_resource.h"
+
#include "pipe/p_defines.h"
+
#include "util/u_inlines.h"
#include "util/u_pack_color.h"
-
#include "util/u_format.h"
+#include "nv50_context.h"
+#include "nv50_resource.h"
+
+#include "nv50_defs.xml.h"
+
/* return TRUE for formats that can be converted among each other by NV50_2D */
static INLINE boolean
nv50_2d_format_faithful(enum pipe_format format)
{
- switch (format) {
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- case PIPE_FORMAT_B8G8R8X8_UNORM:
- case PIPE_FORMAT_B8G8R8A8_SRGB:
- case PIPE_FORMAT_B8G8R8X8_SRGB:
- case PIPE_FORMAT_B5G6R5_UNORM:
- case PIPE_FORMAT_B5G5R5A1_UNORM:
- case PIPE_FORMAT_B10G10R10A2_UNORM:
- case PIPE_FORMAT_R8_UNORM:
- case PIPE_FORMAT_R32G32B32A32_FLOAT:
- case PIPE_FORMAT_R32G32B32_FLOAT:
- return TRUE;
- default:
- return FALSE;
- }
+ switch (format) {
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_SRGB:
+ case PIPE_FORMAT_B8G8R8X8_SRGB:
+ case PIPE_FORMAT_B5G6R5_UNORM:
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B10G10R10A2_UNORM:
+ case PIPE_FORMAT_R8_UNORM:
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ return TRUE;
+ default:
+ return FALSE;
+ }
}
static INLINE uint8_t
nv50_2d_format(enum pipe_format format)
{
- 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 2:
- return NV50_2D_DST_FORMAT_R16_UNORM;
- case 4:
- return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM;
- default:
- return 0;
- }
+ 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_SURFACE_FORMAT_R8_UNORM;
+ case 2:
+ return NV50_SURFACE_FORMAT_R16_UNORM;
+ case 4:
+ return NV50_SURFACE_FORMAT_A8R8G8B8_UNORM;
+ default:
+ return 0;
+ }
}
static int
-nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst)
+nv50_2d_texture_set(struct nouveau_channel *chan, int dst,
+ struct nv50_miptree *mt, unsigned level, unsigned layer)
{
- struct nv50_miptree *mt = nv50_miptree(ps->texture);
- struct nouveau_channel *chan = screen->eng2d->channel;
- struct nouveau_grobj *eng2d = screen->eng2d;
- struct nouveau_bo *bo = nv50_miptree(ps->texture)->base.bo;
- 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_2d_format(ps->format);
- if (!format) {
- NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
- util_format_name(ps->format));
- return 1;
- }
-
- if (!nouveau_bo_tile_layout(bo)) {
- BEGIN_RING(chan, eng2d, mthd, 2);
- OUT_RING (chan, format);
- OUT_RING (chan, 1);
- BEGIN_RING(chan, eng2d, mthd + 0x14, 5);
- OUT_RING (chan, mt->level[ps->u.tex.level].pitch);
- OUT_RING (chan, ps->width);
- OUT_RING (chan, ps->height);
- OUT_RELOCh(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
- OUT_RELOCl(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
- } else {
- BEGIN_RING(chan, eng2d, mthd, 5);
- OUT_RING (chan, format);
- OUT_RING (chan, 0);
- OUT_RING (chan, mt->level[ps->u.tex.level].tile_mode << 4);
- OUT_RING (chan, 1);
- OUT_RING (chan, 0);
- BEGIN_RING(chan, eng2d, mthd + 0x18, 4);
- OUT_RING (chan, ps->width);
- OUT_RING (chan, ps->height);
- OUT_RELOCh(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
- OUT_RELOCl(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
- }
-
+ struct nouveau_bo *bo = mt->base.bo;
+ uint32_t width, height, depth;
+ uint32_t format;
+ uint32_t mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT;
+ uint32_t flags = mt->base.domain | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD);
+ uint32_t offset = mt->level[level].offset;
+
+ format = nv50_2d_format(mt->base.base.format);
+ if (!format) {
+ NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
+ util_format_name(mt->base.base.format));
+ return 1;
+ }
+
+ width = u_minify(mt->base.base.width0, level);
+ height = u_minify(mt->base.base.height0, level);
+
+ offset = mt->level[level].offset;
+ if (!mt->layout_3d) {
+ offset += mt->layer_stride * layer;
+ depth = 1;
+ layer = 0;
+ } else {
+ depth = u_minify(mt->base.base.depth0, level);
+ }
+
+ if (!(bo->tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK)) {
+ BEGIN_RING(chan, RING_2D_(mthd), 2);
+ OUT_RING (chan, format);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, RING_2D_(mthd + 0x14), 5);
+ OUT_RING (chan, mt->level[level].pitch);
+ OUT_RING (chan, width);
+ OUT_RING (chan, height);
+ OUT_RELOCh(chan, bo, offset, flags);
+ OUT_RELOCl(chan, bo, offset, flags);
+ } else {
+ BEGIN_RING(chan, RING_2D_(mthd), 5);
+ OUT_RING (chan, format);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, mt->level[level].tile_mode << 4);
+ OUT_RING (chan, depth);
+ OUT_RING (chan, layer);
+ BEGIN_RING(chan, RING_2D_(mthd + 0x18), 4);
+ OUT_RING (chan, width);
+ OUT_RING (chan, height);
+ OUT_RELOCh(chan, bo, offset, flags);
+ OUT_RELOCl(chan, bo, offset, flags);
+ }
+
#if 0
- if (dst) {
- BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
- OUT_RING (chan, 0);
- OUT_RING (chan, 0);
- OUT_RING (chan, surf->width);
- OUT_RING (chan, surf->height);
- }
+ if (dst) {
+ BEGIN_RING(chan, RING_2D_(NV50_2D_CLIP_X), 4);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, width);
+ OUT_RING (chan, height);
+ }
#endif
-
- return 0;
+ return 0;
}
-int
-nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst,
- int dx, int dy, struct pipe_surface *src, int sx, int sy,
- int w, int h)
+static int
+nv50_2d_texture_do_copy(struct nouveau_channel *chan,
+ struct nv50_miptree *dst, unsigned dst_level,
+ unsigned dx, unsigned dy, unsigned dz,
+ struct nv50_miptree *src, unsigned src_level,
+ unsigned sx, unsigned sy, unsigned sz,
+ unsigned w, unsigned h)
{
- struct nouveau_channel *chan = screen->eng2d->channel;
- struct nouveau_grobj *eng2d = screen->eng2d;
- int ret;
-
- ret = MARK_RING(chan, 2*16 + 32, 4);
- if (ret)
- return ret;
-
- ret = nv50_surface_set(screen, dst, 1);
- if (ret)
- return ret;
-
- ret = nv50_surface_set(screen, src, 0);
- if (ret)
- return ret;
-
- BEGIN_RING(chan, eng2d, 0x088c, 1);
- OUT_RING (chan, 0);
- BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 4);
- OUT_RING (chan, dx);
- OUT_RING (chan, dy);
- OUT_RING (chan, w);
- OUT_RING (chan, h);
- BEGIN_RING(chan, eng2d, 0x08c0, 4);
- OUT_RING (chan, 0);
- OUT_RING (chan, 1);
- OUT_RING (chan, 0);
- OUT_RING (chan, 1);
- BEGIN_RING(chan, eng2d, 0x08d0, 4);
- OUT_RING (chan, 0);
- OUT_RING (chan, sx);
- OUT_RING (chan, 0);
- OUT_RING (chan, sy);
-
- return 0;
+ int ret;
+
+ ret = MARK_RING(chan, 2 * 16 + 32, 4);
+ if (ret)
+ return ret;
+
+ ret = nv50_2d_texture_set(chan, 1, dst, dst_level, dz);
+ if (ret)
+ return ret;
+
+ ret = nv50_2d_texture_set(chan, 0, src, src_level, sz);
+ if (ret)
+ return ret;
+
+ /* 0/1 = CENTER/CORNER, 10/00 = POINT/BILINEAR */
+ BEGIN_RING(chan, RING_2D(BLIT_CONTROL), 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, RING_2D(BLIT_DST_X), 4);
+ OUT_RING (chan, dx);
+ OUT_RING (chan, dy);
+ OUT_RING (chan, w);
+ OUT_RING (chan, h);
+ BEGIN_RING(chan, RING_2D(BLIT_DU_DX_FRACT), 4);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, 1);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, RING_2D(BLIT_SRC_X_FRACT), 4);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, sx);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, sy);
+
+ return 0;
}
static void
-nv50_surface_copy(struct pipe_context *pipe,
- struct pipe_resource *dest, unsigned dst_level,
- unsigned destx, unsigned desty, unsigned destz,
- struct pipe_resource *src, unsigned src_level,
- const struct pipe_box *src_box)
+nv50_resource_copy_region(struct pipe_context *pipe,
+ struct pipe_resource *dst, unsigned dst_level,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_resource *src, unsigned src_level,
+ const struct pipe_box *src_box)
{
- struct nv50_context *nv50 = nv50_context(pipe);
- struct nv50_screen *screen = nv50->screen;
- struct pipe_surface *ps_dst, *ps_src, surf_tmpl;
-
-
- assert((src->format == dest->format) ||
- (nv50_2d_format_faithful(src->format) &&
- nv50_2d_format_faithful(dest->format)));
- assert(src_box->depth == 1);
-
- memset(&surf_tmpl, 0, sizeof(surf_tmpl));
- surf_tmpl.format = src->format;
- surf_tmpl.usage = 0; /* no bind flag - not a surface */
- surf_tmpl.u.tex.level = src_level;
- surf_tmpl.u.tex.first_layer = src_box->z;
- surf_tmpl.u.tex.last_layer = src_box->z;
- /* XXX really need surfaces here? */
- ps_src = nv50_miptree_surface_new(pipe, src, &surf_tmpl);
- surf_tmpl.format = dest->format;
- surf_tmpl.usage = 0; /* no bind flag - not a surface */
- surf_tmpl.u.tex.level = dst_level;
- surf_tmpl.u.tex.first_layer = destz;
- surf_tmpl.u.tex.last_layer = destz;
- ps_dst = nv50_miptree_surface_new(pipe, dest, &surf_tmpl);
-
- nv50_surface_do_copy(screen, ps_dst, destx, desty, ps_src, src_box->x,
- src_box->y, src_box->width, src_box->height);
-
- nv50_miptree_surface_del(pipe, ps_src);
- nv50_miptree_surface_del(pipe, ps_dst);
+ struct nv50_screen *screen = nv50_context(pipe)->screen;
+ int ret;
+ unsigned dst_layer = dstz, src_layer = src_box->z;
+
+ assert((src->format == dst->format) ||
+ (nv50_2d_format_faithful(src->format) &&
+ nv50_2d_format_faithful(dst->format)));
+
+ for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {
+ ret = nv50_2d_texture_do_copy(screen->base.channel,
+ nv50_miptree(dst), dst_level,
+ dstx, dsty, dst_layer,
+ nv50_miptree(src), src_level,
+ src_box->x, src_box->y, src_layer,
+ src_box->width, src_box->height);
+ if (ret)
+ return;
+ }
}
static void
nv50_clear_render_target(struct pipe_context *pipe,
- struct pipe_surface *dst,
- const float *rgba,
- unsigned dstx, unsigned dsty,
- unsigned width, unsigned height)
+ struct pipe_surface *dst,
+ const float *rgba,
+ 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;
-
- 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]);
-
- if (MARK_RING(chan, 18, 2))
- return;
-
- 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, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
- OUT_RELOCl(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
- OUT_RING (chan, nv50_format_table[dst->format].rt);
- OUT_RING (chan, mt->level[dst->u.tex.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;
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nv50_screen *screen = nv50->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nv50_miptree *mt = nv50_miptree(dst->texture);
+ struct nv50_surface *sf = nv50_surface(dst);
+ struct nouveau_bo *bo = mt->base.bo;
+
+ BEGIN_RING(chan, RING_3D(CLEAR_COLOR(0)), 4);
+ OUT_RINGf (chan, rgba[0]);
+ OUT_RINGf (chan, rgba[1]);
+ OUT_RINGf (chan, rgba[2]);
+ OUT_RINGf (chan, rgba[3]);
+
+ if (MARK_RING(chan, 18, 2))
+ return;
+
+ BEGIN_RING(chan, RING_3D(RT_CONTROL), 1);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(0)), 5);
+ OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RING (chan, nv50_format_table[dst->format].rt);
+ OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, RING_3D(RT_HORIZ(0)), 2);
+ OUT_RING (chan, sf->width);
+ OUT_RING (chan, sf->height);
+ BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1);
+ OUT_RING (chan, 1);
+
+ /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */
+
+ BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
+ OUT_RING (chan, (width << 16) | dstx);
+ OUT_RING (chan, (height << 16) | dsty);
+
+ BEGIN_RING(chan, RING_3D(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 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 nv50_miptree *mt = nv50_miptree(dst->texture);
+ struct nv50_surface *sf = nv50_surface(dst);
+ struct nouveau_bo *bo = mt->base.bo;
+ uint32_t mode = 0;
+
+ if (clear_flags & PIPE_CLEAR_DEPTH) {
+ BEGIN_RING(chan, RING_3D(CLEAR_DEPTH), 1);
+ OUT_RINGf (chan, depth);
+ mode |= NV50_3D_CLEAR_BUFFERS_Z;
+ }
+
+ if (clear_flags & PIPE_CLEAR_STENCIL) {
+ BEGIN_RING(chan, RING_3D(CLEAR_STENCIL), 1);
+ OUT_RING (chan, stencil & 0xff);
+ mode |= NV50_3D_CLEAR_BUFFERS_S;
+ }
+
+ if (MARK_RING(chan, 17, 2))
+ return;
+
+ BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5);
+ OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RING (chan, nv50_format_table[dst->format].rt);
+ OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3);
+ OUT_RING (chan, sf->width);
+ OUT_RING (chan, sf->height);
+ OUT_RING (chan, (1 << 16) | 1);
+
+ BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
+ OUT_RING (chan, (width << 16) | dstx);
+ OUT_RING (chan, (height << 16) | dsty);
+
+ BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
+ OUT_RING (chan, mode);
+
+ nv50->dirty |= NV50_NEW_FRAMEBUFFER;
+}
+
+void
+nv50_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil)
{
- 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, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5);
- OUT_RELOCh(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
- OUT_RELOCl(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
- OUT_RING (chan, nv50_format_table[dst->format].rt);
- OUT_RING (chan, mt->level[dst->u.tex.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;
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nouveau_channel *chan = nv50->screen->base.channel;
+ struct pipe_framebuffer_state *fb = &nv50->framebuffer;
+ unsigned i;
+ const unsigned dirty = nv50->dirty;
+ uint32_t mode = 0;
+
+ /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
+ nv50->dirty &= NV50_NEW_FRAMEBUFFER;
+ if (!nv50_state_validate(nv50))
+ return;
+
+ if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
+ BEGIN_RING(chan, RING_3D(CLEAR_COLOR(0)), 4);
+ OUT_RINGf (chan, rgba[0]);
+ OUT_RINGf (chan, rgba[1]);
+ OUT_RINGf (chan, rgba[2]);
+ OUT_RINGf (chan, rgba[3]);
+ mode =
+ NV50_3D_CLEAR_BUFFERS_R | NV50_3D_CLEAR_BUFFERS_G |
+ NV50_3D_CLEAR_BUFFERS_B | NV50_3D_CLEAR_BUFFERS_A;
+ }
+
+ if (buffers & PIPE_CLEAR_DEPTH) {
+ BEGIN_RING(chan, RING_3D(CLEAR_DEPTH), 1);
+ OUT_RING (chan, fui(depth));
+ mode |= NV50_3D_CLEAR_BUFFERS_Z;
+ }
+
+ if (buffers & PIPE_CLEAR_STENCIL) {
+ BEGIN_RING(chan, RING_3D(CLEAR_STENCIL), 1);
+ OUT_RING (chan, stencil & 0xff);
+ mode |= NV50_3D_CLEAR_BUFFERS_S;
+ }
+
+ BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
+ OUT_RING (chan, mode);
+
+ for (i = 1; i < fb->nr_cbufs; i++) {
+ BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
+ OUT_RING (chan, (i << 6) | 0x3c);
+ }
+
+ nv50->dirty = dirty & ~NV50_NEW_FRAMEBUFFER;
}
void
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;
+ struct pipe_context *pipe = &nv50->base.pipe;
+
+ pipe->resource_copy_region = nv50_resource_copy_region;
+ pipe->clear_render_target = nv50_clear_render_target;
+ pipe->clear_depth_stencil = nv50_clear_depth_stencil;
}