1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26#include "main/glheader.h"
27#include "main/context.h"
28#include "main/imports.h"
29#include "main/format_pack.h"
30#include "main/format_unpack.h"
31#include "main/core.h"
32#include "main/stencil.h"
33
34#include "s_context.h"
35#include "s_depth.h"
36#include "s_stencil.h"
37#include "s_span.h"
38
39
40
41/* Stencil Logic:
42
43IF stencil test fails THEN
44   Apply fail-op to stencil value
45   Don't write the pixel (RGBA,Z)
46ELSE
47   IF doing depth test && depth test fails THEN
48      Apply zfail-op to stencil value
49      Write RGBA and Z to appropriate buffers
50   ELSE
51      Apply zpass-op to stencil value
52ENDIF
53
54*/
55
56
57
58/**
59 * Compute/return the offset of the stencil value in a pixel.
60 * For example, if the format is Z24+S8, the position of the stencil bits
61 * within the 4-byte pixel will be either 0 or 3.
62 */
63static GLint
64get_stencil_offset(mesa_format format)
65{
66   const GLubyte one = 1;
67   GLubyte pixel[MAX_PIXEL_BYTES];
68   GLint bpp = _mesa_get_format_bytes(format);
69   GLint i;
70
71   assert(_mesa_get_format_bits(format, GL_STENCIL_BITS) == 8);
72   memset(pixel, 0, sizeof(pixel));
73   _mesa_pack_ubyte_stencil_row(format, 1, &one, pixel);
74
75   for (i = 0; i < bpp; i++) {
76      if (pixel[i])
77         return i;
78   }
79
80   _mesa_problem(NULL, "get_stencil_offset() failed\n");
81   return 0;
82}
83
84
85/** Clamp the stencil value to [0, 255] */
86static inline GLubyte
87clamp(GLint val)
88{
89   if (val < 0)
90      return 0;
91   else if (val > 255)
92      return 255;
93   else
94      return val;
95}
96
97
98#define STENCIL_OP(NEW_VAL)                                                 \
99   if (invmask == 0) {                                                      \
100      for (i = j = 0; i < n; i++, j += stride) {                            \
101         if (mask[i]) {                                                     \
102            GLubyte s = stencil[j];                                         \
103            (void) s;                                                       \
104            stencil[j] = (GLubyte) (NEW_VAL);                               \
105         }                                                                  \
106      }                                                                     \
107   }                                                                        \
108   else {                                                                   \
109      for (i = j = 0; i < n; i++, j += stride) {                            \
110         if (mask[i]) {                                                     \
111            GLubyte s = stencil[j];                                         \
112            stencil[j] = (GLubyte) ((invmask & s) | (wrtmask & (NEW_VAL))); \
113         }                                                                  \
114      }                                                                     \
115   }
116
117
118/**
119 * Apply the given stencil operator to the array of stencil values.
120 * Don't touch stencil[i] if mask[i] is zero.
121 * @param n   number of stencil values
122 * @param oper  the stencil buffer operator
123 * @param face  0 or 1 for front or back face operation
124 * @param stencil  array of stencil values (in/out)
125 * @param mask  array [n] of flag:  1=apply operator, 0=don't apply operator
126 * @param stride  stride between stencil values
127 */
128static void
129apply_stencil_op(const struct gl_context *ctx, GLenum oper, GLuint face,
130                 GLuint n, GLubyte stencil[], const GLubyte mask[],
131                 GLint stride)
132{
133   const GLubyte ref = _mesa_get_stencil_ref(ctx, face);
134   const GLubyte wrtmask = ctx->Stencil.WriteMask[face];
135   const GLubyte invmask = (GLubyte) (~wrtmask);
136   GLuint i, j;
137
138   switch (oper) {
139   case GL_KEEP:
140      /* do nothing */
141      break;
142   case GL_ZERO:
143      /* replace stencil buf values with zero */
144      STENCIL_OP(0);
145      break;
146   case GL_REPLACE:
147      /* replace stencil buf values with ref value */
148      STENCIL_OP(ref);
149      break;
150   case GL_INCR:
151      /* increment stencil buf values, with clamping */
152      STENCIL_OP(clamp(s + 1));
153      break;
154   case GL_DECR:
155      /* increment stencil buf values, with clamping */
156      STENCIL_OP(clamp(s - 1));
157      break;
158   case GL_INCR_WRAP_EXT:
159      /* increment stencil buf values, without clamping */
160      STENCIL_OP(s + 1);
161      break;
162   case GL_DECR_WRAP_EXT:
163      /* increment stencil buf values, without clamping */
164      STENCIL_OP(s - 1);
165      break;
166   case GL_INVERT:
167      /* replace stencil buf values with inverted value */
168      STENCIL_OP(~s);
169      break;
170   default:
171      _mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
172   }
173}
174
175
176
177#define STENCIL_TEST(FUNC)                        \
178   for (i = j = 0; i < n; i++, j += stride) {     \
179      if (mask[i]) {                              \
180         s = (GLubyte) (stencil[j] & valueMask);  \
181         if (FUNC) {                              \
182            /* stencil pass */                    \
183            fail[i] = 0;                          \
184         }                                        \
185         else {                                   \
186            /* stencil fail */                    \
187            fail[i] = 1;                          \
188            mask[i] = 0;                          \
189         }                                        \
190      }                                           \
191      else {                                      \
192         fail[i] = 0;                             \
193      }                                           \
194   }
195
196
197
198/**
199 * Apply stencil test to an array of stencil values (before depth buffering).
200 * For the values that fail, we'll apply the GL_STENCIL_FAIL operator to
201 * the stencil values.
202 *
203 * @param face  0 or 1 for front or back-face polygons
204 * @param n  number of pixels in the array
205 * @param stencil  array of [n] stencil values (in/out)
206 * @param mask  array [n] of flag:  0=skip the pixel, 1=stencil the pixel,
207 *              values are set to zero where the stencil test fails.
208 * @param stride  stride between stencil values
209 * @return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
210 */
211static GLboolean
212do_stencil_test(struct gl_context *ctx, GLuint face, GLuint n,
213                GLubyte stencil[], GLubyte mask[], GLint stride)
214{
215   SWcontext *swrast = SWRAST_CONTEXT(ctx);
216   GLubyte *fail = swrast->stencil_temp.buf2;
217   GLboolean allfail = GL_FALSE;
218   GLuint i, j;
219   const GLuint valueMask = ctx->Stencil.ValueMask[face];
220   const GLubyte ref = (GLubyte) (_mesa_get_stencil_ref(ctx, face) & valueMask);
221   GLubyte s;
222
223   /*
224    * Perform stencil test.  The results of this operation are stored
225    * in the fail[] array:
226    *   IF fail[i] is non-zero THEN
227    *       the stencil fail operator is to be applied
228    *   ELSE
229    *       the stencil fail operator is not to be applied
230    *   ENDIF
231    */
232   switch (ctx->Stencil.Function[face]) {
233   case GL_NEVER:
234      STENCIL_TEST(0);
235      allfail = GL_TRUE;
236      break;
237   case GL_LESS:
238      STENCIL_TEST(ref < s);
239      break;
240   case GL_LEQUAL:
241      STENCIL_TEST(ref <= s);
242      break;
243   case GL_GREATER:
244      STENCIL_TEST(ref > s);
245      break;
246   case GL_GEQUAL:
247      STENCIL_TEST(ref >= s);
248      break;
249   case GL_EQUAL:
250      STENCIL_TEST(ref == s);
251      break;
252   case GL_NOTEQUAL:
253      STENCIL_TEST(ref != s);
254      break;
255   case GL_ALWAYS:
256      STENCIL_TEST(1);
257      break;
258   default:
259      _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
260      return 0;
261   }
262
263   if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
264      apply_stencil_op(ctx, ctx->Stencil.FailFunc[face], face, n, stencil,
265                       fail, stride);
266   }
267
268   return !allfail;
269}
270
271
272/**
273 * Compute the zpass/zfail masks by comparing the pre- and post-depth test
274 * masks.
275 */
276static inline void
277compute_pass_fail_masks(GLuint n, const GLubyte origMask[],
278                        const GLubyte newMask[],
279                        GLubyte passMask[], GLubyte failMask[])
280{
281   GLuint i;
282   for (i = 0; i < n; i++) {
283      assert(newMask[i] == 0 || newMask[i] == 1);
284      passMask[i] = origMask[i] & newMask[i];
285      failMask[i] = origMask[i] & (newMask[i] ^ 1);
286   }
287}
288
289
290/**
291 * Get 8-bit stencil values from random locations in the stencil buffer.
292 */
293static void
294get_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
295              GLuint count, const GLint x[], const GLint y[],
296              GLubyte stencil[])
297{
298   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
299   const GLint w = rb->Width, h = rb->Height;
300   const GLubyte *map = _swrast_pixel_address(rb, 0, 0);
301   GLuint i;
302
303   if (rb->Format == MESA_FORMAT_S_UINT8) {
304      const GLint rowStride = srb->RowStride;
305      for (i = 0; i < count; i++) {
306         if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
307            stencil[i] = *(map + y[i] * rowStride + x[i]);
308         }
309      }
310   }
311   else {
312      const GLint bpp = _mesa_get_format_bytes(rb->Format);
313      const GLint rowStride = srb->RowStride;
314      for (i = 0; i < count; i++) {
315         if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
316            const GLubyte *src = map + y[i] * rowStride + x[i] * bpp;
317            _mesa_unpack_ubyte_stencil_row(rb->Format, 1, src, &stencil[i]);
318         }
319      }
320   }
321}
322
323
324/**
325 * Put 8-bit stencil values at random locations into the stencil buffer.
326 */
327static void
328put_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
329              GLuint count, const GLint x[], const GLint y[],
330              const GLubyte stencil[])
331{
332   const GLint w = rb->Width, h = rb->Height;
333   gl_pack_ubyte_stencil_func pack_stencil =
334      _mesa_get_pack_ubyte_stencil_func(rb->Format);
335   GLuint i;
336
337   for (i = 0; i < count; i++) {
338      if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
339         GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]);
340         pack_stencil(&stencil[i], dst);
341      }
342   }
343}
344
345
346/**
347 * /return GL_TRUE = one or more fragments passed,
348 * GL_FALSE = all fragments failed.
349 */
350GLboolean
351_swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span)
352{
353   SWcontext *swrast = SWRAST_CONTEXT(ctx);
354   struct gl_framebuffer *fb = ctx->DrawBuffer;
355   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
356   const GLint stencilOffset = get_stencil_offset(rb->Format);
357   const GLint stencilStride = _mesa_get_format_bytes(rb->Format);
358   const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
359   const GLuint count = span->end;
360   GLubyte *mask = span->array->mask;
361   GLubyte *stencilTemp = swrast->stencil_temp.buf1;
362   GLubyte *stencilBuf;
363
364   if (span->arrayMask & SPAN_XY) {
365      /* read stencil values from random locations */
366      get_s8_values(ctx, rb, count, span->array->x, span->array->y,
367                    stencilTemp);
368      stencilBuf = stencilTemp;
369   }
370   else {
371      /* Processing a horizontal run of pixels.  Since stencil is always
372       * 8 bits for all MESA_FORMATs, we just need to use the right offset
373       * and stride to access them.
374       */
375      stencilBuf = _swrast_pixel_address(rb, span->x, span->y) + stencilOffset;
376   }
377
378   /*
379    * Apply the stencil test to the fragments.
380    * failMask[i] is 1 if the stencil test failed.
381    */
382   if (!do_stencil_test(ctx, face, count, stencilBuf, mask, stencilStride)) {
383      /* all fragments failed the stencil test, we're done. */
384      span->writeAll = GL_FALSE;
385      if (span->arrayMask & SPAN_XY) {
386         /* need to write the updated stencil values back to the buffer */
387         put_s8_values(ctx, rb, count, span->array->x, span->array->y,
388                       stencilTemp);
389      }
390      return GL_FALSE;
391   }
392
393   /*
394    * Some fragments passed the stencil test, apply depth test to them
395    * and apply Zpass and Zfail stencil ops.
396    */
397   if (ctx->Depth.Test == GL_FALSE ||
398       ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer == NULL) {
399      /*
400       * No depth buffer, just apply zpass stencil function to active pixels.
401       */
402      apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, count,
403                       stencilBuf, mask, stencilStride);
404   }
405   else {
406      /*
407       * Perform depth buffering, then apply zpass or zfail stencil function.
408       */
409      SWcontext *swrast = SWRAST_CONTEXT(ctx);
410      GLubyte *passMask = swrast->stencil_temp.buf2;
411      GLubyte *failMask = swrast->stencil_temp.buf3;
412      GLubyte *origMask = swrast->stencil_temp.buf4;
413
414      /* save the current mask bits */
415      memcpy(origMask, mask, count * sizeof(GLubyte));
416
417      /* apply the depth test */
418      _swrast_depth_test_span(ctx, span);
419
420      compute_pass_fail_masks(count, origMask, mask, passMask, failMask);
421
422      /* apply the pass and fail operations */
423      if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
424         apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
425                          count, stencilBuf, failMask, stencilStride);
426      }
427      if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
428         apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
429                          count, stencilBuf, passMask, stencilStride);
430      }
431   }
432
433   /* Write updated stencil values back into hardware stencil buffer */
434   if (span->arrayMask & SPAN_XY) {
435      put_s8_values(ctx, rb, count, span->array->x, span->array->y,
436                    stencilBuf);
437   }
438
439   span->writeAll = GL_FALSE;
440
441   return GL_TRUE;  /* one or more fragments passed both tests */
442}
443
444
445
446
447/**
448 * Return a span of stencil values from the stencil buffer.
449 * Used for glRead/CopyPixels
450 * Input:  n - how many pixels
451 *         x,y - location of first pixel
452 * Output:  stencil - the array of stencil values
453 */
454void
455_swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
456                          GLint n, GLint x, GLint y, GLubyte stencil[])
457{
458   GLubyte *src;
459
460   if (y < 0 || y >= (GLint) rb->Height ||
461       x + n <= 0 || x >= (GLint) rb->Width) {
462      /* span is completely outside framebuffer */
463      return; /* undefined values OK */
464   }
465
466   if (x < 0) {
467      GLint dx = -x;
468      x = 0;
469      n -= dx;
470      stencil += dx;
471   }
472   if (x + n > (GLint) rb->Width) {
473      GLint dx = x + n - rb->Width;
474      n -= dx;
475   }
476   if (n <= 0) {
477      return;
478   }
479
480   src = _swrast_pixel_address(rb, x, y);
481   _mesa_unpack_ubyte_stencil_row(rb->Format, n, src, stencil);
482}
483
484
485
486/**
487 * Write a span of stencil values to the stencil buffer.  This function
488 * applies the stencil write mask when needed.
489 * Used for glDraw/CopyPixels
490 * Input:  n - how many pixels
491 *         x, y - location of first pixel
492 *         stencil - the array of stencil values
493 */
494void
495_swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y,
496                           const GLubyte stencil[] )
497{
498   SWcontext *swrast = SWRAST_CONTEXT(ctx);
499   struct gl_framebuffer *fb = ctx->DrawBuffer;
500   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
501   const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
502   const GLuint stencilMask = ctx->Stencil.WriteMask[0];
503   GLubyte *stencilBuf;
504
505   if (y < 0 || y >= (GLint) rb->Height ||
506       x + n <= 0 || x >= (GLint) rb->Width) {
507      /* span is completely outside framebuffer */
508      return; /* undefined values OK */
509   }
510   if (x < 0) {
511      GLint dx = -x;
512      x = 0;
513      n -= dx;
514      stencil += dx;
515   }
516   if (x + n > (GLint) rb->Width) {
517      GLint dx = x + n - rb->Width;
518      n -= dx;
519   }
520   if (n <= 0) {
521      return;
522   }
523
524   stencilBuf = _swrast_pixel_address(rb, x, y);
525
526   if ((stencilMask & stencilMax) != stencilMax) {
527      /* need to apply writemask */
528      GLubyte *destVals = swrast->stencil_temp.buf1;
529      GLubyte *newVals = swrast->stencil_temp.buf2;
530      GLint i;
531
532      _mesa_unpack_ubyte_stencil_row(rb->Format, n, stencilBuf, destVals);
533      for (i = 0; i < n; i++) {
534         newVals[i]
535            = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
536      }
537      _mesa_pack_ubyte_stencil_row(rb->Format, n, newVals, stencilBuf);
538   }
539   else {
540      _mesa_pack_ubyte_stencil_row(rb->Format, n, stencil, stencilBuf);
541   }
542}
543
544
545
546/**
547 * Clear the stencil buffer.  If the buffer is a combined
548 * depth+stencil buffer, only the stencil bits will be touched.
549 */
550void
551_swrast_clear_stencil_buffer(struct gl_context *ctx)
552{
553   struct gl_renderbuffer *rb =
554      ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
555   const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
556   const GLuint writeMask = ctx->Stencil.WriteMask[0];
557   const GLuint stencilMax = (1 << stencilBits) - 1;
558   GLint x, y, width, height;
559   GLubyte *map;
560   GLint rowStride, i, j;
561   GLbitfield mapMode;
562
563   if (!rb || writeMask == 0)
564      return;
565
566   /* compute region to clear */
567   x = ctx->DrawBuffer->_Xmin;
568   y = ctx->DrawBuffer->_Ymin;
569   width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
570   height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
571
572   mapMode = GL_MAP_WRITE_BIT;
573   if ((writeMask & stencilMax) != stencilMax) {
574      /* need to mask stencil values */
575      mapMode |= GL_MAP_READ_BIT;
576   }
577   else if (_mesa_get_format_bits(rb->Format, GL_DEPTH_BITS) > 0) {
578      /* combined depth+stencil, need to mask Z values */
579      mapMode |= GL_MAP_READ_BIT;
580   }
581
582   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
583                               mapMode, &map, &rowStride);
584   if (!map) {
585      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(stencil)");
586      return;
587   }
588
589   switch (rb->Format) {
590   case MESA_FORMAT_S_UINT8:
591      {
592         GLubyte clear = ctx->Stencil.Clear & writeMask & 0xff;
593         GLubyte mask = (~writeMask) & 0xff;
594         if (mask != 0) {
595            /* masked clear */
596            for (i = 0; i < height; i++) {
597               GLubyte *row = map;
598               for (j = 0; j < width; j++) {
599                  row[j] = (row[j] & mask) | clear;
600               }
601               map += rowStride;
602            }
603         }
604         else if (rowStride == width) {
605            /* clear whole buffer */
606            memset(map, clear, width * height);
607         }
608         else {
609            /* clear scissored */
610            for (i = 0; i < height; i++) {
611               memset(map, clear, width);
612               map += rowStride;
613            }
614         }
615      }
616      break;
617   case MESA_FORMAT_Z24_UNORM_S8_UINT:
618      {
619         GLuint clear = (ctx->Stencil.Clear & writeMask & 0xff) << 24;
620         GLuint mask = (((~writeMask) & 0xff) << 24) | 0xffffff;
621         for (i = 0; i < height; i++) {
622            GLuint *row = (GLuint *) map;
623            for (j = 0; j < width; j++) {
624               row[j] = (row[j] & mask) | clear;
625            }
626            map += rowStride;
627         }
628      }
629      break;
630   case MESA_FORMAT_S8_UINT_Z24_UNORM:
631      {
632         GLuint clear = ctx->Stencil.Clear & writeMask & 0xff;
633         GLuint mask = 0xffffff00 | ((~writeMask) & 0xff);
634         for (i = 0; i < height; i++) {
635            GLuint *row = (GLuint *) map;
636            for (j = 0; j < width; j++) {
637               row[j] = (row[j] & mask) | clear;
638            }
639            map += rowStride;
640         }
641      }
642      break;
643   default:
644      _mesa_problem(ctx, "Unexpected stencil buffer format %s"
645                    " in _swrast_clear_stencil_buffer()",
646                    _mesa_get_format_name(rb->Format));
647   }
648
649   ctx->Driver.UnmapRenderbuffer(ctx, rb);
650}
651