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