renderbuffer.c revision acafeeb6dce74382fb3a48b83ab72bf67b7581ea
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
65static void *
66get_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
76static void
77get_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
86static void
87get_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
100static void
101put_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
121static void
122put_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
145static void
146put_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
162static void
163put_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
184static void *
185get_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
196static void
197get_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
206static void
207get_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
220static void
221put_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
241static void
242put_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
265static void
266put_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
282static void
283put_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
313static void *
314get_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
324static void
325get_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
334static void
335get_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
348static void
349put_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
369static void
370put_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
385static void
386put_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
402static void
403put_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
426static void *
427get_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
437static void
438get_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
454static void
455get_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
472static void
473put_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
491static void
492put_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
510static void
511put_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
537static void
538put_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
557static void
558put_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
584static void *
585get_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
595static void
596get_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
605static void
606get_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
620static void
621put_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
642static void
643put_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
662static void
663put_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
694static void
695put_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
712static void
713put_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
735static void *
736get_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
746static void
747get_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
756static void
757get_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
771static void
772put_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
795static void
796put_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
820static void
821put_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
848static void
849put_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
868static void
869put_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 */
906static GLboolean
907soft_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 */
1147struct alpha_renderbuffer
1148{
1149   struct gl_renderbuffer Base;        /* the alpha buffer */
1150   struct gl_renderbuffer *RGBbuffer;  /* the wrapped RGB buffer */
1151};
1152
1153
1154static GLboolean
1155alloc_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 */
1190static void
1191delete_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
1204static void *
1205get_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
1212static void
1213get_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
1231static void
1232get_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
1249static void
1250put_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
1269static void
1270put_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
1289static void
1290put_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
1314static void
1315put_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
1335static void
1336put_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 */
1366static void *
1367nop_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 */
1376void
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 */
1414struct 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 */
1429void
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 */
1444struct 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 */
1467GLboolean
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 */
1533GLboolean
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 */
1593GLboolean
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 */
1675GLboolean
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 */
1717GLboolean
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 */
1760GLboolean
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 */
1800GLboolean
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 */
1842void
1843_mesa_add_renderbuffer(struct gl_framebuffer *fb,
1844                       GLuint bufferName, struct gl_renderbuffer *rb)
1845{
1846   assert(fb);
1847   assert(rb);
1848#if 00
1849   /* there should be no previous renderbuffer on this attachment point! */
1850   assert(fb->Attachment[bufferName].Renderbuffer == NULL);
1851#endif
1852   assert(bufferName < BUFFER_COUNT);
1853
1854   /* winsys vs. user-created buffer cross check */
1855   if (fb->Name) {
1856      assert(rb->Name);
1857   }
1858   else {
1859      assert(!rb->Name);
1860   }
1861
1862   fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
1863   fb->Attachment[bufferName].Complete = GL_TRUE;
1864   fb->Attachment[bufferName].Renderbuffer = rb;
1865}
1866