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