2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
30 #include "depthstencil.h"
31 #include "renderbuffer.h"
35 * Adaptor/wrappers for GL_DEPTH_STENCIL renderbuffers.
37 * The problem with a GL_DEPTH_STENCIL renderbuffer is that sometimes we
38 * want to treat it as a stencil buffer, other times we want to treat it
39 * as a depth/z buffer and still other times when we want to treat it as
40 * a combined Z+stencil buffer! That implies we need three different sets
41 * of Get/Put functions.
43 * We solve this by wrapping the Z24_S8 or S8_Z24 renderbuffer with depth and
44 * stencil adaptors, each with the right kind of depth/stencil Get/Put functions.
49 nop_get_pointer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
60 * Delete a depth or stencil wrapper renderbuffer.
63 delete_wrapper(struct gl_renderbuffer *rb)
65 ASSERT(rb->Format == MESA_FORMAT_S8 ||
66 rb->Format == MESA_FORMAT_X8_Z24);
67 _mesa_reference_renderbuffer(&rb->Wrapped, NULL);
73 * Realloc storage for wrapper.
76 alloc_wrapper_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
77 GLenum internalFormat, GLuint width, GLuint height)
79 /* just pass this on to the wrapped renderbuffer */
80 struct gl_renderbuffer *dsrb = rb->Wrapped;
83 (void) internalFormat;
85 ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
86 dsrb->Format == MESA_FORMAT_Z24_X8 ||
87 dsrb->Format == MESA_FORMAT_S8_Z24 ||
88 dsrb->Format == MESA_FORMAT_X8_Z24);
90 retVal = dsrb->AllocStorage(ctx, dsrb, dsrb->InternalFormat, width, height);
94 rb->RowStride = dsrb->RowStride;
102 /*======================================================================
103 * Depth wrapper around depth/stencil renderbuffer
107 get_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
108 GLint x, GLint y, void *values)
110 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
111 GLuint temp[MAX_WIDTH], i;
112 GLuint *dst = (GLuint *) values;
113 const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
114 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
115 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
117 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
120 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
121 for (i = 0; i < count; i++) {
122 dst[i] = src[i] >> 8;
126 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
127 for (i = 0; i < count; i++) {
128 dst[i] = src[i] & 0xffffff;
134 get_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
135 const GLint x[], const GLint y[], void *values)
137 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
138 GLuint temp[MAX_WIDTH], i;
139 GLuint *dst = (GLuint *) values;
140 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
141 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
142 ASSERT(count <= MAX_WIDTH);
143 /* don't bother trying direct access */
144 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
145 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
146 for (i = 0; i < count; i++) {
147 dst[i] = temp[i] >> 8;
151 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
152 for (i = 0; i < count; i++) {
153 dst[i] = temp[i] & 0xffffff;
159 put_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
160 GLint x, GLint y, const void *values, const GLubyte *mask)
162 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
163 const GLuint *src = (const GLuint *) values;
164 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
165 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
166 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
170 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
171 for (i = 0; i < count; i++) {
172 if (!mask || mask[i]) {
173 dst[i] = (src[i] << 8) | (dst[i] & 0xff);
178 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
179 for (i = 0; i < count; i++) {
180 if (!mask || mask[i]) {
181 dst[i] = (src[i] & 0xffffff) | (dst[i] & 0xff000000);
187 /* get, modify, put */
188 GLuint temp[MAX_WIDTH], i;
189 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
190 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
191 for (i = 0; i < count; i++) {
192 if (!mask || mask[i]) {
193 temp[i] = (src[i] << 8) | (temp[i] & 0xff);
198 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
199 for (i = 0; i < count; i++) {
200 if (!mask || mask[i]) {
201 temp[i] = (src[i] & 0xffffff) | (temp[i] & 0xff000000);
205 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
210 put_mono_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
211 GLint x, GLint y, const void *value, const GLubyte *mask)
213 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
214 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
215 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
216 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
220 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
221 const GLuint shiftedVal = *((GLuint *) value) << 8;
222 for (i = 0; i < count; i++) {
223 if (!mask || mask[i]) {
224 dst[i] = shiftedVal | (dst[i] & 0xff);
229 const GLuint shiftedVal = *((GLuint *) value);
230 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
231 for (i = 0; i < count; i++) {
232 if (!mask || mask[i]) {
233 dst[i] = shiftedVal | (dst[i] & 0xff000000);
239 /* get, modify, put */
240 GLuint temp[MAX_WIDTH], i;
241 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
242 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
243 const GLuint shiftedVal = *((GLuint *) value) << 8;
244 for (i = 0; i < count; i++) {
245 if (!mask || mask[i]) {
246 temp[i] = shiftedVal | (temp[i] & 0xff);
251 const GLuint shiftedVal = *((GLuint *) value);
252 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
253 for (i = 0; i < count; i++) {
254 if (!mask || mask[i]) {
255 temp[i] = shiftedVal | (temp[i] & 0xff000000);
259 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
264 put_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
265 const GLint x[], const GLint y[],
266 const void *values, const GLubyte *mask)
268 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
269 const GLuint *src = (const GLuint *) values;
270 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
271 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
272 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
275 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
276 for (i = 0; i < count; i++) {
277 if (!mask || mask[i]) {
278 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
279 *dst = (src[i] << 8) | (*dst & 0xff);
284 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
285 for (i = 0; i < count; i++) {
286 if (!mask || mask[i]) {
287 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
288 *dst = (src[i] & 0xffffff) | (*dst & 0xff000000);
294 /* get, modify, put */
295 GLuint temp[MAX_WIDTH], i;
296 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
297 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
298 for (i = 0; i < count; i++) {
299 if (!mask || mask[i]) {
300 temp[i] = (src[i] << 8) | (temp[i] & 0xff);
305 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
306 for (i = 0; i < count; i++) {
307 if (!mask || mask[i]) {
308 temp[i] = (src[i] & 0xffffff) | (temp[i] & 0xff000000);
312 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
317 put_mono_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb,
318 GLuint count, const GLint x[], const GLint y[],
319 const void *value, const GLubyte *mask)
321 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
322 GLuint temp[MAX_WIDTH], i;
323 /* get, modify, put */
324 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
325 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
326 const GLuint shiftedVal = *((GLuint *) value) << 8;
327 for (i = 0; i < count; i++) {
328 if (!mask || mask[i]) {
329 temp[i] = shiftedVal | (temp[i] & 0xff);
334 const GLuint shiftedVal = *((GLuint *) value);
335 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
336 for (i = 0; i < count; i++) {
337 if (!mask || mask[i]) {
338 temp[i] = shiftedVal | (temp[i] & 0xff000000);
342 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
347 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
348 * a depth renderbuffer.
349 * \return new depth renderbuffer
351 struct gl_renderbuffer *
352 _mesa_new_z24_renderbuffer_wrapper(struct gl_context *ctx,
353 struct gl_renderbuffer *dsrb)
355 struct gl_renderbuffer *z24rb;
357 ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
358 dsrb->Format == MESA_FORMAT_Z24_X8 ||
359 dsrb->Format == MESA_FORMAT_S8_Z24 ||
360 dsrb->Format == MESA_FORMAT_X8_Z24);
361 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
363 z24rb = ctx->Driver.NewRenderbuffer(ctx, 0);
367 /* NOTE: need to do manual refcounting here */
368 z24rb->Wrapped = dsrb;
371 z24rb->Name = dsrb->Name;
373 z24rb->Width = dsrb->Width;
374 z24rb->Height = dsrb->Height;
375 z24rb->RowStride = dsrb->RowStride;
376 z24rb->InternalFormat = GL_DEPTH_COMPONENT24;
377 z24rb->Format = MESA_FORMAT_X8_Z24;
378 z24rb->_BaseFormat = GL_DEPTH_COMPONENT;
379 z24rb->DataType = GL_UNSIGNED_INT;
381 z24rb->Delete = delete_wrapper;
382 z24rb->AllocStorage = alloc_wrapper_storage;
383 z24rb->GetPointer = nop_get_pointer;
384 z24rb->GetRow = get_row_z24;
385 z24rb->GetValues = get_values_z24;
386 z24rb->PutRow = put_row_z24;
387 z24rb->PutRowRGB = NULL;
388 z24rb->PutMonoRow = put_mono_row_z24;
389 z24rb->PutValues = put_values_z24;
390 z24rb->PutMonoValues = put_mono_values_z24;
396 /*======================================================================
397 * Stencil wrapper around depth/stencil renderbuffer
401 get_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
402 GLint x, GLint y, void *values)
404 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
405 GLuint temp[MAX_WIDTH], i;
406 GLubyte *dst = (GLubyte *) values;
407 const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
408 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
409 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
411 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
414 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
415 for (i = 0; i < count; i++) {
416 dst[i] = src[i] & 0xff;
420 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
421 for (i = 0; i < count; i++) {
422 dst[i] = src[i] >> 24;
428 get_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
429 const GLint x[], const GLint y[], void *values)
431 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
432 GLuint temp[MAX_WIDTH], i;
433 GLubyte *dst = (GLubyte *) values;
434 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
435 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
436 ASSERT(count <= MAX_WIDTH);
437 /* don't bother trying direct access */
438 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
439 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
440 for (i = 0; i < count; i++) {
441 dst[i] = temp[i] & 0xff;
445 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
446 for (i = 0; i < count; i++) {
447 dst[i] = temp[i] >> 24;
453 put_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
454 GLint x, GLint y, const void *values, const GLubyte *mask)
456 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
457 const GLubyte *src = (const GLubyte *) values;
458 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
459 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
460 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
464 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
465 for (i = 0; i < count; i++) {
466 if (!mask || mask[i]) {
467 dst[i] = (dst[i] & 0xffffff00) | src[i];
472 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
473 for (i = 0; i < count; i++) {
474 if (!mask || mask[i]) {
475 dst[i] = (dst[i] & 0xffffff) | (src[i] << 24);
481 /* get, modify, put */
482 GLuint temp[MAX_WIDTH], i;
483 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
484 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
485 for (i = 0; i < count; i++) {
486 if (!mask || mask[i]) {
487 temp[i] = (temp[i] & 0xffffff00) | src[i];
492 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
493 for (i = 0; i < count; i++) {
494 if (!mask || mask[i]) {
495 temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
499 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
504 put_mono_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
505 GLint x, GLint y, const void *value, const GLubyte *mask)
507 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
508 const GLubyte val = *((GLubyte *) value);
509 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
510 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
511 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
515 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
516 for (i = 0; i < count; i++) {
517 if (!mask || mask[i]) {
518 dst[i] = (dst[i] & 0xffffff00) | val;
523 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
524 for (i = 0; i < count; i++) {
525 if (!mask || mask[i]) {
526 dst[i] = (dst[i] & 0xffffff) | (val << 24);
532 /* get, modify, put */
533 GLuint temp[MAX_WIDTH], i;
534 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
535 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
536 for (i = 0; i < count; i++) {
537 if (!mask || mask[i]) {
538 temp[i] = (temp[i] & 0xffffff00) | val;
543 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
544 for (i = 0; i < count; i++) {
545 if (!mask || mask[i]) {
546 temp[i] = (temp[i] & 0xffffff) | (val << 24);
550 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
555 put_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
556 const GLint x[], const GLint y[],
557 const void *values, const GLubyte *mask)
559 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
560 const GLubyte *src = (const GLubyte *) values;
561 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
562 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
563 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
566 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
567 for (i = 0; i < count; i++) {
568 if (!mask || mask[i]) {
569 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
570 *dst = (*dst & 0xffffff00) | src[i];
575 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
576 for (i = 0; i < count; i++) {
577 if (!mask || mask[i]) {
578 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
579 *dst = (*dst & 0xffffff) | (src[i] << 24);
585 /* get, modify, put */
586 GLuint temp[MAX_WIDTH], i;
587 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
588 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
589 for (i = 0; i < count; i++) {
590 if (!mask || mask[i]) {
591 temp[i] = (temp[i] & 0xffffff00) | src[i];
596 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
597 for (i = 0; i < count; i++) {
598 if (!mask || mask[i]) {
599 temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
603 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
608 put_mono_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
609 const GLint x[], const GLint y[],
610 const void *value, const GLubyte *mask)
612 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
613 GLuint temp[MAX_WIDTH], i;
614 const GLubyte val = *((GLubyte *) value);
615 /* get, modify, put */
616 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
617 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
618 for (i = 0; i < count; i++) {
619 if (!mask || mask[i]) {
620 temp[i] = (temp[i] & 0xffffff00) | val;
625 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
626 for (i = 0; i < count; i++) {
627 if (!mask || mask[i]) {
628 temp[i] = (temp[i] & 0xffffff) | (val << 24);
632 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
637 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
638 * a stencil renderbuffer.
639 * \return new stencil renderbuffer
641 struct gl_renderbuffer *
642 _mesa_new_s8_renderbuffer_wrapper(struct gl_context *ctx, struct gl_renderbuffer *dsrb)
644 struct gl_renderbuffer *s8rb;
646 ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
647 dsrb->Format == MESA_FORMAT_S8_Z24);
648 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
650 s8rb = ctx->Driver.NewRenderbuffer(ctx, 0);
654 /* NOTE: need to do manual refcounting here */
655 s8rb->Wrapped = dsrb;
658 s8rb->Name = dsrb->Name;
660 s8rb->Width = dsrb->Width;
661 s8rb->Height = dsrb->Height;
662 s8rb->RowStride = dsrb->RowStride;
663 s8rb->InternalFormat = GL_STENCIL_INDEX8_EXT;
664 s8rb->Format = MESA_FORMAT_S8;
665 s8rb->_BaseFormat = GL_STENCIL_INDEX;
666 s8rb->DataType = GL_UNSIGNED_BYTE;
668 s8rb->Delete = delete_wrapper;
669 s8rb->AllocStorage = alloc_wrapper_storage;
670 s8rb->GetPointer = nop_get_pointer;
671 s8rb->GetRow = get_row_s8;
672 s8rb->GetValues = get_values_s8;
673 s8rb->PutRow = put_row_s8;
674 s8rb->PutRowRGB = NULL;
675 s8rb->PutMonoRow = put_mono_row_s8;
676 s8rb->PutValues = put_values_s8;
677 s8rb->PutMonoValues = put_mono_values_s8;
685 ** The following functions are useful for hardware drivers that only
686 ** implement combined depth/stencil buffers.
687 ** The GL_EXT_framebuffer_object extension allows indepedent depth and
688 ** stencil buffers to be used in any combination.
689 ** Therefore, we sometimes have to merge separate depth and stencil
690 ** renderbuffers into a single depth+stencil renderbuffer. And sometimes
691 ** we have to split combined depth+stencil renderbuffers into separate
697 * Extract stencil values from the combined depth/stencil renderbuffer, storing
698 * the values into a separate stencil renderbuffer.
699 * \param dsRb the source depth/stencil renderbuffer
700 * \param stencilRb the destination stencil renderbuffer
701 * (either 8-bit or 32-bit)
704 _mesa_extract_stencil(struct gl_context *ctx,
705 struct gl_renderbuffer *dsRb,
706 struct gl_renderbuffer *stencilRb)
708 GLuint row, width, height;
713 ASSERT(dsRb->Format == MESA_FORMAT_Z24_S8);
714 ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
715 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8 ||
716 stencilRb->Format == MESA_FORMAT_S8);
717 ASSERT(dsRb->Width == stencilRb->Width);
718 ASSERT(dsRb->Height == stencilRb->Height);
721 height = dsRb->Height;
723 for (row = 0; row < height; row++) {
724 GLuint depthStencil[MAX_WIDTH];
725 dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
726 if (stencilRb->Format == MESA_FORMAT_S8) {
728 GLubyte stencil[MAX_WIDTH];
730 for (i = 0; i < width; i++) {
731 stencil[i] = depthStencil[i] & 0xff;
733 stencilRb->PutRow(ctx, stencilRb, width, 0, row, stencil, NULL);
737 /* the 24 depth bits will be ignored */
738 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8);
739 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
740 stencilRb->PutRow(ctx, stencilRb, width, 0, row, depthStencil, NULL);
747 * Copy stencil values from a stencil renderbuffer into a combined
748 * depth/stencil renderbuffer.
749 * \param dsRb the destination depth/stencil renderbuffer
750 * \param stencilRb the source stencil buffer (either 8-bit or 32-bit)
753 _mesa_insert_stencil(struct gl_context *ctx,
754 struct gl_renderbuffer *dsRb,
755 struct gl_renderbuffer *stencilRb)
757 GLuint row, width, height;
762 ASSERT(dsRb->Format == MESA_FORMAT_Z24_S8);
763 ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
764 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8 ||
765 stencilRb->Format == MESA_FORMAT_S8);
767 ASSERT(dsRb->Width == stencilRb->Width);
768 ASSERT(dsRb->Height == stencilRb->Height);
771 height = dsRb->Height;
773 for (row = 0; row < height; row++) {
774 GLuint depthStencil[MAX_WIDTH];
776 dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
778 if (stencilRb->Format == MESA_FORMAT_S8) {
780 GLubyte stencil[MAX_WIDTH];
782 stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
783 for (i = 0; i < width; i++) {
784 depthStencil[i] = (depthStencil[i] & 0xffffff00) | stencil[i];
788 /* 32bpp stencil buffer */
789 GLuint stencil[MAX_WIDTH], i;
790 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8);
791 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
792 stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
793 for (i = 0; i < width; i++) {
795 = (depthStencil[i] & 0xffffff00) | (stencil[i] & 0xff);
799 dsRb->PutRow(ctx, dsRb, width, 0, row, depthStencil, NULL);
805 * Convert the stencil buffer from 8bpp to 32bpp depth/stencil.
806 * \param stencilRb the stencil renderbuffer to promote
809 _mesa_promote_stencil(struct gl_context *ctx, struct gl_renderbuffer *stencilRb)
811 const GLsizei width = stencilRb->Width;
812 const GLsizei height = stencilRb->Height;
816 ASSERT(stencilRb->Format == MESA_FORMAT_S8);
817 ASSERT(stencilRb->Data);
819 data = (GLubyte *) stencilRb->Data;
820 stencilRb->Data = NULL;
821 stencilRb->AllocStorage(ctx, stencilRb, GL_DEPTH24_STENCIL8_EXT,
824 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
827 for (i = 0; i < height; i++) {
828 GLuint depthStencil[MAX_WIDTH];
829 for (j = 0; j < width; j++) {
830 depthStencil[j] = data[k++];
832 stencilRb->PutRow(ctx, stencilRb, width, 0, i, depthStencil, NULL);