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