[Nouveau] [PATCH/Gallium] nv50: update nv50_clear to new interface
Christoph
e0425955 at student.tuwien.ac.at
Wed Apr 8 14:26:16 PDT 2009
Commit eb168e26aa63f11a47d70c4555cae30691a2cd57 changed the way
pipe->clear works so I figured I'd try to make an updated version, so
below is the diff - my concerns/uncertainties should be contained in
the comments.
Or maybe you want to do it the way NV40 does it, just calling
surface_fill through a utility function (althoug this does currently
seem to only clear one color buffer) . I'll have a look at my REnouveau
dumps to see if there are push buffer commands to clear buffers of the
other formats, though I'll most probably fail. And I expect you
probably have another/better implementation, but here's my try (I still
need to learn a lot, I hope there are no new bugs at least):
---
src/gallium/drivers/nv50/nv50_clear.c | 85 ++++++++++++++++++++++----------
1 files changed, 58 insertions(+), 27 deletions(-)
diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c
index db44a9d..45d0a00 100644
--- a/src/gallium/drivers/nv50/nv50_clear.c
+++ b/src/gallium/drivers/nv50/nv50_clear.c
@@ -26,10 +26,15 @@
#include "nv50_context.h"
+#include "util/u_pack_color.h"
+
void
-nv50_clear(struct pipe_context *pipe, struct pipe_surface *ps,
- unsigned clearValue)
+nv50_clear(struct pipe_context *pipe, unsigned buffers,
+ const float *rgba, double depth, unsigned stencil)
{
+ struct pipe_surface *ps = NULL;
+ /* silenced 'used uninitialized' warning by setting NULL,
+ * GCC doesn't know it can't actually happen */
struct nv50_context *nv50 = nv50_context(pipe);
struct nouveau_channel *chan = nv50->screen->nvws->channel;
struct nouveau_grobj *tesla = nv50->screen->tesla;
@@ -37,21 +42,45 @@ nv50_clear(struct pipe_context *pipe, struct pipe_surface *ps,
struct pipe_scissor_state sc, s_sc = nv50->scissor;
unsigned dirty = nv50->dirty;
+ /* if 'no buffers' case is possible, change this to if/return */
+ assert(buffers && (s_fb.nr_cbufs > 0 || s_fb.zsbuf != NULL));
+
nv50->dirty = 0;
+ fb.nr_cbufs = 0;
- if (ps->format == PIPE_FORMAT_Z24S8_UNORM ||
- ps->format == PIPE_FORMAT_Z16_UNORM) {
- fb.nr_cbufs = 0;
- fb.zsbuf = ps;
+ if (buffers & PIPE_CLEAR_COLOR) {
+ /* Should we clear all color buffers (nv40 doesn't), clear_with_quad
+ * from the mesa state tracker seems to ? */
+ for (unsigned i = 0; i < s_fb.nr_cbufs; ++i) {
+ unsigned color;
+ ps = s_fb.cbufs[i];
+
+ if (ps->format == PIPE_FORMAT_A8R8G8B8_UNORM) {
+ fb.cbufs[fb.nr_cbufs++] = ps;
+ } else {
+ util_pack_color(rgba, ps->format, &color);
+ pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height,
+ color);
+ }
+ }
+ }
+
+ if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
+ ps = fb.zsbuf = s_fb.zsbuf;
} else {
- fb.nr_cbufs = 1;
- fb.cbufs[0] = ps;
fb.zsbuf = NULL;
}
+
+ /* actually this can't happen, so initializing ps to NULL isn't
+ * really necessary as well */
+ assert(ps);
+
fb.width = ps->width;
fb.height = ps->height;
pipe->set_framebuffer_state(pipe, &fb);
+ /* XXX: mesa state tracker does clear_with_quad if scissor is enabled,
+ * so this is probably unnecessary (?) */
sc.minx = sc.miny = 0;
sc.maxx = fb.width;
sc.maxy = fb.height;
@@ -59,28 +88,30 @@ nv50_clear(struct pipe_context *pipe, struct pipe_surface *ps,
nv50_state_validate(nv50);
- switch (ps->format) {
- case PIPE_FORMAT_A8R8G8B8_UNORM:
+ if (fb.nr_cbufs > 0) {
+ /* Does this clear all color buffers ? */
BEGIN_RING(chan, tesla, 0x0d80, 4);
- OUT_RINGf (chan, ubyte_to_float((clearValue >> 16) & 0xff));
- OUT_RINGf (chan, ubyte_to_float((clearValue >> 8) & 0xff));
- OUT_RINGf (chan, ubyte_to_float((clearValue >> 0) & 0xff));
- OUT_RINGf (chan, ubyte_to_float((clearValue >> 24) & 0xff));
+ OUT_RINGf (chan, rgba[0]);
+ OUT_RINGf (chan, rgba[1]);
+ OUT_RINGf (chan, rgba[2]);
+ OUT_RINGf (chan, rgba[3]);
BEGIN_RING(chan, tesla, 0x19d0, 1);
OUT_RING (chan, 0x3c);
- break;
- case PIPE_FORMAT_Z24S8_UNORM:
- BEGIN_RING(chan, tesla, 0x0d90, 1);
- OUT_RINGf (chan, (float)(clearValue >> 8) * (1.0 / 16777215.0));
- BEGIN_RING(chan, tesla, 0x0da0, 1);
- OUT_RING (chan, clearValue & 0xff);
- BEGIN_RING(chan, tesla, 0x19d0, 1);
- OUT_RING (chan, 0x03);
- break;
- default:
- pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height,
- clearValue);
- break;
+ }
+
+ if (fb.zsbuf) {
+ if (ps->format == PIPE_FORMAT_Z24S8_UNORM) {
+ BEGIN_RING(chan, tesla, 0x0d90, 1);
+ OUT_RINGf (chan, (float)depth);
+ BEGIN_RING(chan, tesla, 0x0da0, 1);
+ OUT_RING (chan, stencil);
+ BEGIN_RING(chan, tesla, 0x19d0, 1);
+ OUT_RING (chan, 0x03);
+ } else {
+ /* ps has been set to zsbuf above if we get here */
+ pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height,
+ util_pack_z_stencil(ps->format, depth, stencil));
+ }
}
pipe->set_framebuffer_state(pipe, &s_fb);
--
1.6.0.6
More information about the Nouveau
mailing list