ab62c97fe5ac5728b71cf3dac2a5363acee01b13
[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(struct gl_context *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(struct gl_context *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 rb->RowStride = dsrb->RowStride;
95 }
96 return retVal;
97 }
98
99
100
101
102 /*======================================================================
103 * Depth wrapper around depth/stencil renderbuffer
104 */
105
106 static void
107 get_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
108 GLint x, GLint y, void *values)
109 {
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);
116 if (!src) {
117 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
118 src = temp;
119 }
120 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
121 for (i = 0; i < count; i++) {
122 dst[i] = src[i] >> 8;
123 }
124 }
125 else {
126 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
127 for (i = 0; i < count; i++) {
128 dst[i] = src[i] & 0xffffff;
129 }
130 }
131 }
132
133 static void
134 get_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
135 const GLint x[], const GLint y[], void *values)
136 {
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;
148 }
149 }
150 else {
151 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
152 for (i = 0; i < count; i++) {
153 dst[i] = temp[i] & 0xffffff;
154 }
155 }
156 }
157
158 static void
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)
161 {
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);
167 if (dst) {
168 /* direct access */
169 GLuint i;
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);
174 }
175 }
176 }
177 else {
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);
182 }
183 }
184 }
185 }
186 else {
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);
194 }
195 }
196 }
197 else {
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);
202 }
203 }
204 }
205 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
206 }
207 }
208
209 static void
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)
212 {
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);
217 if (dst) {
218 /* direct access */
219 GLuint i;
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);
225 }
226 }
227 }
228 else {
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);
234 }
235 }
236 }
237 }
238 else {
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);
247 }
248 }
249 }
250 else {
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);
256 }
257 }
258 }
259 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
260 }
261 }
262
263 static void
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)
267 {
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)) {
273 /* direct access */
274 GLuint i;
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);
280 }
281 }
282 }
283 else {
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);
289 }
290 }
291 }
292 }
293 else {
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);
301 }
302 }
303 }
304 else {
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);
309 }
310 }
311 }
312 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
313 }
314 }
315
316 static void
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)
320 {
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);
330 }
331 }
332 }
333 else {
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);
339 }
340 }
341 }
342 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
343 }
344
345
346 /**
347 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
348 * a depth renderbuffer.
349 * \return new depth renderbuffer
350 */
351 struct gl_renderbuffer *
352 _mesa_new_z24_renderbuffer_wrapper(struct gl_context *ctx,
353 struct gl_renderbuffer *dsrb)
354 {
355 struct gl_renderbuffer *z24rb;
356
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);
362
363 z24rb = ctx->Driver.NewRenderbuffer(ctx, 0);
364 if (!z24rb)
365 return NULL;
366
367 /* NOTE: need to do manual refcounting here */
368 z24rb->Wrapped = dsrb;
369 dsrb->RefCount++;
370
371 z24rb->Name = dsrb->Name;
372 z24rb->RefCount = 0;
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;
380 z24rb->Data = NULL;
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;
391
392 return z24rb;
393 }
394
395
396 /*======================================================================
397 * Stencil wrapper around depth/stencil renderbuffer
398 */
399
400 static void
401 get_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
402 GLint x, GLint y, void *values)
403 {
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);
410 if (!src) {
411 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
412 src = temp;
413 }
414 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
415 for (i = 0; i < count; i++) {
416 dst[i] = src[i] & 0xff;
417 }
418 }
419 else {
420 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
421 for (i = 0; i < count; i++) {
422 dst[i] = src[i] >> 24;
423 }
424 }
425 }
426
427 static void
428 get_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
429 const GLint x[], const GLint y[], void *values)
430 {
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;
442 }
443 }
444 else {
445 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
446 for (i = 0; i < count; i++) {
447 dst[i] = temp[i] >> 24;
448 }
449 }
450 }
451
452 static void
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)
455 {
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);
461 if (dst) {
462 /* direct access */
463 GLuint i;
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];
468 }
469 }
470 }
471 else {
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);
476 }
477 }
478 }
479 }
480 else {
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];
488 }
489 }
490 }
491 else {
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);
496 }
497 }
498 }
499 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
500 }
501 }
502
503 static void
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)
506 {
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);
512 if (dst) {
513 /* direct access */
514 GLuint i;
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;
519 }
520 }
521 }
522 else {
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);
527 }
528 }
529 }
530 }
531 else {
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;
539 }
540 }
541 }
542 else {
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);
547 }
548 }
549 }
550 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
551 }
552 }
553
554 static void
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)
558 {
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)) {
564 /* direct access */
565 GLuint i;
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];
571 }
572 }
573 }
574 else {
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);
580 }
581 }
582 }
583 }
584 else {
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];
592 }
593 }
594 }
595 else {
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);
600 }
601 }
602 }
603 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
604 }
605 }
606
607 static void
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)
611 {
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;
621 }
622 }
623 }
624 else {
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);
629 }
630 }
631 }
632 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
633 }
634
635
636 /**
637 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
638 * a stencil renderbuffer.
639 * \return new stencil renderbuffer
640 */
641 struct gl_renderbuffer *
642 _mesa_new_s8_renderbuffer_wrapper(struct gl_context *ctx, struct gl_renderbuffer *dsrb)
643 {
644 struct gl_renderbuffer *s8rb;
645
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);
649
650 s8rb = ctx->Driver.NewRenderbuffer(ctx, 0);
651 if (!s8rb)
652 return NULL;
653
654 /* NOTE: need to do manual refcounting here */
655 s8rb->Wrapped = dsrb;
656 dsrb->RefCount++;
657
658 s8rb->Name = dsrb->Name;
659 s8rb->RefCount = 0;
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;
667 s8rb->Data = NULL;
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;
678
679 return s8rb;
680 }
681
682
683
684 /**
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
692 ** renderbuffers.
693 **/
694
695
696 /**
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)
702 */
703 void
704 _mesa_extract_stencil(struct gl_context *ctx,
705 struct gl_renderbuffer *dsRb,
706 struct gl_renderbuffer *stencilRb)
707 {
708 GLuint row, width, height;
709
710 ASSERT(dsRb);
711 ASSERT(stencilRb);
712
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);
719
720 width = dsRb->Width;
721 height = dsRb->Height;
722
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) {
727 /* 8bpp stencil */
728 GLubyte stencil[MAX_WIDTH];
729 GLuint i;
730 for (i = 0; i < width; i++) {
731 stencil[i] = depthStencil[i] & 0xff;
732 }
733 stencilRb->PutRow(ctx, stencilRb, width, 0, row, stencil, NULL);
734 }
735 else {
736 /* 32bpp stencil */
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);
741 }
742 }
743 }
744
745
746 /**
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)
751 */
752 void
753 _mesa_insert_stencil(struct gl_context *ctx,
754 struct gl_renderbuffer *dsRb,
755 struct gl_renderbuffer *stencilRb)
756 {
757 GLuint row, width, height;
758
759 ASSERT(dsRb);
760 ASSERT(stencilRb);
761
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);
766
767 ASSERT(dsRb->Width == stencilRb->Width);
768 ASSERT(dsRb->Height == stencilRb->Height);
769
770 width = dsRb->Width;
771 height = dsRb->Height;
772
773 for (row = 0; row < height; row++) {
774 GLuint depthStencil[MAX_WIDTH];
775
776 dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
777
778 if (stencilRb->Format == MESA_FORMAT_S8) {
779 /* 8bpp stencil */
780 GLubyte stencil[MAX_WIDTH];
781 GLuint i;
782 stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
783 for (i = 0; i < width; i++) {
784 depthStencil[i] = (depthStencil[i] & 0xffffff00) | stencil[i];
785 }
786 }
787 else {
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++) {
794 depthStencil[i]
795 = (depthStencil[i] & 0xffffff00) | (stencil[i] & 0xff);
796 }
797 }
798
799 dsRb->PutRow(ctx, dsRb, width, 0, row, depthStencil, NULL);
800 }
801 }
802
803
804 /**
805 * Convert the stencil buffer from 8bpp to 32bpp depth/stencil.
806 * \param stencilRb the stencil renderbuffer to promote
807 */
808 void
809 _mesa_promote_stencil(struct gl_context *ctx, struct gl_renderbuffer *stencilRb)
810 {
811 const GLsizei width = stencilRb->Width;
812 const GLsizei height = stencilRb->Height;
813 GLubyte *data;
814 GLint i, j, k;
815
816 ASSERT(stencilRb->Format == MESA_FORMAT_S8);
817 ASSERT(stencilRb->Data);
818
819 data = (GLubyte *) stencilRb->Data;
820 stencilRb->Data = NULL;
821 stencilRb->AllocStorage(ctx, stencilRb, GL_DEPTH24_STENCIL8_EXT,
822 width, height);
823
824 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
825
826 k = 0;
827 for (i = 0; i < height; i++) {
828 GLuint depthStencil[MAX_WIDTH];
829 for (j = 0; j < width; j++) {
830 depthStencil[j] = data[k++];
831 }
832 stencilRb->PutRow(ctx, stencilRb, width, 0, i, depthStencil, NULL);
833 }
834 free(data);
835 }