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