[Mesa-dev] [PATCH 1/3] swrast: do depth/stencil clearing with Map/UnmapRenderbuffer()

Brian Paul brian.e.paul at gmail.com
Mon Dec 12 10:35:54 PST 2011


On Mon, Dec 12, 2011 at 10:28 AM, Eric Anholt <eric at anholt.net> wrote:
> On Sat, 10 Dec 2011 12:00:52 -0700, Brian Paul <brianp at vmware.com> wrote:
>> Another step toward getting rid of the renderbuffer PutRow/etc functions.
>
>> +   if (buffers & BUFFER_DS) {
>> +      struct gl_renderbuffer *rb =
>> +         ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
>> +
>> +      if ((buffers & BUFFER_DS) == BUFFER_DS && rb &&
>> +          _mesa_is_format_packed_depth_stencil(rb->Format)) {
>> +         /* clear depth and stencil together */
>> +         _swrast_clear_depth_stencil_buffer(ctx);
>
> I think this would be wrong for the case of
>
> Attachment[BUFFER_DEPTH] = depthstencil texture
> Attachment[BUFFER_STENCIL = separate stencil RB
>
> Granted, that's a pretty crazy setup, but I think this just needs an rb
> == Attachment[BUFFER_STENCIL].Renderbuffer check.

Will do.


>> +   mapMode = GL_MAP_WRITE_BIT;
>> +   if (_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0) {
>> +      mapMode |= GL_MAP_READ_BIT;
>> +   }
>
> You only set the READ bit if there are stencil bits...
>
>> +   case MESA_FORMAT_S8_Z24:
>> +   case MESA_FORMAT_X8_Z24:
>> +   case MESA_FORMAT_Z24_S8:
>> +   case MESA_FORMAT_Z24_X8:
>
>>           for (i = 0; i < height; i++) {
>> -            rb->PutMonoRow(ctx, rb, width, x, y + i, &clearVal16, NULL);
>> +            GLuint *row = (GLuint *) map;
>> +            for (j = 0; j < width; j++) {
>> +               row[j] = (row[j] & mask) | clearVal;
>> +            }
>> +            map += rowStride;
>>           }
>> +
>
> but then the S8_Z24 and X8_Z24 paths both do the same set of reads.
>
>> +   case MESA_FORMAT_Z32_FLOAT_X24S8:
>> +      /* XXX untested */
>> +      {
>> +         GLfloat clearVal = (GLfloat) ctx->Depth.Clear;
>>           for (i = 0; i < height; i++) {
>> -            rb->PutMonoRow(ctx, rb, width, x, y + i, &clearValue, NULL);
>> +            GLfloat *row = (GLfloat *) map;
>> +            for (j = 0; j < width; j++) {
>> +               row[j * 2] = clearVal;
>> +            }
>> +            map += rowStride;
>>           }
>
> It looks good, at least.  Once I land my outstanding driver bits it
> should be easy to test.
>
>> +/**
>> + * Clear both depth and stencil values in a combined depth+stencil buffer.
>> + */
>> +void
>> +_swrast_clear_depth_stencil_buffer(struct gl_context *ctx)
>> +{
>
>> +   case MESA_FORMAT_Z32_FLOAT_X24S8:
>> +      /* XXX untested */
>> +      {
>> +         GLfloat zClear = (GLfloat) ctx->Depth.Clear;
>> +         GLuint sClear = ctx->Stencil.Clear;
>> +         for (i = 0; i < height; i++) {
>> +            GLfloat *zRow = (GLfloat *) map;
>> +            GLuint *sRow = (GLuint *) map;
>> +            for (j = 0; j < width; j++) {
>> +               zRow[j * 2 + 0] = zClear;
>> +            }
>> +            for (j = 0; j < width; j++) {
>> +               sRow[j * 2 + 1] = sClear;
>> +            }
>
> Missing stencil mask treatment.

Will fix.


>> diff --git a/src/mesa/swrast/s_stencil.c b/src/mesa/swrast/s_stencil.c
>> index 101ee50..5c5ebd4 100644
>> --- a/src/mesa/swrast/s_stencil.c
>> +++ b/src/mesa/swrast/s_stencil.c
>> @@ -1124,121 +1124,108 @@ _swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y,
>>
>>
>>  /**
>> - * Clear the stencil buffer.
>> + * Clear the stencil buffer.  If the buffer is a combined
>> + * depth+stencil buffer, only the stencil bits will be touched.
>>   */
>>  void
>> -_swrast_clear_stencil_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb )
>> +_swrast_clear_stencil_buffer(struct gl_context *ctx)
>>  {
>> +   struct gl_renderbuffer *rb =
>> +      ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
>>     const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
>> -   const GLuint mask = ctx->Stencil.WriteMask[0];
>> -   const GLuint invMask = ~mask;
>> -   const GLuint clearVal = (ctx->Stencil.Clear & mask);
>> +   const GLuint writeMask = ctx->Stencil.WriteMask[0];
>> +   const GLuint clearVal = (ctx->Stencil.Clear & writeMask);
>>     const GLuint stencilMax = (1 << stencilBits) - 1;
>>     GLint x, y, width, height;
>> +   GLubyte *map;
>> +   GLint rowStride, i, j;
>> +   GLbitfield mapMode;
>
>> +   mapMode = GL_MAP_WRITE_BIT;
>> +   if ((writeMask & stencilMax) != stencilMax) {
>> +      /* need to mask stencil values */
>> +      mapMode |= GL_MAP_READ_BIT;
>> +   }
>> +   else if (_mesa_get_format_bits(rb->Format, GL_DEPTH_BITS) > 0) {
>> +      /* combined depth+stencil, need to mask Z values */
>> +      mapMode |= GL_MAP_READ_BIT;
>> +   }
>
>> +   switch (rb->Format) {
>> +   case MESA_FORMAT_S8:
>> +      {
>> +         GLubyte clear = clearVal & 0xff;
>> +         GLubyte mask = (~writeMask) & 0xff;
>> +         if (mask != 0) {
>
> mask != 0xff, right?  0 was already tested at the top, and there's that
> else case below.

I think I have that right.  mask is the complement of the stencil
WriteMask value here.  And if mask==0 it means that we're replacing
the dest values completely.  That's what the else clauses do.


>> -                  _mesa_memset16((short unsigned int*) stencil, clearVal, width);
>
> note, _mesa_memset16 is dead code now.

OK, I'll rm that later.

-Brian


More information about the mesa-dev mailing list