swrast: remove calls to _swrast_update_depth/stencil_buffer()
[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->PutValues = put_values_z24;
307
308 return z24rb;
309 }
310
311
312 static void
313 get_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
314 GLint x, GLint y, void *values)
315 {
316 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
317 GLfloat temp[MAX_WIDTH*2];
318 GLfloat *dst = (GLfloat *) values;
319 const GLfloat *src = (const GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y);
320 GLuint i;
321 ASSERT(z32frb->DataType == GL_FLOAT);
322 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
323 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
324 if (!src) {
325 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
326 src = temp;
327 }
328 for (i = 0; i < count; i++) {
329 dst[i] = src[i*2];
330 }
331 }
332
333 static void
334 get_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
335 const GLint x[], const GLint y[], void *values)
336 {
337 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
338 GLfloat temp[MAX_WIDTH*2];
339 GLfloat *dst = (GLfloat *) values;
340 GLuint i;
341 ASSERT(z32frb->DataType == GL_FLOAT);
342 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
343 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
344 ASSERT(count <= MAX_WIDTH);
345 /* don't bother trying direct access */
346 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
347 for (i = 0; i < count; i++) {
348 dst[i] = temp[i*2];
349 }
350 }
351
352 static void
353 put_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
354 GLint x, GLint y, const void *values, const GLubyte *mask)
355 {
356 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
357 const GLfloat *src = (const GLfloat *) values;
358 GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y);
359 ASSERT(z32frb->DataType == GL_FLOAT);
360 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
361 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
362 if (dst) {
363 /* direct access */
364 GLuint i;
365 for (i = 0; i < count; i++) {
366 if (!mask || mask[i]) {
367 dst[i*2] = src[i];
368 }
369 }
370 }
371 else {
372 /* get, modify, put */
373 GLfloat temp[MAX_WIDTH*2];
374 GLuint i;
375 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
376 for (i = 0; i < count; i++) {
377 if (!mask || mask[i]) {
378 temp[i*2] = src[i];
379 }
380 }
381 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
382 }
383 }
384
385
386 static void
387 put_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
388 const GLint x[], const GLint y[],
389 const void *values, const GLubyte *mask)
390 {
391 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
392 const GLfloat *src = (const GLfloat *) values;
393 ASSERT(z32frb->DataType == GL_FLOAT);
394 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
395 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
396 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
397 /* direct access */
398 GLuint i;
399 for (i = 0; i < count; i++) {
400 if (!mask || mask[i]) {
401 GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
402 *dst = src[i];
403 }
404 }
405 }
406 else {
407 /* get, modify, put */
408 GLfloat temp[MAX_WIDTH*2];
409 GLuint i;
410 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
411 for (i = 0; i < count; i++) {
412 if (!mask || mask[i]) {
413 temp[i*2] = src[i];
414 }
415 }
416 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
417 }
418 }
419
420
421 /**
422 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
423 * a depth renderbuffer.
424 * \return new depth renderbuffer
425 */
426 static struct gl_renderbuffer *
427 new_z32f_renderbuffer_wrapper(struct gl_context *ctx,
428 struct gl_renderbuffer *dsrb)
429 {
430 struct gl_renderbuffer *z32frb;
431
432 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
433 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
434
435 z32frb = ctx->Driver.NewRenderbuffer(ctx, 0);
436 if (!z32frb)
437 return NULL;
438
439 /* NOTE: need to do manual refcounting here */
440 z32frb->Wrapped = dsrb;
441 dsrb->RefCount++;
442
443 z32frb->Name = dsrb->Name;
444 z32frb->RefCount = 0;
445 z32frb->Width = dsrb->Width;
446 z32frb->Height = dsrb->Height;
447 z32frb->RowStride = dsrb->RowStride;
448 z32frb->InternalFormat = GL_DEPTH_COMPONENT32F;
449 z32frb->Format = MESA_FORMAT_Z32_FLOAT;
450 z32frb->_BaseFormat = GL_DEPTH_COMPONENT;
451 z32frb->DataType = GL_FLOAT;
452 z32frb->Data = NULL;
453 z32frb->Delete = delete_wrapper;
454 z32frb->AllocStorage = alloc_wrapper_storage;
455 z32frb->GetPointer = nop_get_pointer;
456 z32frb->GetRow = get_row_z32f;
457 z32frb->GetValues = get_values_z32f;
458 z32frb->PutRow = put_row_z32f;
459 z32frb->PutValues = put_values_z32f;
460
461 return z32frb;
462 }
463
464
465 /*======================================================================
466 * Stencil wrapper around depth/stencil renderbuffer
467 */
468
469 static void
470 get_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
471 GLint x, GLint y, void *values)
472 {
473 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
474 GLuint temp[MAX_WIDTH*2], i;
475 GLubyte *dst = (GLubyte *) values;
476 const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
477 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
478 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
479 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
480 if (!src) {
481 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
482 src = temp;
483 }
484 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
485 for (i = 0; i < count; i++) {
486 dst[i] = src[i*2+1] & 0xff;
487 }
488 }
489 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
490 for (i = 0; i < count; i++) {
491 dst[i] = src[i] & 0xff;
492 }
493 }
494 else {
495 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
496 for (i = 0; i < count; i++) {
497 dst[i] = src[i] >> 24;
498 }
499 }
500 }
501
502 static void
503 get_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
504 const GLint x[], const GLint y[], void *values)
505 {
506 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
507 GLuint temp[MAX_WIDTH*2], i;
508 GLubyte *dst = (GLubyte *) values;
509 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
510 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
511 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
512 ASSERT(count <= MAX_WIDTH);
513 /* don't bother trying direct access */
514 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
515 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
516 for (i = 0; i < count; i++) {
517 dst[i] = temp[i*2+1] & 0xff;
518 }
519 }
520 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
521 for (i = 0; i < count; i++) {
522 dst[i] = temp[i] & 0xff;
523 }
524 }
525 else {
526 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
527 for (i = 0; i < count; i++) {
528 dst[i] = temp[i] >> 24;
529 }
530 }
531 }
532
533 static void
534 put_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
535 GLint x, GLint y, const void *values, const GLubyte *mask)
536 {
537 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
538 const GLubyte *src = (const GLubyte *) values;
539 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
540 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
541 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
542 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
543 if (dst) {
544 /* direct access */
545 GLuint i;
546 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
547 for (i = 0; i < count; i++) {
548 if (!mask || mask[i]) {
549 dst[i*2+1] = src[i];
550 }
551 }
552 }
553 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
554 for (i = 0; i < count; i++) {
555 if (!mask || mask[i]) {
556 dst[i] = (dst[i] & 0xffffff00) | src[i];
557 }
558 }
559 }
560 else {
561 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
562 for (i = 0; i < count; i++) {
563 if (!mask || mask[i]) {
564 dst[i] = (dst[i] & 0xffffff) | (src[i] << 24);
565 }
566 }
567 }
568 }
569 else {
570 /* get, modify, put */
571 GLuint temp[MAX_WIDTH*2], i;
572 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
573 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
574 for (i = 0; i < count; i++) {
575 if (!mask || mask[i]) {
576 temp[i*2+1] = src[i];
577 }
578 }
579 }
580 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
581 for (i = 0; i < count; i++) {
582 if (!mask || mask[i]) {
583 temp[i] = (temp[i] & 0xffffff00) | src[i];
584 }
585 }
586 }
587 else {
588 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
589 for (i = 0; i < count; i++) {
590 if (!mask || mask[i]) {
591 temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
592 }
593 }
594 }
595 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
596 }
597 }
598
599
600 static void
601 put_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
602 const GLint x[], const GLint y[],
603 const void *values, const GLubyte *mask)
604 {
605 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
606 const GLubyte *src = (const GLubyte *) values;
607 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
608 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
609 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
610 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
611 /* direct access */
612 GLuint i;
613 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
614 for (i = 0; i < count; i++) {
615 if (!mask || mask[i]) {
616 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
617 dst[1] = src[i];
618 }
619 }
620 }
621 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
622 for (i = 0; i < count; i++) {
623 if (!mask || mask[i]) {
624 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
625 *dst = (*dst & 0xffffff00) | src[i];
626 }
627 }
628 }
629 else {
630 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
631 for (i = 0; i < count; i++) {
632 if (!mask || mask[i]) {
633 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
634 *dst = (*dst & 0xffffff) | (src[i] << 24);
635 }
636 }
637 }
638 }
639 else {
640 /* get, modify, put */
641 GLuint temp[MAX_WIDTH*2], i;
642 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
643 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
644 for (i = 0; i < count; i++) {
645 if (!mask || mask[i]) {
646 temp[i*2+1] = src[i];
647 }
648 }
649 }
650 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
651 for (i = 0; i < count; i++) {
652 if (!mask || mask[i]) {
653 temp[i] = (temp[i] & 0xffffff00) | src[i];
654 }
655 }
656 }
657 else {
658 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
659 for (i = 0; i < count; i++) {
660 if (!mask || mask[i]) {
661 temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
662 }
663 }
664 }
665 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
666 }
667 }
668
669
670 /**
671 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
672 * a stencil renderbuffer.
673 * \return new stencil renderbuffer
674 */
675 static struct gl_renderbuffer *
676 new_s8_renderbuffer_wrapper(struct gl_context *ctx, struct gl_renderbuffer *dsrb)
677 {
678 struct gl_renderbuffer *s8rb;
679
680 ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
681 dsrb->Format == MESA_FORMAT_S8_Z24 ||
682 dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
683 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
684 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
685
686 s8rb = ctx->Driver.NewRenderbuffer(ctx, 0);
687 if (!s8rb)
688 return NULL;
689
690 /* NOTE: need to do manual refcounting here */
691 s8rb->Wrapped = dsrb;
692 dsrb->RefCount++;
693
694 s8rb->Name = dsrb->Name;
695 s8rb->RefCount = 0;
696 s8rb->Width = dsrb->Width;
697 s8rb->Height = dsrb->Height;
698 s8rb->RowStride = dsrb->RowStride;
699 s8rb->InternalFormat = GL_STENCIL_INDEX8_EXT;
700 s8rb->Format = MESA_FORMAT_S8;
701 s8rb->_BaseFormat = GL_STENCIL_INDEX;
702 s8rb->DataType = GL_UNSIGNED_BYTE;
703 s8rb->Data = NULL;
704 s8rb->Delete = delete_wrapper;
705 s8rb->AllocStorage = alloc_wrapper_storage;
706 s8rb->GetPointer = nop_get_pointer;
707 s8rb->GetRow = get_row_s8;
708 s8rb->GetValues = get_values_s8;
709 s8rb->PutRow = put_row_s8;
710 s8rb->PutValues = put_values_s8;
711
712 return s8rb;
713 }
714
715
716 /**
717 * Update the framebuffer's _DepthBuffer field using the renderbuffer
718 * found at the given attachment index.
719 *
720 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
721 * create and install a depth wrapper/adaptor.
722 *
723 * \param fb the framebuffer whose _DepthBuffer field to update
724 */
725 void
726 _swrast_update_depth_buffer(struct gl_context *ctx, struct gl_framebuffer *fb)
727 {
728 struct gl_renderbuffer *depthRb =
729 fb->Attachment[BUFFER_DEPTH].Renderbuffer;
730
731 if (depthRb && _mesa_is_format_packed_depth_stencil(depthRb->Format)) {
732 /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */
733 if (!fb->_DepthBuffer
734 || fb->_DepthBuffer->Wrapped != depthRb
735 || _mesa_get_format_base_format(fb->_DepthBuffer->Format) != GL_DEPTH_COMPONENT) {
736 /* need to update wrapper */
737 struct gl_renderbuffer *wrapper;
738
739 if (depthRb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
740 wrapper = new_z32f_renderbuffer_wrapper(ctx, depthRb);
741 }
742 else {
743 wrapper = new_z24_renderbuffer_wrapper(ctx, depthRb);
744 }
745 _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper);
746 }
747 ASSERT(fb->_DepthBuffer->Wrapped == depthRb);
748 fb->_DepthBuffer->Width = depthRb->Width;
749 fb->_DepthBuffer->Height = depthRb->Height;
750 }
751 else {
752 /* depthRb may be null */
753 _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb);
754 }
755 }
756
757
758 /**
759 * Update the framebuffer's _StencilBuffer field using the renderbuffer
760 * found at the given attachment index.
761 *
762 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
763 * create and install a stencil wrapper/adaptor.
764 *
765 * \param fb the framebuffer whose _StencilBuffer field to update
766 */
767 void
768 _swrast_update_stencil_buffer(struct gl_context *ctx, struct gl_framebuffer *fb)
769 {
770 struct gl_renderbuffer *stencilRb =
771 fb->Attachment[BUFFER_STENCIL].Renderbuffer;
772
773 if (stencilRb && _mesa_is_format_packed_depth_stencil(stencilRb->Format)) {
774 /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */
775 if (!fb->_StencilBuffer
776 || fb->_StencilBuffer->Wrapped != stencilRb
777 || _mesa_get_format_base_format(fb->_StencilBuffer->Format) != GL_STENCIL_INDEX) {
778 /* need to update wrapper */
779 struct gl_renderbuffer *wrapper
780 = new_s8_renderbuffer_wrapper(ctx, stencilRb);
781 _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper);
782 }
783 ASSERT(fb->_StencilBuffer->Wrapped == stencilRb);
784 fb->_StencilBuffer->Width = stencilRb->Width;
785 fb->_StencilBuffer->Height = stencilRb->Height;
786 }
787 else {
788 /* stencilRb may be null */
789 _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb);
790 }
791 }