Christoph
2009-Apr-08 21:26 UTC
[Nouveau] [PATCH/Gallium] nv50: update nv50_clear to new interface
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
Apparently Analagous Threads
- [PATCH/Gallium] nv50_clear again (might work better)
- [PATCH] Fix surface_fill alpha
- [Mesa-dev] [PATCH] nv50, nvc0: only clear out the buffers that we were asked to clear
- [Mesa-dev] [PATCH] nv50, nvc0: only clear out the buffers that we were asked to clear
- [PATCH] nv50, nvc0: only clear out the buffers that we were asked to clear