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