2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 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 renderbuffer with depth and stencil
44 * adaptors, each with the right kind of depth/stencil Get/Put functions.
49 nop_get_pointer(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLint x
, GLint y
)
56 * Delete a depth or stencil renderbuffer.
59 delete_wrapper(struct gl_renderbuffer
*rb
)
61 struct gl_renderbuffer
*dsrb
= rb
->Wrapped
;
63 assert(rb
->InternalFormat
== GL_DEPTH_COMPONENT24
||
64 rb
->InternalFormat
== GL_STENCIL_INDEX8_EXT
);
65 /* decrement refcount on the wrapped buffer and delete it if necessary */
67 if (dsrb
->RefCount
<= 0) {
74 /*======================================================================
75 * Depth wrapper around depth/stencil renderbuffer
79 get_row_z24(GLcontext
*ctx
, struct gl_renderbuffer
*z24rb
, GLuint count
,
80 GLint x
, GLint y
, void *values
)
82 struct gl_renderbuffer
*dsrb
= z24rb
->Wrapped
;
83 GLuint temp
[MAX_WIDTH
], i
;
84 GLuint
*dst
= (GLuint
*) values
;
85 const GLuint
*src
= (const GLuint
*) dsrb
->GetPointer(ctx
, dsrb
, x
, y
);
86 ASSERT(z24rb
->DataType
== GL_UNSIGNED_INT
);
87 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
89 dsrb
->GetRow(ctx
, dsrb
, count
, x
, y
, temp
);
92 for (i
= 0; i
< count
; i
++) {
98 get_values_z24(GLcontext
*ctx
, struct gl_renderbuffer
*z24rb
, GLuint count
,
99 const GLint x
[], const GLint y
[], void *values
)
101 struct gl_renderbuffer
*dsrb
= z24rb
->Wrapped
;
102 GLuint temp
[MAX_WIDTH
], i
;
103 GLuint
*dst
= (GLuint
*) values
;
104 ASSERT(z24rb
->DataType
== GL_UNSIGNED_INT
);
105 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
106 ASSERT(count
<= MAX_WIDTH
);
107 /* don't bother trying direct access */
108 dsrb
->GetValues(ctx
, dsrb
, count
, x
, y
, temp
);
109 for (i
= 0; i
< count
; i
++) {
110 dst
[i
] = temp
[i
] >> 8;
115 put_row_z24(GLcontext
*ctx
, struct gl_renderbuffer
*z24rb
, GLuint count
,
116 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
118 struct gl_renderbuffer
*dsrb
= z24rb
->Wrapped
;
119 const GLuint
*src
= (const GLuint
*) values
;
120 GLuint
*dst
= (GLuint
*) dsrb
->GetPointer(ctx
, dsrb
, x
, y
);
121 ASSERT(z24rb
->DataType
== GL_UNSIGNED_INT
);
122 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
126 for (i
= 0; i
< count
; i
++) {
127 if (!mask
|| mask
[i
]) {
128 dst
[i
] = (src
[i
] << 8) | (dst
[i
] & 0xff);
133 /* get, modify, put */
134 GLuint temp
[MAX_WIDTH
], i
;
135 dsrb
->GetRow(ctx
, dsrb
, count
, x
, y
, temp
);
136 for (i
= 0; i
< count
; i
++) {
137 if (!mask
|| mask
[i
]) {
138 temp
[i
] = (src
[i
] << 8) | (temp
[i
] & 0xff);
141 dsrb
->PutRow(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
146 put_mono_row_z24(GLcontext
*ctx
, struct gl_renderbuffer
*z24rb
, GLuint count
,
147 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
149 struct gl_renderbuffer
*dsrb
= z24rb
->Wrapped
;
150 const GLuint shiftedVal
= *((GLuint
*) value
) << 8;
151 GLuint
*dst
= (GLuint
*) dsrb
->GetPointer(ctx
, dsrb
, x
, y
);
152 ASSERT(z24rb
->DataType
== GL_UNSIGNED_INT
);
153 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
157 for (i
= 0; i
< count
; i
++) {
158 if (!mask
|| mask
[i
]) {
159 dst
[i
] = shiftedVal
| (dst
[i
] & 0xff);
164 /* get, modify, put */
165 GLuint temp
[MAX_WIDTH
], i
;
166 dsrb
->GetRow(ctx
, dsrb
, count
, x
, y
, temp
);
167 for (i
= 0; i
< count
; i
++) {
168 if (!mask
|| mask
[i
]) {
169 temp
[i
] = shiftedVal
| (temp
[i
] & 0xff);
172 dsrb
->PutRow(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
177 put_values_z24(GLcontext
*ctx
, struct gl_renderbuffer
*z24rb
, GLuint count
,
178 const GLint x
[], const GLint y
[],
179 const void *values
, const GLubyte
*mask
)
181 struct gl_renderbuffer
*dsrb
= z24rb
->Wrapped
;
182 const GLubyte
*src
= (const GLubyte
*) values
;
183 ASSERT(z24rb
->DataType
== GL_UNSIGNED_INT
);
184 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
185 if (dsrb
->GetPointer(ctx
, dsrb
, 0, 0)) {
188 for (i
= 0; i
< count
; i
++) {
189 if (!mask
|| mask
[i
]) {
190 GLuint
*dst
= (GLuint
*) dsrb
->GetPointer(ctx
, dsrb
, x
[i
], y
[i
]);
191 *dst
= (src
[i
] << 8) | (*dst
& 0xff);
196 /* get, modify, put */
197 GLuint temp
[MAX_WIDTH
], i
;
198 dsrb
->GetValues(ctx
, dsrb
, count
, x
, y
, temp
);
199 for (i
= 0; i
< count
; i
++) {
200 if (!mask
|| mask
[i
]) {
201 temp
[i
] = (src
[i
] << 8) | (temp
[i
] & 0xff);
204 dsrb
->PutValues(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
209 put_mono_values_z24(GLcontext
*ctx
, struct gl_renderbuffer
*z24rb
,
210 GLuint count
, const GLint x
[], const GLint y
[],
211 const void *value
, const GLubyte
*mask
)
213 struct gl_renderbuffer
*dsrb
= z24rb
->Wrapped
;
214 GLuint temp
[MAX_WIDTH
], i
;
215 const GLuint shiftedVal
= *((GLuint
*) value
) << 8;
216 /* get, modify, put */
217 dsrb
->GetValues(ctx
, dsrb
, count
, x
, y
, temp
);
218 for (i
= 0; i
< count
; i
++) {
219 if (!mask
|| mask
[i
]) {
220 temp
[i
] = shiftedVal
| (temp
[i
] & 0xff);
223 dsrb
->PutValues(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
228 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
229 * a depth renderbuffer.
230 * \return new depth renderbuffer
232 struct gl_renderbuffer
*
233 _mesa_new_z24_renderbuffer_wrapper(GLcontext
*ctx
,
234 struct gl_renderbuffer
*dsrb
)
236 struct gl_renderbuffer
*z24rb
;
238 ASSERT(dsrb
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
);
239 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
241 z24rb
= _mesa_new_renderbuffer(ctx
, 0);
245 z24rb
->Wrapped
= dsrb
;
246 z24rb
->Name
= dsrb
->Name
;
248 z24rb
->Width
= dsrb
->Width
;
249 z24rb
->Height
= dsrb
->Height
;
250 z24rb
->InternalFormat
= GL_DEPTH_COMPONENT24_ARB
;
251 z24rb
->_BaseFormat
= GL_DEPTH_COMPONENT
;
252 z24rb
->DataType
= GL_UNSIGNED_INT
;
253 z24rb
->DepthBits
= 24;
255 z24rb
->Delete
= delete_wrapper
;
256 z24rb
->GetPointer
= nop_get_pointer
;
257 z24rb
->GetRow
= get_row_z24
;
258 z24rb
->GetValues
= get_values_z24
;
259 z24rb
->PutRow
= put_row_z24
;
260 z24rb
->PutRowRGB
= NULL
;
261 z24rb
->PutMonoRow
= put_mono_row_z24
;
262 z24rb
->PutValues
= put_values_z24
;
263 z24rb
->PutMonoValues
= put_mono_values_z24
;
269 /*======================================================================
270 * Stencil wrapper around depth/stencil renderbuffer
274 get_row_s8(GLcontext
*ctx
, struct gl_renderbuffer
*s8rb
, GLuint count
,
275 GLint x
, GLint y
, void *values
)
277 struct gl_renderbuffer
*dsrb
= s8rb
->Wrapped
;
278 GLuint temp
[MAX_WIDTH
], i
;
279 GLubyte
*dst
= (GLubyte
*) values
;
280 const GLuint
*src
= (const GLuint
*) dsrb
->GetPointer(ctx
, dsrb
, x
, y
);
281 ASSERT(s8rb
->DataType
== GL_UNSIGNED_BYTE
);
282 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
284 dsrb
->GetRow(ctx
, dsrb
, count
, x
, y
, temp
);
287 for (i
= 0; i
< count
; i
++) {
288 dst
[i
] = src
[i
] & 0xff;
293 get_values_s8(GLcontext
*ctx
, struct gl_renderbuffer
*s8rb
, GLuint count
,
294 const GLint x
[], const GLint y
[], void *values
)
296 struct gl_renderbuffer
*dsrb
= s8rb
->Wrapped
;
297 GLuint temp
[MAX_WIDTH
], i
;
298 GLubyte
*dst
= (GLubyte
*) values
;
299 ASSERT(s8rb
->DataType
== GL_UNSIGNED_BYTE
);
300 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
301 ASSERT(count
<= MAX_WIDTH
);
302 /* don't bother trying direct access */
303 dsrb
->GetValues(ctx
, dsrb
, count
, x
, y
, temp
);
304 for (i
= 0; i
< count
; i
++) {
305 dst
[i
] = temp
[i
] & 0xff;
310 put_row_s8(GLcontext
*ctx
, struct gl_renderbuffer
*s8rb
, GLuint count
,
311 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
313 struct gl_renderbuffer
*dsrb
= s8rb
->Wrapped
;
314 const GLubyte
*src
= (const GLubyte
*) values
;
315 GLuint
*dst
= (GLuint
*) dsrb
->GetPointer(ctx
, dsrb
, x
, y
);
316 ASSERT(s8rb
->DataType
== GL_UNSIGNED_BYTE
);
317 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
321 for (i
= 0; i
< count
; i
++) {
322 if (!mask
|| mask
[i
]) {
323 dst
[i
] = (dst
[i
] & 0xffffff00) | src
[i
];
328 /* get, modify, put */
329 GLuint temp
[MAX_WIDTH
], i
;
330 dsrb
->GetRow(ctx
, dsrb
, count
, x
, y
, temp
);
331 for (i
= 0; i
< count
; i
++) {
332 if (!mask
|| mask
[i
]) {
333 temp
[i
] = (temp
[i
] & 0xffffff00) | src
[i
];
336 dsrb
->PutRow(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
341 put_mono_row_s8(GLcontext
*ctx
, struct gl_renderbuffer
*s8rb
, GLuint count
,
342 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
344 struct gl_renderbuffer
*dsrb
= s8rb
->Wrapped
;
345 const GLubyte val
= *((GLubyte
*) value
);
346 GLuint
*dst
= (GLuint
*) dsrb
->GetPointer(ctx
, dsrb
, x
, y
);
347 ASSERT(s8rb
->DataType
== GL_UNSIGNED_BYTE
);
348 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
352 for (i
= 0; i
< count
; i
++) {
353 if (!mask
|| mask
[i
]) {
354 dst
[i
] = (dst
[i
] & 0xffffff00) | val
;
359 /* get, modify, put */
360 GLuint temp
[MAX_WIDTH
], i
;
361 dsrb
->GetRow(ctx
, dsrb
, count
, x
, y
, temp
);
362 for (i
= 0; i
< count
; i
++) {
363 if (!mask
|| mask
[i
]) {
364 temp
[i
] = (temp
[i
] & 0xffffff00) | val
;
367 dsrb
->PutRow(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
372 put_values_s8(GLcontext
*ctx
, struct gl_renderbuffer
*s8rb
, GLuint count
,
373 const GLint x
[], const GLint y
[],
374 const void *values
, const GLubyte
*mask
)
376 struct gl_renderbuffer
*dsrb
= s8rb
->Wrapped
;
377 const GLubyte
*src
= (const GLubyte
*) values
;
378 ASSERT(s8rb
->DataType
== GL_UNSIGNED_BYTE
);
379 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
380 if (dsrb
->GetPointer(ctx
, dsrb
, 0, 0)) {
383 for (i
= 0; i
< count
; i
++) {
384 if (!mask
|| mask
[i
]) {
385 GLuint
*dst
= (GLuint
*) dsrb
->GetPointer(ctx
, dsrb
, x
[i
], y
[i
]);
386 *dst
= (*dst
& 0xffffff00) | src
[i
];
391 /* get, modify, put */
392 GLuint temp
[MAX_WIDTH
], i
;
393 dsrb
->GetValues(ctx
, dsrb
, count
, x
, y
, temp
);
394 for (i
= 0; i
< count
; i
++) {
395 if (!mask
|| mask
[i
]) {
396 temp
[i
] = (temp
[i
] & 0xffffff00) | src
[i
];
399 dsrb
->PutValues(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
404 put_mono_values_s8(GLcontext
*ctx
, struct gl_renderbuffer
*s8rb
, GLuint count
,
405 const GLint x
[], const GLint y
[],
406 const void *value
, const GLubyte
*mask
)
408 struct gl_renderbuffer
*dsrb
= s8rb
->Wrapped
;
409 GLuint temp
[MAX_WIDTH
], i
;
410 const GLubyte val
= *((GLubyte
*) value
);
411 /* get, modify, put */
412 dsrb
->GetValues(ctx
, dsrb
, count
, x
, y
, temp
);
413 for (i
= 0; i
< count
; i
++) {
414 if (!mask
|| mask
[i
]) {
415 temp
[i
] = (temp
[i
] & 0xffffff) | val
;
418 dsrb
->PutValues(ctx
, dsrb
, count
, x
, y
, temp
, mask
);
423 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
424 * a stencil renderbuffer.
425 * \return new stencil renderbuffer
427 struct gl_renderbuffer
*
428 _mesa_new_s8_renderbuffer_wrapper(GLcontext
*ctx
, struct gl_renderbuffer
*dsrb
)
430 struct gl_renderbuffer
*s8rb
;
432 ASSERT(dsrb
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
);
433 ASSERT(dsrb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
435 s8rb
= _mesa_new_renderbuffer(ctx
, 0);
439 s8rb
->Wrapped
= dsrb
;
440 s8rb
->Name
= dsrb
->Name
;
442 s8rb
->Width
= dsrb
->Width
;
443 s8rb
->Height
= dsrb
->Height
;
444 s8rb
->InternalFormat
= GL_STENCIL_INDEX8_EXT
;
445 s8rb
->_BaseFormat
= GL_STENCIL_INDEX
;
446 s8rb
->DataType
= GL_UNSIGNED_BYTE
;
447 s8rb
->StencilBits
= 8;
449 s8rb
->Delete
= delete_wrapper
;
450 s8rb
->GetPointer
= nop_get_pointer
;
451 s8rb
->GetRow
= get_row_s8
;
452 s8rb
->GetValues
= get_values_s8
;
453 s8rb
->PutRow
= put_row_s8
;
454 s8rb
->PutRowRGB
= NULL
;
455 s8rb
->PutMonoRow
= put_mono_row_s8
;
456 s8rb
->PutValues
= put_values_s8
;
457 s8rb
->PutMonoValues
= put_mono_values_s8
;
464 * Merge data from a depth renderbuffer and a stencil renderbuffer into a
465 * combined depth/stencil renderbuffer.
468 _mesa_merge_depth_stencil_buffers(GLcontext
*ctx
,
469 struct gl_renderbuffer
*dest
,
470 struct gl_renderbuffer
*depth
,
471 struct gl_renderbuffer
*stencil
)
473 GLuint depthVals
[MAX_WIDTH
];
474 GLubyte stencilVals
[MAX_WIDTH
];
475 GLuint combined
[MAX_WIDTH
];
482 ASSERT(dest
->InternalFormat
== GL_DEPTH24_STENCIL8_EXT
);
483 ASSERT(dest
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
484 ASSERT(depth
->InternalFormat
== GL_DEPTH_COMPONENT24
);
485 ASSERT(depth
->DataType
== GL_UNSIGNED_INT
);
486 ASSERT(stencil
->InternalFormat
== GL_STENCIL_INDEX8_EXT
);
487 ASSERT(stencil
->DataType
== GL_UNSIGNED_BYTE
);
489 ASSERT(dest
->Width
== depth
->Width
);
490 ASSERT(dest
->Height
== depth
->Height
);
491 ASSERT(dest
->Width
== stencil
->Width
);
492 ASSERT(dest
->Height
== stencil
->Height
);
495 for (row
= 0; row
< dest
->Height
; row
++) {
497 depth
->GetRow(ctx
, depth
, width
, 0, row
, depthVals
);
498 stencil
->GetRow(ctx
, stencil
, width
, 0, row
, stencilVals
);
499 for (i
= 0; i
< width
; i
++) {
500 combined
[i
] = (depthVals
[i
] << 8) | stencilVals
[i
];
502 dest
->PutRow(ctx
, dest
, width
, 0, row
, combined
, NULL
);
508 * Split combined depth/stencil renderbuffer data into separate depth/stencil
512 _mesa_split_depth_stencil_buffer(GLcontext
*ctx
,
513 struct gl_renderbuffer
*source
,
514 struct gl_renderbuffer
*depth
,
515 struct gl_renderbuffer
*stencil
)
517 GLuint depthVals
[MAX_WIDTH
];
518 GLubyte stencilVals
[MAX_WIDTH
];
519 GLuint combined
[MAX_WIDTH
];
526 ASSERT(source
->InternalFormat
== GL_DEPTH24_STENCIL8_EXT
);
527 ASSERT(source
->DataType
== GL_UNSIGNED_INT_24_8_EXT
);
528 ASSERT(depth
->InternalFormat
== GL_DEPTH_COMPONENT24
);
529 ASSERT(depth
->DataType
== GL_UNSIGNED_INT
);
530 ASSERT(stencil
->InternalFormat
== GL_STENCIL_INDEX8_EXT
);
531 ASSERT(stencil
->DataType
== GL_UNSIGNED_BYTE
);
533 ASSERT(source
->Width
== depth
->Width
);
534 ASSERT(source
->Height
== depth
->Height
);
535 ASSERT(source
->Width
== stencil
->Width
);
536 ASSERT(source
->Height
== stencil
->Height
);
538 width
= source
->Width
;
539 for (row
= 0; row
< source
->Height
; row
++) {
541 source
->GetRow(ctx
, source
, width
, 0, row
, combined
);
542 for (i
= 0; i
< width
; i
++) {
543 depthVals
[i
] = combined
[i
] >> 8;
544 stencilVals
[i
] = combined
[i
] & 0xff;
546 depth
->PutRow(ctx
, depth
, width
, 0, row
, depthVals
, NULL
);
547 stencil
->PutRow(ctx
, stencil
, width
, 0, row
, stencilVals
, NULL
);