32 and z24s8 softpipe buffers
[mesa.git] / src / mesa / main / renderbuffer.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
26 /**
27 * Functions for allocating/managing renderbuffers.
28 * Also, routines for reading/writing software-based renderbuffer data as
29 * ubytes, ushorts, uints, etc.
30 *
31 * The 'alpha8' renderbuffer is interesting. It's used to add a software-based
32 * alpha channel to RGB renderbuffers. This is done by wrapping the RGB
33 * renderbuffer with the alpha renderbuffer. We can do this because of the
34 * OO-nature of renderbuffers.
35 *
36 * Down the road we'll use this for run-time support of 8, 16 and 32-bit
37 * color channels. For example, Mesa may use 32-bit/float color channels
38 * internally (swrast) and use wrapper renderbuffers to convert 32-bit
39 * values down to 16 or 8-bit values for whatever kind of framebuffer we have.
40 */
41
42
43 #include "glheader.h"
44 #include "imports.h"
45 #include "context.h"
46 #include "mtypes.h"
47 #include "fbobject.h"
48 #include "renderbuffer.h"
49
50 #include "rbadaptors.h"
51
52 #include "pipe/softpipe/sp_z_surface.h"
53 #include "pipe/p_state.h"
54 #include "pipe/p_defines.h"
55
56
57 /* 32-bit color index format. Not a public format. */
58 #define COLOR_INDEX32 0x424243
59
60
61 /*
62 * Routines for get/put values in common buffer formats follow.
63 * Someday add support for arbitrary row stride to make them more
64 * flexible.
65 */
66
67 /**********************************************************************
68 * Functions for buffers of 1 X GLubyte values.
69 * Typically stencil.
70 */
71
72 static void *
73 get_pointer_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb,
74 GLint x, GLint y)
75 {
76 if (!rb->Data)
77 return NULL;
78 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
79 /* Can't assert _ActualFormat since these funcs may be used for serveral
80 * different formats (GL_ALPHA8, GL_STENCIL_INDEX8, etc).
81 */
82 return (GLubyte *) rb->Data + y * rb->Width + x;
83 }
84
85
86 static void
87 get_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
88 GLint x, GLint y, void *values)
89 {
90 const GLubyte *src = (const GLubyte *) rb->Data + y * rb->Width + x;
91 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
92 _mesa_memcpy(values, src, count * sizeof(GLubyte));
93 }
94
95
96 static void
97 get_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
98 const GLint x[], const GLint y[], void *values)
99 {
100 GLubyte *dst = (GLubyte *) values;
101 GLuint i;
102 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
103 for (i = 0; i < count; i++) {
104 const GLubyte *src = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
105 dst[i] = *src;
106 }
107 }
108
109
110 static void
111 put_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
112 GLint x, GLint y, const void *values, const GLubyte *mask)
113 {
114 const GLubyte *src = (const GLubyte *) values;
115 GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
116 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
117 if (mask) {
118 GLuint i;
119 for (i = 0; i < count; i++) {
120 if (mask[i]) {
121 dst[i] = src[i];
122 }
123 }
124 }
125 else {
126 _mesa_memcpy(dst, values, count * sizeof(GLubyte));
127 }
128 }
129
130
131 static void
132 put_mono_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
133 GLint x, GLint y, const void *value, const GLubyte *mask)
134 {
135 const GLubyte val = *((const GLubyte *) value);
136 GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
137 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
138 if (mask) {
139 GLuint i;
140 for (i = 0; i < count; i++) {
141 if (mask[i]) {
142 dst[i] = val;
143 }
144 }
145 }
146 else {
147 GLuint i;
148 for (i = 0; i < count; i++) {
149 dst[i] = val;
150 }
151 }
152 }
153
154
155 static void
156 put_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
157 const GLint x[], const GLint y[],
158 const void *values, const GLubyte *mask)
159 {
160 const GLubyte *src = (const GLubyte *) values;
161 GLuint i;
162 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
163 for (i = 0; i < count; i++) {
164 if (!mask || mask[i]) {
165 GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
166 *dst = src[i];
167 }
168 }
169 }
170
171
172 static void
173 put_mono_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
174 const GLint x[], const GLint y[],
175 const void *value, const GLubyte *mask)
176 {
177 const GLubyte val = *((const GLubyte *) value);
178 GLuint i;
179 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
180 for (i = 0; i < count; i++) {
181 if (!mask || mask[i]) {
182 GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
183 *dst = val;
184 }
185 }
186 }
187
188
189 /**********************************************************************
190 * Functions for buffers of 1 X GLushort values.
191 * Typically depth/Z.
192 */
193
194 static void *
195 get_pointer_ushort(GLcontext *ctx, struct gl_renderbuffer *rb,
196 GLint x, GLint y)
197 {
198 if (!rb->Data)
199 return NULL;
200 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
201 ASSERT(rb->Width > 0);
202 return (GLushort *) rb->Data + y * rb->Width + x;
203 }
204
205
206 static void
207 get_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
208 GLint x, GLint y, void *values)
209 {
210 const void *src = rb->GetPointer(ctx, rb, x, y);
211 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
212 _mesa_memcpy(values, src, count * sizeof(GLushort));
213 }
214
215
216 static void
217 get_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
218 const GLint x[], const GLint y[], void *values)
219 {
220 GLushort *dst = (GLushort *) values;
221 GLuint i;
222 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
223 for (i = 0; i < count; i++) {
224 const GLushort *src = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
225 dst[i] = *src;
226 }
227 }
228
229
230 static void
231 put_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
232 GLint x, GLint y, const void *values, const GLubyte *mask)
233 {
234 const GLushort *src = (const GLushort *) values;
235 GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x;
236 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
237 if (mask) {
238 GLuint i;
239 for (i = 0; i < count; i++) {
240 if (mask[i]) {
241 dst[i] = src[i];
242 }
243 }
244 }
245 else {
246 _mesa_memcpy(dst, src, count * sizeof(GLushort));
247 }
248 }
249
250
251 static void
252 put_mono_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
253 GLint x, GLint y, const void *value, const GLubyte *mask)
254 {
255 const GLushort val = *((const GLushort *) value);
256 GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x;
257 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
258 if (mask) {
259 GLuint i;
260 for (i = 0; i < count; i++) {
261 if (mask[i]) {
262 dst[i] = val;
263 }
264 }
265 }
266 else {
267 GLuint i;
268 for (i = 0; i < count; i++) {
269 dst[i] = val;
270 }
271 }
272 }
273
274
275 static void
276 put_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
277 const GLint x[], const GLint y[], const void *values,
278 const GLubyte *mask)
279 {
280 const GLushort *src = (const GLushort *) values;
281 GLuint i;
282 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
283 for (i = 0; i < count; i++) {
284 if (!mask || mask[i]) {
285 GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
286 *dst = src[i];
287 }
288 }
289 }
290
291
292 static void
293 put_mono_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb,
294 GLuint count, const GLint x[], const GLint y[],
295 const void *value, const GLubyte *mask)
296 {
297 const GLushort val = *((const GLushort *) value);
298 ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
299 if (mask) {
300 GLuint i;
301 for (i = 0; i < count; i++) {
302 if (mask[i]) {
303 GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
304 *dst = val;
305 }
306 }
307 }
308 else {
309 GLuint i;
310 for (i = 0; i < count; i++) {
311 GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
312 *dst = val;
313 }
314 }
315 }
316
317
318 /**********************************************************************
319 * Functions for buffers of 1 X GLuint values.
320 * Typically depth/Z or color index.
321 */
322
323 static void *
324 get_pointer_uint(GLcontext *ctx, struct gl_renderbuffer *rb,
325 GLint x, GLint y)
326 {
327 if (!rb->Data)
328 return NULL;
329 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
330 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
331 return (GLuint *) rb->Data + y * rb->Width + x;
332 }
333
334
335 static void
336 get_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
337 GLint x, GLint y, void *values)
338 {
339 const void *src = rb->GetPointer(ctx, rb, x, y);
340 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
341 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
342 _mesa_memcpy(values, src, count * sizeof(GLuint));
343 }
344
345
346 static void
347 get_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
348 const GLint x[], const GLint y[], void *values)
349 {
350 GLuint *dst = (GLuint *) values;
351 GLuint i;
352 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
353 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
354 for (i = 0; i < count; i++) {
355 const GLuint *src = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
356 dst[i] = *src;
357 }
358 }
359
360
361 static void
362 put_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
363 GLint x, GLint y, const void *values, const GLubyte *mask)
364 {
365 const GLuint *src = (const GLuint *) values;
366 GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
367 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
368 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
369 if (mask) {
370 GLuint i;
371 for (i = 0; i < count; i++) {
372 if (mask[i]) {
373 dst[i] = src[i];
374 }
375 }
376 }
377 else {
378 _mesa_memcpy(dst, src, count * sizeof(GLuint));
379 }
380 }
381
382
383 static void
384 put_mono_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
385 GLint x, GLint y, const void *value, const GLubyte *mask)
386 {
387 const GLuint val = *((const GLuint *) value);
388 GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
389 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
390 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
391 if (mask) {
392 GLuint i;
393 for (i = 0; i < count; i++) {
394 if (mask[i]) {
395 dst[i] = val;
396 }
397 }
398 }
399 else {
400 GLuint i;
401 for (i = 0; i < count; i++) {
402 dst[i] = val;
403 }
404 }
405 }
406
407
408 static void
409 put_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
410 const GLint x[], const GLint y[], const void *values,
411 const GLubyte *mask)
412 {
413 const GLuint *src = (const GLuint *) values;
414 GLuint i;
415 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
416 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
417 for (i = 0; i < count; i++) {
418 if (!mask || mask[i]) {
419 GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
420 *dst = src[i];
421 }
422 }
423 }
424
425
426 static void
427 put_mono_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
428 const GLint x[], const GLint y[], const void *value,
429 const GLubyte *mask)
430 {
431 const GLuint val = *((const GLuint *) value);
432 GLuint i;
433 ASSERT(rb->DataType == GL_UNSIGNED_INT ||
434 rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
435 for (i = 0; i < count; i++) {
436 if (!mask || mask[i]) {
437 GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
438 *dst = val;
439 }
440 }
441 }
442
443
444 /**********************************************************************
445 * Functions for buffers of 3 X GLubyte (or GLbyte) values.
446 * Typically color buffers.
447 * NOTE: the incoming and outgoing colors are RGBA! We ignore incoming
448 * alpha values and return 255 for outgoing alpha values.
449 */
450
451 static void *
452 get_pointer_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
453 GLint x, GLint y)
454 {
455 ASSERT(rb->_ActualFormat == GL_RGB8);
456 /* No direct access since this buffer is RGB but caller will be
457 * treating it as if it were RGBA.
458 */
459 return NULL;
460 }
461
462
463 static void
464 get_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
465 GLint x, GLint y, void *values)
466 {
467 const GLubyte *src = (const GLubyte *) rb->Data + 3 * (y * rb->Width + x);
468 GLubyte *dst = (GLubyte *) values;
469 GLuint i;
470 ASSERT(rb->_ActualFormat == GL_RGB8);
471 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
472 for (i = 0; i < count; i++) {
473 dst[i * 4 + 0] = src[i * 3 + 0];
474 dst[i * 4 + 1] = src[i * 3 + 1];
475 dst[i * 4 + 2] = src[i * 3 + 2];
476 dst[i * 4 + 3] = 255;
477 }
478 }
479
480
481 static void
482 get_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
483 const GLint x[], const GLint y[], void *values)
484 {
485 GLubyte *dst = (GLubyte *) values;
486 GLuint i;
487 ASSERT(rb->_ActualFormat == GL_RGB8);
488 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
489 for (i = 0; i < count; i++) {
490 const GLubyte *src
491 = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
492 dst[i * 4 + 0] = src[0];
493 dst[i * 4 + 1] = src[1];
494 dst[i * 4 + 2] = src[2];
495 dst[i * 4 + 3] = 255;
496 }
497 }
498
499
500 static void
501 put_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
502 GLint x, GLint y, const void *values, const GLubyte *mask)
503 {
504 /* note: incoming values are RGB+A! */
505 const GLubyte *src = (const GLubyte *) values;
506 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
507 GLuint i;
508 ASSERT(rb->_ActualFormat == GL_RGB8);
509 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
510 for (i = 0; i < count; i++) {
511 if (!mask || mask[i]) {
512 dst[i * 3 + 0] = src[i * 4 + 0];
513 dst[i * 3 + 1] = src[i * 4 + 1];
514 dst[i * 3 + 2] = src[i * 4 + 2];
515 }
516 }
517 }
518
519
520 static void
521 put_row_rgb_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
522 GLint x, GLint y, const void *values, const GLubyte *mask)
523 {
524 /* note: incoming values are RGB+A! */
525 const GLubyte *src = (const GLubyte *) values;
526 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
527 GLuint i;
528 ASSERT(rb->_ActualFormat == GL_RGB8);
529 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
530 for (i = 0; i < count; i++) {
531 if (!mask || mask[i]) {
532 dst[i * 3 + 0] = src[i * 3 + 0];
533 dst[i * 3 + 1] = src[i * 3 + 1];
534 dst[i * 3 + 2] = src[i * 3 + 2];
535 }
536 }
537 }
538
539
540 static void
541 put_mono_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
542 GLint x, GLint y, const void *value, const GLubyte *mask)
543 {
544 /* note: incoming value is RGB+A! */
545 const GLubyte val0 = ((const GLubyte *) value)[0];
546 const GLubyte val1 = ((const GLubyte *) value)[1];
547 const GLubyte val2 = ((const GLubyte *) value)[2];
548 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
549 ASSERT(rb->_ActualFormat == GL_RGB8);
550 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
551 if (!mask && val0 == val1 && val1 == val2) {
552 /* optimized case */
553 _mesa_memset(dst, val0, 3 * count);
554 }
555 else {
556 GLuint i;
557 for (i = 0; i < count; i++) {
558 if (!mask || mask[i]) {
559 dst[i * 3 + 0] = val0;
560 dst[i * 3 + 1] = val1;
561 dst[i * 3 + 2] = val2;
562 }
563 }
564 }
565 }
566
567
568 static void
569 put_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
570 const GLint x[], const GLint y[], const void *values,
571 const GLubyte *mask)
572 {
573 /* note: incoming values are RGB+A! */
574 const GLubyte *src = (const GLubyte *) values;
575 GLuint i;
576 ASSERT(rb->_ActualFormat == GL_RGB8);
577 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
578 for (i = 0; i < count; i++) {
579 if (!mask || mask[i]) {
580 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
581 dst[0] = src[i * 4 + 0];
582 dst[1] = src[i * 4 + 1];
583 dst[2] = src[i * 4 + 2];
584 }
585 }
586 }
587
588
589 static void
590 put_mono_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
591 GLuint count, const GLint x[], const GLint y[],
592 const void *value, const GLubyte *mask)
593 {
594 /* note: incoming value is RGB+A! */
595 const GLubyte val0 = ((const GLubyte *) value)[0];
596 const GLubyte val1 = ((const GLubyte *) value)[1];
597 const GLubyte val2 = ((const GLubyte *) value)[2];
598 GLuint i;
599 ASSERT(rb->_ActualFormat == GL_RGB8);
600 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
601 for (i = 0; i < count; i++) {
602 if (!mask || mask[i]) {
603 GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
604 dst[0] = val0;
605 dst[1] = val1;
606 dst[2] = val2;
607 }
608 }
609 }
610
611
612 /**********************************************************************
613 * Functions for buffers of 4 X GLubyte (or GLbyte) values.
614 * Typically color buffers.
615 */
616
617 static void *
618 get_pointer_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
619 GLint x, GLint y)
620 {
621 if (!rb->Data)
622 return NULL;
623 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
624 ASSERT(rb->_ActualFormat == GL_RGBA8);
625 return (GLubyte *) rb->Data + 4 * (y * rb->Width + x);
626 }
627
628
629 static void
630 get_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
631 GLint x, GLint y, void *values)
632 {
633 const GLubyte *src = (const GLubyte *) rb->Data + 4 * (y * rb->Width + x);
634 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
635 ASSERT(rb->_ActualFormat == GL_RGBA8);
636 _mesa_memcpy(values, src, 4 * count * sizeof(GLubyte));
637 }
638
639
640 static void
641 get_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
642 const GLint x[], const GLint y[], void *values)
643 {
644 /* treat 4*GLubyte as 1*GLuint */
645 GLuint *dst = (GLuint *) values;
646 GLuint i;
647 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
648 ASSERT(rb->_ActualFormat == GL_RGBA8);
649 for (i = 0; i < count; i++) {
650 const GLuint *src = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
651 dst[i] = *src;
652 }
653 }
654
655
656 static void
657 put_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
658 GLint x, GLint y, const void *values, const GLubyte *mask)
659 {
660 /* treat 4*GLubyte as 1*GLuint */
661 const GLuint *src = (const GLuint *) values;
662 GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
663 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
664 ASSERT(rb->_ActualFormat == GL_RGBA8);
665 if (mask) {
666 GLuint i;
667 for (i = 0; i < count; i++) {
668 if (mask[i]) {
669 dst[i] = src[i];
670 }
671 }
672 }
673 else {
674 _mesa_memcpy(dst, src, 4 * count * sizeof(GLubyte));
675 }
676 }
677
678
679 static void
680 put_row_rgb_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
681 GLint x, GLint y, const void *values, const GLubyte *mask)
682 {
683 /* Store RGB values in RGBA buffer */
684 const GLubyte *src = (const GLubyte *) values;
685 GLubyte *dst = (GLubyte *) rb->Data + 4 * (y * rb->Width + x);
686 GLuint i;
687 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
688 ASSERT(rb->_ActualFormat == GL_RGBA8);
689 for (i = 0; i < count; i++) {
690 if (!mask || mask[i]) {
691 dst[i * 4 + 0] = src[i * 3 + 0];
692 dst[i * 4 + 1] = src[i * 3 + 1];
693 dst[i * 4 + 2] = src[i * 3 + 2];
694 dst[i * 4 + 3] = 0xff;
695 }
696 }
697 }
698
699
700 static void
701 put_mono_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
702 GLint x, GLint y, const void *value, const GLubyte *mask)
703 {
704 /* treat 4*GLubyte as 1*GLuint */
705 const GLuint val = *((const GLuint *) value);
706 GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
707 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
708 ASSERT(rb->_ActualFormat == GL_RGBA8);
709 if (!mask && val == 0) {
710 /* common case */
711 _mesa_bzero(dst, count * 4 * sizeof(GLubyte));
712 }
713 else {
714 /* general case */
715 if (mask) {
716 GLuint i;
717 for (i = 0; i < count; i++) {
718 if (mask[i]) {
719 dst[i] = val;
720 }
721 }
722 }
723 else {
724 GLuint i;
725 for (i = 0; i < count; i++) {
726 dst[i] = val;
727 }
728 }
729 }
730 }
731
732
733 static void
734 put_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
735 const GLint x[], const GLint y[], const void *values,
736 const GLubyte *mask)
737 {
738 /* treat 4*GLubyte as 1*GLuint */
739 const GLuint *src = (const GLuint *) values;
740 GLuint i;
741 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
742 ASSERT(rb->_ActualFormat == GL_RGBA8);
743 for (i = 0; i < count; i++) {
744 if (!mask || mask[i]) {
745 GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
746 *dst = src[i];
747 }
748 }
749 }
750
751
752 static void
753 put_mono_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
754 GLuint count, const GLint x[], const GLint y[],
755 const void *value, const GLubyte *mask)
756 {
757 /* treat 4*GLubyte as 1*GLuint */
758 const GLuint val = *((const GLuint *) value);
759 GLuint i;
760 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
761 ASSERT(rb->_ActualFormat == GL_RGBA8);
762 for (i = 0; i < count; i++) {
763 if (!mask || mask[i]) {
764 GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
765 *dst = val;
766 }
767 }
768 }
769
770
771 /**********************************************************************
772 * Functions for buffers of 4 X GLushort (or GLshort) values.
773 * Typically accum buffer.
774 */
775
776 static void *
777 get_pointer_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb,
778 GLint x, GLint y)
779 {
780 if (!rb->Data)
781 return NULL;
782 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
783 return (GLushort *) rb->Data + 4 * (y * rb->Width + x);
784 }
785
786
787 static void
788 get_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
789 GLint x, GLint y, void *values)
790 {
791 const GLshort *src = (const GLshort *) rb->Data + 4 * (y * rb->Width + x);
792 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
793 _mesa_memcpy(values, src, 4 * count * sizeof(GLshort));
794 }
795
796
797 static void
798 get_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
799 const GLint x[], const GLint y[], void *values)
800 {
801 GLushort *dst = (GLushort *) values;
802 GLuint i;
803 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
804 for (i = 0; i < count; i++) {
805 const GLushort *src
806 = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
807 dst[i] = *src;
808 }
809 }
810
811
812 static void
813 put_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
814 GLint x, GLint y, const void *values, const GLubyte *mask)
815 {
816 const GLushort *src = (const GLushort *) values;
817 GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
818 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
819 if (mask) {
820 GLuint i;
821 for (i = 0; i < count; i++) {
822 if (mask[i]) {
823 dst[i * 4 + 0] = src[i * 4 + 0];
824 dst[i * 4 + 1] = src[i * 4 + 1];
825 dst[i * 4 + 2] = src[i * 4 + 2];
826 dst[i * 4 + 3] = src[i * 4 + 3];
827 }
828 }
829 }
830 else {
831 _mesa_memcpy(dst, src, 4 * count * sizeof(GLushort));
832 }
833 }
834
835
836 static void
837 put_row_rgb_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
838 GLint x, GLint y, const void *values, const GLubyte *mask)
839 {
840 /* Put RGB values in RGBA buffer */
841 const GLushort *src = (const GLushort *) values;
842 GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
843 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
844 if (mask) {
845 GLuint i;
846 for (i = 0; i < count; i++) {
847 if (mask[i]) {
848 dst[i * 4 + 0] = src[i * 3 + 0];
849 dst[i * 4 + 1] = src[i * 3 + 1];
850 dst[i * 4 + 2] = src[i * 3 + 2];
851 dst[i * 4 + 3] = 0xffff;
852 }
853 }
854 }
855 else {
856 _mesa_memcpy(dst, src, 4 * count * sizeof(GLushort));
857 }
858 }
859
860
861 static void
862 put_mono_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
863 GLint x, GLint y, const void *value, const GLubyte *mask)
864 {
865 const GLushort val0 = ((const GLushort *) value)[0];
866 const GLushort val1 = ((const GLushort *) value)[1];
867 const GLushort val2 = ((const GLushort *) value)[2];
868 const GLushort val3 = ((const GLushort *) value)[3];
869 GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
870 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
871 if (!mask && val0 == 0 && val1 == 0 && val2 == 0 && val3 == 0) {
872 /* common case for clearing accum buffer */
873 _mesa_bzero(dst, count * 4 * sizeof(GLushort));
874 }
875 else {
876 GLuint i;
877 for (i = 0; i < count; i++) {
878 if (!mask || mask[i]) {
879 dst[i * 4 + 0] = val0;
880 dst[i * 4 + 1] = val1;
881 dst[i * 4 + 2] = val2;
882 dst[i * 4 + 3] = val3;
883 }
884 }
885 }
886 }
887
888
889 static void
890 put_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
891 const GLint x[], const GLint y[], const void *values,
892 const GLubyte *mask)
893 {
894 const GLushort *src = (const GLushort *) values;
895 GLuint i;
896 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
897 for (i = 0; i < count; i++) {
898 if (!mask || mask[i]) {
899 GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
900 dst[0] = src[i * 4 + 0];
901 dst[1] = src[i * 4 + 1];
902 dst[2] = src[i * 4 + 2];
903 dst[3] = src[i * 4 + 3];
904 }
905 }
906 }
907
908
909 static void
910 put_mono_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb,
911 GLuint count, const GLint x[], const GLint y[],
912 const void *value, const GLubyte *mask)
913 {
914 const GLushort val0 = ((const GLushort *) value)[0];
915 const GLushort val1 = ((const GLushort *) value)[1];
916 const GLushort val2 = ((const GLushort *) value)[2];
917 const GLushort val3 = ((const GLushort *) value)[3];
918 GLuint i;
919 ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
920 for (i = 0; i < count; i++) {
921 if (!mask || mask[i]) {
922 GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
923 dst[0] = val0;
924 dst[1] = val1;
925 dst[2] = val2;
926 dst[3] = val3;
927 }
928 }
929 }
930
931
932
933 /**
934 * This is a software fallback for the gl_renderbuffer->AllocStorage
935 * function.
936 * Device drivers will typically override this function for the buffers
937 * which it manages (typically color buffers, Z and stencil).
938 * Other buffers (like software accumulation and aux buffers) which the driver
939 * doesn't manage can be handled with this function.
940 *
941 * This one multi-purpose function can allocate stencil, depth, accum, color
942 * or color-index buffers!
943 *
944 * This function also plugs in the appropriate GetPointer, Get/PutRow and
945 * Get/PutValues functions.
946 */
947 GLboolean
948 _mesa_soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
949 GLenum internalFormat,
950 GLuint width, GLuint height)
951 {
952 GLuint pixelSize;
953
954 /* first clear these fields */
955 rb->RedBits =
956 rb->GreenBits =
957 rb->BlueBits =
958 rb->AlphaBits =
959 rb->IndexBits =
960 rb->DepthBits =
961 rb->StencilBits = 0;
962
963 switch (internalFormat) {
964 case GL_RGB:
965 case GL_R3_G3_B2:
966 case GL_RGB4:
967 case GL_RGB5:
968 case GL_RGB8:
969 case GL_RGB10:
970 case GL_RGB12:
971 case GL_RGB16:
972 rb->_ActualFormat = GL_RGB8;
973 rb->_BaseFormat = GL_RGB;
974 rb->DataType = GL_UNSIGNED_BYTE;
975 rb->GetPointer = get_pointer_ubyte3;
976 rb->GetRow = get_row_ubyte3;
977 rb->GetValues = get_values_ubyte3;
978 rb->PutRow = put_row_ubyte3;
979 rb->PutRowRGB = put_row_rgb_ubyte3;
980 rb->PutMonoRow = put_mono_row_ubyte3;
981 rb->PutValues = put_values_ubyte3;
982 rb->PutMonoValues = put_mono_values_ubyte3;
983 rb->RedBits = 8 * sizeof(GLubyte);
984 rb->GreenBits = 8 * sizeof(GLubyte);
985 rb->BlueBits = 8 * sizeof(GLubyte);
986 rb->AlphaBits = 0;
987 pixelSize = 3 * sizeof(GLubyte);
988 break;
989 case GL_RGBA:
990 case GL_RGBA2:
991 case GL_RGBA4:
992 case GL_RGB5_A1:
993 case GL_RGBA8:
994 rb->_ActualFormat = GL_RGBA8;
995 rb->_BaseFormat = GL_RGBA;
996 rb->DataType = GL_UNSIGNED_BYTE;
997 rb->GetPointer = get_pointer_ubyte4;
998 rb->GetRow = get_row_ubyte4;
999 rb->GetValues = get_values_ubyte4;
1000 rb->PutRow = put_row_ubyte4;
1001 rb->PutRowRGB = put_row_rgb_ubyte4;
1002 rb->PutMonoRow = put_mono_row_ubyte4;
1003 rb->PutValues = put_values_ubyte4;
1004 rb->PutMonoValues = put_mono_values_ubyte4;
1005 rb->RedBits = 8 * sizeof(GLubyte);
1006 rb->GreenBits = 8 * sizeof(GLubyte);
1007 rb->BlueBits = 8 * sizeof(GLubyte);
1008 rb->AlphaBits = 8 * sizeof(GLubyte);
1009 pixelSize = 4 * sizeof(GLubyte);
1010 break;
1011 case GL_RGB10_A2:
1012 case GL_RGBA12:
1013 case GL_RGBA16:
1014 rb->_ActualFormat = GL_RGBA16;
1015 rb->_BaseFormat = GL_RGBA;
1016 rb->DataType = GL_UNSIGNED_SHORT;
1017 rb->GetPointer = get_pointer_ushort4;
1018 rb->GetRow = get_row_ushort4;
1019 rb->GetValues = get_values_ushort4;
1020 rb->PutRow = put_row_ushort4;
1021 rb->PutRowRGB = put_row_rgb_ushort4;
1022 rb->PutMonoRow = put_mono_row_ushort4;
1023 rb->PutValues = put_values_ushort4;
1024 rb->PutMonoValues = put_mono_values_ushort4;
1025 rb->RedBits = 8 * sizeof(GLushort);
1026 rb->GreenBits = 8 * sizeof(GLushort);
1027 rb->BlueBits = 8 * sizeof(GLushort);
1028 rb->AlphaBits = 8 * sizeof(GLushort);
1029 pixelSize = 4 * sizeof(GLushort);
1030 break;
1031 #if 00
1032 case GL_ALPHA8:
1033 rb->_ActualFormat = GL_ALPHA8;
1034 rb->_BaseFormat = GL_RGBA; /* Yes, not GL_ALPHA! */
1035 rb->DataType = GL_UNSIGNED_BYTE;
1036 rb->GetPointer = get_pointer_alpha8;
1037 rb->GetRow = get_row_alpha8;
1038 rb->GetValues = get_values_alpha8;
1039 rb->PutRow = put_row_alpha8;
1040 rb->PutRowRGB = NULL;
1041 rb->PutMonoRow = put_mono_row_alpha8;
1042 rb->PutValues = put_values_alpha8;
1043 rb->PutMonoValues = put_mono_values_alpha8;
1044 rb->RedBits = 0; /*red*/
1045 rb->GreenBits = 0; /*green*/
1046 rb->BlueBits = 0; /*blue*/
1047 rb->AlphaBits = 8 * sizeof(GLubyte);
1048 pixelSize = sizeof(GLubyte);
1049 break;
1050 #endif
1051 case GL_STENCIL_INDEX:
1052 case GL_STENCIL_INDEX1_EXT:
1053 case GL_STENCIL_INDEX4_EXT:
1054 case GL_STENCIL_INDEX8_EXT:
1055 rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
1056 rb->_BaseFormat = GL_STENCIL_INDEX;
1057 rb->DataType = GL_UNSIGNED_BYTE;
1058 rb->GetPointer = get_pointer_ubyte;
1059 rb->GetRow = get_row_ubyte;
1060 rb->GetValues = get_values_ubyte;
1061 rb->PutRow = put_row_ubyte;
1062 rb->PutRowRGB = NULL;
1063 rb->PutMonoRow = put_mono_row_ubyte;
1064 rb->PutValues = put_values_ubyte;
1065 rb->PutMonoValues = put_mono_values_ubyte;
1066 rb->StencilBits = 8 * sizeof(GLubyte);
1067 pixelSize = sizeof(GLubyte);
1068 break;
1069 case GL_STENCIL_INDEX16_EXT:
1070 rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
1071 rb->_BaseFormat = GL_STENCIL_INDEX;
1072 rb->DataType = GL_UNSIGNED_SHORT;
1073 rb->GetPointer = get_pointer_ushort;
1074 rb->GetRow = get_row_ushort;
1075 rb->GetValues = get_values_ushort;
1076 rb->PutRow = put_row_ushort;
1077 rb->PutRowRGB = NULL;
1078 rb->PutMonoRow = put_mono_row_ushort;
1079 rb->PutValues = put_values_ushort;
1080 rb->PutMonoValues = put_mono_values_ushort;
1081 rb->StencilBits = 8 * sizeof(GLushort);
1082 pixelSize = sizeof(GLushort);
1083 break;
1084 case GL_DEPTH_COMPONENT:
1085 case GL_DEPTH_COMPONENT16:
1086 rb->_ActualFormat = GL_DEPTH_COMPONENT16;
1087 rb->_BaseFormat = GL_DEPTH_COMPONENT;
1088 rb->DataType = GL_UNSIGNED_SHORT;
1089 rb->GetPointer = get_pointer_ushort;
1090 rb->GetRow = get_row_ushort;
1091 rb->GetValues = get_values_ushort;
1092 rb->PutRow = put_row_ushort;
1093 rb->PutRowRGB = NULL;
1094 rb->PutMonoRow = put_mono_row_ushort;
1095 rb->PutValues = put_values_ushort;
1096 rb->PutMonoValues = put_mono_values_ushort;
1097 rb->DepthBits = 8 * sizeof(GLushort);
1098 rb->surface
1099 = (struct pipe_surface *) softpipe_new_z_surface(PIPE_FORMAT_U_Z16);
1100 pixelSize = sizeof(GLushort);
1101 break;
1102 case GL_DEPTH_COMPONENT24:
1103 case GL_DEPTH_COMPONENT32:
1104 rb->_BaseFormat = GL_DEPTH_COMPONENT;
1105 rb->DataType = GL_UNSIGNED_INT;
1106 rb->GetPointer = get_pointer_uint;
1107 rb->GetRow = get_row_uint;
1108 rb->GetValues = get_values_uint;
1109 rb->PutRow = put_row_uint;
1110 rb->PutRowRGB = NULL;
1111 rb->PutMonoRow = put_mono_row_uint;
1112 rb->PutValues = put_values_uint;
1113 rb->PutMonoValues = put_mono_values_uint;
1114 if (internalFormat == GL_DEPTH_COMPONENT24) {
1115 rb->_ActualFormat = GL_DEPTH_COMPONENT24;
1116 rb->DepthBits = 24;
1117 }
1118 else {
1119 rb->_ActualFormat = GL_DEPTH_COMPONENT32;
1120 rb->DepthBits = 32;
1121 }
1122 rb->surface
1123 = (struct pipe_surface *) softpipe_new_z_surface(PIPE_FORMAT_U_Z32);
1124 pixelSize = sizeof(GLuint);
1125 break;
1126 case GL_DEPTH_STENCIL_EXT:
1127 case GL_DEPTH24_STENCIL8_EXT:
1128 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
1129 rb->_BaseFormat = GL_DEPTH_STENCIL_EXT;
1130 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
1131 rb->GetPointer = get_pointer_uint;
1132 rb->GetRow = get_row_uint;
1133 rb->GetValues = get_values_uint;
1134 rb->PutRow = put_row_uint;
1135 rb->PutRowRGB = NULL;
1136 rb->PutMonoRow = put_mono_row_uint;
1137 rb->PutValues = put_values_uint;
1138 rb->PutMonoValues = put_mono_values_uint;
1139 rb->DepthBits = 24;
1140 rb->StencilBits = 8;
1141 rb->surface
1142 = (struct pipe_surface *) softpipe_new_z_surface(PIPE_FORMAT_Z24_S8);
1143 pixelSize = sizeof(GLuint);
1144 break;
1145 case GL_COLOR_INDEX8_EXT:
1146 rb->_ActualFormat = GL_COLOR_INDEX8_EXT;
1147 rb->_BaseFormat = GL_COLOR_INDEX;
1148 rb->DataType = GL_UNSIGNED_BYTE;
1149 rb->GetPointer = get_pointer_ubyte;
1150 rb->GetRow = get_row_ubyte;
1151 rb->GetValues = get_values_ubyte;
1152 rb->PutRow = put_row_ubyte;
1153 rb->PutRowRGB = NULL;
1154 rb->PutMonoRow = put_mono_row_ubyte;
1155 rb->PutValues = put_values_ubyte;
1156 rb->PutMonoValues = put_mono_values_ubyte;
1157 rb->IndexBits = 8 * sizeof(GLubyte);
1158 pixelSize = sizeof(GLubyte);
1159 break;
1160 case GL_COLOR_INDEX16_EXT:
1161 rb->_ActualFormat = GL_COLOR_INDEX16_EXT;
1162 rb->_BaseFormat = GL_COLOR_INDEX;
1163 rb->DataType = GL_UNSIGNED_SHORT;
1164 rb->GetPointer = get_pointer_ushort;
1165 rb->GetRow = get_row_ushort;
1166 rb->GetValues = get_values_ushort;
1167 rb->PutRow = put_row_ushort;
1168 rb->PutRowRGB = NULL;
1169 rb->PutMonoRow = put_mono_row_ushort;
1170 rb->PutValues = put_values_ushort;
1171 rb->PutMonoValues = put_mono_values_ushort;
1172 rb->IndexBits = 8 * sizeof(GLushort);
1173 pixelSize = sizeof(GLushort);
1174 break;
1175 case COLOR_INDEX32:
1176 rb->_ActualFormat = COLOR_INDEX32;
1177 rb->_BaseFormat = GL_COLOR_INDEX;
1178 rb->DataType = GL_UNSIGNED_INT;
1179 rb->GetPointer = get_pointer_uint;
1180 rb->GetRow = get_row_uint;
1181 rb->GetValues = get_values_uint;
1182 rb->PutRow = put_row_uint;
1183 rb->PutRowRGB = NULL;
1184 rb->PutMonoRow = put_mono_row_uint;
1185 rb->PutValues = put_values_uint;
1186 rb->PutMonoValues = put_mono_values_uint;
1187 rb->IndexBits = 8 * sizeof(GLuint);
1188 pixelSize = sizeof(GLuint);
1189 break;
1190 default:
1191 _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage");
1192 return GL_FALSE;
1193 }
1194
1195 ASSERT(rb->DataType);
1196 ASSERT(rb->GetPointer);
1197 ASSERT(rb->GetRow);
1198 ASSERT(rb->GetValues);
1199 ASSERT(rb->PutRow);
1200 ASSERT(rb->PutMonoRow);
1201 ASSERT(rb->PutValues);
1202 ASSERT(rb->PutMonoValues);
1203
1204 /* free old buffer storage */
1205 if (rb->Data) {
1206 if (rb->surface) {
1207 /* pipe surface */
1208 }
1209 else {
1210 /* legacy renderbuffer */
1211 _mesa_free(rb->Data);
1212 }
1213 rb->Data = NULL;
1214 }
1215
1216 if (width > 0 && height > 0) {
1217 /* allocate new buffer storage */
1218 if (rb->surface) {
1219 /* pipe surface */
1220 rb->surface->resize(rb->surface, width, height);
1221 rb->Data = rb->surface->buffer.ptr;
1222 }
1223 else {
1224 /* legacy renderbuffer */
1225 rb->Data = _mesa_malloc(width * height * pixelSize);
1226 }
1227 if (rb->Data == NULL) {
1228 rb->Width = 0;
1229 rb->Height = 0;
1230 _mesa_error(ctx, GL_OUT_OF_MEMORY,
1231 "software renderbuffer allocation (%d x %d x %d)",
1232 width, height, pixelSize);
1233 return GL_FALSE;
1234 }
1235 }
1236
1237 rb->Width = width;
1238 rb->Height = height;
1239
1240 return GL_TRUE;
1241 }
1242
1243
1244
1245 /**********************************************************************/
1246 /**********************************************************************/
1247 /**********************************************************************/
1248
1249
1250 /**
1251 * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha
1252 * buffer wrapper around an existing RGB renderbuffer (hw or sw).
1253 *
1254 * When PutRow is called (for example), we store the alpha values in
1255 * this buffer, then pass on the PutRow call to the wrapped RGB
1256 * buffer.
1257 */
1258
1259
1260 static GLboolean
1261 alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1262 GLenum internalFormat, GLuint width, GLuint height)
1263 {
1264 ASSERT(arb != arb->Wrapped);
1265 ASSERT(arb->_ActualFormat == GL_ALPHA8);
1266
1267 /* first, pass the call to the wrapped RGB buffer */
1268 if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat,
1269 width, height)) {
1270 return GL_FALSE;
1271 }
1272
1273 /* next, resize my alpha buffer */
1274 if (arb->Data) {
1275 _mesa_free(arb->Data);
1276 }
1277
1278 arb->Data = _mesa_malloc(width * height * sizeof(GLubyte));
1279 if (arb->Data == NULL) {
1280 arb->Width = 0;
1281 arb->Height = 0;
1282 _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
1283 return GL_FALSE;
1284 }
1285
1286 arb->Width = width;
1287 arb->Height = height;
1288
1289 return GL_TRUE;
1290 }
1291
1292
1293 /**
1294 * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
1295 */
1296 static void
1297 delete_renderbuffer_alpha8(struct gl_renderbuffer *arb)
1298 {
1299 if (arb->Data) {
1300 _mesa_free(arb->Data);
1301 }
1302 ASSERT(arb->Wrapped);
1303 ASSERT(arb != arb->Wrapped);
1304 arb->Wrapped->Delete(arb->Wrapped);
1305 arb->Wrapped = NULL;
1306 _mesa_free(arb);
1307 }
1308
1309
1310 static void *
1311 get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1312 GLint x, GLint y)
1313 {
1314 return NULL; /* don't allow direct access! */
1315 }
1316
1317
1318 static void
1319 get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1320 GLint x, GLint y, void *values)
1321 {
1322 /* NOTE: 'values' is RGBA format! */
1323 const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x;
1324 GLubyte *dst = (GLubyte *) values;
1325 GLuint i;
1326 ASSERT(arb != arb->Wrapped);
1327 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1328 /* first, pass the call to the wrapped RGB buffer */
1329 arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values);
1330 /* second, fill in alpha values from this buffer! */
1331 for (i = 0; i < count; i++) {
1332 dst[i * 4 + 3] = src[i];
1333 }
1334 }
1335
1336
1337 static void
1338 get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1339 const GLint x[], const GLint y[], void *values)
1340 {
1341 GLubyte *dst = (GLubyte *) values;
1342 GLuint i;
1343 ASSERT(arb != arb->Wrapped);
1344 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1345 /* first, pass the call to the wrapped RGB buffer */
1346 arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values);
1347 /* second, fill in alpha values from this buffer! */
1348 for (i = 0; i < count; i++) {
1349 const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1350 dst[i * 4 + 3] = *src;
1351 }
1352 }
1353
1354
1355 static void
1356 put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1357 GLint x, GLint y, const void *values, const GLubyte *mask)
1358 {
1359 const GLubyte *src = (const GLubyte *) values;
1360 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1361 GLuint i;
1362 ASSERT(arb != arb->Wrapped);
1363 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1364 /* first, pass the call to the wrapped RGB buffer */
1365 arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask);
1366 /* second, store alpha in our buffer */
1367 for (i = 0; i < count; i++) {
1368 if (!mask || mask[i]) {
1369 dst[i] = src[i * 4 + 3];
1370 }
1371 }
1372 }
1373
1374
1375 static void
1376 put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1377 GLint x, GLint y, const void *values, const GLubyte *mask)
1378 {
1379 const GLubyte *src = (const GLubyte *) values;
1380 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1381 GLuint i;
1382 ASSERT(arb != arb->Wrapped);
1383 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1384 /* first, pass the call to the wrapped RGB buffer */
1385 arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask);
1386 /* second, store alpha in our buffer */
1387 for (i = 0; i < count; i++) {
1388 if (!mask || mask[i]) {
1389 dst[i] = src[i * 4 + 3];
1390 }
1391 }
1392 }
1393
1394
1395 static void
1396 put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1397 GLint x, GLint y, const void *value, const GLubyte *mask)
1398 {
1399 const GLubyte val = ((const GLubyte *) value)[3];
1400 GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
1401 ASSERT(arb != arb->Wrapped);
1402 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1403 /* first, pass the call to the wrapped RGB buffer */
1404 arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask);
1405 /* second, store alpha in our buffer */
1406 if (mask) {
1407 GLuint i;
1408 for (i = 0; i < count; i++) {
1409 if (mask[i]) {
1410 dst[i] = val;
1411 }
1412 }
1413 }
1414 else {
1415 _mesa_memset(dst, val, count);
1416 }
1417 }
1418
1419
1420 static void
1421 put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
1422 const GLint x[], const GLint y[],
1423 const void *values, const GLubyte *mask)
1424 {
1425 const GLubyte *src = (const GLubyte *) values;
1426 GLuint i;
1427 ASSERT(arb != arb->Wrapped);
1428 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1429 /* first, pass the call to the wrapped RGB buffer */
1430 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask);
1431 /* second, store alpha in our buffer */
1432 for (i = 0; i < count; i++) {
1433 if (!mask || mask[i]) {
1434 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1435 *dst = src[i * 4 + 3];
1436 }
1437 }
1438 }
1439
1440
1441 static void
1442 put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
1443 GLuint count, const GLint x[], const GLint y[],
1444 const void *value, const GLubyte *mask)
1445 {
1446 const GLubyte val = ((const GLubyte *) value)[3];
1447 GLuint i;
1448 ASSERT(arb != arb->Wrapped);
1449 ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
1450 /* first, pass the call to the wrapped RGB buffer */
1451 arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask);
1452 /* second, store alpha in our buffer */
1453 for (i = 0; i < count; i++) {
1454 if (!mask || mask[i]) {
1455 GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
1456 *dst = val;
1457 }
1458 }
1459 }
1460
1461
1462 static void
1463 copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src)
1464 {
1465 ASSERT(dst->_ActualFormat == GL_ALPHA8);
1466 ASSERT(src->_ActualFormat == GL_ALPHA8);
1467 ASSERT(dst->Width == src->Width);
1468 ASSERT(dst->Height == src->Height);
1469
1470 _mesa_memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte));
1471 }
1472
1473
1474 /**********************************************************************/
1475 /**********************************************************************/
1476 /**********************************************************************/
1477
1478
1479 /**
1480 * Default GetPointer routine. Always return NULL to indicate that
1481 * direct buffer access is not supported.
1482 */
1483 static void *
1484 nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
1485 {
1486 return NULL;
1487 }
1488
1489
1490 /**
1491 * Initialize the fields of a gl_renderbuffer to default values.
1492 */
1493 void
1494 _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
1495 {
1496 _glthread_INIT_MUTEX(rb->Mutex);
1497
1498 rb->Magic = RB_MAGIC;
1499 rb->ClassID = 0;
1500 rb->Name = name;
1501 rb->RefCount = 0;
1502 rb->Delete = _mesa_delete_renderbuffer;
1503
1504 /* The rest of these should be set later by the caller of this function or
1505 * the AllocStorage method:
1506 */
1507 rb->AllocStorage = NULL;
1508
1509 rb->Width = 0;
1510 rb->Height = 0;
1511 rb->InternalFormat = GL_NONE;
1512 rb->_ActualFormat = GL_NONE;
1513 rb->_BaseFormat = GL_NONE;
1514 rb->DataType = GL_NONE;
1515 rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0;
1516 rb->IndexBits = 0;
1517 rb->DepthBits = 0;
1518 rb->StencilBits = 0;
1519 rb->Data = NULL;
1520
1521 /* Point back to ourself so that we don't have to check for Wrapped==NULL
1522 * all over the drivers.
1523 */
1524 rb->Wrapped = rb;
1525
1526 rb->GetPointer = nop_get_pointer;
1527 rb->GetRow = NULL;
1528 rb->GetValues = NULL;
1529 rb->PutRow = NULL;
1530 rb->PutRowRGB = NULL;
1531 rb->PutMonoRow = NULL;
1532 rb->PutValues = NULL;
1533 rb->PutMonoValues = NULL;
1534 }
1535
1536
1537 /**
1538 * Allocate a new gl_renderbuffer object. This can be used for user-created
1539 * renderbuffers or window-system renderbuffers.
1540 */
1541 struct gl_renderbuffer *
1542 _mesa_new_renderbuffer(GLcontext *ctx, GLuint name)
1543 {
1544 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1545 if (rb) {
1546 _mesa_init_renderbuffer(rb, name);
1547 }
1548 return rb;
1549 }
1550
1551
1552 /**
1553 * Delete a gl_framebuffer.
1554 * This is the default function for renderbuffer->Delete().
1555 */
1556 void
1557 _mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
1558 {
1559 if (rb->Data) {
1560 _mesa_free(rb->Data);
1561 }
1562 _mesa_free(rb);
1563 }
1564
1565
1566 /**
1567 * Allocate a software-based renderbuffer. This is called via the
1568 * ctx->Driver.NewRenderbuffer() function when the user creates a new
1569 * renderbuffer.
1570 * This would not be used for hardware-based renderbuffers.
1571 */
1572 struct gl_renderbuffer *
1573 _mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
1574 {
1575 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1576 if (rb) {
1577 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1578 /* Normally, one would setup the PutRow, GetRow, etc functions here.
1579 * But we're doing that in the _mesa_soft_renderbuffer_storage() function
1580 * instead.
1581 */
1582 }
1583 return rb;
1584 }
1585
1586
1587 /**
1588 * Add software-based color renderbuffers to the given framebuffer.
1589 * This is a helper routine for device drivers when creating a
1590 * window system framebuffer (not a user-created render/framebuffer).
1591 * Once this function is called, you can basically forget about this
1592 * renderbuffer; core Mesa will handle all the buffer management and
1593 * rendering!
1594 */
1595 GLboolean
1596 _mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1597 GLuint rgbBits, GLuint alphaBits,
1598 GLboolean frontLeft, GLboolean backLeft,
1599 GLboolean frontRight, GLboolean backRight)
1600 {
1601 GLuint b;
1602
1603 if (rgbBits > 16 || alphaBits > 16) {
1604 _mesa_problem(ctx,
1605 "Unsupported bit depth in _mesa_add_color_renderbuffers");
1606 return GL_FALSE;
1607 }
1608
1609 assert(MAX_COLOR_ATTACHMENTS >= 4);
1610
1611 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1612 struct gl_renderbuffer *rb;
1613
1614 if (b == BUFFER_FRONT_LEFT && !frontLeft)
1615 continue;
1616 else if (b == BUFFER_BACK_LEFT && !backLeft)
1617 continue;
1618 else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1619 continue;
1620 else if (b == BUFFER_BACK_RIGHT && !backRight)
1621 continue;
1622
1623 assert(fb->Attachment[b].Renderbuffer == NULL);
1624
1625 rb = _mesa_new_renderbuffer(ctx, 0);
1626 if (!rb) {
1627 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1628 return GL_FALSE;
1629 }
1630
1631 if (rgbBits <= 8) {
1632 if (alphaBits)
1633 rb->_ActualFormat = GL_RGBA8;
1634 else
1635 rb->_ActualFormat = GL_RGB8;
1636 }
1637 else {
1638 assert(rgbBits <= 16);
1639 if (alphaBits)
1640 rb->_ActualFormat = GL_RGBA16;
1641 else
1642 rb->_ActualFormat = GL_RGBA16; /* don't really have RGB16 yet */
1643 }
1644 rb->InternalFormat = rb->_ActualFormat;
1645
1646 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1647 _mesa_add_renderbuffer(fb, b, rb);
1648 }
1649
1650 return GL_TRUE;
1651 }
1652
1653
1654 /**
1655 * Add software-based color index renderbuffers to the given framebuffer.
1656 * This is a helper routine for device drivers when creating a
1657 * window system framebuffer (not a user-created render/framebuffer).
1658 * Once this function is called, you can basically forget about this
1659 * renderbuffer; core Mesa will handle all the buffer management and
1660 * rendering!
1661 */
1662 GLboolean
1663 _mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1664 GLuint indexBits,
1665 GLboolean frontLeft, GLboolean backLeft,
1666 GLboolean frontRight, GLboolean backRight)
1667 {
1668 GLuint b;
1669
1670 if (indexBits > 8) {
1671 _mesa_problem(ctx,
1672 "Unsupported bit depth in _mesa_add_color_index_renderbuffers");
1673 return GL_FALSE;
1674 }
1675
1676 assert(MAX_COLOR_ATTACHMENTS >= 4);
1677
1678 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1679 struct gl_renderbuffer *rb;
1680
1681 if (b == BUFFER_FRONT_LEFT && !frontLeft)
1682 continue;
1683 else if (b == BUFFER_BACK_LEFT && !backLeft)
1684 continue;
1685 else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1686 continue;
1687 else if (b == BUFFER_BACK_RIGHT && !backRight)
1688 continue;
1689
1690 assert(fb->Attachment[b].Renderbuffer == NULL);
1691
1692 rb = _mesa_new_renderbuffer(ctx, 0);
1693 if (!rb) {
1694 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
1695 return GL_FALSE;
1696 }
1697
1698 if (indexBits <= 8) {
1699 /* only support GLuint for now */
1700 /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/
1701 rb->_ActualFormat = COLOR_INDEX32;
1702 }
1703 else {
1704 rb->_ActualFormat = COLOR_INDEX32;
1705 }
1706 rb->InternalFormat = rb->_ActualFormat;
1707
1708 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1709 _mesa_add_renderbuffer(fb, b, rb);
1710 }
1711
1712 return GL_TRUE;
1713 }
1714
1715
1716 /**
1717 * Add software-based alpha renderbuffers to the given framebuffer.
1718 * This is a helper routine for device drivers when creating a
1719 * window system framebuffer (not a user-created render/framebuffer).
1720 * Once this function is called, you can basically forget about this
1721 * renderbuffer; core Mesa will handle all the buffer management and
1722 * rendering!
1723 */
1724 GLboolean
1725 _mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1726 GLuint alphaBits,
1727 GLboolean frontLeft, GLboolean backLeft,
1728 GLboolean frontRight, GLboolean backRight)
1729 {
1730 GLuint b;
1731
1732 /* for window system framebuffers only! */
1733 assert(fb->Name == 0);
1734
1735 if (alphaBits > 8) {
1736 _mesa_problem(ctx,
1737 "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
1738 return GL_FALSE;
1739 }
1740
1741 assert(MAX_COLOR_ATTACHMENTS >= 4);
1742
1743 /* Wrap each of the RGB color buffers with an alpha renderbuffer.
1744 */
1745 for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
1746 struct gl_renderbuffer *arb;
1747
1748 if (b == BUFFER_FRONT_LEFT && !frontLeft)
1749 continue;
1750 else if (b == BUFFER_BACK_LEFT && !backLeft)
1751 continue;
1752 else if (b == BUFFER_FRONT_RIGHT && !frontRight)
1753 continue;
1754 else if (b == BUFFER_BACK_RIGHT && !backRight)
1755 continue;
1756
1757 /* the RGB buffer to wrap must already exist!! */
1758 assert(fb->Attachment[b].Renderbuffer);
1759
1760 /* only GLubyte supported for now */
1761 assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
1762
1763 /* allocate alpha renderbuffer */
1764 arb = _mesa_new_renderbuffer(ctx, 0);
1765 if (!arb) {
1766 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
1767 return GL_FALSE;
1768 }
1769
1770 /* wrap the alpha renderbuffer around the RGB renderbuffer */
1771 arb->Wrapped = fb->Attachment[b].Renderbuffer;
1772
1773 /* Set up my alphabuffer fields and plug in my functions.
1774 * The functions will put/get the alpha values from/to RGBA arrays
1775 * and then call the wrapped buffer's functions to handle the RGB
1776 * values.
1777 */
1778 arb->InternalFormat = arb->Wrapped->InternalFormat;
1779 arb->_ActualFormat = GL_ALPHA8;
1780 arb->_BaseFormat = arb->Wrapped->_BaseFormat;
1781 arb->DataType = arb->Wrapped->DataType;
1782 arb->AllocStorage = alloc_storage_alpha8;
1783 arb->Delete = delete_renderbuffer_alpha8;
1784 arb->GetPointer = get_pointer_alpha8;
1785 arb->GetRow = get_row_alpha8;
1786 arb->GetValues = get_values_alpha8;
1787 arb->PutRow = put_row_alpha8;
1788 arb->PutRowRGB = put_row_rgb_alpha8;
1789 arb->PutMonoRow = put_mono_row_alpha8;
1790 arb->PutValues = put_values_alpha8;
1791 arb->PutMonoValues = put_mono_values_alpha8;
1792
1793 /* clear the pointer to avoid assertion/sanity check failure later */
1794 fb->Attachment[b].Renderbuffer = NULL;
1795
1796 /* plug the alpha renderbuffer into the colorbuffer attachment */
1797 _mesa_add_renderbuffer(fb, b, arb);
1798 }
1799
1800 return GL_TRUE;
1801 }
1802
1803
1804 /**
1805 * For framebuffers that use a software alpha channel wrapper
1806 * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
1807 * copy the back buffer alpha channel into the front buffer alpha channel.
1808 */
1809 void
1810 _mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb)
1811 {
1812 if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
1813 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer)
1814 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer,
1815 fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
1816
1817
1818 if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
1819 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer)
1820 copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer,
1821 fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
1822 }
1823
1824
1825 /**
1826 * Add a software-based depth renderbuffer to the given framebuffer.
1827 * This is a helper routine for device drivers when creating a
1828 * window system framebuffer (not a user-created render/framebuffer).
1829 * Once this function is called, you can basically forget about this
1830 * renderbuffer; core Mesa will handle all the buffer management and
1831 * rendering!
1832 */
1833 GLboolean
1834 _mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1835 GLuint depthBits)
1836 {
1837 struct gl_renderbuffer *rb;
1838
1839 if (depthBits > 32) {
1840 _mesa_problem(ctx,
1841 "Unsupported depthBits in _mesa_add_depth_renderbuffer");
1842 return GL_FALSE;
1843 }
1844
1845 assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
1846
1847 rb = _mesa_new_renderbuffer(ctx, 0);
1848 if (!rb) {
1849 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
1850 return GL_FALSE;
1851 }
1852
1853 if (depthBits <= 16) {
1854 rb->_ActualFormat = GL_DEPTH_COMPONENT16;
1855 }
1856 else if (depthBits <= 24) {
1857 rb->_ActualFormat = GL_DEPTH_COMPONENT24;
1858 }
1859 else {
1860 rb->_ActualFormat = GL_DEPTH_COMPONENT32;
1861 }
1862 rb->InternalFormat = rb->_ActualFormat;
1863
1864 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1865 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
1866
1867 return GL_TRUE;
1868 }
1869
1870
1871 /**
1872 * Add a software-based stencil renderbuffer to the given framebuffer.
1873 * This is a helper routine for device drivers when creating a
1874 * window system framebuffer (not a user-created render/framebuffer).
1875 * Once this function is called, you can basically forget about this
1876 * renderbuffer; core Mesa will handle all the buffer management and
1877 * rendering!
1878 */
1879 GLboolean
1880 _mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1881 GLuint stencilBits)
1882 {
1883 struct gl_renderbuffer *rb;
1884
1885 if (stencilBits > 16) {
1886 _mesa_problem(ctx,
1887 "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
1888 return GL_FALSE;
1889 }
1890
1891 assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
1892
1893 rb = _mesa_new_renderbuffer(ctx, 0);
1894 if (!rb) {
1895 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
1896 return GL_FALSE;
1897 }
1898
1899 if (stencilBits <= 8) {
1900 rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
1901 }
1902 else {
1903 /* not really supported (see s_stencil.c code) */
1904 rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
1905 }
1906 rb->InternalFormat = rb->_ActualFormat;
1907
1908 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1909 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
1910
1911 return GL_TRUE;
1912 }
1913
1914
1915 /**
1916 * Add a software-based accumulation renderbuffer to the given framebuffer.
1917 * This is a helper routine for device drivers when creating a
1918 * window system framebuffer (not a user-created render/framebuffer).
1919 * Once this function is called, you can basically forget about this
1920 * renderbuffer; core Mesa will handle all the buffer management and
1921 * rendering!
1922 */
1923 GLboolean
1924 _mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
1925 GLuint redBits, GLuint greenBits,
1926 GLuint blueBits, GLuint alphaBits)
1927 {
1928 struct gl_renderbuffer *rb;
1929
1930 if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
1931 _mesa_problem(ctx,
1932 "Unsupported accumBits in _mesa_add_accum_renderbuffer");
1933 return GL_FALSE;
1934 }
1935
1936 assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
1937
1938 rb = _mesa_new_renderbuffer(ctx, 0);
1939 if (!rb) {
1940 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1941 return GL_FALSE;
1942 }
1943
1944 rb->_ActualFormat = GL_RGBA16;
1945 rb->InternalFormat = GL_RGBA16;
1946 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1947 _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
1948
1949 return GL_TRUE;
1950 }
1951
1952
1953
1954 /**
1955 * Add a software-based accumulation renderbuffer to the given framebuffer.
1956 * This is a helper routine for device drivers when creating a
1957 * window system framebuffer (not a user-created render/framebuffer).
1958 * Once this function is called, you can basically forget about this
1959 * renderbuffer; core Mesa will handle all the buffer management and
1960 * rendering!
1961 *
1962 * NOTE: color-index aux buffers not supported.
1963 */
1964 GLboolean
1965 _mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
1966 GLuint colorBits, GLuint numBuffers)
1967 {
1968 GLuint i;
1969
1970 if (colorBits > 16) {
1971 _mesa_problem(ctx,
1972 "Unsupported accumBits in _mesa_add_aux_renderbuffers");
1973 return GL_FALSE;
1974 }
1975
1976 assert(numBuffers < MAX_AUX_BUFFERS);
1977
1978 for (i = 0; i < numBuffers; i++) {
1979 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
1980
1981 assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
1982
1983 if (!rb) {
1984 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
1985 return GL_FALSE;
1986 }
1987
1988 if (colorBits <= 8) {
1989 rb->_ActualFormat = GL_RGBA8;
1990 }
1991 else {
1992 rb->_ActualFormat = GL_RGBA16;
1993 }
1994 rb->InternalFormat = rb->_ActualFormat;
1995
1996 rb->AllocStorage = _mesa_soft_renderbuffer_storage;
1997 _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
1998 }
1999 return GL_TRUE;
2000 }
2001
2002
2003 /**
2004 * Create/attach software-based renderbuffers to the given framebuffer.
2005 * This is a helper routine for device drivers. Drivers can just as well
2006 * call the individual _mesa_add_*_renderbuffer() routines directly.
2007 */
2008 void
2009 _mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
2010 GLboolean color,
2011 GLboolean depth,
2012 GLboolean stencil,
2013 GLboolean accum,
2014 GLboolean alpha,
2015 GLboolean aux)
2016 {
2017 GLboolean frontLeft = GL_TRUE;
2018 GLboolean backLeft = fb->Visual.doubleBufferMode;
2019 GLboolean frontRight = fb->Visual.stereoMode;
2020 GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
2021
2022 if (color) {
2023 if (fb->Visual.rgbMode) {
2024 assert(fb->Visual.redBits == fb->Visual.greenBits);
2025 assert(fb->Visual.redBits == fb->Visual.blueBits);
2026 _mesa_add_color_renderbuffers(NULL, fb,
2027 fb->Visual.redBits,
2028 fb->Visual.alphaBits,
2029 frontLeft, backLeft,
2030 frontRight, backRight);
2031 }
2032 else {
2033 _mesa_add_color_index_renderbuffers(NULL, fb,
2034 fb->Visual.indexBits,
2035 frontLeft, backLeft,
2036 frontRight, backRight);
2037 }
2038 }
2039
2040 if (depth) {
2041 assert(fb->Visual.depthBits > 0);
2042 _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
2043 }
2044
2045 if (stencil) {
2046 assert(fb->Visual.stencilBits > 0);
2047 _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
2048 }
2049
2050 if (accum) {
2051 assert(fb->Visual.rgbMode);
2052 assert(fb->Visual.accumRedBits > 0);
2053 assert(fb->Visual.accumGreenBits > 0);
2054 assert(fb->Visual.accumBlueBits > 0);
2055 _mesa_add_accum_renderbuffer(NULL, fb,
2056 fb->Visual.accumRedBits,
2057 fb->Visual.accumGreenBits,
2058 fb->Visual.accumBlueBits,
2059 fb->Visual.accumAlphaBits);
2060 }
2061
2062 if (aux) {
2063 assert(fb->Visual.rgbMode);
2064 assert(fb->Visual.numAuxBuffers > 0);
2065 _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
2066 fb->Visual.numAuxBuffers);
2067 }
2068
2069 if (alpha) {
2070 assert(fb->Visual.rgbMode);
2071 assert(fb->Visual.alphaBits > 0);
2072 _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
2073 frontLeft, backLeft,
2074 frontRight, backRight);
2075 }
2076
2077 #if 0
2078 if (multisample) {
2079 /* maybe someday */
2080 }
2081 #endif
2082 }
2083
2084
2085 /**
2086 * Attach a renderbuffer to a framebuffer.
2087 */
2088 void
2089 _mesa_add_renderbuffer(struct gl_framebuffer *fb,
2090 GLuint bufferName, struct gl_renderbuffer *rb)
2091 {
2092 assert(fb);
2093 assert(rb);
2094 assert(bufferName < BUFFER_COUNT);
2095
2096 /* There should be no previous renderbuffer on this attachment point,
2097 * with the exception of depth/stencil since the same renderbuffer may
2098 * be used for both.
2099 */
2100 assert(bufferName == BUFFER_DEPTH ||
2101 bufferName == BUFFER_STENCIL ||
2102 fb->Attachment[bufferName].Renderbuffer == NULL);
2103
2104 /* winsys vs. user-created buffer cross check */
2105 if (fb->Name) {
2106 assert(rb->Name);
2107 }
2108 else {
2109 assert(!rb->Name);
2110 }
2111
2112 /* If Mesa's compiled with deep color channels (16 or 32 bits / channel)
2113 * and the device driver is expecting 8-bit values (GLubyte), we can
2114 * use a "renderbuffer adaptor/wrapper" to do the necessary conversions.
2115 */
2116 if (rb->_BaseFormat == GL_RGBA) {
2117 if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) {
2118 GET_CURRENT_CONTEXT(ctx);
2119 rb = _mesa_new_renderbuffer_16wrap8(ctx, rb);
2120 }
2121 else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) {
2122 GET_CURRENT_CONTEXT(ctx);
2123 rb = _mesa_new_renderbuffer_32wrap8(ctx, rb);
2124 }
2125 else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) {
2126 GET_CURRENT_CONTEXT(ctx);
2127 rb = _mesa_new_renderbuffer_32wrap16(ctx, rb);
2128 }
2129 }
2130
2131 fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
2132 fb->Attachment[bufferName].Complete = GL_TRUE;
2133 _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
2134 }
2135
2136
2137 /**
2138 * Remove the named renderbuffer from the given framebuffer.
2139 */
2140 void
2141 _mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName)
2142 {
2143 struct gl_renderbuffer *rb;
2144
2145 assert(bufferName < BUFFER_COUNT);
2146
2147 rb = fb->Attachment[bufferName].Renderbuffer;
2148 if (!rb)
2149 return;
2150
2151 _mesa_reference_renderbuffer(&rb, NULL);
2152
2153 fb->Attachment[bufferName].Renderbuffer = NULL;
2154 }
2155
2156
2157 /**
2158 * Set *ptr to point to rb. If *ptr points to another renderbuffer,
2159 * dereference that buffer first. The new renderbuffer's refcount will
2160 * be incremented. The old renderbuffer's refcount will be decremented.
2161 */
2162 void
2163 _mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
2164 struct gl_renderbuffer *rb)
2165 {
2166 assert(ptr);
2167 if (*ptr == rb) {
2168 /* no change */
2169 return;
2170 }
2171
2172 if (*ptr) {
2173 /* Unreference the old renderbuffer */
2174 GLboolean deleteFlag = GL_FALSE;
2175 struct gl_renderbuffer *oldRb = *ptr;
2176
2177 assert(oldRb->Magic == RB_MAGIC);
2178 _glthread_LOCK_MUTEX(oldRb->Mutex);
2179 assert(oldRb->Magic == RB_MAGIC);
2180 ASSERT(oldRb->RefCount > 0);
2181 oldRb->RefCount--;
2182 /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
2183 deleteFlag = (oldRb->RefCount == 0);
2184 _glthread_UNLOCK_MUTEX(oldRb->Mutex);
2185
2186 if (deleteFlag) {
2187 oldRb->Magic = 0; /* now invalid memory! */
2188 oldRb->Delete(oldRb);
2189 }
2190
2191 *ptr = NULL;
2192 }
2193 assert(!*ptr);
2194
2195 if (rb) {
2196 assert(rb->Magic == RB_MAGIC);
2197 /* reference new renderbuffer */
2198 _glthread_LOCK_MUTEX(rb->Mutex);
2199 rb->RefCount++;
2200 /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
2201 _glthread_UNLOCK_MUTEX(rb->Mutex);
2202 *ptr = rb;
2203 }
2204 }
2205
2206
2207 /**
2208 * Create a new combined depth/stencil renderbuffer for implementing
2209 * the GL_EXT_packed_depth_stencil extension.
2210 * \return new depth/stencil renderbuffer
2211 */
2212 struct gl_renderbuffer *
2213 _mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name)
2214 {
2215 struct gl_renderbuffer *dsrb;
2216
2217 dsrb = _mesa_new_renderbuffer(ctx, name);
2218 if (!dsrb)
2219 return NULL;
2220
2221 /* init fields not covered by _mesa_new_renderbuffer() */
2222 dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
2223 dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
2224 dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
2225
2226 return dsrb;
2227 }