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