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