e2558c4859afc07e474cba8efaae2c7e68765a27
[mesa.git] / src / mesa / swrast / s_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 "main/glheader.h"
26 #include "main/imports.h"
27 #include "main/context.h"
28 #include "main/formats.h"
29 #include "main/mtypes.h"
30 #include "main/renderbuffer.h"
31 #include "swrast/s_depthstencil.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 rb->Format == MESA_FORMAT_Z32_FLOAT);
68 _mesa_reference_renderbuffer(&rb->Wrapped, NULL);
69 free(rb);
70 }
71
72
73 /**
74 * Realloc storage for wrapper.
75 */
76 static GLboolean
77 alloc_wrapper_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
78 GLenum internalFormat, GLuint width, GLuint height)
79 {
80 /* just pass this on to the wrapped renderbuffer */
81 struct gl_renderbuffer *dsrb = rb->Wrapped;
82 GLboolean retVal;
83
84 (void) internalFormat;
85
86 ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
87 dsrb->Format == MESA_FORMAT_Z24_X8 ||
88 dsrb->Format == MESA_FORMAT_S8_Z24 ||
89 dsrb->Format == MESA_FORMAT_X8_Z24);
90
91 retVal = dsrb->AllocStorage(ctx, dsrb, dsrb->InternalFormat, width, height);
92 if (retVal) {
93 rb->Width = width;
94 rb->Height = height;
95 rb->RowStride = dsrb->RowStride;
96 }
97 return retVal;
98 }
99
100
101
102
103 /*======================================================================
104 * Depth wrapper around depth/stencil renderbuffer
105 */
106
107 static void
108 get_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
109 GLint x, GLint y, void *values)
110 {
111 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
112 GLuint temp[MAX_WIDTH], i;
113 GLuint *dst = (GLuint *) values;
114 const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
115 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
116 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
117 if (!src) {
118 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
119 src = temp;
120 }
121 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
122 for (i = 0; i < count; i++) {
123 dst[i] = src[i] >> 8;
124 }
125 }
126 else {
127 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
128 for (i = 0; i < count; i++) {
129 dst[i] = src[i] & 0xffffff;
130 }
131 }
132 }
133
134 static void
135 get_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
136 const GLint x[], const GLint y[], void *values)
137 {
138 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
139 GLuint temp[MAX_WIDTH], i;
140 GLuint *dst = (GLuint *) values;
141 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
142 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
143 ASSERT(count <= MAX_WIDTH);
144 /* don't bother trying direct access */
145 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
146 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
147 for (i = 0; i < count; i++) {
148 dst[i] = temp[i] >> 8;
149 }
150 }
151 else {
152 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
153 for (i = 0; i < count; i++) {
154 dst[i] = temp[i] & 0xffffff;
155 }
156 }
157 }
158
159 static void
160 put_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
161 GLint x, GLint y, const void *values, const GLubyte *mask)
162 {
163 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
164 const GLuint *src = (const GLuint *) values;
165 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
166 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
167 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
168 if (dst) {
169 /* direct access */
170 GLuint i;
171 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
172 for (i = 0; i < count; i++) {
173 if (!mask || mask[i]) {
174 dst[i] = (src[i] << 8) | (dst[i] & 0xff);
175 }
176 }
177 }
178 else {
179 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
180 for (i = 0; i < count; i++) {
181 if (!mask || mask[i]) {
182 dst[i] = (src[i] & 0xffffff) | (dst[i] & 0xff000000);
183 }
184 }
185 }
186 }
187 else {
188 /* get, modify, put */
189 GLuint temp[MAX_WIDTH], i;
190 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
191 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
192 for (i = 0; i < count; i++) {
193 if (!mask || mask[i]) {
194 temp[i] = (src[i] << 8) | (temp[i] & 0xff);
195 }
196 }
197 }
198 else {
199 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
200 for (i = 0; i < count; i++) {
201 if (!mask || mask[i]) {
202 temp[i] = (src[i] & 0xffffff) | (temp[i] & 0xff000000);
203 }
204 }
205 }
206 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
207 }
208 }
209
210
211 static void
212 put_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
213 const GLint x[], const GLint y[],
214 const void *values, const GLubyte *mask)
215 {
216 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
217 const GLuint *src = (const GLuint *) values;
218 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
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 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
224 for (i = 0; i < count; i++) {
225 if (!mask || mask[i]) {
226 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
227 *dst = (src[i] << 8) | (*dst & 0xff);
228 }
229 }
230 }
231 else {
232 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
233 for (i = 0; i < count; i++) {
234 if (!mask || mask[i]) {
235 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
236 *dst = (src[i] & 0xffffff) | (*dst & 0xff000000);
237 }
238 }
239 }
240 }
241 else {
242 /* get, modify, put */
243 GLuint temp[MAX_WIDTH], i;
244 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
245 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
246 for (i = 0; i < count; i++) {
247 if (!mask || mask[i]) {
248 temp[i] = (src[i] << 8) | (temp[i] & 0xff);
249 }
250 }
251 }
252 else {
253 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
254 for (i = 0; i < count; i++) {
255 if (!mask || mask[i]) {
256 temp[i] = (src[i] & 0xffffff) | (temp[i] & 0xff000000);
257 }
258 }
259 }
260 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
261 }
262 }
263
264
265 /**
266 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
267 * a depth renderbuffer.
268 * \return new depth renderbuffer
269 */
270 static struct gl_renderbuffer *
271 new_z24_renderbuffer_wrapper(struct gl_context *ctx,
272 struct gl_renderbuffer *dsrb)
273 {
274 struct gl_renderbuffer *z24rb;
275
276 ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
277 dsrb->Format == MESA_FORMAT_Z24_X8 ||
278 dsrb->Format == MESA_FORMAT_S8_Z24 ||
279 dsrb->Format == MESA_FORMAT_X8_Z24);
280 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
281
282 z24rb = ctx->Driver.NewRenderbuffer(ctx, 0);
283 if (!z24rb)
284 return NULL;
285
286 /* NOTE: need to do manual refcounting here */
287 z24rb->Wrapped = dsrb;
288 dsrb->RefCount++;
289
290 z24rb->Name = dsrb->Name;
291 z24rb->RefCount = 0;
292 z24rb->Width = dsrb->Width;
293 z24rb->Height = dsrb->Height;
294 z24rb->RowStride = dsrb->RowStride;
295 z24rb->InternalFormat = GL_DEPTH_COMPONENT24;
296 z24rb->Format = MESA_FORMAT_X8_Z24;
297 z24rb->_BaseFormat = GL_DEPTH_COMPONENT;
298 z24rb->DataType = GL_UNSIGNED_INT;
299 z24rb->Data = NULL;
300 z24rb->Delete = delete_wrapper;
301 z24rb->AllocStorage = alloc_wrapper_storage;
302 z24rb->GetPointer = nop_get_pointer;
303 z24rb->GetRow = get_row_z24;
304 z24rb->GetValues = get_values_z24;
305 z24rb->PutRow = put_row_z24;
306 z24rb->PutRowRGB = NULL;
307 z24rb->PutValues = put_values_z24;
308
309 return z24rb;
310 }
311
312
313 static void
314 get_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
315 GLint x, GLint y, void *values)
316 {
317 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
318 GLfloat temp[MAX_WIDTH*2];
319 GLfloat *dst = (GLfloat *) values;
320 const GLfloat *src = (const GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y);
321 GLuint i;
322 ASSERT(z32frb->DataType == GL_FLOAT);
323 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
324 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
325 if (!src) {
326 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
327 src = temp;
328 }
329 for (i = 0; i < count; i++) {
330 dst[i] = src[i*2];
331 }
332 }
333
334 static void
335 get_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
336 const GLint x[], const GLint y[], void *values)
337 {
338 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
339 GLfloat temp[MAX_WIDTH*2];
340 GLfloat *dst = (GLfloat *) values;
341 GLuint i;
342 ASSERT(z32frb->DataType == GL_FLOAT);
343 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
344 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
345 ASSERT(count <= MAX_WIDTH);
346 /* don't bother trying direct access */
347 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
348 for (i = 0; i < count; i++) {
349 dst[i] = temp[i*2];
350 }
351 }
352
353 static void
354 put_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
355 GLint x, GLint y, const void *values, const GLubyte *mask)
356 {
357 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
358 const GLfloat *src = (const GLfloat *) values;
359 GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y);
360 ASSERT(z32frb->DataType == GL_FLOAT);
361 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
362 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
363 if (dst) {
364 /* direct access */
365 GLuint i;
366 for (i = 0; i < count; i++) {
367 if (!mask || mask[i]) {
368 dst[i*2] = src[i];
369 }
370 }
371 }
372 else {
373 /* get, modify, put */
374 GLfloat temp[MAX_WIDTH*2];
375 GLuint i;
376 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
377 for (i = 0; i < count; i++) {
378 if (!mask || mask[i]) {
379 temp[i*2] = src[i];
380 }
381 }
382 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
383 }
384 }
385
386
387 static void
388 put_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
389 const GLint x[], const GLint y[],
390 const void *values, const GLubyte *mask)
391 {
392 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
393 const GLfloat *src = (const GLfloat *) values;
394 ASSERT(z32frb->DataType == GL_FLOAT);
395 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
396 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
397 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
398 /* direct access */
399 GLuint i;
400 for (i = 0; i < count; i++) {
401 if (!mask || mask[i]) {
402 GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
403 *dst = src[i];
404 }
405 }
406 }
407 else {
408 /* get, modify, put */
409 GLfloat temp[MAX_WIDTH*2];
410 GLuint i;
411 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
412 for (i = 0; i < count; i++) {
413 if (!mask || mask[i]) {
414 temp[i*2] = src[i];
415 }
416 }
417 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
418 }
419 }
420
421
422 /**
423 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
424 * a depth renderbuffer.
425 * \return new depth renderbuffer
426 */
427 static struct gl_renderbuffer *
428 new_z32f_renderbuffer_wrapper(struct gl_context *ctx,
429 struct gl_renderbuffer *dsrb)
430 {
431 struct gl_renderbuffer *z32frb;
432
433 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
434 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
435
436 z32frb = ctx->Driver.NewRenderbuffer(ctx, 0);
437 if (!z32frb)
438 return NULL;
439
440 /* NOTE: need to do manual refcounting here */
441 z32frb->Wrapped = dsrb;
442 dsrb->RefCount++;
443
444 z32frb->Name = dsrb->Name;
445 z32frb->RefCount = 0;
446 z32frb->Width = dsrb->Width;
447 z32frb->Height = dsrb->Height;
448 z32frb->RowStride = dsrb->RowStride;
449 z32frb->InternalFormat = GL_DEPTH_COMPONENT32F;
450 z32frb->Format = MESA_FORMAT_Z32_FLOAT;
451 z32frb->_BaseFormat = GL_DEPTH_COMPONENT;
452 z32frb->DataType = GL_FLOAT;
453 z32frb->Data = NULL;
454 z32frb->Delete = delete_wrapper;
455 z32frb->AllocStorage = alloc_wrapper_storage;
456 z32frb->GetPointer = nop_get_pointer;
457 z32frb->GetRow = get_row_z32f;
458 z32frb->GetValues = get_values_z32f;
459 z32frb->PutRow = put_row_z32f;
460 z32frb->PutRowRGB = NULL;
461 z32frb->PutValues = put_values_z32f;
462
463 return z32frb;
464 }
465
466
467 /*======================================================================
468 * Stencil wrapper around depth/stencil renderbuffer
469 */
470
471 static void
472 get_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
473 GLint x, GLint y, void *values)
474 {
475 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
476 GLuint temp[MAX_WIDTH*2], i;
477 GLubyte *dst = (GLubyte *) values;
478 const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
479 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
480 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
481 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
482 if (!src) {
483 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
484 src = temp;
485 }
486 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
487 for (i = 0; i < count; i++) {
488 dst[i] = src[i*2+1] & 0xff;
489 }
490 }
491 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
492 for (i = 0; i < count; i++) {
493 dst[i] = src[i] & 0xff;
494 }
495 }
496 else {
497 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
498 for (i = 0; i < count; i++) {
499 dst[i] = src[i] >> 24;
500 }
501 }
502 }
503
504 static void
505 get_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
506 const GLint x[], const GLint y[], void *values)
507 {
508 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
509 GLuint temp[MAX_WIDTH*2], i;
510 GLubyte *dst = (GLubyte *) values;
511 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
512 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
513 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
514 ASSERT(count <= MAX_WIDTH);
515 /* don't bother trying direct access */
516 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
517 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
518 for (i = 0; i < count; i++) {
519 dst[i] = temp[i*2+1] & 0xff;
520 }
521 }
522 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
523 for (i = 0; i < count; i++) {
524 dst[i] = temp[i] & 0xff;
525 }
526 }
527 else {
528 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
529 for (i = 0; i < count; i++) {
530 dst[i] = temp[i] >> 24;
531 }
532 }
533 }
534
535 static void
536 put_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
537 GLint x, GLint y, const void *values, const GLubyte *mask)
538 {
539 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
540 const GLubyte *src = (const GLubyte *) values;
541 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
542 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
543 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
544 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
545 if (dst) {
546 /* direct access */
547 GLuint i;
548 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
549 for (i = 0; i < count; i++) {
550 if (!mask || mask[i]) {
551 dst[i*2+1] = src[i];
552 }
553 }
554 }
555 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
556 for (i = 0; i < count; i++) {
557 if (!mask || mask[i]) {
558 dst[i] = (dst[i] & 0xffffff00) | src[i];
559 }
560 }
561 }
562 else {
563 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
564 for (i = 0; i < count; i++) {
565 if (!mask || mask[i]) {
566 dst[i] = (dst[i] & 0xffffff) | (src[i] << 24);
567 }
568 }
569 }
570 }
571 else {
572 /* get, modify, put */
573 GLuint temp[MAX_WIDTH*2], i;
574 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
575 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
576 for (i = 0; i < count; i++) {
577 if (!mask || mask[i]) {
578 temp[i*2+1] = src[i];
579 }
580 }
581 }
582 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
583 for (i = 0; i < count; i++) {
584 if (!mask || mask[i]) {
585 temp[i] = (temp[i] & 0xffffff00) | src[i];
586 }
587 }
588 }
589 else {
590 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
591 for (i = 0; i < count; i++) {
592 if (!mask || mask[i]) {
593 temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
594 }
595 }
596 }
597 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
598 }
599 }
600
601
602 static void
603 put_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
604 const GLint x[], const GLint y[],
605 const void *values, const GLubyte *mask)
606 {
607 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
608 const GLubyte *src = (const GLubyte *) values;
609 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
610 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
611 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
612 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
613 /* direct access */
614 GLuint i;
615 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
616 for (i = 0; i < count; i++) {
617 if (!mask || mask[i]) {
618 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
619 dst[1] = src[i];
620 }
621 }
622 }
623 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
624 for (i = 0; i < count; i++) {
625 if (!mask || mask[i]) {
626 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
627 *dst = (*dst & 0xffffff00) | src[i];
628 }
629 }
630 }
631 else {
632 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
633 for (i = 0; i < count; i++) {
634 if (!mask || mask[i]) {
635 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
636 *dst = (*dst & 0xffffff) | (src[i] << 24);
637 }
638 }
639 }
640 }
641 else {
642 /* get, modify, put */
643 GLuint temp[MAX_WIDTH*2], i;
644 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
645 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
646 for (i = 0; i < count; i++) {
647 if (!mask || mask[i]) {
648 temp[i*2+1] = src[i];
649 }
650 }
651 }
652 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
653 for (i = 0; i < count; i++) {
654 if (!mask || mask[i]) {
655 temp[i] = (temp[i] & 0xffffff00) | src[i];
656 }
657 }
658 }
659 else {
660 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
661 for (i = 0; i < count; i++) {
662 if (!mask || mask[i]) {
663 temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
664 }
665 }
666 }
667 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
668 }
669 }
670
671
672 /**
673 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
674 * a stencil renderbuffer.
675 * \return new stencil renderbuffer
676 */
677 static struct gl_renderbuffer *
678 new_s8_renderbuffer_wrapper(struct gl_context *ctx, struct gl_renderbuffer *dsrb)
679 {
680 struct gl_renderbuffer *s8rb;
681
682 ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
683 dsrb->Format == MESA_FORMAT_S8_Z24 ||
684 dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
685 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
686 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
687
688 s8rb = ctx->Driver.NewRenderbuffer(ctx, 0);
689 if (!s8rb)
690 return NULL;
691
692 /* NOTE: need to do manual refcounting here */
693 s8rb->Wrapped = dsrb;
694 dsrb->RefCount++;
695
696 s8rb->Name = dsrb->Name;
697 s8rb->RefCount = 0;
698 s8rb->Width = dsrb->Width;
699 s8rb->Height = dsrb->Height;
700 s8rb->RowStride = dsrb->RowStride;
701 s8rb->InternalFormat = GL_STENCIL_INDEX8_EXT;
702 s8rb->Format = MESA_FORMAT_S8;
703 s8rb->_BaseFormat = GL_STENCIL_INDEX;
704 s8rb->DataType = GL_UNSIGNED_BYTE;
705 s8rb->Data = NULL;
706 s8rb->Delete = delete_wrapper;
707 s8rb->AllocStorage = alloc_wrapper_storage;
708 s8rb->GetPointer = nop_get_pointer;
709 s8rb->GetRow = get_row_s8;
710 s8rb->GetValues = get_values_s8;
711 s8rb->PutRow = put_row_s8;
712 s8rb->PutRowRGB = NULL;
713 s8rb->PutValues = put_values_s8;
714
715 return s8rb;
716 }
717
718
719 /**
720 * Update the framebuffer's _DepthBuffer field using the renderbuffer
721 * found at the given attachment index.
722 *
723 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
724 * create and install a depth wrapper/adaptor.
725 *
726 * \param fb the framebuffer whose _DepthBuffer field to update
727 */
728 void
729 _swrast_update_depth_buffer(struct gl_context *ctx, struct gl_framebuffer *fb)
730 {
731 struct gl_renderbuffer *depthRb =
732 fb->Attachment[BUFFER_DEPTH].Renderbuffer;
733
734 if (depthRb && _mesa_is_format_packed_depth_stencil(depthRb->Format)) {
735 /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */
736 if (!fb->_DepthBuffer
737 || fb->_DepthBuffer->Wrapped != depthRb
738 || _mesa_get_format_base_format(fb->_DepthBuffer->Format) != GL_DEPTH_COMPONENT) {
739 /* need to update wrapper */
740 struct gl_renderbuffer *wrapper;
741
742 if (depthRb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
743 wrapper = new_z32f_renderbuffer_wrapper(ctx, depthRb);
744 }
745 else {
746 wrapper = new_z24_renderbuffer_wrapper(ctx, depthRb);
747 }
748 _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper);
749 }
750 ASSERT(fb->_DepthBuffer->Wrapped == depthRb);
751 fb->_DepthBuffer->Width = depthRb->Width;
752 fb->_DepthBuffer->Height = depthRb->Height;
753 }
754 else {
755 /* depthRb may be null */
756 _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb);
757 }
758 }
759
760
761 /**
762 * Update the framebuffer's _StencilBuffer field using the renderbuffer
763 * found at the given attachment index.
764 *
765 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
766 * create and install a stencil wrapper/adaptor.
767 *
768 * \param fb the framebuffer whose _StencilBuffer field to update
769 */
770 void
771 _swrast_update_stencil_buffer(struct gl_context *ctx, struct gl_framebuffer *fb)
772 {
773 struct gl_renderbuffer *stencilRb =
774 fb->Attachment[BUFFER_STENCIL].Renderbuffer;
775
776 if (stencilRb && _mesa_is_format_packed_depth_stencil(stencilRb->Format)) {
777 /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */
778 if (!fb->_StencilBuffer
779 || fb->_StencilBuffer->Wrapped != stencilRb
780 || _mesa_get_format_base_format(fb->_StencilBuffer->Format) != GL_STENCIL_INDEX) {
781 /* need to update wrapper */
782 struct gl_renderbuffer *wrapper
783 = new_s8_renderbuffer_wrapper(ctx, stencilRb);
784 _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper);
785 }
786 ASSERT(fb->_StencilBuffer->Wrapped == stencilRb);
787 fb->_StencilBuffer->Width = stencilRb->Width;
788 fb->_StencilBuffer->Height = stencilRb->Height;
789 }
790 else {
791 /* stencilRb may be null */
792 _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb);
793 }
794 }