2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
27 * Functions for allocating/managing software-based renderbuffers.
28 * Also, routines for reading/writing software-based renderbuffer data as
29 * ubytes, ushorts, uints, etc.
33 #include "main/glheader.h"
34 #include "main/imports.h"
35 #include "main/context.h"
36 #include "main/fbobject.h"
37 #include "main/formats.h"
38 #include "main/mtypes.h"
39 #include "main/renderbuffer.h"
40 #include "swrast/s_renderbuffer.h"
44 * This is a software fallback for the gl_renderbuffer->AllocStorage
46 * Device drivers will typically override this function for the buffers
47 * which it manages (typically color buffers, Z and stencil).
48 * Other buffers (like software accumulation and aux buffers) which the driver
49 * doesn't manage can be handled with this function.
51 * This one multi-purpose function can allocate stencil, depth, accum, color
52 * or color-index buffers!
55 soft_renderbuffer_storage(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
56 GLenum internalFormat
,
57 GLuint width
, GLuint height
)
59 switch (internalFormat
) {
68 rb
->Format
= MESA_FORMAT_RGB888
;
79 if (_mesa_little_endian())
80 rb
->Format
= MESA_FORMAT_RGBA8888_REV
;
82 rb
->Format
= MESA_FORMAT_RGBA8888
;
86 /* for accum buffer */
87 rb
->Format
= MESA_FORMAT_SIGNED_RGBA_16
;
89 case GL_STENCIL_INDEX
:
90 case GL_STENCIL_INDEX1_EXT
:
91 case GL_STENCIL_INDEX4_EXT
:
92 case GL_STENCIL_INDEX8_EXT
:
93 case GL_STENCIL_INDEX16_EXT
:
94 rb
->Format
= MESA_FORMAT_S8
;
96 case GL_DEPTH_COMPONENT
:
97 case GL_DEPTH_COMPONENT16
:
98 rb
->Format
= MESA_FORMAT_Z16
;
100 case GL_DEPTH_COMPONENT24
:
101 rb
->Format
= MESA_FORMAT_X8_Z24
;
103 case GL_DEPTH_COMPONENT32
:
104 rb
->Format
= MESA_FORMAT_Z32
;
106 case GL_DEPTH_STENCIL_EXT
:
107 case GL_DEPTH24_STENCIL8_EXT
:
108 rb
->Format
= MESA_FORMAT_Z24_S8
;
111 /* unsupported format */
115 /* free old buffer storage */
121 rb
->RowStrideBytes
= width
* _mesa_get_format_bytes(rb
->Format
);
123 if (width
> 0 && height
> 0) {
124 /* allocate new buffer storage */
125 rb
->Data
= malloc(width
* height
* _mesa_get_format_bytes(rb
->Format
));
127 if (rb
->Data
== NULL
) {
130 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
131 "software renderbuffer allocation (%d x %d x %d)",
132 width
, height
, _mesa_get_format_bytes(rb
->Format
));
139 rb
->_BaseFormat
= _mesa_base_fbo_format(ctx
, internalFormat
);
142 internalFormat
== GL_RGBA16_SNORM
&&
143 rb
->_BaseFormat
== 0) {
144 /* NOTE: This is a special case just for accumulation buffers.
145 * This is a very limited use case- there's no snorm texturing or
146 * rendering going on.
148 rb
->_BaseFormat
= GL_RGBA
;
151 /* the internalFormat should have been error checked long ago */
152 ASSERT(rb
->_BaseFormat
);
160 * Called via gl_renderbuffer::Delete()
163 soft_renderbuffer_delete(struct gl_renderbuffer
*rb
)
174 _swrast_map_soft_renderbuffer(struct gl_context
*ctx
,
175 struct gl_renderbuffer
*rb
,
176 GLuint x
, GLuint y
, GLuint w
, GLuint h
,
181 GLubyte
*map
= rb
->Data
;
182 int cpp
= _mesa_get_format_bytes(rb
->Format
);
183 int stride
= rb
->Width
* cpp
;
191 *out_stride
= stride
;
196 _swrast_unmap_soft_renderbuffer(struct gl_context
*ctx
,
197 struct gl_renderbuffer
*rb
)
204 * Allocate a software-based renderbuffer. This is called via the
205 * ctx->Driver.NewRenderbuffer() function when the user creates a new
207 * This would not be used for hardware-based renderbuffers.
209 struct gl_renderbuffer
*
210 _swrast_new_soft_renderbuffer(struct gl_context
*ctx
, GLuint name
)
212 struct gl_renderbuffer
*rb
= _mesa_new_renderbuffer(ctx
, name
);
214 rb
->AllocStorage
= soft_renderbuffer_storage
;
215 rb
->Delete
= soft_renderbuffer_delete
;
222 * Add software-based color renderbuffers to the given framebuffer.
223 * This is a helper routine for device drivers when creating a
224 * window system framebuffer (not a user-created render/framebuffer).
225 * Once this function is called, you can basically forget about this
226 * renderbuffer; core Mesa will handle all the buffer management and
230 add_color_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
231 GLuint rgbBits
, GLuint alphaBits
,
232 GLboolean frontLeft
, GLboolean backLeft
,
233 GLboolean frontRight
, GLboolean backRight
)
237 if (rgbBits
> 16 || alphaBits
> 16) {
239 "Unsupported bit depth in add_color_renderbuffers");
243 assert(MAX_COLOR_ATTACHMENTS
>= 4);
245 for (b
= BUFFER_FRONT_LEFT
; b
<= BUFFER_BACK_RIGHT
; b
++) {
246 struct gl_renderbuffer
*rb
;
248 if (b
== BUFFER_FRONT_LEFT
&& !frontLeft
)
250 else if (b
== BUFFER_BACK_LEFT
&& !backLeft
)
252 else if (b
== BUFFER_FRONT_RIGHT
&& !frontRight
)
254 else if (b
== BUFFER_BACK_RIGHT
&& !backRight
)
257 assert(fb
->Attachment
[b
].Renderbuffer
== NULL
);
259 rb
= _mesa_new_renderbuffer(ctx
, 0);
261 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating color buffer");
265 rb
->InternalFormat
= GL_RGBA
;
267 rb
->AllocStorage
= soft_renderbuffer_storage
;
268 _mesa_add_renderbuffer(fb
, b
, rb
);
276 * Add a software-based depth renderbuffer to the given framebuffer.
277 * This is a helper routine for device drivers when creating a
278 * window system framebuffer (not a user-created render/framebuffer).
279 * Once this function is called, you can basically forget about this
280 * renderbuffer; core Mesa will handle all the buffer management and
284 add_depth_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
287 struct gl_renderbuffer
*rb
;
289 if (depthBits
> 32) {
291 "Unsupported depthBits in add_depth_renderbuffer");
295 assert(fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
== NULL
);
297 rb
= _mesa_new_renderbuffer(ctx
, 0);
299 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating depth buffer");
303 if (depthBits
<= 16) {
304 rb
->InternalFormat
= GL_DEPTH_COMPONENT16
;
306 else if (depthBits
<= 24) {
307 rb
->InternalFormat
= GL_DEPTH_COMPONENT24
;
310 rb
->InternalFormat
= GL_DEPTH_COMPONENT32
;
313 rb
->AllocStorage
= soft_renderbuffer_storage
;
314 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, rb
);
321 * Add a software-based stencil renderbuffer to the given framebuffer.
322 * This is a helper routine for device drivers when creating a
323 * window system framebuffer (not a user-created render/framebuffer).
324 * Once this function is called, you can basically forget about this
325 * renderbuffer; core Mesa will handle all the buffer management and
329 add_stencil_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
332 struct gl_renderbuffer
*rb
;
334 if (stencilBits
> 16) {
336 "Unsupported stencilBits in add_stencil_renderbuffer");
340 assert(fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
== NULL
);
342 rb
= _mesa_new_renderbuffer(ctx
, 0);
344 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating stencil buffer");
348 assert(stencilBits
<= 8);
349 rb
->InternalFormat
= GL_STENCIL_INDEX8
;
351 rb
->AllocStorage
= soft_renderbuffer_storage
;
352 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, rb
);
359 add_depth_stencil_renderbuffer(struct gl_context
*ctx
,
360 struct gl_framebuffer
*fb
)
362 struct gl_renderbuffer
*rb
;
364 assert(fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
== NULL
);
365 assert(fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
== NULL
);
367 rb
= _mesa_new_renderbuffer(ctx
, 0);
369 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating depth+stencil buffer");
373 rb
->InternalFormat
= GL_DEPTH_STENCIL
;
375 rb
->AllocStorage
= soft_renderbuffer_storage
;
376 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, rb
);
377 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, rb
);
384 * Add a software-based accumulation renderbuffer to the given framebuffer.
385 * This is a helper routine for device drivers when creating a
386 * window system framebuffer (not a user-created render/framebuffer).
387 * Once this function is called, you can basically forget about this
388 * renderbuffer; core Mesa will handle all the buffer management and
392 add_accum_renderbuffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
393 GLuint redBits
, GLuint greenBits
,
394 GLuint blueBits
, GLuint alphaBits
)
396 struct gl_renderbuffer
*rb
;
398 if (redBits
> 16 || greenBits
> 16 || blueBits
> 16 || alphaBits
> 16) {
400 "Unsupported accumBits in add_accum_renderbuffer");
404 assert(fb
->Attachment
[BUFFER_ACCUM
].Renderbuffer
== NULL
);
406 rb
= _mesa_new_renderbuffer(ctx
, 0);
408 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating accum buffer");
412 rb
->InternalFormat
= GL_RGBA16_SNORM
;
413 rb
->AllocStorage
= soft_renderbuffer_storage
;
414 _mesa_add_renderbuffer(fb
, BUFFER_ACCUM
, rb
);
422 * Add a software-based aux renderbuffer to the given framebuffer.
423 * This is a helper routine for device drivers when creating a
424 * window system framebuffer (not a user-created render/framebuffer).
425 * Once this function is called, you can basically forget about this
426 * renderbuffer; core Mesa will handle all the buffer management and
429 * NOTE: color-index aux buffers not supported.
432 add_aux_renderbuffers(struct gl_context
*ctx
, struct gl_framebuffer
*fb
,
433 GLuint colorBits
, GLuint numBuffers
)
437 if (colorBits
> 16) {
439 "Unsupported colorBits in add_aux_renderbuffers");
443 assert(numBuffers
<= MAX_AUX_BUFFERS
);
445 for (i
= 0; i
< numBuffers
; i
++) {
446 struct gl_renderbuffer
*rb
= _mesa_new_renderbuffer(ctx
, 0);
448 assert(fb
->Attachment
[BUFFER_AUX0
+ i
].Renderbuffer
== NULL
);
451 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "Allocating aux buffer");
455 assert (colorBits
<= 8);
456 rb
->InternalFormat
= GL_RGBA
;
458 rb
->AllocStorage
= soft_renderbuffer_storage
;
459 _mesa_add_renderbuffer(fb
, BUFFER_AUX0
+ i
, rb
);
466 * Create/attach software-based renderbuffers to the given framebuffer.
467 * This is a helper routine for device drivers. Drivers can just as well
468 * call the individual _mesa_add_*_renderbuffer() routines directly.
471 _swrast_add_soft_renderbuffers(struct gl_framebuffer
*fb
,
479 GLboolean frontLeft
= GL_TRUE
;
480 GLboolean backLeft
= fb
->Visual
.doubleBufferMode
;
481 GLboolean frontRight
= fb
->Visual
.stereoMode
;
482 GLboolean backRight
= fb
->Visual
.stereoMode
&& fb
->Visual
.doubleBufferMode
;
485 assert(fb
->Visual
.redBits
== fb
->Visual
.greenBits
);
486 assert(fb
->Visual
.redBits
== fb
->Visual
.blueBits
);
487 add_color_renderbuffers(NULL
, fb
,
489 fb
->Visual
.alphaBits
,
491 frontRight
, backRight
);
495 /* This is pretty much for debugging purposes only since there's a perf
496 * hit for using combined depth/stencil in swrast.
498 if (depth
&& fb
->Visual
.depthBits
== 24 &&
499 stencil
&& fb
->Visual
.stencilBits
== 8) {
500 /* use combined depth/stencil buffer */
501 add_depth_stencil_renderbuffer(NULL
, fb
);
505 (void) add_depth_stencil_renderbuffer
;
509 assert(fb
->Visual
.depthBits
> 0);
510 add_depth_renderbuffer(NULL
, fb
, fb
->Visual
.depthBits
);
514 assert(fb
->Visual
.stencilBits
> 0);
515 add_stencil_renderbuffer(NULL
, fb
, fb
->Visual
.stencilBits
);
520 assert(fb
->Visual
.accumRedBits
> 0);
521 assert(fb
->Visual
.accumGreenBits
> 0);
522 assert(fb
->Visual
.accumBlueBits
> 0);
523 add_accum_renderbuffer(NULL
, fb
,
524 fb
->Visual
.accumRedBits
,
525 fb
->Visual
.accumGreenBits
,
526 fb
->Visual
.accumBlueBits
,
527 fb
->Visual
.accumAlphaBits
);
531 assert(fb
->Visual
.numAuxBuffers
> 0);
532 add_aux_renderbuffers(NULL
, fb
, fb
->Visual
.redBits
,
533 fb
->Visual
.numAuxBuffers
);