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