v2:
- change patch name to "nvc0: implement clear_buffer"
- rename nvc0_clear_buffer_rgb32 -> nvc0_clear_buffer_cpu and make it work
for
all formats
- remove superfluous fenciing in nvc0_clear_buffer_cpu
- coding style fixes
v3:
- more coding style fixes
- nvc0_clear_buffer() - don't mark the framebuffer dirty for if we
don't touch
the GPU
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de>
---
src/gallium/drivers/nouveau/nvc0/nvc0_surface.c | 151 ++++++++++++++++++++++++
1 file changed, 151 insertions(+)
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
index 6b7c30c..3572193 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
@@ -345,6 +345,156 @@ nvc0_clear_render_target(struct pipe_context *pipe,
}
static void
+nvc0_clear_buffer_cpu(struct pipe_context *pipe,
+ struct pipe_resource *res,
+ unsigned offset, unsigned size,
+ const void *data, int data_size)
+{
+ struct nv04_resource *buf = nv04_resource(res);
+ struct pipe_transfer *pt;
+ struct pipe_box box;
+ unsigned elements, i;
+
+ elements = size / data_size;
+
+ u_box_1d(0, size, &box);
+
+ uint8_t *map = buf->vtbl->transfer_map(pipe, res, 0,
PIPE_TRANSFER_WRITE,
+ &box, &pt);
+
+ for (i = 0; i < elements; ++i)
+ memcpy(&map[i*data_size], data, data_size);
+
+ buf->vtbl->transfer_unmap(pipe, pt);
+}
+
+static void
+nvc0_clear_buffer(struct pipe_context *pipe,
+ struct pipe_resource *res,
+ unsigned offset, unsigned size,
+ const void *data, int data_size)
+{
+ struct nvc0_context *nvc0 = nvc0_context(pipe);
+ struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+ struct nv04_resource *buf = nv04_resource(res);
+ union pipe_color_union color;
+ enum pipe_format dst_fmt;
+ unsigned width, height, elements;
+
+ assert(res->target == PIPE_BUFFER);
+ assert(nouveau_bo_memtype(buf->bo) == 0);
+
+ switch (data_size) {
+ case 16:
+ dst_fmt = PIPE_FORMAT_R32G32B32A32_UINT;
+ memcpy(&color.ui, data, 16);
+ break;
+ case 12:
+ /*
+ * dst_fmt = PIPE_FORMAT_R32G32B32_UINT;
+ * memcpy(&color.ui, data, 12);
+ * memset(&color.ui[3], 0, 4);
+ * break;
+ */
+ case 8:
+ dst_fmt = PIPE_FORMAT_R32G32_UINT;
+ memcpy(&color.ui, data, 8);
+ memset(&color.ui[2], 0, 8);
+ break;
+ case 4:
+ dst_fmt = PIPE_FORMAT_R32_UINT;
+ memcpy(&color.ui, data, 4);
+ memset(&color.ui[1], 0, 12);
+ break;
+ case 2:
+ dst_fmt = PIPE_FORMAT_R16_UINT;
+ color.ui[0] = util_cpu_to_le32(
+ util_le16_to_cpu(*(unsigned short *)data));
+ memset(&color.ui[1], 0, 12);
+ break;
+ case 1:
+ dst_fmt = PIPE_FORMAT_R8_UINT;
+ color.ui[0] = util_cpu_to_le32(*(unsigned char *)data);
+ memset(&color.ui[1], 0, 12);
+ break;
+ default:
+ assert(!"Unsupported element size");
+ return;
+ }
+
+ assert(size % data_size == 0);
+
+ if (data_size == 12) {
+ /* TODO: Find a way to do this with the GPU! */
+ nvc0_clear_buffer_cpu(pipe, res, offset, size, data, data_size);
+ return;
+ }
+
+ elements = size / data_size;
+
+ height = (elements + 16383) / 16384;
+
+ width = elements / height;
+
+ if (!PUSH_SPACE(push, 40))
+ return;
+
+ PUSH_REFN (push, buf->bo, buf->domain | NOUVEAU_BO_WR);
+
+ BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4);
+ PUSH_DATAf(push, color.f[0]);
+ PUSH_DATAf(push, color.f[1]);
+ PUSH_DATAf(push, color.f[2]);
+ PUSH_DATAf(push, color.f[3]);
+ BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
+ PUSH_DATA (push, width << 16);
+ PUSH_DATA (push, height << 16);
+
+ IMMED_NVC0(push, NVC0_3D(RT_CONTROL), 1);
+
+ BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 9);
+ PUSH_DATAh(push, buf->address + offset);
+ PUSH_DATA (push, buf->address + offset);
+
+ PUSH_DATA (push, width * data_size);
+ PUSH_DATA (push, height);
+
+ PUSH_DATA (push, nvc0_format_table[dst_fmt].rt);
+ PUSH_DATA (push, 1 << 12);
+ PUSH_DATA (push, 1);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, 0);
+
+ IMMED_NVC0(push, NVC0_3D(ZETA_ENABLE), 0);
+
+ IMMED_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 0x3c);
+
+ if (width * height != elements) {
+ offset += width * height * data_size;
+ width = elements - width * height;
+ height = 1;
+
+ BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
+ PUSH_DATA (push, width << 16);
+ PUSH_DATA (push, height << 16);
+
+ BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 2);
+ PUSH_DATAh(push, buf->address + offset);
+ PUSH_DATA (push, buf->address + offset);
+
+ BEGIN_NVC0(push, NVC0_3D(RT_HORIZ(0)), 2);
+ PUSH_DATA (push, width * data_size);
+ PUSH_DATA (push, height);
+
+ IMMED_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 0x3c);
+ }
+
+ nouveau_fence_ref(nvc0->screen->base.fence.current,
&buf->fence);
+ nouveau_fence_ref(nvc0->screen->base.fence.current,
&buf->fence_wr);
+ nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
+}
+
+static void
nvc0_clear_depth_stencil(struct pipe_context *pipe,
struct pipe_surface *dst,
unsigned clear_flags,
@@ -1363,4 +1513,5 @@ nvc0_init_surface_functions(struct nvc0_context *nvc0)
pipe->flush_resource = nvc0_flush_resource;
pipe->clear_render_target = nvc0_clear_render_target;
pipe->clear_depth_stencil = nvc0_clear_depth_stencil;
+ pipe->clear_buffer = nvc0_clear_buffer;
}
--
1.8.4.5
Made a few very minor changes to it and pushed out as http://cgit.freedesktop.org/mesa/mesa/commit/?id=a26e2bc2e3578b50bd581c8f8d8e3c428c85158f On Mon, May 26, 2014 at 8:19 PM, Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> wrote:> v2: > - change patch name to "nvc0: implement clear_buffer" > - rename nvc0_clear_buffer_rgb32 -> nvc0_clear_buffer_cpu and make it work for > all formats > - remove superfluous fenciing in nvc0_clear_buffer_cpu > - coding style fixes > v3: > - more coding style fixes > - nvc0_clear_buffer() - don't mark the framebuffer dirty for if we don't touch > the GPU > > Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann at mni.thm.de> > --- > src/gallium/drivers/nouveau/nvc0/nvc0_surface.c | 151 ++++++++++++++++++++++++ > 1 file changed, 151 insertions(+) > > diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c > index 6b7c30c..3572193 100644 > --- a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c > +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c > @@ -345,6 +345,156 @@ nvc0_clear_render_target(struct pipe_context *pipe, > } > > static void > +nvc0_clear_buffer_cpu(struct pipe_context *pipe, > + struct pipe_resource *res, > + unsigned offset, unsigned size, > + const void *data, int data_size) > +{ > + struct nv04_resource *buf = nv04_resource(res); > + struct pipe_transfer *pt; > + struct pipe_box box; > + unsigned elements, i; > + > + elements = size / data_size; > + > + u_box_1d(0, size, &box); > + > + uint8_t *map = buf->vtbl->transfer_map(pipe, res, 0, PIPE_TRANSFER_WRITE, > + &box, &pt); > + > + for (i = 0; i < elements; ++i) > + memcpy(&map[i*data_size], data, data_size); > + > + buf->vtbl->transfer_unmap(pipe, pt); > +} > + > +static void > +nvc0_clear_buffer(struct pipe_context *pipe, > + struct pipe_resource *res, > + unsigned offset, unsigned size, > + const void *data, int data_size) > +{ > + struct nvc0_context *nvc0 = nvc0_context(pipe); > + struct nouveau_pushbuf *push = nvc0->base.pushbuf; > + struct nv04_resource *buf = nv04_resource(res); > + union pipe_color_union color; > + enum pipe_format dst_fmt; > + unsigned width, height, elements; > + > + assert(res->target == PIPE_BUFFER); > + assert(nouveau_bo_memtype(buf->bo) == 0); > + > + switch (data_size) { > + case 16: > + dst_fmt = PIPE_FORMAT_R32G32B32A32_UINT; > + memcpy(&color.ui, data, 16); > + break; > + case 12: > + /* > + * dst_fmt = PIPE_FORMAT_R32G32B32_UINT; > + * memcpy(&color.ui, data, 12); > + * memset(&color.ui[3], 0, 4); > + * break; > + */ > + case 8: > + dst_fmt = PIPE_FORMAT_R32G32_UINT; > + memcpy(&color.ui, data, 8); > + memset(&color.ui[2], 0, 8); > + break; > + case 4: > + dst_fmt = PIPE_FORMAT_R32_UINT; > + memcpy(&color.ui, data, 4); > + memset(&color.ui[1], 0, 12); > + break; > + case 2: > + dst_fmt = PIPE_FORMAT_R16_UINT; > + color.ui[0] = util_cpu_to_le32( > + util_le16_to_cpu(*(unsigned short *)data)); > + memset(&color.ui[1], 0, 12); > + break; > + case 1: > + dst_fmt = PIPE_FORMAT_R8_UINT; > + color.ui[0] = util_cpu_to_le32(*(unsigned char *)data); > + memset(&color.ui[1], 0, 12); > + break; > + default: > + assert(!"Unsupported element size"); > + return; > + } > + > + assert(size % data_size == 0); > + > + if (data_size == 12) { > + /* TODO: Find a way to do this with the GPU! */ > + nvc0_clear_buffer_cpu(pipe, res, offset, size, data, data_size); > + return; > + } > + > + elements = size / data_size; > + > + height = (elements + 16383) / 16384; > + > + width = elements / height; > + > + if (!PUSH_SPACE(push, 40)) > + return; > + > + PUSH_REFN (push, buf->bo, buf->domain | NOUVEAU_BO_WR); > + > + BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4); > + PUSH_DATAf(push, color.f[0]); > + PUSH_DATAf(push, color.f[1]); > + PUSH_DATAf(push, color.f[2]); > + PUSH_DATAf(push, color.f[3]); > + BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2); > + PUSH_DATA (push, width << 16); > + PUSH_DATA (push, height << 16); > + > + IMMED_NVC0(push, NVC0_3D(RT_CONTROL), 1); > + > + BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 9); > + PUSH_DATAh(push, buf->address + offset); > + PUSH_DATA (push, buf->address + offset); > + > + PUSH_DATA (push, width * data_size); > + PUSH_DATA (push, height); > + > + PUSH_DATA (push, nvc0_format_table[dst_fmt].rt); > + PUSH_DATA (push, 1 << 12); > + PUSH_DATA (push, 1); > + PUSH_DATA (push, 0); > + PUSH_DATA (push, 0); > + > + IMMED_NVC0(push, NVC0_3D(ZETA_ENABLE), 0); > + > + IMMED_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 0x3c); > + > + if (width * height != elements) { > + offset += width * height * data_size; > + width = elements - width * height; > + height = 1; > + > + BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2); > + PUSH_DATA (push, width << 16); > + PUSH_DATA (push, height << 16); > + > + BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 2); > + PUSH_DATAh(push, buf->address + offset); > + PUSH_DATA (push, buf->address + offset); > + > + BEGIN_NVC0(push, NVC0_3D(RT_HORIZ(0)), 2); > + PUSH_DATA (push, width * data_size); > + PUSH_DATA (push, height); > + > + IMMED_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 0x3c); > + } > + > + nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence); > + nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence_wr); > + nvc0->dirty |= NVC0_NEW_FRAMEBUFFER; > +} > + > +static void > nvc0_clear_depth_stencil(struct pipe_context *pipe, > struct pipe_surface *dst, > unsigned clear_flags, > @@ -1363,4 +1513,5 @@ nvc0_init_surface_functions(struct nvc0_context *nvc0) > pipe->flush_resource = nvc0_flush_resource; > pipe->clear_render_target = nvc0_clear_render_target; > pipe->clear_depth_stencil = nvc0_clear_depth_stencil; > + pipe->clear_buffer = nvc0_clear_buffer; > } > -- > 1.8.4.5 >
Seemingly Similar Threads
- [PATCH V2] nvc0: implement clear_buffer
- Implement buffer_clear for nvc0
- [PATCH] nvc0: Implement buffer_clear for this type of hardware
- [PATCH] nv50, nvc0: only clear out the buffers that we were asked to clear
- [PATCH] nv50, nvc0: don't crash on a null cbuf