<div dir="ltr"><div>Fixes the test on Kepler<br><br></div>Tested-by: Nick Sarnie <<a href="mailto:commendsarnex@gmail.com">commendsarnex@gmail.com</a>></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Jan 30, 2016 at 10:10 AM, Ilia Mirkin <span dir="ltr"><<a href="mailto:imirkin@alum.mit.edu" target="_blank">imirkin@alum.mit.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">It appears that the nvidia render engine is quite picky when it comes to<br>
linear surfaces. It doesn't like non-256-byte aligned offsets, and<br>
apparently doesn't even do non-256-byte strides.<br>
<br>
This makes arb_clear_buffer_object-unaligned pass on both nv50 and nvc0.<br>
<br>
As a side-effect this also allows RGB32 clears to work via GPU data<br>
upload instead of synchronizing the buffer to the CPU (nvc0 only).<br>
<br>
Signed-off-by: Ilia Mirkin <<a href="mailto:imirkin@alum.mit.edu">imirkin@alum.mit.edu</a>><br>
Cc: <a href="mailto:mesa-stable@lists.freedesktop.org">mesa-stable@lists.freedesktop.org</a><br>
---<br>
 src/gallium/drivers/nouveau/nv50/nv50_surface.c | 190 ++++++++++++++------<br>
 src/gallium/drivers/nouveau/nvc0/nvc0_surface.c | 229 ++++++++++++++++++------<br>
 2 files changed, 307 insertions(+), 112 deletions(-)<br>
<br>
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_surface.c b/src/gallium/drivers/nouveau/nv50/nv50_surface.c<br>
index 86be1b4..618c39c 100644<br>
--- a/src/gallium/drivers/nouveau/nv50/nv50_surface.c<br>
+++ b/src/gallium/drivers/nouveau/nv50/nv50_surface.c<br>
@@ -595,6 +595,82 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers,<br>
 }<br>
<br>
 static void<br>
+nv50_clear_buffer_push(struct pipe_context *pipe,<br>
+                       struct pipe_resource *res,<br>
+                       unsigned offset, unsigned size,<br>
+                       const void *data, int data_size)<br>
+{<br>
+   struct nv50_context *nv50 = nv50_context(pipe);<br>
+   struct nouveau_pushbuf *push = nv50->base.pushbuf;<br>
+   struct nv04_resource *buf = nv04_resource(res);<br>
+   unsigned count = (size + 3) / 4;<br>
+   unsigned xcoord = offset & 0xff;<br>
+   unsigned tmp, i;<br>
+<br>
+   if (data_size == 1) {<br>
+      tmp = *(unsigned char *)data;<br>
+      tmp = (tmp << 24) | (tmp << 16) | (tmp << 8) | tmp;<br>
+      data = &tmp;<br>
+      data_size = 4;<br>
+   } else if (data_size == 2) {<br>
+      tmp = *(unsigned short *)data;<br>
+      tmp = (tmp << 16) | tmp;<br>
+      data = &tmp;<br>
+      data_size = 4;<br>
+   }<br>
+<br>
+   unsigned data_words = data_size / 4;<br>
+<br>
+   nouveau_bufctx_refn(nv50->bufctx, 0, buf->bo, buf->domain | NOUVEAU_BO_WR);<br>
+   nouveau_pushbuf_bufctx(push, nv50->bufctx);<br>
+   nouveau_pushbuf_validate(push);<br>
+<br>
+   offset &= ~0xff;<br>
+<br>
+   BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2);<br>
+   PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM);<br>
+   PUSH_DATA (push, 1);<br>
+   BEGIN_NV04(push, NV50_2D(DST_PITCH), 5);<br>
+   PUSH_DATA (push, 262144);<br>
+   PUSH_DATA (push, 65536);<br>
+   PUSH_DATA (push, 1);<br>
+   PUSH_DATAh(push, buf->address + offset);<br>
+   PUSH_DATA (push, buf->address + offset);<br>
+   BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2);<br>
+   PUSH_DATA (push, 0);<br>
+   PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM);<br>
+   BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10);<br>
+   PUSH_DATA (push, size);<br>
+   PUSH_DATA (push, 1);<br>
+   PUSH_DATA (push, 0);<br>
+   PUSH_DATA (push, 1);<br>
+   PUSH_DATA (push, 0);<br>
+   PUSH_DATA (push, 1);<br>
+   PUSH_DATA (push, 0);<br>
+   PUSH_DATA (push, xcoord);<br>
+   PUSH_DATA (push, 0);<br>
+   PUSH_DATA (push, 0);<br>
+<br>
+   while (count) {<br>
+      unsigned nr_data = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN) / data_words;<br>
+      unsigned nr = nr_data * data_words;<br>
+<br>
+      BEGIN_NI04(push, NV50_2D(SIFC_DATA), nr);<br>
+      for (i = 0; i < nr_data; i++)<br>
+         PUSH_DATAp(push, data, data_words);<br>
+<br>
+      count -= nr;<br>
+   }<br>
+<br>
+   if (buf->mm) {<br>
+      nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence);<br>
+      nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence_wr);<br>
+   }<br>
+<br>
+   nouveau_bufctx_reset(nv50->bufctx, 0);<br>
+}<br>
+<br>
+static void<br>
 nv50_clear_buffer(struct pipe_context *pipe,<br>
                   struct pipe_resource *res,<br>
                   unsigned offset, unsigned size,<br>
@@ -643,77 +719,85 @@ nv50_clear_buffer(struct pipe_context *pipe,<br>
<br>
    assert(size % data_size == 0);<br>
<br>
+   if (offset & 0xff) {<br>
+      unsigned fixup_size = MIN2(size, align(offset, 0x100) - offset);<br>
+      assert(fixup_size % data_size == 0);<br>
+      nv50_clear_buffer_push(pipe, res, offset, fixup_size, data, data_size);<br>
+      offset += fixup_size;<br>
+      size -= fixup_size;<br>
+      if (!size)<br>
+         return;<br>
+   }<br>
+<br>
    elements = size / data_size;<br>
    height = (elements + 8191) / 8192;<br>
    width = elements / height;<br>
+   width &= ~0xff;<br>
<br>
-   BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4);<br>
-   PUSH_DATAf(push, color.f[0]);<br>
-   PUSH_DATAf(push, color.f[1]);<br>
-   PUSH_DATAf(push, color.f[2]);<br>
-   PUSH_DATAf(push, color.f[3]);<br>
+   if (width) {<br>
+      BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4);<br>
+      PUSH_DATAf(push, color.f[0]);<br>
+      PUSH_DATAf(push, color.f[1]);<br>
+      PUSH_DATAf(push, color.f[2]);<br>
+      PUSH_DATAf(push, color.f[3]);<br>
<br>
-   if (nouveau_pushbuf_space(push, 32, 1, 0))<br>
-      return;<br>
+      if (nouveau_pushbuf_space(push, 32, 1, 0))<br>
+         return;<br>
<br>
-   PUSH_REFN(push, buf->bo, buf->domain | NOUVEAU_BO_WR);<br>
+      PUSH_REFN(push, buf->bo, buf->domain | NOUVEAU_BO_WR);<br>
<br>
-   BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);<br>
-   PUSH_DATA (push, width << 16);<br>
-   PUSH_DATA (push, height << 16);<br>
-   BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);<br>
-   PUSH_DATA (push, 8192 << 16);<br>
-   PUSH_DATA (push, 8192 << 16);<br>
-   nv50->scissors_dirty |= 1;<br>
+      BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);<br>
+      PUSH_DATA (push, width << 16);<br>
+      PUSH_DATA (push, height << 16);<br>
+      BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);<br>
+      PUSH_DATA (push, 8192 << 16);<br>
+      PUSH_DATA (push, 8192 << 16);<br>
+      nv50->scissors_dirty |= 1;<br>
<br>
-   BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);<br>
-   PUSH_DATA (push, 1);<br>
-   BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 5);<br>
-   PUSH_DATAh(push, buf->bo->offset + buf->offset + offset);<br>
-   PUSH_DATA (push, buf->bo->offset + buf->offset + offset);<br>
-   PUSH_DATA (push, nv50_format_table[dst_fmt].rt);<br>
-   PUSH_DATA (push, 0);<br>
-   PUSH_DATA (push, 0);<br>
-   BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2);<br>
-   PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | (width * data_size));<br>
-   PUSH_DATA (push, height);<br>
-   BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);<br>
-   PUSH_DATA (push, 0);<br>
-   BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);<br>
-   PUSH_DATA (push, 0);<br>
+      BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);<br>
+      PUSH_DATA (push, 1);<br>
+      BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 5);<br>
+      PUSH_DATAh(push, buf->address + offset);<br>
+      PUSH_DATA (push, buf->address + offset);<br>
+      PUSH_DATA (push, nv50_format_table[dst_fmt].rt);<br>
+      PUSH_DATA (push, 0);<br>
+      PUSH_DATA (push, 0);<br>
+      BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2);<br>
+      PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | (width * data_size));<br>
+      PUSH_DATA (push, height);<br>
+      BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);<br>
+      PUSH_DATA (push, 0);<br>
+      BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);<br>
+      PUSH_DATA (push, 0);<br>
<br>
-   /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */<br>
+      /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */<br>
<br>
-   BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);<br>
-   PUSH_DATA (push, (width << 16));<br>
-   PUSH_DATA (push, (height << 16));<br>
+      BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);<br>
+      PUSH_DATA (push, (width << 16));<br>
+      PUSH_DATA (push, (height << 16));<br>
<br>
-   BEGIN_NV04(push, NV50_3D(COND_MODE), 1);<br>
-   PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS);<br>
+      BEGIN_NV04(push, NV50_3D(COND_MODE), 1);<br>
+      PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS);<br>
+<br>
+      BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), 1);<br>
+      PUSH_DATA (push, 0x3c);<br>
<br>
-   BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), 1);<br>
-   PUSH_DATA (push, 0x3c);<br>
+      BEGIN_NV04(push, NV50_3D(COND_MODE), 1);<br>
+      PUSH_DATA (push, nv50->cond_condmode);<br>
+<br>
+      if (buf->mm) {<br>
+         nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence);<br>
+         nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence_wr);<br>
+      }<br>
+   }<br>
<br>
    if (width * height != elements) {<br>
       offset += width * height * data_size;<br>
       width = elements - width * height;<br>
-      height = 1;<br>
-      BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 2);<br>
-      PUSH_DATAh(push, buf->bo->offset + buf->offset + offset);<br>
-      PUSH_DATA (push, buf->bo->offset + buf->offset + offset);<br>
-      BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2);<br>
-      PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | (width * data_size));<br>
-      PUSH_DATA (push, height);<br>
-      BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), 1);<br>
-      PUSH_DATA (push, 0x3c);<br>
+      nv50_clear_buffer_push(pipe, res, offset, width * data_size,<br>
+                             data, data_size);<br>
    }<br>
<br>
-   BEGIN_NV04(push, NV50_3D(COND_MODE), 1);<br>
-   PUSH_DATA (push, nv50->cond_condmode);<br>
-<br>
-   nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence);<br>
-   nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence_wr);<br>
-<br>
    nv50->dirty |= NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR;<br>
 }<br>
<br>
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c<br>
index 4e43c4e..be4c531 100644<br>
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c<br>
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c<br>
@@ -357,27 +357,132 @@ nvc0_clear_render_target(struct pipe_context *pipe,<br>
 }<br>
<br>
 static void<br>
-nvc0_clear_buffer_cpu(struct pipe_context *pipe,<br>
-                      struct pipe_resource *res,<br>
-                      unsigned offset, unsigned size,<br>
-                      const void *data, int data_size)<br>
+nvc0_clear_buffer_push_nvc0(struct pipe_context *pipe,<br>
+                            struct pipe_resource *res,<br>
+                            unsigned offset, unsigned size,<br>
+                            const void *data, int data_size)<br>
 {<br>
+   struct nvc0_context *nvc0 = nvc0_context(pipe);<br>
+   struct nouveau_pushbuf *push = nvc0->base.pushbuf;<br>
    struct nv04_resource *buf = nv04_resource(res);<br>
-   struct pipe_transfer *pt;<br>
-   struct pipe_box box;<br>
-   unsigned elements, i;<br>
+   unsigned i;<br>
<br>
-   elements = size / data_size;<br>
+   nouveau_bufctx_refn(nvc0->bufctx, 0, buf->bo, buf->domain | NOUVEAU_BO_WR);<br>
+   nouveau_pushbuf_bufctx(push, nvc0->bufctx);<br>
+   nouveau_pushbuf_validate(push);<br>
+<br>
+   unsigned count = (size + 3) / 4;<br>
+   unsigned data_words = data_size / 4;<br>
+<br>
+   while (count) {<br>
+      unsigned nr_data = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN) / data_words;<br>
+      unsigned nr = nr_data * data_words;<br>
<br>
-   u_box_1d(offset, size, &box);<br>
+      if (!PUSH_SPACE(push, nr + 9))<br>
+         break;<br>
+<br>
+      BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2);<br>
+      PUSH_DATAh(push, buf->address + offset);<br>
+      PUSH_DATA (push, buf->address + offset);<br>
+      BEGIN_NVC0(push, NVC0_M2MF(LINE_LENGTH_IN), 2);<br>
+      PUSH_DATA (push, MIN2(size, nr * 4));<br>
+      PUSH_DATA (push, 1);<br>
+      BEGIN_NVC0(push, NVC0_M2MF(EXEC), 1);<br>
+      PUSH_DATA (push, 0x100111);<br>
<br>
-   uint8_t *map = buf->vtbl->transfer_map(pipe, res, 0, PIPE_TRANSFER_WRITE,<br>
-                                          &box, &pt);<br>
+      /* must not be interrupted (trap on QUERY fence, 0x50 works however) */<br>
+      BEGIN_NIC0(push, NVC0_M2MF(DATA), nr);<br>
+      for (i = 0; i < nr_data; i++)<br>
+         PUSH_DATAp(push, data, data_words);<br>
<br>
-   for (i = 0; i < elements; ++i)<br>
-      memcpy(&map[i*data_size], data, data_size);<br>
+      count -= nr;<br>
+      offset += nr * 4;<br>
+      size -= nr * 4;<br>
+   }<br>
+<br>
+   if (buf->mm) {<br>
+      nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence);<br>
+      nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence_wr);<br>
+   }<br>
+<br>
+   nouveau_bufctx_reset(nvc0->bufctx, 0);<br>
+}<br>
+<br>
+static void<br>
+nvc0_clear_buffer_push_nve4(struct pipe_context *pipe,<br>
+                            struct pipe_resource *res,<br>
+                            unsigned offset, unsigned size,<br>
+                            const void *data, int data_size)<br>
+{<br>
+   struct nvc0_context *nvc0 = nvc0_context(pipe);<br>
+   struct nouveau_pushbuf *push = nvc0->base.pushbuf;<br>
+   struct nv04_resource *buf = nv04_resource(res);<br>
+   unsigned i;<br>
+<br>
+   nouveau_bufctx_refn(nvc0->bufctx, 0, buf->bo, buf->domain | NOUVEAU_BO_WR);<br>
+   nouveau_pushbuf_bufctx(push, nvc0->bufctx);<br>
+   nouveau_pushbuf_validate(push);<br>
+<br>
+   unsigned count = (size + 3) / 4;<br>
+   unsigned data_words = data_size / 4;<br>
+<br>
+   while (count) {<br>
+      unsigned nr_data = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN) / data_words;<br>
+      unsigned nr = nr_data * data_words;<br>
+<br>
+      if (!PUSH_SPACE(push, nr + 10))<br>
+         break;<br>
+<br>
+      BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_DST_ADDRESS_HIGH), 2);<br>
+      PUSH_DATAh(push, buf->address + offset);<br>
+      PUSH_DATA (push, buf->address + offset);<br>
+      BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_LINE_LENGTH_IN), 2);<br>
+      PUSH_DATA (push, MIN2(size, nr * 4));<br>
+      PUSH_DATA (push, 1);<br>
+      /* must not be interrupted (trap on QUERY fence, 0x50 works however) */<br>
+      BEGIN_1IC0(push, NVE4_P2MF(UPLOAD_EXEC), nr + 1);<br>
+      PUSH_DATA (push, 0x1001);<br>
+      for (i = 0; i < nr_data; i++)<br>
+         PUSH_DATAp(push, data, data_words);<br>
+<br>
+      count -= nr;<br>
+      offset += nr * 4;<br>
+      size -= nr * 4;<br>
+   }<br>
+<br>
+   if (buf->mm) {<br>
+      nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence);<br>
+      nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence_wr);<br>
+   }<br>
+<br>
+   nouveau_bufctx_reset(nvc0->bufctx, 0);<br>
+}<br>
+<br>
+static void<br>
+nvc0_clear_buffer_push(struct pipe_context *pipe,<br>
+                       struct pipe_resource *res,<br>
+                       unsigned offset, unsigned size,<br>
+                       const void *data, int data_size)<br>
+{<br>
+   struct nvc0_context *nvc0 = nvc0_context(pipe);<br>
+   unsigned tmp;<br>
+<br>
+   if (data_size == 1) {<br>
+      tmp = *(unsigned char *)data;<br>
+      tmp = (tmp << 24) | (tmp << 16) | (tmp << 8) | tmp;<br>
+      data = &tmp;<br>
+      data_size = 4;<br>
+   } else if (data_size == 2) {<br>
+      tmp = *(unsigned short *)data;<br>
+      tmp = (tmp << 16) | tmp;<br>
+      data = &tmp;<br>
+      data_size = 4;<br>
+   }<br>
<br>
-   buf->vtbl->transfer_unmap(pipe, pt);<br>
+   if (nvc0->screen->base.class_3d < NVE4_3D_CLASS)<br>
+      nvc0_clear_buffer_push_nvc0(pipe, res, offset, size, data, data_size);<br>
+   else<br>
+      nvc0_clear_buffer_push_nve4(pipe, res, offset, size, data, data_size);<br>
 }<br>
<br>
 static void<br>
@@ -402,10 +507,8 @@ nvc0_clear_buffer(struct pipe_context *pipe,<br>
       memcpy(&color.ui, data, 16);<br>
       break;<br>
    case 12:<br>
-      /* This doesn't work, RGB32 is not a valid RT format.<br>
-       * dst_fmt = PIPE_FORMAT_R32G32B32_UINT;<br>
-       * memcpy(&color.ui, data, 12);<br>
-       * memset(&color.ui[3], 0, 4);<br>
+      /* RGB32 is not a valid RT format. This will be handled by the pushbuf<br>
+       * uploader.<br>
        */<br>
       break;<br>
    case 8:<br>
@@ -437,67 +540,75 @@ nvc0_clear_buffer(struct pipe_context *pipe,<br>
    assert(size % data_size == 0);<br>
<br>
    if (data_size == 12) {<br>
-      /* TODO: Find a way to do this with the GPU! */<br>
-      nvc0_clear_buffer_cpu(pipe, res, offset, size, data, data_size);<br>
+      nvc0_clear_buffer_push(pipe, res, offset, size, data, data_size);<br>
       return;<br>
    }<br>
<br>
+   if (offset & 0xff) {<br>
+      unsigned fixup_size = MIN2(size, align(offset, 0x100) - offset);<br>
+      assert(fixup_size % data_size == 0);<br>
+      nvc0_clear_buffer_push(pipe, res, offset, fixup_size, data, data_size);<br>
+      offset += fixup_size;<br>
+      size -= fixup_size;<br>
+      if (!size)<br>
+         return;<br>
+   }<br>
+<br>
    elements = size / data_size;<br>
    height = (elements + 16383) / 16384;<br>
    width = elements / height;<br>
+   width &= ~0xff;<br>
<br>
-   if (!PUSH_SPACE(push, 40))<br>
-      return;<br>
-<br>
-   PUSH_REFN (push, buf->bo, buf->domain | NOUVEAU_BO_WR);<br>
-<br>
-   BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4);<br>
-   PUSH_DATAf(push, color.f[0]);<br>
-   PUSH_DATAf(push, color.f[1]);<br>
-   PUSH_DATAf(push, color.f[2]);<br>
-   PUSH_DATAf(push, color.f[3]);<br>
-   BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);<br>
-   PUSH_DATA (push, width << 16);<br>
-   PUSH_DATA (push, height << 16);<br>
-<br>
-   IMMED_NVC0(push, NVC0_3D(RT_CONTROL), 1);<br>
-<br>
-   BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 9);<br>
-   PUSH_DATAh(push, buf->address + offset);<br>
-   PUSH_DATA (push, buf->address + offset);<br>
-   PUSH_DATA (push, width * data_size);<br>
-   PUSH_DATA (push, height);<br>
-   PUSH_DATA (push, nvc0_format_table[dst_fmt].rt);<br>
-   PUSH_DATA (push, NVC0_3D_RT_TILE_MODE_LINEAR);<br>
-   PUSH_DATA (push, 1);<br>
-   PUSH_DATA (push, 0);<br>
-   PUSH_DATA (push, 0);<br>
-<br>
-   IMMED_NVC0(push, NVC0_3D(ZETA_ENABLE), 0);<br>
-   IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_MODE), 0);<br>
+   if (width) {<br>
+      if (!PUSH_SPACE(push, 40))<br>
+         return;<br>
<br>
-   IMMED_NVC0(push, NVC0_3D(COND_MODE), NVC0_3D_COND_MODE_ALWAYS);<br>
+      PUSH_REFN (push, buf->bo, buf->domain | NOUVEAU_BO_WR);<br>
<br>
-   IMMED_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 0x3c);<br>
+      BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4);<br>
+      PUSH_DATAf(push, color.f[0]);<br>
+      PUSH_DATAf(push, color.f[1]);<br>
+      PUSH_DATAf(push, color.f[2]);<br>
+      PUSH_DATAf(push, color.f[3]);<br>
+      BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);<br>
+      PUSH_DATA (push, width << 16);<br>
+      PUSH_DATA (push, height << 16);<br>
<br>
-   if (width * height != elements) {<br>
-      offset += width * height * data_size;<br>
-      width = elements - width * height;<br>
-      height = 1;<br>
+      IMMED_NVC0(push, NVC0_3D(RT_CONTROL), 1);<br>
<br>
-      BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 4);<br>
+      BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 9);<br>
       PUSH_DATAh(push, buf->address + offset);<br>
       PUSH_DATA (push, buf->address + offset);<br>
       PUSH_DATA (push, width * data_size);<br>
       PUSH_DATA (push, height);<br>
+      PUSH_DATA (push, nvc0_format_table[dst_fmt].rt);<br>
+      PUSH_DATA (push, NVC0_3D_RT_TILE_MODE_LINEAR);<br>
+      PUSH_DATA (push, 1);<br>
+      PUSH_DATA (push, 0);<br>
+      PUSH_DATA (push, 0);<br>
+<br>
+      IMMED_NVC0(push, NVC0_3D(ZETA_ENABLE), 0);<br>
+      IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_MODE), 0);<br>
+<br>
+      IMMED_NVC0(push, NVC0_3D(COND_MODE), NVC0_3D_COND_MODE_ALWAYS);<br>
<br>
       IMMED_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 0x3c);<br>
+<br>
+      IMMED_NVC0(push, NVC0_3D(COND_MODE), nvc0->cond_condmode);<br>
+<br>
+      if (buf->mm) {<br>
+         nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence);<br>
+         nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence_wr);<br>
+      }<br>
    }<br>
<br>
-   IMMED_NVC0(push, NVC0_3D(COND_MODE), nvc0->cond_condmode);<br>
+   if (width * height != elements) {<br>
+      offset += width * height * data_size;<br>
+      width = elements - width * height;<br>
+      nvc0_clear_buffer_push(pipe, res, offset, width * data_size,<br>
+                             data, data_size);<br>
+   }<br>
<br>
-   nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence);<br>
-   nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence_wr);<br>
    nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;<br>
 }<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
2.4.10<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div>