ab62c97fe5ac5728b71cf3dac2a5363acee01b13
2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
30 #include "depthstencil.h"
31 #include "renderbuffer.h"
35 * Adaptor/wrappers for GL_DEPTH_STENCIL renderbuffers.
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.
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.
49 nop_get_pointer(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLint x
, GLint y
)
60 * Delete a depth or stencil wrapper renderbuffer.
63 delete_wrapper(struct gl_renderbuffer
*rb
)
65 ASSERT(rb
->Format
== MESA_FORMAT_S8
||
66 rb
->Format
== MESA_FORMAT_X8_Z24
);
67 _mesa_reference_renderbuffer(&rb
->Wrapped
, NULL
);
73 * Realloc storage for wrapper.
76 alloc_wrapper_storage(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
77 GLenum internalFormat
, GLuint width
, GLuint height
)
79 /* just pass this on to the wrapped renderbuffer */
80 struct gl_renderbuffer
*dsrb
= rb
->Wrapped
;
83 (void) internalFormat
;
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
);
90 retVal
= dsrb
->AllocStorage(ctx
, dsrb
, dsrb
->InternalFormat
, width
, height
);
94 rb
->RowStride
= dsrb
->RowStride
;
102 /*======================================================================
103 * Depth wrapper around depth/stencil renderbuffer
107 get_row_z24(struct gl_context
*ctx
, struct gl_renderbuffer
*z24rb
, GLuint count
,
108 GLint x
, GLint y
, void *values
)
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
);
117 dsrb
->GetRow(ctx
, dsrb
, count
, x
, y
, temp
);
120 if (dsrb
->Format
== MESA_FORMAT_Z24_S8
) {
121 for (i
= 0; i
< count
; i
++) {
122 dst
[i
] = src
[i
] >> 8;
126 assert(dsrb
->Format
== MESA_FORMAT_S8_Z24
);
127 for (i
= 0; i
< count
; i
++) {
128 dst
[i
] = src
[i
] & 0xffffff;
134 get_values_z24(struct gl_context
*ctx
, struct gl_renderbuffer
*z24rb
, GLuint count
,
135 const GLint x
[], const GLint y
[], void *values
)
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;
151 assert(dsrb
->Format
== MESA_FORMAT_S8_Z24
);
152 for (i
= 0; i
< count
; i
++) {
153 dst
[i
] = temp
[i
] & 0xffffff;
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
)
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
);
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);
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);
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);
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);
205 dsrb
->PutRow(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
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
)
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
);
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);
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);
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);
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);
259 dsrb
->PutRow(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
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
)
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)) {
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);
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);
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);
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);
312 dsrb
->PutValues(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
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
)
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);
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);
342 dsrb
->PutValues(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
347 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
348 * a depth renderbuffer.
349 * \return new depth renderbuffer
351 struct gl_renderbuffer
*
352 _mesa_new_z24_renderbuffer_wrapper(struct gl_context
*ctx
,
353 struct gl_renderbuffer
*dsrb
)
355 struct gl_renderbuffer
*z24rb
;
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
);
363 z24rb
= ctx
->Driver
.NewRenderbuffer(ctx
, 0);
367 /* NOTE: need to do manual refcounting here */
368 z24rb
->Wrapped
= dsrb
;
371 z24rb
->Name
= dsrb
->Name
;
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
;
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
;
396 /*======================================================================
397 * Stencil wrapper around depth/stencil renderbuffer
401 get_row_s8(struct gl_context
*ctx
, struct gl_renderbuffer
*s8rb
, GLuint count
,
402 GLint x
, GLint y
, void *values
)
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
);
411 dsrb
->GetRow(ctx
, dsrb
, count
, x
, y
, temp
);
414 if (dsrb
->Format
== MESA_FORMAT_Z24_S8
) {
415 for (i
= 0; i
< count
; i
++) {
416 dst
[i
] = src
[i
] & 0xff;
420 assert(dsrb
->Format
== MESA_FORMAT_S8_Z24
);
421 for (i
= 0; i
< count
; i
++) {
422 dst
[i
] = src
[i
] >> 24;
428 get_values_s8(struct gl_context
*ctx
, struct gl_renderbuffer
*s8rb
, GLuint count
,
429 const GLint x
[], const GLint y
[], void *values
)
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;
445 assert(dsrb
->Format
== MESA_FORMAT_S8_Z24
);
446 for (i
= 0; i
< count
; i
++) {
447 dst
[i
] = temp
[i
] >> 24;
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
)
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
);
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
];
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);
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
];
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);
499 dsrb
->PutRow(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
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
)
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
);
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
;
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);
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
;
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);
550 dsrb
->PutRow(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
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
)
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)) {
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
];
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);
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
];
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);
603 dsrb
->PutValues(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
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
)
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
;
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);
632 dsrb
->PutValues(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
637 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
638 * a stencil renderbuffer.
639 * \return new stencil renderbuffer
641 struct gl_renderbuffer
*
642 _mesa_new_s8_renderbuffer_wrapper(struct gl_context
*ctx
, struct gl_renderbuffer
*dsrb
)
644 struct gl_renderbuffer
*s8rb
;
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
);
650 s8rb
= ctx
->Driver
.NewRenderbuffer(ctx
, 0);
654 /* NOTE: need to do manual refcounting here */
655 s8rb
->Wrapped
= dsrb
;
658 s8rb
->Name
= dsrb
->Name
;
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
;
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
;
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
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)
704 _mesa_extract_stencil(struct gl_context
*ctx
,
705 struct gl_renderbuffer
*dsRb
,
706 struct gl_renderbuffer
*stencilRb
)
708 GLuint row
, width
, height
;
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
);
721 height
= dsRb
->Height
;
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
) {
728 GLubyte stencil
[MAX_WIDTH
];
730 for (i
= 0; i
< width
; i
++) {
731 stencil
[i
] = depthStencil
[i
] & 0xff;
733 stencilRb
->PutRow(ctx
, stencilRb
, width
, 0, row
, stencil
, NULL
);
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
);
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)
753 _mesa_insert_stencil(struct gl_context
*ctx
,
754 struct gl_renderbuffer
*dsRb
,
755 struct gl_renderbuffer
*stencilRb
)
757 GLuint row
, width
, height
;
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
);
767 ASSERT(dsRb
->Width
== stencilRb
->Width
);
768 ASSERT(dsRb
->Height
== stencilRb
->Height
);
771 height
= dsRb
->Height
;
773 for (row
= 0; row
< height
; row
++) {
774 GLuint depthStencil
[MAX_WIDTH
];
776 dsRb
->GetRow(ctx
, dsRb
, width
, 0, row
, depthStencil
);
778 if (stencilRb
->Format
== MESA_FORMAT_S8
) {
780 GLubyte stencil
[MAX_WIDTH
];
782 stencilRb
->GetRow(ctx
, stencilRb
, width
, 0, row
, stencil
);
783 for (i
= 0; i
< width
; i
++) {
784 depthStencil
[i
] = (depthStencil
[i
] & 0xffffff00) | stencil
[i
];
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
++) {
795 = (depthStencil
[i
] & 0xffffff00) | (stencil
[i
] & 0xff);
799 dsRb
->PutRow(ctx
, dsRb
, width
, 0, row
, depthStencil
, NULL
);
805 * Convert the stencil buffer from 8bpp to 32bpp depth/stencil.
806 * \param stencilRb the stencil renderbuffer to promote
809 _mesa_promote_stencil(struct gl_context
*ctx
, struct gl_renderbuffer
*stencilRb
)
811 const GLsizei width
= stencilRb
->Width
;
812 const GLsizei height
= stencilRb
->Height
;
816 ASSERT(stencilRb
->Format
== MESA_FORMAT_S8
);
817 ASSERT(stencilRb
->Data
);
819 data
= (GLubyte
*) stencilRb
->Data
;
820 stencilRb
->Data
= NULL
;
821 stencilRb
->AllocStorage(ctx
, stencilRb
, GL_DEPTH24_STENCIL8_EXT
,
824 ASSERT(stencilRb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
827 for (i
= 0; i
< height
; i
++) {
828 GLuint depthStencil
[MAX_WIDTH
];
829 for (j
= 0; j
< width
; j
++) {
830 depthStencil
[j
] = data
[k
++];
832 stencilRb
->PutRow(ctx
, stencilRb
, width
, 0, i
, depthStencil
, NULL
);