mesa: update assertions and fix refcounting in depth/stencil renderbuffer code
[mesa.git] / src / mesa / main / depthstencil.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2006 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 #include "glheader.h"
26 #include "imports.h"
27 #include "context.h"
28 #include "formats.h"
29 #include "mtypes.h"
30 #include "depthstencil.h"
31 #include "renderbuffer.h"
32
33
34 /**
35 * Adaptor/wrappers for GL_DEPTH_STENCIL renderbuffers.
36 *
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.
42 *
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.
45 */
46
47
48 static void *
49 nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
50 {
51 (void) ctx;
52 (void) rb;
53 (void) x;
54 (void) y;
55 return NULL;
56 }
57
58
59 /**
60 * Delete a depth or stencil wrapper renderbuffer.
61 */
62 static void
63 delete_wrapper(struct gl_renderbuffer *rb)
64 {
65 ASSERT(rb->Format == MESA_FORMAT_S8 ||
66 rb->Format == MESA_FORMAT_X8_Z24);
67 _mesa_reference_renderbuffer(&rb->Wrapped, NULL);
68 free(rb);
69 }
70
71
72 /**
73 * Realloc storage for wrapper.
74 */
75 static GLboolean
76 alloc_wrapper_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
77 GLenum internalFormat, GLuint width, GLuint height)
78 {
79 /* just pass this on to the wrapped renderbuffer */
80 struct gl_renderbuffer *dsrb = rb->Wrapped;
81 GLboolean retVal;
82
83 (void) internalFormat;
84
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);
89
90 retVal = dsrb->AllocStorage(ctx, dsrb, dsrb->InternalFormat, width, height);
91 if (retVal) {
92 rb->Width = width;
93 rb->Height = height;
94 }
95 return retVal;
96 }
97
98
99
100
101 /*======================================================================
102 * Depth wrapper around depth/stencil renderbuffer
103 */
104
105 static void
106 get_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
107 GLint x, GLint y, void *values)
108 {
109 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
110 GLuint temp[MAX_WIDTH], i;
111 GLuint *dst = (GLuint *) values;
112 const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
113 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
114 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
115 if (!src) {
116 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
117 src = temp;
118 }
119 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
120 for (i = 0; i < count; i++) {
121 dst[i] = src[i] >> 8;
122 }
123 }
124 else {
125 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
126 for (i = 0; i < count; i++) {
127 dst[i] = src[i] & 0xffffff;
128 }
129 }
130 }
131
132 static void
133 get_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
134 const GLint x[], const GLint y[], void *values)
135 {
136 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
137 GLuint temp[MAX_WIDTH], i;
138 GLuint *dst = (GLuint *) values;
139 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
140 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
141 ASSERT(count <= MAX_WIDTH);
142 /* don't bother trying direct access */
143 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
144 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
145 for (i = 0; i < count; i++) {
146 dst[i] = temp[i] >> 8;
147 }
148 }
149 else {
150 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
151 for (i = 0; i < count; i++) {
152 dst[i] = temp[i] & 0xffffff;
153 }
154 }
155 }
156
157 static void
158 put_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
159 GLint x, GLint y, const void *values, const GLubyte *mask)
160 {
161 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
162 const GLuint *src = (const GLuint *) values;
163 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
164 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
165 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
166 if (dst) {
167 /* direct access */
168 GLuint i;
169 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
170 for (i = 0; i < count; i++) {
171 if (!mask || mask[i]) {
172 dst[i] = (src[i] << 8) | (dst[i] & 0xff);
173 }
174 }
175 }
176 else {
177 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
178 for (i = 0; i < count; i++) {
179 if (!mask || mask[i]) {
180 dst[i] = (src[i] & 0xffffff) | (dst[i] & 0xff000000);
181 }
182 }
183 }
184 }
185 else {
186 /* get, modify, put */
187 GLuint temp[MAX_WIDTH], i;
188 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
189 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
190 for (i = 0; i < count; i++) {
191 if (!mask || mask[i]) {
192 temp[i] = (src[i] << 8) | (temp[i] & 0xff);
193 }
194 }
195 }
196 else {
197 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
198 for (i = 0; i < count; i++) {
199 if (!mask || mask[i]) {
200 temp[i] = (src[i] & 0xffffff) | (temp[i] & 0xff000000);
201 }
202 }
203 }
204 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
205 }
206 }
207
208 static void
209 put_mono_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
210 GLint x, GLint y, const void *value, const GLubyte *mask)
211 {
212 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
213 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
214 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
215 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
216 if (dst) {
217 /* direct access */
218 GLuint i;
219 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
220 const GLuint shiftedVal = *((GLuint *) value) << 8;
221 for (i = 0; i < count; i++) {
222 if (!mask || mask[i]) {
223 dst[i] = shiftedVal | (dst[i] & 0xff);
224 }
225 }
226 }
227 else {
228 const GLuint shiftedVal = *((GLuint *) value);
229 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
230 for (i = 0; i < count; i++) {
231 if (!mask || mask[i]) {
232 dst[i] = shiftedVal | (dst[i] & 0xff000000);
233 }
234 }
235 }
236 }
237 else {
238 /* get, modify, put */
239 GLuint temp[MAX_WIDTH], i;
240 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
241 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
242 const GLuint shiftedVal = *((GLuint *) value) << 8;
243 for (i = 0; i < count; i++) {
244 if (!mask || mask[i]) {
245 temp[i] = shiftedVal | (temp[i] & 0xff);
246 }
247 }
248 }
249 else {
250 const GLuint shiftedVal = *((GLuint *) value);
251 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
252 for (i = 0; i < count; i++) {
253 if (!mask || mask[i]) {
254 temp[i] = shiftedVal | (temp[i] & 0xff000000);
255 }
256 }
257 }
258 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
259 }
260 }
261
262 static void
263 put_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
264 const GLint x[], const GLint y[],
265 const void *values, const GLubyte *mask)
266 {
267 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
268 const GLuint *src = (const GLuint *) values;
269 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
270 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
271 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
272 /* direct access */
273 GLuint i;
274 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
275 for (i = 0; i < count; i++) {
276 if (!mask || mask[i]) {
277 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
278 *dst = (src[i] << 8) | (*dst & 0xff);
279 }
280 }
281 }
282 else {
283 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
284 for (i = 0; i < count; i++) {
285 if (!mask || mask[i]) {
286 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
287 *dst = (src[i] & 0xffffff) | (*dst & 0xff000000);
288 }
289 }
290 }
291 }
292 else {
293 /* get, modify, put */
294 GLuint temp[MAX_WIDTH], i;
295 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
296 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
297 for (i = 0; i < count; i++) {
298 if (!mask || mask[i]) {
299 temp[i] = (src[i] << 8) | (temp[i] & 0xff);
300 }
301 }
302 }
303 else {
304 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
305 for (i = 0; i < count; i++) {
306 if (!mask || mask[i]) {
307 temp[i] = (src[i] & 0xffffff) | (temp[i] & 0xff000000);
308 }
309 }
310 }
311 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
312 }
313 }
314
315 static void
316 put_mono_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb,
317 GLuint count, const GLint x[], const GLint y[],
318 const void *value, const GLubyte *mask)
319 {
320 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
321 GLuint temp[MAX_WIDTH], i;
322 /* get, modify, put */
323 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
324 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
325 const GLuint shiftedVal = *((GLuint *) value) << 8;
326 for (i = 0; i < count; i++) {
327 if (!mask || mask[i]) {
328 temp[i] = shiftedVal | (temp[i] & 0xff);
329 }
330 }
331 }
332 else {
333 const GLuint shiftedVal = *((GLuint *) value);
334 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
335 for (i = 0; i < count; i++) {
336 if (!mask || mask[i]) {
337 temp[i] = shiftedVal | (temp[i] & 0xff000000);
338 }
339 }
340 }
341 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
342 }
343
344
345 /**
346 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
347 * a depth renderbuffer.
348 * \return new depth renderbuffer
349 */
350 struct gl_renderbuffer *
351 _mesa_new_z24_renderbuffer_wrapper(GLcontext *ctx,
352 struct gl_renderbuffer *dsrb)
353 {
354 struct gl_renderbuffer *z24rb;
355
356 ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
357 dsrb->Format == MESA_FORMAT_Z24_X8 ||
358 dsrb->Format == MESA_FORMAT_S8_Z24 ||
359 dsrb->Format == MESA_FORMAT_X8_Z24);
360 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
361
362 z24rb = _mesa_new_renderbuffer(ctx, 0);
363 if (!z24rb)
364 return NULL;
365
366 /* NOTE: need to do manual refcounting here */
367 z24rb->Wrapped = dsrb;
368 dsrb->RefCount++;
369
370 z24rb->Name = dsrb->Name;
371 z24rb->RefCount = 0;
372 z24rb->Width = dsrb->Width;
373 z24rb->Height = dsrb->Height;
374 z24rb->InternalFormat = GL_DEPTH_COMPONENT24;
375 z24rb->Format = MESA_FORMAT_X8_Z24;
376 z24rb->_BaseFormat = GL_DEPTH_COMPONENT;
377 z24rb->DataType = GL_UNSIGNED_INT;
378 z24rb->Data = NULL;
379 z24rb->Delete = delete_wrapper;
380 z24rb->AllocStorage = alloc_wrapper_storage;
381 z24rb->GetPointer = nop_get_pointer;
382 z24rb->GetRow = get_row_z24;
383 z24rb->GetValues = get_values_z24;
384 z24rb->PutRow = put_row_z24;
385 z24rb->PutRowRGB = NULL;
386 z24rb->PutMonoRow = put_mono_row_z24;
387 z24rb->PutValues = put_values_z24;
388 z24rb->PutMonoValues = put_mono_values_z24;
389
390 return z24rb;
391 }
392
393
394 /*======================================================================
395 * Stencil wrapper around depth/stencil renderbuffer
396 */
397
398 static void
399 get_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
400 GLint x, GLint y, void *values)
401 {
402 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
403 GLuint temp[MAX_WIDTH], i;
404 GLubyte *dst = (GLubyte *) values;
405 const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
406 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
407 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
408 if (!src) {
409 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
410 src = temp;
411 }
412 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
413 for (i = 0; i < count; i++) {
414 dst[i] = src[i] & 0xff;
415 }
416 }
417 else {
418 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
419 for (i = 0; i < count; i++) {
420 dst[i] = src[i] >> 24;
421 }
422 }
423 }
424
425 static void
426 get_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
427 const GLint x[], const GLint y[], void *values)
428 {
429 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
430 GLuint temp[MAX_WIDTH], i;
431 GLubyte *dst = (GLubyte *) values;
432 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
433 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
434 ASSERT(count <= MAX_WIDTH);
435 /* don't bother trying direct access */
436 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
437 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
438 for (i = 0; i < count; i++) {
439 dst[i] = temp[i] & 0xff;
440 }
441 }
442 else {
443 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
444 for (i = 0; i < count; i++) {
445 dst[i] = temp[i] >> 24;
446 }
447 }
448 }
449
450 static void
451 put_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
452 GLint x, GLint y, const void *values, const GLubyte *mask)
453 {
454 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
455 const GLubyte *src = (const GLubyte *) values;
456 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
457 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
458 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
459 if (dst) {
460 /* direct access */
461 GLuint i;
462 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
463 for (i = 0; i < count; i++) {
464 if (!mask || mask[i]) {
465 dst[i] = (dst[i] & 0xffffff00) | src[i];
466 }
467 }
468 }
469 else {
470 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
471 for (i = 0; i < count; i++) {
472 if (!mask || mask[i]) {
473 dst[i] = (dst[i] & 0xffffff) | (src[i] << 24);
474 }
475 }
476 }
477 }
478 else {
479 /* get, modify, put */
480 GLuint temp[MAX_WIDTH], i;
481 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
482 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
483 for (i = 0; i < count; i++) {
484 if (!mask || mask[i]) {
485 temp[i] = (temp[i] & 0xffffff00) | src[i];
486 }
487 }
488 }
489 else {
490 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
491 for (i = 0; i < count; i++) {
492 if (!mask || mask[i]) {
493 temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
494 }
495 }
496 }
497 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
498 }
499 }
500
501 static void
502 put_mono_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
503 GLint x, GLint y, const void *value, const GLubyte *mask)
504 {
505 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
506 const GLubyte val = *((GLubyte *) value);
507 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
508 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
509 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
510 if (dst) {
511 /* direct access */
512 GLuint i;
513 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
514 for (i = 0; i < count; i++) {
515 if (!mask || mask[i]) {
516 dst[i] = (dst[i] & 0xffffff00) | val;
517 }
518 }
519 }
520 else {
521 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
522 for (i = 0; i < count; i++) {
523 if (!mask || mask[i]) {
524 dst[i] = (dst[i] & 0xffffff) | (val << 24);
525 }
526 }
527 }
528 }
529 else {
530 /* get, modify, put */
531 GLuint temp[MAX_WIDTH], i;
532 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
533 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
534 for (i = 0; i < count; i++) {
535 if (!mask || mask[i]) {
536 temp[i] = (temp[i] & 0xffffff00) | val;
537 }
538 }
539 }
540 else {
541 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
542 for (i = 0; i < count; i++) {
543 if (!mask || mask[i]) {
544 temp[i] = (temp[i] & 0xffffff) | (val << 24);
545 }
546 }
547 }
548 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
549 }
550 }
551
552 static void
553 put_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
554 const GLint x[], const GLint y[],
555 const void *values, const GLubyte *mask)
556 {
557 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
558 const GLubyte *src = (const GLubyte *) values;
559 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
560 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
561 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
562 /* direct access */
563 GLuint i;
564 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
565 for (i = 0; i < count; i++) {
566 if (!mask || mask[i]) {
567 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
568 *dst = (*dst & 0xffffff00) | src[i];
569 }
570 }
571 }
572 else {
573 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
574 for (i = 0; i < count; i++) {
575 if (!mask || mask[i]) {
576 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
577 *dst = (*dst & 0xffffff) | (src[i] << 24);
578 }
579 }
580 }
581 }
582 else {
583 /* get, modify, put */
584 GLuint temp[MAX_WIDTH], i;
585 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
586 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
587 for (i = 0; i < count; i++) {
588 if (!mask || mask[i]) {
589 temp[i] = (temp[i] & 0xffffff00) | src[i];
590 }
591 }
592 }
593 else {
594 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
595 for (i = 0; i < count; i++) {
596 if (!mask || mask[i]) {
597 temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
598 }
599 }
600 }
601 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
602 }
603 }
604
605 static void
606 put_mono_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
607 const GLint x[], const GLint y[],
608 const void *value, const GLubyte *mask)
609 {
610 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
611 GLuint temp[MAX_WIDTH], i;
612 const GLubyte val = *((GLubyte *) value);
613 /* get, modify, put */
614 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
615 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
616 for (i = 0; i < count; i++) {
617 if (!mask || mask[i]) {
618 temp[i] = (temp[i] & 0xffffff00) | val;
619 }
620 }
621 }
622 else {
623 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
624 for (i = 0; i < count; i++) {
625 if (!mask || mask[i]) {
626 temp[i] = (temp[i] & 0xffffff) | (val << 24);
627 }
628 }
629 }
630 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
631 }
632
633
634 /**
635 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
636 * a stencil renderbuffer.
637 * \return new stencil renderbuffer
638 */
639 struct gl_renderbuffer *
640 _mesa_new_s8_renderbuffer_wrapper(GLcontext *ctx, struct gl_renderbuffer *dsrb)
641 {
642 struct gl_renderbuffer *s8rb;
643
644 ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
645 dsrb->Format == MESA_FORMAT_S8_Z24);
646 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
647
648 s8rb = _mesa_new_renderbuffer(ctx, 0);
649 if (!s8rb)
650 return NULL;
651
652 /* NOTE: need to do manual refcounting here */
653 s8rb->Wrapped = dsrb;
654 dsrb->RefCount++;
655
656 s8rb->Name = dsrb->Name;
657 s8rb->RefCount = 0;
658 s8rb->Width = dsrb->Width;
659 s8rb->Height = dsrb->Height;
660 s8rb->InternalFormat = GL_STENCIL_INDEX8_EXT;
661 s8rb->Format = MESA_FORMAT_S8;
662 s8rb->_BaseFormat = GL_STENCIL_INDEX;
663 s8rb->DataType = GL_UNSIGNED_BYTE;
664 s8rb->Data = NULL;
665 s8rb->Delete = delete_wrapper;
666 s8rb->AllocStorage = alloc_wrapper_storage;
667 s8rb->GetPointer = nop_get_pointer;
668 s8rb->GetRow = get_row_s8;
669 s8rb->GetValues = get_values_s8;
670 s8rb->PutRow = put_row_s8;
671 s8rb->PutRowRGB = NULL;
672 s8rb->PutMonoRow = put_mono_row_s8;
673 s8rb->PutValues = put_values_s8;
674 s8rb->PutMonoValues = put_mono_values_s8;
675
676 return s8rb;
677 }
678
679
680
681 /**
682 ** The following functions are useful for hardware drivers that only
683 ** implement combined depth/stencil buffers.
684 ** The GL_EXT_framebuffer_object extension allows indepedent depth and
685 ** stencil buffers to be used in any combination.
686 ** Therefore, we sometimes have to merge separate depth and stencil
687 ** renderbuffers into a single depth+stencil renderbuffer. And sometimes
688 ** we have to split combined depth+stencil renderbuffers into separate
689 ** renderbuffers.
690 **/
691
692
693 /**
694 * Extract stencil values from the combined depth/stencil renderbuffer, storing
695 * the values into a separate stencil renderbuffer.
696 * \param dsRb the source depth/stencil renderbuffer
697 * \param stencilRb the destination stencil renderbuffer
698 * (either 8-bit or 32-bit)
699 */
700 void
701 _mesa_extract_stencil(GLcontext *ctx,
702 struct gl_renderbuffer *dsRb,
703 struct gl_renderbuffer *stencilRb)
704 {
705 GLuint row, width, height;
706
707 ASSERT(dsRb);
708 ASSERT(stencilRb);
709
710 ASSERT(dsRb->Format == MESA_FORMAT_Z24_S8);
711 ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
712 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8 ||
713 stencilRb->Format == MESA_FORMAT_S8);
714 ASSERT(dsRb->Width == stencilRb->Width);
715 ASSERT(dsRb->Height == stencilRb->Height);
716
717 width = dsRb->Width;
718 height = dsRb->Height;
719
720 for (row = 0; row < height; row++) {
721 GLuint depthStencil[MAX_WIDTH];
722 dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
723 if (stencilRb->Format == MESA_FORMAT_S8) {
724 /* 8bpp stencil */
725 GLubyte stencil[MAX_WIDTH];
726 GLuint i;
727 for (i = 0; i < width; i++) {
728 stencil[i] = depthStencil[i] & 0xff;
729 }
730 stencilRb->PutRow(ctx, stencilRb, width, 0, row, stencil, NULL);
731 }
732 else {
733 /* 32bpp stencil */
734 /* the 24 depth bits will be ignored */
735 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8);
736 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
737 stencilRb->PutRow(ctx, stencilRb, width, 0, row, depthStencil, NULL);
738 }
739 }
740 }
741
742
743 /**
744 * Copy stencil values from a stencil renderbuffer into a combined
745 * depth/stencil renderbuffer.
746 * \param dsRb the destination depth/stencil renderbuffer
747 * \param stencilRb the source stencil buffer (either 8-bit or 32-bit)
748 */
749 void
750 _mesa_insert_stencil(GLcontext *ctx,
751 struct gl_renderbuffer *dsRb,
752 struct gl_renderbuffer *stencilRb)
753 {
754 GLuint row, width, height;
755
756 ASSERT(dsRb);
757 ASSERT(stencilRb);
758
759 ASSERT(dsRb->Format == MESA_FORMAT_Z24_S8);
760 ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
761 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8 ||
762 stencilRb->Format == MESA_FORMAT_S8);
763
764 ASSERT(dsRb->Width == stencilRb->Width);
765 ASSERT(dsRb->Height == stencilRb->Height);
766
767 width = dsRb->Width;
768 height = dsRb->Height;
769
770 for (row = 0; row < height; row++) {
771 GLuint depthStencil[MAX_WIDTH];
772
773 dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
774
775 if (stencilRb->Format == MESA_FORMAT_S8) {
776 /* 8bpp stencil */
777 GLubyte stencil[MAX_WIDTH];
778 GLuint i;
779 stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
780 for (i = 0; i < width; i++) {
781 depthStencil[i] = (depthStencil[i] & 0xffffff00) | stencil[i];
782 }
783 }
784 else {
785 /* 32bpp stencil buffer */
786 GLuint stencil[MAX_WIDTH], i;
787 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8);
788 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
789 stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
790 for (i = 0; i < width; i++) {
791 depthStencil[i]
792 = (depthStencil[i] & 0xffffff00) | (stencil[i] & 0xff);
793 }
794 }
795
796 dsRb->PutRow(ctx, dsRb, width, 0, row, depthStencil, NULL);
797 }
798 }
799
800
801 /**
802 * Convert the stencil buffer from 8bpp to 32bpp depth/stencil.
803 * \param stencilRb the stencil renderbuffer to promote
804 */
805 void
806 _mesa_promote_stencil(GLcontext *ctx, struct gl_renderbuffer *stencilRb)
807 {
808 const GLsizei width = stencilRb->Width;
809 const GLsizei height = stencilRb->Height;
810 GLubyte *data;
811 GLint i, j, k;
812
813 ASSERT(stencilRb->Format == MESA_FORMAT_S8);
814 ASSERT(stencilRb->Data);
815
816 data = (GLubyte *) stencilRb->Data;
817 stencilRb->Data = NULL;
818 stencilRb->AllocStorage(ctx, stencilRb, GL_DEPTH24_STENCIL8_EXT,
819 width, height);
820
821 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
822
823 k = 0;
824 for (i = 0; i < height; i++) {
825 GLuint depthStencil[MAX_WIDTH];
826 for (j = 0; j < width; j++) {
827 depthStencil[j] = data[k++];
828 }
829 stencilRb->PutRow(ctx, stencilRb, width, 0, i, depthStencil, NULL);
830 }
831 free(data);
832 }