Merge commit 'origin/gallium-0.1' into gallium-0.2
[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 "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 renderbuffer with depth and stencil
44 * 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 struct gl_renderbuffer *dsrb = rb->Wrapped;
66 ASSERT(dsrb);
67 ASSERT(rb->_ActualFormat == GL_DEPTH_COMPONENT24 ||
68 rb->_ActualFormat == GL_STENCIL_INDEX8_EXT);
69 /* decrement refcount on the wrapped buffer and delete it if necessary */
70 dsrb->RefCount--;
71 if (dsrb->RefCount <= 0) {
72 dsrb->Delete(dsrb);
73 }
74 _mesa_free(rb);
75 }
76
77
78 /**
79 * Realloc storage for wrapper.
80 */
81 static GLboolean
82 alloc_wrapper_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
83 GLenum internalFormat, GLuint width, GLuint height)
84 {
85 /* just pass this on to the wrapped renderbuffer */
86 struct gl_renderbuffer *dsrb = rb->Wrapped;
87 GLboolean retVal;
88
89 (void) internalFormat;
90
91 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
92
93 retVal = dsrb->AllocStorage(ctx, dsrb, dsrb->InternalFormat, width, height);
94 if (retVal) {
95 rb->Width = width;
96 rb->Height = height;
97 }
98 return retVal;
99 }
100
101
102
103
104 /*======================================================================
105 * Depth wrapper around depth/stencil renderbuffer
106 */
107
108 static void
109 get_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
110 GLint x, GLint y, void *values)
111 {
112 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
113 GLuint temp[MAX_WIDTH], i;
114 GLuint *dst = (GLuint *) values;
115 const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
116 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
117 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
118 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
119 if (!src) {
120 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
121 src = temp;
122 }
123 for (i = 0; i < count; i++) {
124 dst[i] = src[i] >> 8;
125 }
126 }
127
128 static void
129 get_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
130 const GLint x[], const GLint y[], void *values)
131 {
132 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
133 GLuint temp[MAX_WIDTH], i;
134 GLuint *dst = (GLuint *) values;
135 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
136 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
137 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
138 ASSERT(count <= MAX_WIDTH);
139 /* don't bother trying direct access */
140 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
141 for (i = 0; i < count; i++) {
142 dst[i] = temp[i] >> 8;
143 }
144 }
145
146 static void
147 put_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
148 GLint x, GLint y, const void *values, const GLubyte *mask)
149 {
150 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
151 const GLuint *src = (const GLuint *) values;
152 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
153 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
154 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
155 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
156 if (dst) {
157 /* direct access */
158 GLuint i;
159 for (i = 0; i < count; i++) {
160 if (!mask || mask[i]) {
161 dst[i] = (src[i] << 8) | (dst[i] & 0xff);
162 }
163 }
164 }
165 else {
166 /* get, modify, put */
167 GLuint temp[MAX_WIDTH], i;
168 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
169 for (i = 0; i < count; i++) {
170 if (!mask || mask[i]) {
171 temp[i] = (src[i] << 8) | (temp[i] & 0xff);
172 }
173 }
174 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
175 }
176 }
177
178 static void
179 put_mono_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
180 GLint x, GLint y, const void *value, const GLubyte *mask)
181 {
182 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
183 const GLuint shiftedVal = *((GLuint *) value) << 8;
184 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
185 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
186 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
187 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
188 if (dst) {
189 /* direct access */
190 GLuint i;
191 for (i = 0; i < count; i++) {
192 if (!mask || mask[i]) {
193 dst[i] = shiftedVal | (dst[i] & 0xff);
194 }
195 }
196 }
197 else {
198 /* get, modify, put */
199 GLuint temp[MAX_WIDTH], i;
200 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
201 for (i = 0; i < count; i++) {
202 if (!mask || mask[i]) {
203 temp[i] = shiftedVal | (temp[i] & 0xff);
204 }
205 }
206 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
207 }
208 }
209
210 static void
211 put_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
212 const GLint x[], const GLint y[],
213 const void *values, const GLubyte *mask)
214 {
215 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
216 const GLuint *src = (const GLuint *) values;
217 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
218 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
219 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
220 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
221 /* direct access */
222 GLuint i;
223 for (i = 0; i < count; i++) {
224 if (!mask || mask[i]) {
225 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
226 *dst = (src[i] << 8) | (*dst & 0xff);
227 }
228 }
229 }
230 else {
231 /* get, modify, put */
232 GLuint temp[MAX_WIDTH], i;
233 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
234 for (i = 0; i < count; i++) {
235 if (!mask || mask[i]) {
236 temp[i] = (src[i] << 8) | (temp[i] & 0xff);
237 }
238 }
239 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
240 }
241 }
242
243 static void
244 put_mono_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb,
245 GLuint count, const GLint x[], const GLint y[],
246 const void *value, const GLubyte *mask)
247 {
248 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
249 GLuint temp[MAX_WIDTH], i;
250 const GLuint shiftedVal = *((GLuint *) value) << 8;
251 /* get, modify, put */
252 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
253 for (i = 0; i < count; i++) {
254 if (!mask || mask[i]) {
255 temp[i] = shiftedVal | (temp[i] & 0xff);
256 }
257 }
258 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
259 }
260
261
262 /**
263 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
264 * a depth renderbuffer.
265 * \return new depth renderbuffer
266 */
267 struct gl_renderbuffer *
268 _mesa_new_z24_renderbuffer_wrapper(GLcontext *ctx,
269 struct gl_renderbuffer *dsrb)
270 {
271 struct gl_renderbuffer *z24rb;
272
273 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
274 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
275
276 z24rb = _mesa_new_renderbuffer(ctx, 0);
277 if (!z24rb)
278 return NULL;
279
280 z24rb->Wrapped = dsrb;
281 z24rb->Name = dsrb->Name;
282 z24rb->RefCount = 1;
283 z24rb->Width = dsrb->Width;
284 z24rb->Height = dsrb->Height;
285 z24rb->InternalFormat = GL_DEPTH_COMPONENT24;
286 z24rb->_ActualFormat = GL_DEPTH_COMPONENT24;
287 z24rb->_BaseFormat = GL_DEPTH_COMPONENT;
288 z24rb->DataType = GL_UNSIGNED_INT;
289 z24rb->DepthBits = 24;
290 z24rb->Data = NULL;
291 z24rb->Delete = delete_wrapper;
292 z24rb->AllocStorage = alloc_wrapper_storage;
293 z24rb->GetPointer = nop_get_pointer;
294 z24rb->GetRow = get_row_z24;
295 z24rb->GetValues = get_values_z24;
296 z24rb->PutRow = put_row_z24;
297 z24rb->PutRowRGB = NULL;
298 z24rb->PutMonoRow = put_mono_row_z24;
299 z24rb->PutValues = put_values_z24;
300 z24rb->PutMonoValues = put_mono_values_z24;
301
302 return z24rb;
303 }
304
305
306 /*======================================================================
307 * Stencil wrapper around depth/stencil renderbuffer
308 */
309
310 static void
311 get_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
312 GLint x, GLint y, void *values)
313 {
314 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
315 GLuint temp[MAX_WIDTH], i;
316 GLubyte *dst = (GLubyte *) values;
317 const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
318 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
319 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
320 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
321 if (!src) {
322 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
323 src = temp;
324 }
325 for (i = 0; i < count; i++) {
326 dst[i] = src[i] & 0xff;
327 }
328 }
329
330 static void
331 get_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
332 const GLint x[], const GLint y[], void *values)
333 {
334 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
335 GLuint temp[MAX_WIDTH], i;
336 GLubyte *dst = (GLubyte *) values;
337 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
338 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
339 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
340 ASSERT(count <= MAX_WIDTH);
341 /* don't bother trying direct access */
342 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
343 for (i = 0; i < count; i++) {
344 dst[i] = temp[i] & 0xff;
345 }
346 }
347
348 static void
349 put_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
350 GLint x, GLint y, const void *values, const GLubyte *mask)
351 {
352 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
353 const GLubyte *src = (const GLubyte *) values;
354 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
355 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
356 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
357 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
358 if (dst) {
359 /* direct access */
360 GLuint i;
361 for (i = 0; i < count; i++) {
362 if (!mask || mask[i]) {
363 dst[i] = (dst[i] & 0xffffff00) | src[i];
364 }
365 }
366 }
367 else {
368 /* get, modify, put */
369 GLuint temp[MAX_WIDTH], i;
370 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
371 for (i = 0; i < count; i++) {
372 if (!mask || mask[i]) {
373 temp[i] = (temp[i] & 0xffffff00) | src[i];
374 }
375 }
376 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
377 }
378 }
379
380 static void
381 put_mono_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
382 GLint x, GLint y, const void *value, const GLubyte *mask)
383 {
384 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
385 const GLubyte val = *((GLubyte *) value);
386 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
387 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
388 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
389 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
390 if (dst) {
391 /* direct access */
392 GLuint i;
393 for (i = 0; i < count; i++) {
394 if (!mask || mask[i]) {
395 dst[i] = (dst[i] & 0xffffff00) | val;
396 }
397 }
398 }
399 else {
400 /* get, modify, put */
401 GLuint temp[MAX_WIDTH], i;
402 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
403 for (i = 0; i < count; i++) {
404 if (!mask || mask[i]) {
405 temp[i] = (temp[i] & 0xffffff00) | val;
406 }
407 }
408 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
409 }
410 }
411
412 static void
413 put_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
414 const GLint x[], const GLint y[],
415 const void *values, const GLubyte *mask)
416 {
417 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
418 const GLubyte *src = (const GLubyte *) values;
419 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
420 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
421 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
422 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
423 /* direct access */
424 GLuint i;
425 for (i = 0; i < count; i++) {
426 if (!mask || mask[i]) {
427 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
428 *dst = (*dst & 0xffffff00) | src[i];
429 }
430 }
431 }
432 else {
433 /* get, modify, put */
434 GLuint temp[MAX_WIDTH], i;
435 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
436 for (i = 0; i < count; i++) {
437 if (!mask || mask[i]) {
438 temp[i] = (temp[i] & 0xffffff00) | src[i];
439 }
440 }
441 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
442 }
443 }
444
445 static void
446 put_mono_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
447 const GLint x[], const GLint y[],
448 const void *value, const GLubyte *mask)
449 {
450 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
451 GLuint temp[MAX_WIDTH], i;
452 const GLubyte val = *((GLubyte *) value);
453 /* get, modify, put */
454 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
455 for (i = 0; i < count; i++) {
456 if (!mask || mask[i]) {
457 temp[i] = (temp[i] & 0xffffff) | val;
458 }
459 }
460 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
461 }
462
463
464 /**
465 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
466 * a stencil renderbuffer.
467 * \return new stencil renderbuffer
468 */
469 struct gl_renderbuffer *
470 _mesa_new_s8_renderbuffer_wrapper(GLcontext *ctx, struct gl_renderbuffer *dsrb)
471 {
472 struct gl_renderbuffer *s8rb;
473
474 ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
475 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
476
477 s8rb = _mesa_new_renderbuffer(ctx, 0);
478 if (!s8rb)
479 return NULL;
480
481 s8rb->Wrapped = dsrb;
482 s8rb->Name = dsrb->Name;
483 s8rb->RefCount = 1;
484 s8rb->Width = dsrb->Width;
485 s8rb->Height = dsrb->Height;
486 s8rb->InternalFormat = GL_STENCIL_INDEX8_EXT;
487 s8rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
488 s8rb->_BaseFormat = GL_STENCIL_INDEX;
489 s8rb->DataType = GL_UNSIGNED_BYTE;
490 s8rb->StencilBits = 8;
491 s8rb->Data = NULL;
492 s8rb->Delete = delete_wrapper;
493 s8rb->AllocStorage = alloc_wrapper_storage;
494 s8rb->GetPointer = nop_get_pointer;
495 s8rb->GetRow = get_row_s8;
496 s8rb->GetValues = get_values_s8;
497 s8rb->PutRow = put_row_s8;
498 s8rb->PutRowRGB = NULL;
499 s8rb->PutMonoRow = put_mono_row_s8;
500 s8rb->PutValues = put_values_s8;
501 s8rb->PutMonoValues = put_mono_values_s8;
502
503 return s8rb;
504 }
505
506
507
508 /**
509 ** The following functions are useful for hardware drivers that only
510 ** implement combined depth/stencil buffers.
511 ** The GL_EXT_framebuffer_object extension allows indepedent depth and
512 ** stencil buffers to be used in any combination.
513 ** Therefore, we sometimes have to merge separate depth and stencil
514 ** renderbuffers into a single depth+stencil renderbuffer. And sometimes
515 ** we have to split combined depth+stencil renderbuffers into separate
516 ** renderbuffers.
517 **/
518
519
520 /**
521 * Extract stencil values from the combined depth/stencil renderbuffer, storing
522 * the values into a separate stencil renderbuffer.
523 * \param dsRb the source depth/stencil renderbuffer
524 * \param stencilRb the destination stencil renderbuffer
525 * (either 8-bit or 32-bit)
526 */
527 void
528 _mesa_extract_stencil(GLcontext *ctx,
529 struct gl_renderbuffer *dsRb,
530 struct gl_renderbuffer *stencilRb)
531 {
532 GLuint row, width, height;
533
534 ASSERT(dsRb);
535 ASSERT(stencilRb);
536
537 ASSERT(dsRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
538 ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
539 ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT ||
540 stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT);
541 ASSERT(dsRb->Width == stencilRb->Width);
542 ASSERT(dsRb->Height == stencilRb->Height);
543
544 width = dsRb->Width;
545 height = dsRb->Height;
546
547 for (row = 0; row < height; row++) {
548 GLuint depthStencil[MAX_WIDTH];
549 dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
550 if (stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT) {
551 /* 8bpp stencil */
552 GLubyte stencil[MAX_WIDTH];
553 GLuint i;
554 for (i = 0; i < width; i++) {
555 stencil[i] = depthStencil[i] & 0xff;
556 }
557 stencilRb->PutRow(ctx, stencilRb, width, 0, row, stencil, NULL);
558 }
559 else {
560 /* 32bpp stencil */
561 /* the 24 depth bits will be ignored */
562 ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
563 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
564 stencilRb->PutRow(ctx, stencilRb, width, 0, row, depthStencil, NULL);
565 }
566 }
567 }
568
569
570 /**
571 * Copy stencil values from a stencil renderbuffer into a combined
572 * depth/stencil renderbuffer.
573 * \param dsRb the destination depth/stencil renderbuffer
574 * \param stencilRb the source stencil buffer (either 8-bit or 32-bit)
575 */
576 void
577 _mesa_insert_stencil(GLcontext *ctx,
578 struct gl_renderbuffer *dsRb,
579 struct gl_renderbuffer *stencilRb)
580 {
581 GLuint row, width, height;
582
583 ASSERT(dsRb);
584 ASSERT(stencilRb);
585
586 ASSERT(dsRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
587 ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
588 ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT ||
589 stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT);
590
591 ASSERT(dsRb->Width == stencilRb->Width);
592 ASSERT(dsRb->Height == stencilRb->Height);
593
594 width = dsRb->Width;
595 height = dsRb->Height;
596
597 for (row = 0; row < height; row++) {
598 GLuint depthStencil[MAX_WIDTH];
599
600 dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
601
602 if (stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT) {
603 /* 8bpp stencil */
604 GLubyte stencil[MAX_WIDTH];
605 GLuint i;
606 stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
607 for (i = 0; i < width; i++) {
608 depthStencil[i] = (depthStencil[i] & 0xffffff00) | stencil[i];
609 }
610 }
611 else {
612 /* 32bpp stencil buffer */
613 GLuint stencil[MAX_WIDTH], i;
614 ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
615 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
616 stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
617 for (i = 0; i < width; i++) {
618 depthStencil[i]
619 = (depthStencil[i] & 0xffffff00) | (stencil[i] & 0xff);
620 }
621 }
622
623 dsRb->PutRow(ctx, dsRb, width, 0, row, depthStencil, NULL);
624 }
625 }
626
627
628 /**
629 * Convert the stencil buffer from 8bpp to 32bpp depth/stencil.
630 * \param stencilRb the stencil renderbuffer to promote
631 */
632 void
633 _mesa_promote_stencil(GLcontext *ctx, struct gl_renderbuffer *stencilRb)
634 {
635 const GLsizei width = stencilRb->Width;
636 const GLsizei height = stencilRb->Height;
637 GLubyte *data;
638 GLint i, j, k;
639
640 ASSERT(stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT);
641 ASSERT(stencilRb->Data);
642
643 data = (GLubyte *) stencilRb->Data;
644 stencilRb->Data = NULL;
645 stencilRb->AllocStorage(ctx, stencilRb, GL_DEPTH24_STENCIL8_EXT,
646 width, height);
647
648 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
649
650 k = 0;
651 for (i = 0; i < height; i++) {
652 GLuint depthStencil[MAX_WIDTH];
653 for (j = 0; j < width; j++) {
654 depthStencil[j] = data[k++];
655 }
656 stencilRb->PutRow(ctx, stencilRb, width, 0, i, depthStencil, NULL);
657 }
658 _mesa_free(data);
659
660 stencilRb->_BaseFormat = GL_DEPTH_STENCIL_EXT;
661 }