Fix gcc version checks for _mesa_bitcount
[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 "formats.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 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 static void
211 put_mono_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
212 GLint x, GLint y, const void *value, const GLubyte *mask)
213 {
214 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
215 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
216 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
217 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
218 if (dst) {
219 /* direct access */
220 GLuint i;
221 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
222 const GLuint shiftedVal = *((GLuint *) value) << 8;
223 for (i = 0; i < count; i++) {
224 if (!mask || mask[i]) {
225 dst[i] = shiftedVal | (dst[i] & 0xff);
226 }
227 }
228 }
229 else {
230 const GLuint shiftedVal = *((GLuint *) value);
231 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
232 for (i = 0; i < count; i++) {
233 if (!mask || mask[i]) {
234 dst[i] = shiftedVal | (dst[i] & 0xff000000);
235 }
236 }
237 }
238 }
239 else {
240 /* get, modify, put */
241 GLuint temp[MAX_WIDTH], i;
242 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
243 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
244 const GLuint shiftedVal = *((GLuint *) value) << 8;
245 for (i = 0; i < count; i++) {
246 if (!mask || mask[i]) {
247 temp[i] = shiftedVal | (temp[i] & 0xff);
248 }
249 }
250 }
251 else {
252 const GLuint shiftedVal = *((GLuint *) value);
253 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
254 for (i = 0; i < count; i++) {
255 if (!mask || mask[i]) {
256 temp[i] = shiftedVal | (temp[i] & 0xff000000);
257 }
258 }
259 }
260 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
261 }
262 }
263
264 static void
265 put_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count,
266 const GLint x[], const GLint y[],
267 const void *values, const GLubyte *mask)
268 {
269 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
270 const GLuint *src = (const GLuint *) values;
271 ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
272 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
273 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
274 /* direct access */
275 GLuint i;
276 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
277 for (i = 0; i < count; i++) {
278 if (!mask || mask[i]) {
279 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
280 *dst = (src[i] << 8) | (*dst & 0xff);
281 }
282 }
283 }
284 else {
285 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
286 for (i = 0; i < count; i++) {
287 if (!mask || mask[i]) {
288 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
289 *dst = (src[i] & 0xffffff) | (*dst & 0xff000000);
290 }
291 }
292 }
293 }
294 else {
295 /* get, modify, put */
296 GLuint temp[MAX_WIDTH], i;
297 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
298 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
299 for (i = 0; i < count; i++) {
300 if (!mask || mask[i]) {
301 temp[i] = (src[i] << 8) | (temp[i] & 0xff);
302 }
303 }
304 }
305 else {
306 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
307 for (i = 0; i < count; i++) {
308 if (!mask || mask[i]) {
309 temp[i] = (src[i] & 0xffffff) | (temp[i] & 0xff000000);
310 }
311 }
312 }
313 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
314 }
315 }
316
317 static void
318 put_mono_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb,
319 GLuint count, const GLint x[], const GLint y[],
320 const void *value, const GLubyte *mask)
321 {
322 struct gl_renderbuffer *dsrb = z24rb->Wrapped;
323 GLuint temp[MAX_WIDTH], i;
324 /* get, modify, put */
325 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
326 if (dsrb->Format == MESA_FORMAT_Z24_S8) {
327 const GLuint shiftedVal = *((GLuint *) value) << 8;
328 for (i = 0; i < count; i++) {
329 if (!mask || mask[i]) {
330 temp[i] = shiftedVal | (temp[i] & 0xff);
331 }
332 }
333 }
334 else {
335 const GLuint shiftedVal = *((GLuint *) value);
336 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
337 for (i = 0; i < count; i++) {
338 if (!mask || mask[i]) {
339 temp[i] = shiftedVal | (temp[i] & 0xff000000);
340 }
341 }
342 }
343 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
344 }
345
346
347 /**
348 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
349 * a depth renderbuffer.
350 * \return new depth renderbuffer
351 */
352 struct gl_renderbuffer *
353 _mesa_new_z24_renderbuffer_wrapper(struct gl_context *ctx,
354 struct gl_renderbuffer *dsrb)
355 {
356 struct gl_renderbuffer *z24rb;
357
358 ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
359 dsrb->Format == MESA_FORMAT_Z24_X8 ||
360 dsrb->Format == MESA_FORMAT_S8_Z24 ||
361 dsrb->Format == MESA_FORMAT_X8_Z24);
362 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
363
364 z24rb = ctx->Driver.NewRenderbuffer(ctx, 0);
365 if (!z24rb)
366 return NULL;
367
368 /* NOTE: need to do manual refcounting here */
369 z24rb->Wrapped = dsrb;
370 dsrb->RefCount++;
371
372 z24rb->Name = dsrb->Name;
373 z24rb->RefCount = 0;
374 z24rb->Width = dsrb->Width;
375 z24rb->Height = dsrb->Height;
376 z24rb->RowStride = dsrb->RowStride;
377 z24rb->InternalFormat = GL_DEPTH_COMPONENT24;
378 z24rb->Format = MESA_FORMAT_X8_Z24;
379 z24rb->_BaseFormat = GL_DEPTH_COMPONENT;
380 z24rb->DataType = GL_UNSIGNED_INT;
381 z24rb->Data = NULL;
382 z24rb->Delete = delete_wrapper;
383 z24rb->AllocStorage = alloc_wrapper_storage;
384 z24rb->GetPointer = nop_get_pointer;
385 z24rb->GetRow = get_row_z24;
386 z24rb->GetValues = get_values_z24;
387 z24rb->PutRow = put_row_z24;
388 z24rb->PutRowRGB = NULL;
389 z24rb->PutMonoRow = put_mono_row_z24;
390 z24rb->PutValues = put_values_z24;
391 z24rb->PutMonoValues = put_mono_values_z24;
392
393 return z24rb;
394 }
395
396
397 static void
398 get_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
399 GLint x, GLint y, void *values)
400 {
401 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
402 GLfloat temp[MAX_WIDTH*2];
403 GLfloat *dst = (GLfloat *) values;
404 const GLfloat *src = (const GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y);
405 GLuint i;
406 ASSERT(z32frb->DataType == GL_FLOAT);
407 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
408 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
409 if (!src) {
410 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
411 src = temp;
412 }
413 for (i = 0; i < count; i++) {
414 dst[i] = src[i*2];
415 }
416 }
417
418 static void
419 get_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
420 const GLint x[], const GLint y[], void *values)
421 {
422 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
423 GLfloat temp[MAX_WIDTH*2];
424 GLfloat *dst = (GLfloat *) values;
425 GLuint i;
426 ASSERT(z32frb->DataType == GL_FLOAT);
427 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
428 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
429 ASSERT(count <= MAX_WIDTH);
430 /* don't bother trying direct access */
431 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
432 for (i = 0; i < count; i++) {
433 dst[i] = temp[i*2];
434 }
435 }
436
437 static void
438 put_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
439 GLint x, GLint y, const void *values, const GLubyte *mask)
440 {
441 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
442 const GLfloat *src = (const GLfloat *) values;
443 GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y);
444 ASSERT(z32frb->DataType == GL_FLOAT);
445 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
446 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
447 if (dst) {
448 /* direct access */
449 GLuint i;
450 for (i = 0; i < count; i++) {
451 if (!mask || mask[i]) {
452 dst[i*2] = src[i];
453 }
454 }
455 }
456 else {
457 /* get, modify, put */
458 GLfloat temp[MAX_WIDTH*2];
459 GLuint i;
460 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
461 for (i = 0; i < count; i++) {
462 if (!mask || mask[i]) {
463 temp[i*2] = src[i];
464 }
465 }
466 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
467 }
468 }
469
470 static void
471 put_mono_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
472 GLint x, GLint y, const void *value, const GLubyte *mask)
473 {
474 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
475 GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y);
476 ASSERT(z32frb->DataType == GL_FLOAT);
477 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
478 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
479 if (dst) {
480 /* direct access */
481 GLuint i;
482 const GLfloat val = *(GLfloat*)value;
483 for (i = 0; i < count; i++) {
484 if (!mask || mask[i]) {
485 dst[i*2] = val;
486 }
487 }
488 }
489 else {
490 /* get, modify, put */
491 GLfloat temp[MAX_WIDTH*2];
492 GLuint i;
493 const GLfloat val = *(GLfloat *)value;
494 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
495 for (i = 0; i < count; i++) {
496 if (!mask || mask[i]) {
497 temp[i*2] = val;
498 }
499 }
500 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
501 }
502 }
503
504 static void
505 put_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count,
506 const GLint x[], const GLint y[],
507 const void *values, const GLubyte *mask)
508 {
509 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
510 const GLfloat *src = (const GLfloat *) values;
511 ASSERT(z32frb->DataType == GL_FLOAT);
512 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
513 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
514 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
515 /* direct access */
516 GLuint i;
517 for (i = 0; i < count; i++) {
518 if (!mask || mask[i]) {
519 GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
520 *dst = src[i];
521 }
522 }
523 }
524 else {
525 /* get, modify, put */
526 GLfloat temp[MAX_WIDTH*2];
527 GLuint i;
528 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
529 for (i = 0; i < count; i++) {
530 if (!mask || mask[i]) {
531 temp[i*2] = src[i];
532 }
533 }
534 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
535 }
536 }
537
538 static void
539 put_mono_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb,
540 GLuint count, const GLint x[], const GLint y[],
541 const void *value, const GLubyte *mask)
542 {
543 struct gl_renderbuffer *dsrb = z32frb->Wrapped;
544 GLfloat temp[MAX_WIDTH*2];
545 GLuint i;
546 const GLfloat val = *(GLfloat *)value;
547 ASSERT(z32frb->DataType == GL_FLOAT);
548 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
549 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
550 /* get, modify, put */
551 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
552 for (i = 0; i < count; i++) {
553 if (!mask || mask[i]) {
554 temp[i*2] = val;
555 }
556 }
557 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
558 }
559
560
561 /**
562 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
563 * a depth renderbuffer.
564 * \return new depth renderbuffer
565 */
566 struct gl_renderbuffer *
567 _mesa_new_z32f_renderbuffer_wrapper(struct gl_context *ctx,
568 struct gl_renderbuffer *dsrb)
569 {
570 struct gl_renderbuffer *z32frb;
571
572 ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
573 ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
574
575 z32frb = ctx->Driver.NewRenderbuffer(ctx, 0);
576 if (!z32frb)
577 return NULL;
578
579 /* NOTE: need to do manual refcounting here */
580 z32frb->Wrapped = dsrb;
581 dsrb->RefCount++;
582
583 z32frb->Name = dsrb->Name;
584 z32frb->RefCount = 0;
585 z32frb->Width = dsrb->Width;
586 z32frb->Height = dsrb->Height;
587 z32frb->RowStride = dsrb->RowStride;
588 z32frb->InternalFormat = GL_DEPTH_COMPONENT32F;
589 z32frb->Format = MESA_FORMAT_Z32_FLOAT;
590 z32frb->_BaseFormat = GL_DEPTH_COMPONENT;
591 z32frb->DataType = GL_FLOAT;
592 z32frb->Data = NULL;
593 z32frb->Delete = delete_wrapper;
594 z32frb->AllocStorage = alloc_wrapper_storage;
595 z32frb->GetPointer = nop_get_pointer;
596 z32frb->GetRow = get_row_z32f;
597 z32frb->GetValues = get_values_z32f;
598 z32frb->PutRow = put_row_z32f;
599 z32frb->PutRowRGB = NULL;
600 z32frb->PutMonoRow = put_mono_row_z32f;
601 z32frb->PutValues = put_values_z32f;
602 z32frb->PutMonoValues = put_mono_values_z32f;
603
604 return z32frb;
605 }
606
607
608 /*======================================================================
609 * Stencil wrapper around depth/stencil renderbuffer
610 */
611
612 static void
613 get_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
614 GLint x, GLint y, void *values)
615 {
616 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
617 GLuint temp[MAX_WIDTH*2], i;
618 GLubyte *dst = (GLubyte *) values;
619 const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
620 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
621 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
622 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
623 if (!src) {
624 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
625 src = temp;
626 }
627 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
628 for (i = 0; i < count; i++) {
629 dst[i] = src[i*2+1] & 0xff;
630 }
631 }
632 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
633 for (i = 0; i < count; i++) {
634 dst[i] = src[i] & 0xff;
635 }
636 }
637 else {
638 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
639 for (i = 0; i < count; i++) {
640 dst[i] = src[i] >> 24;
641 }
642 }
643 }
644
645 static void
646 get_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
647 const GLint x[], const GLint y[], void *values)
648 {
649 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
650 GLuint temp[MAX_WIDTH*2], i;
651 GLubyte *dst = (GLubyte *) values;
652 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
653 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
654 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
655 ASSERT(count <= MAX_WIDTH);
656 /* don't bother trying direct access */
657 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
658 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
659 for (i = 0; i < count; i++) {
660 dst[i] = temp[i*2+1] & 0xff;
661 }
662 }
663 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
664 for (i = 0; i < count; i++) {
665 dst[i] = temp[i] & 0xff;
666 }
667 }
668 else {
669 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
670 for (i = 0; i < count; i++) {
671 dst[i] = temp[i] >> 24;
672 }
673 }
674 }
675
676 static void
677 put_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
678 GLint x, GLint y, const void *values, const GLubyte *mask)
679 {
680 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
681 const GLubyte *src = (const GLubyte *) values;
682 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
683 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
684 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
685 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
686 if (dst) {
687 /* direct access */
688 GLuint i;
689 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
690 for (i = 0; i < count; i++) {
691 if (!mask || mask[i]) {
692 dst[i*2+1] = src[i];
693 }
694 }
695 }
696 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
697 for (i = 0; i < count; i++) {
698 if (!mask || mask[i]) {
699 dst[i] = (dst[i] & 0xffffff00) | src[i];
700 }
701 }
702 }
703 else {
704 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
705 for (i = 0; i < count; i++) {
706 if (!mask || mask[i]) {
707 dst[i] = (dst[i] & 0xffffff) | (src[i] << 24);
708 }
709 }
710 }
711 }
712 else {
713 /* get, modify, put */
714 GLuint temp[MAX_WIDTH*2], i;
715 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
716 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
717 for (i = 0; i < count; i++) {
718 if (!mask || mask[i]) {
719 temp[i*2+1] = src[i];
720 }
721 }
722 }
723 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
724 for (i = 0; i < count; i++) {
725 if (!mask || mask[i]) {
726 temp[i] = (temp[i] & 0xffffff00) | src[i];
727 }
728 }
729 }
730 else {
731 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
732 for (i = 0; i < count; i++) {
733 if (!mask || mask[i]) {
734 temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
735 }
736 }
737 }
738 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
739 }
740 }
741
742 static void
743 put_mono_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
744 GLint x, GLint y, const void *value, const GLubyte *mask)
745 {
746 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
747 const GLubyte val = *((GLubyte *) value);
748 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
749 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
750 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
751 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
752 if (dst) {
753 /* direct access */
754 GLuint i;
755 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
756 for (i = 0; i < count; i++) {
757 if (!mask || mask[i]) {
758 dst[i*2+1] = val;
759 }
760 }
761 }
762 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
763 for (i = 0; i < count; i++) {
764 if (!mask || mask[i]) {
765 dst[i] = (dst[i] & 0xffffff00) | val;
766 }
767 }
768 }
769 else {
770 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
771 for (i = 0; i < count; i++) {
772 if (!mask || mask[i]) {
773 dst[i] = (dst[i] & 0xffffff) | (val << 24);
774 }
775 }
776 }
777 }
778 else {
779 /* get, modify, put */
780 GLuint temp[MAX_WIDTH*2], i;
781 dsrb->GetRow(ctx, dsrb, count, x, y, temp);
782 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
783 for (i = 0; i < count; i++) {
784 if (!mask || mask[i]) {
785 temp[i*2+1] = val;
786 }
787 }
788 }
789 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
790 for (i = 0; i < count; i++) {
791 if (!mask || mask[i]) {
792 temp[i] = (temp[i] & 0xffffff00) | val;
793 }
794 }
795 }
796 else {
797 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
798 for (i = 0; i < count; i++) {
799 if (!mask || mask[i]) {
800 temp[i] = (temp[i] & 0xffffff) | (val << 24);
801 }
802 }
803 }
804 dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
805 }
806 }
807
808 static void
809 put_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
810 const GLint x[], const GLint y[],
811 const void *values, const GLubyte *mask)
812 {
813 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
814 const GLubyte *src = (const GLubyte *) values;
815 ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
816 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
817 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
818 if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
819 /* direct access */
820 GLuint i;
821 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
822 for (i = 0; i < count; i++) {
823 if (!mask || mask[i]) {
824 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
825 dst[1] = src[i];
826 }
827 }
828 }
829 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
830 for (i = 0; i < count; i++) {
831 if (!mask || mask[i]) {
832 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
833 *dst = (*dst & 0xffffff00) | src[i];
834 }
835 }
836 }
837 else {
838 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
839 for (i = 0; i < count; i++) {
840 if (!mask || mask[i]) {
841 GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
842 *dst = (*dst & 0xffffff) | (src[i] << 24);
843 }
844 }
845 }
846 }
847 else {
848 /* get, modify, put */
849 GLuint temp[MAX_WIDTH*2], i;
850 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
851 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
852 for (i = 0; i < count; i++) {
853 if (!mask || mask[i]) {
854 temp[i*2+1] = src[i];
855 }
856 }
857 }
858 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
859 for (i = 0; i < count; i++) {
860 if (!mask || mask[i]) {
861 temp[i] = (temp[i] & 0xffffff00) | src[i];
862 }
863 }
864 }
865 else {
866 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
867 for (i = 0; i < count; i++) {
868 if (!mask || mask[i]) {
869 temp[i] = (temp[i] & 0xffffff) | (src[i] << 24);
870 }
871 }
872 }
873 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
874 }
875 }
876
877 static void
878 put_mono_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count,
879 const GLint x[], const GLint y[],
880 const void *value, const GLubyte *mask)
881 {
882 struct gl_renderbuffer *dsrb = s8rb->Wrapped;
883 GLuint temp[MAX_WIDTH*2], i;
884 const GLubyte val = *((GLubyte *) value);
885 /* get, modify, put */
886 dsrb->GetValues(ctx, dsrb, count, x, y, temp);
887 if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) {
888 for (i = 0; i < count; i++) {
889 if (!mask || mask[i]) {
890 temp[i*2+1] = val;
891 }
892 }
893 }
894 else if (dsrb->Format == MESA_FORMAT_Z24_S8) {
895 for (i = 0; i < count; i++) {
896 if (!mask || mask[i]) {
897 temp[i] = (temp[i] & 0xffffff00) | val;
898 }
899 }
900 }
901 else {
902 assert(dsrb->Format == MESA_FORMAT_S8_Z24);
903 for (i = 0; i < count; i++) {
904 if (!mask || mask[i]) {
905 temp[i] = (temp[i] & 0xffffff) | (val << 24);
906 }
907 }
908 }
909 dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
910 }
911
912
913 /**
914 * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
915 * a stencil renderbuffer.
916 * \return new stencil renderbuffer
917 */
918 struct gl_renderbuffer *
919 _mesa_new_s8_renderbuffer_wrapper(struct gl_context *ctx, struct gl_renderbuffer *dsrb)
920 {
921 struct gl_renderbuffer *s8rb;
922
923 ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 ||
924 dsrb->Format == MESA_FORMAT_S8_Z24 ||
925 dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8);
926 ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT ||
927 dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
928
929 s8rb = ctx->Driver.NewRenderbuffer(ctx, 0);
930 if (!s8rb)
931 return NULL;
932
933 /* NOTE: need to do manual refcounting here */
934 s8rb->Wrapped = dsrb;
935 dsrb->RefCount++;
936
937 s8rb->Name = dsrb->Name;
938 s8rb->RefCount = 0;
939 s8rb->Width = dsrb->Width;
940 s8rb->Height = dsrb->Height;
941 s8rb->RowStride = dsrb->RowStride;
942 s8rb->InternalFormat = GL_STENCIL_INDEX8_EXT;
943 s8rb->Format = MESA_FORMAT_S8;
944 s8rb->_BaseFormat = GL_STENCIL_INDEX;
945 s8rb->DataType = GL_UNSIGNED_BYTE;
946 s8rb->Data = NULL;
947 s8rb->Delete = delete_wrapper;
948 s8rb->AllocStorage = alloc_wrapper_storage;
949 s8rb->GetPointer = nop_get_pointer;
950 s8rb->GetRow = get_row_s8;
951 s8rb->GetValues = get_values_s8;
952 s8rb->PutRow = put_row_s8;
953 s8rb->PutRowRGB = NULL;
954 s8rb->PutMonoRow = put_mono_row_s8;
955 s8rb->PutValues = put_values_s8;
956 s8rb->PutMonoValues = put_mono_values_s8;
957
958 return s8rb;
959 }
960
961
962
963 /**
964 ** The following functions are useful for hardware drivers that only
965 ** implement combined depth/stencil buffers.
966 ** The GL_EXT_framebuffer_object extension allows indepedent depth and
967 ** stencil buffers to be used in any combination.
968 ** Therefore, we sometimes have to merge separate depth and stencil
969 ** renderbuffers into a single depth+stencil renderbuffer. And sometimes
970 ** we have to split combined depth+stencil renderbuffers into separate
971 ** renderbuffers.
972 **/
973
974
975 /**
976 * Extract stencil values from the combined depth/stencil renderbuffer, storing
977 * the values into a separate stencil renderbuffer.
978 * \param dsRb the source depth/stencil renderbuffer
979 * \param stencilRb the destination stencil renderbuffer
980 * (either 8-bit or 32-bit)
981 */
982 void
983 _mesa_extract_stencil(struct gl_context *ctx,
984 struct gl_renderbuffer *dsRb,
985 struct gl_renderbuffer *stencilRb)
986 {
987 GLuint row, width, height;
988
989 ASSERT(dsRb);
990 ASSERT(stencilRb);
991
992 ASSERT(dsRb->Format == MESA_FORMAT_Z24_S8);
993 ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
994 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8 ||
995 stencilRb->Format == MESA_FORMAT_S8);
996 ASSERT(dsRb->Width == stencilRb->Width);
997 ASSERT(dsRb->Height == stencilRb->Height);
998
999 width = dsRb->Width;
1000 height = dsRb->Height;
1001
1002 for (row = 0; row < height; row++) {
1003 GLuint depthStencil[MAX_WIDTH];
1004 dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
1005 if (stencilRb->Format == MESA_FORMAT_S8) {
1006 /* 8bpp stencil */
1007 GLubyte stencil[MAX_WIDTH];
1008 GLuint i;
1009 for (i = 0; i < width; i++) {
1010 stencil[i] = depthStencil[i] & 0xff;
1011 }
1012 stencilRb->PutRow(ctx, stencilRb, width, 0, row, stencil, NULL);
1013 }
1014 else {
1015 /* 32bpp stencil */
1016 /* the 24 depth bits will be ignored */
1017 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8);
1018 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
1019 stencilRb->PutRow(ctx, stencilRb, width, 0, row, depthStencil, NULL);
1020 }
1021 }
1022 }
1023
1024
1025 /**
1026 * Copy stencil values from a stencil renderbuffer into a combined
1027 * depth/stencil renderbuffer.
1028 * \param dsRb the destination depth/stencil renderbuffer
1029 * \param stencilRb the source stencil buffer (either 8-bit or 32-bit)
1030 */
1031 void
1032 _mesa_insert_stencil(struct gl_context *ctx,
1033 struct gl_renderbuffer *dsRb,
1034 struct gl_renderbuffer *stencilRb)
1035 {
1036 GLuint row, width, height;
1037
1038 ASSERT(dsRb);
1039 ASSERT(stencilRb);
1040
1041 ASSERT(dsRb->Format == MESA_FORMAT_Z24_S8);
1042 ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
1043 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8 ||
1044 stencilRb->Format == MESA_FORMAT_S8);
1045
1046 ASSERT(dsRb->Width == stencilRb->Width);
1047 ASSERT(dsRb->Height == stencilRb->Height);
1048
1049 width = dsRb->Width;
1050 height = dsRb->Height;
1051
1052 for (row = 0; row < height; row++) {
1053 GLuint depthStencil[MAX_WIDTH];
1054
1055 dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
1056
1057 if (stencilRb->Format == MESA_FORMAT_S8) {
1058 /* 8bpp stencil */
1059 GLubyte stencil[MAX_WIDTH];
1060 GLuint i;
1061 stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
1062 for (i = 0; i < width; i++) {
1063 depthStencil[i] = (depthStencil[i] & 0xffffff00) | stencil[i];
1064 }
1065 }
1066 else {
1067 /* 32bpp stencil buffer */
1068 GLuint stencil[MAX_WIDTH], i;
1069 ASSERT(stencilRb->Format == MESA_FORMAT_Z24_S8);
1070 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
1071 stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
1072 for (i = 0; i < width; i++) {
1073 depthStencil[i]
1074 = (depthStencil[i] & 0xffffff00) | (stencil[i] & 0xff);
1075 }
1076 }
1077
1078 dsRb->PutRow(ctx, dsRb, width, 0, row, depthStencil, NULL);
1079 }
1080 }
1081
1082
1083 /**
1084 * Convert the stencil buffer from 8bpp to 32bpp depth/stencil.
1085 * \param stencilRb the stencil renderbuffer to promote
1086 */
1087 void
1088 _mesa_promote_stencil(struct gl_context *ctx, struct gl_renderbuffer *stencilRb)
1089 {
1090 const GLsizei width = stencilRb->Width;
1091 const GLsizei height = stencilRb->Height;
1092 GLubyte *data;
1093 GLint i, j, k;
1094
1095 ASSERT(stencilRb->Format == MESA_FORMAT_S8);
1096 ASSERT(stencilRb->Data);
1097
1098 data = (GLubyte *) stencilRb->Data;
1099 stencilRb->Data = NULL;
1100 stencilRb->AllocStorage(ctx, stencilRb, GL_DEPTH24_STENCIL8_EXT,
1101 width, height);
1102
1103 ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
1104
1105 k = 0;
1106 for (i = 0; i < height; i++) {
1107 GLuint depthStencil[MAX_WIDTH];
1108 for (j = 0; j < width; j++) {
1109 depthStencil[j] = data[k++];
1110 }
1111 stencilRb->PutRow(ctx, stencilRb, width, 0, i, depthStencil, NULL);
1112 }
1113 free(data);
1114 }