mesa: Move OES_read_format support from drivers into the core.
[mesa.git] / src / mesa / main / framebuffer.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.2
4 *
5 * Copyright (C) 1999-2008 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 framebuffers and renderbuffers.
28 * Also, routines for reading/writing renderbuffer data as ubytes,
29 * ushorts, uints, etc.
30 */
31
32
33 #include "glheader.h"
34 #include "imports.h"
35 #include "buffers.h"
36 #include "context.h"
37 #include "depthstencil.h"
38 #include "formats.h"
39 #include "macros.h"
40 #include "mtypes.h"
41 #include "fbobject.h"
42 #include "framebuffer.h"
43 #include "renderbuffer.h"
44 #include "texobj.h"
45
46
47
48 /**
49 * Compute/set the _DepthMax field for the given framebuffer.
50 * This value depends on the Z buffer resolution.
51 */
52 static void
53 compute_depth_max(struct gl_framebuffer *fb)
54 {
55 if (fb->Visual.depthBits == 0) {
56 /* Special case. Even if we don't have a depth buffer we need
57 * good values for DepthMax for Z vertex transformation purposes
58 * and for per-fragment fog computation.
59 */
60 fb->_DepthMax = (1 << 16) - 1;
61 }
62 else if (fb->Visual.depthBits < 32) {
63 fb->_DepthMax = (1 << fb->Visual.depthBits) - 1;
64 }
65 else {
66 /* Special case since shift values greater than or equal to the
67 * number of bits in the left hand expression's type are undefined.
68 */
69 fb->_DepthMax = 0xffffffff;
70 }
71 fb->_DepthMaxF = (GLfloat) fb->_DepthMax;
72
73 /* Minimum resolvable depth value, for polygon offset */
74 fb->_MRD = (GLfloat)1.0 / fb->_DepthMaxF;
75 }
76
77
78 /**
79 * Create and initialize a gl_framebuffer object.
80 * This is intended for creating _window_system_ framebuffers, not generic
81 * framebuffer objects ala GL_EXT_framebuffer_object.
82 *
83 * \sa _mesa_new_framebuffer
84 */
85 struct gl_framebuffer *
86 _mesa_create_framebuffer(const GLvisual *visual)
87 {
88 struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer);
89 assert(visual);
90 if (fb) {
91 _mesa_initialize_framebuffer(fb, visual);
92 }
93 return fb;
94 }
95
96
97 /**
98 * Allocate a new gl_framebuffer object.
99 * This is the default function for ctx->Driver.NewFramebuffer().
100 * This is for allocating user-created framebuffers, not window-system
101 * framebuffers!
102 * \sa _mesa_create_framebuffer
103 */
104 struct gl_framebuffer *
105 _mesa_new_framebuffer(GLcontext *ctx, GLuint name)
106 {
107 struct gl_framebuffer *fb;
108 (void) ctx;
109 assert(name != 0);
110 fb = CALLOC_STRUCT(gl_framebuffer);
111 if (fb) {
112 fb->Name = name;
113 fb->RefCount = 1;
114 fb->_NumColorDrawBuffers = 1;
115 fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT;
116 fb->_ColorDrawBufferIndexes[0] = BUFFER_COLOR0;
117 fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT;
118 fb->_ColorReadBufferIndex = BUFFER_COLOR0;
119 fb->Delete = _mesa_destroy_framebuffer;
120 _glthread_INIT_MUTEX(fb->Mutex);
121 }
122 return fb;
123 }
124
125
126 /**
127 * Initialize a gl_framebuffer object. Typically used to initialize
128 * window system-created framebuffers, not user-created framebuffers.
129 * \sa _mesa_create_framebuffer
130 */
131 void
132 _mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual)
133 {
134 assert(fb);
135 assert(visual);
136
137 _mesa_bzero(fb, sizeof(struct gl_framebuffer));
138
139 _glthread_INIT_MUTEX(fb->Mutex);
140
141 fb->RefCount = 1;
142
143 /* save the visual */
144 fb->Visual = *visual;
145
146 /* Init read/draw renderbuffer state */
147 if (visual->doubleBufferMode) {
148 fb->_NumColorDrawBuffers = 1;
149 fb->ColorDrawBuffer[0] = GL_BACK;
150 fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT;
151 fb->ColorReadBuffer = GL_BACK;
152 fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT;
153 }
154 else {
155 fb->_NumColorDrawBuffers = 1;
156 fb->ColorDrawBuffer[0] = GL_FRONT;
157 fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT;
158 fb->ColorReadBuffer = GL_FRONT;
159 fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT;
160 }
161
162 fb->Delete = _mesa_destroy_framebuffer;
163 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
164
165 compute_depth_max(fb);
166 }
167
168
169 /**
170 * Deallocate buffer and everything attached to it.
171 * Typically called via the gl_framebuffer->Delete() method.
172 */
173 void
174 _mesa_destroy_framebuffer(struct gl_framebuffer *fb)
175 {
176 if (fb) {
177 _mesa_free_framebuffer_data(fb);
178 _mesa_free(fb);
179 }
180 }
181
182
183 /**
184 * Free all the data hanging off the given gl_framebuffer, but don't free
185 * the gl_framebuffer object itself.
186 */
187 void
188 _mesa_free_framebuffer_data(struct gl_framebuffer *fb)
189 {
190 GLuint i;
191
192 assert(fb);
193 assert(fb->RefCount == 0);
194
195 _glthread_DESTROY_MUTEX(fb->Mutex);
196
197 for (i = 0; i < BUFFER_COUNT; i++) {
198 struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
199 if (att->Renderbuffer) {
200 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
201 }
202 if (att->Texture) {
203 _mesa_reference_texobj(&att->Texture, NULL);
204 }
205 ASSERT(!att->Renderbuffer);
206 ASSERT(!att->Texture);
207 att->Type = GL_NONE;
208 }
209
210 /* unbind _Depth/_StencilBuffer to decr ref counts */
211 _mesa_reference_renderbuffer(&fb->_DepthBuffer, NULL);
212 _mesa_reference_renderbuffer(&fb->_StencilBuffer, NULL);
213 }
214
215
216 /**
217 * Set *ptr to point to fb, with refcounting and locking.
218 */
219 void
220 _mesa_reference_framebuffer(struct gl_framebuffer **ptr,
221 struct gl_framebuffer *fb)
222 {
223 assert(ptr);
224 if (*ptr == fb) {
225 /* no change */
226 return;
227 }
228
229 if (*ptr) {
230 /* unreference old renderbuffer */
231 GLboolean deleteFlag = GL_FALSE;
232 struct gl_framebuffer *oldFb = *ptr;
233
234 _glthread_LOCK_MUTEX(oldFb->Mutex);
235 ASSERT(oldFb->RefCount > 0);
236 oldFb->RefCount--;
237 deleteFlag = (oldFb->RefCount == 0);
238 _glthread_UNLOCK_MUTEX(oldFb->Mutex);
239
240 if (deleteFlag)
241 oldFb->Delete(oldFb);
242
243 *ptr = NULL;
244 }
245 assert(!*ptr);
246
247 if (fb) {
248 _glthread_LOCK_MUTEX(fb->Mutex);
249 fb->RefCount++;
250 _glthread_UNLOCK_MUTEX(fb->Mutex);
251 *ptr = fb;
252 }
253 }
254
255
256 /**
257 * Resize the given framebuffer's renderbuffers to the new width and height.
258 * This should only be used for window-system framebuffers, not
259 * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object).
260 * This will typically be called via ctx->Driver.ResizeBuffers() or directly
261 * from a device driver.
262 *
263 * \note it's possible for ctx to be null since a window can be resized
264 * without a currently bound rendering context.
265 */
266 void
267 _mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb,
268 GLuint width, GLuint height)
269 {
270 GLuint i;
271
272 /* XXX I think we could check if the size is not changing
273 * and return early.
274 */
275
276 /* For window system framebuffers, Name is zero */
277 assert(fb->Name == 0);
278
279 for (i = 0; i < BUFFER_COUNT; i++) {
280 struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
281 if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) {
282 struct gl_renderbuffer *rb = att->Renderbuffer;
283 /* only resize if size is changing */
284 if (rb->Width != width || rb->Height != height) {
285 if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {
286 ASSERT(rb->Width == width);
287 ASSERT(rb->Height == height);
288 }
289 else {
290 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");
291 /* no return */
292 }
293 }
294 }
295 }
296
297 if (fb->_DepthBuffer) {
298 struct gl_renderbuffer *rb = fb->_DepthBuffer;
299 if (rb->Width != width || rb->Height != height) {
300 if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {
301 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");
302 }
303 }
304 }
305
306 if (fb->_StencilBuffer) {
307 struct gl_renderbuffer *rb = fb->_StencilBuffer;
308 if (rb->Width != width || rb->Height != height) {
309 if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {
310 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");
311 }
312 }
313 }
314
315 fb->Width = width;
316 fb->Height = height;
317
318 if (ctx) {
319 /* update scissor / window bounds */
320 _mesa_update_draw_buffer_bounds(ctx);
321 /* Signal new buffer state so that swrast will update its clipping
322 * info (the CLIP_BIT flag).
323 */
324 ctx->NewState |= _NEW_BUFFERS;
325 }
326 }
327
328
329
330 /**
331 * XXX THIS IS OBSOLETE - drivers should take care of detecting window
332 * size changes and act accordingly, likely calling _mesa_resize_framebuffer().
333 *
334 * GL_MESA_resize_buffers extension.
335 *
336 * When this function is called, we'll ask the window system how large
337 * the current window is. If it's a new size, we'll call the driver's
338 * ResizeBuffers function. The driver will then resize its color buffers
339 * as needed, and maybe call the swrast's routine for reallocating
340 * swrast-managed depth/stencil/accum/etc buffers.
341 * \note This function should only be called through the GL API, not
342 * from device drivers (as was done in the past).
343 */
344 void
345 _mesa_resizebuffers( GLcontext *ctx )
346 {
347 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
348
349 if (MESA_VERBOSE & VERBOSE_API)
350 _mesa_debug(ctx, "glResizeBuffersMESA\n");
351
352 if (!ctx->Driver.GetBufferSize) {
353 return;
354 }
355
356 if (ctx->WinSysDrawBuffer) {
357 GLuint newWidth, newHeight;
358 GLframebuffer *buffer = ctx->WinSysDrawBuffer;
359
360 assert(buffer->Name == 0);
361
362 /* ask device driver for size of output buffer */
363 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight );
364
365 /* see if size of device driver's color buffer (window) has changed */
366 if (buffer->Width != newWidth || buffer->Height != newHeight) {
367 if (ctx->Driver.ResizeBuffers)
368 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight );
369 }
370 }
371
372 if (ctx->WinSysReadBuffer
373 && ctx->WinSysReadBuffer != ctx->WinSysDrawBuffer) {
374 GLuint newWidth, newHeight;
375 GLframebuffer *buffer = ctx->WinSysReadBuffer;
376
377 assert(buffer->Name == 0);
378
379 /* ask device driver for size of read buffer */
380 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight );
381
382 /* see if size of device driver's color buffer (window) has changed */
383 if (buffer->Width != newWidth || buffer->Height != newHeight) {
384 if (ctx->Driver.ResizeBuffers)
385 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight );
386 }
387 }
388
389 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
390 }
391
392
393 /*
394 * XXX THIS IS OBSOLETE
395 */
396 void GLAPIENTRY
397 _mesa_ResizeBuffersMESA( void )
398 {
399 GET_CURRENT_CONTEXT(ctx);
400
401 if (ctx->Extensions.MESA_resize_buffers)
402 _mesa_resizebuffers( ctx );
403 }
404
405
406
407 /**
408 * Examine all the framebuffer's renderbuffers to update the Width/Height
409 * fields of the framebuffer. If we have renderbuffers with different
410 * sizes, set the framebuffer's width and height to the min size.
411 * Note: this is only intended for user-created framebuffers, not
412 * window-system framebuffes.
413 */
414 static void
415 update_framebuffer_size(GLcontext *ctx, struct gl_framebuffer *fb)
416 {
417 GLuint minWidth = ~0, minHeight = ~0;
418 GLuint i;
419
420 /* user-created framebuffers only */
421 assert(fb->Name);
422
423 for (i = 0; i < BUFFER_COUNT; i++) {
424 struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
425 const struct gl_renderbuffer *rb = att->Renderbuffer;
426 if (rb) {
427 minWidth = MIN2(minWidth, rb->Width);
428 minHeight = MIN2(minHeight, rb->Height);
429 }
430 }
431
432 if (minWidth != ~0) {
433 fb->Width = minWidth;
434 fb->Height = minHeight;
435 }
436 else {
437 fb->Width = 0;
438 fb->Height = 0;
439 }
440 }
441
442
443 /**
444 * Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields.
445 * These values are computed from the buffer's width and height and
446 * the scissor box, if it's enabled.
447 * \param ctx the GL context.
448 */
449 void
450 _mesa_update_draw_buffer_bounds(GLcontext *ctx)
451 {
452 struct gl_framebuffer *buffer = ctx->DrawBuffer;
453
454 if (!buffer)
455 return;
456
457 if (buffer->Name) {
458 /* user-created framebuffer size depends on the renderbuffers */
459 update_framebuffer_size(ctx, buffer);
460 }
461
462 buffer->_Xmin = 0;
463 buffer->_Ymin = 0;
464 buffer->_Xmax = buffer->Width;
465 buffer->_Ymax = buffer->Height;
466
467 if (ctx->Scissor.Enabled) {
468 if (ctx->Scissor.X > buffer->_Xmin) {
469 buffer->_Xmin = ctx->Scissor.X;
470 }
471 if (ctx->Scissor.Y > buffer->_Ymin) {
472 buffer->_Ymin = ctx->Scissor.Y;
473 }
474 if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) {
475 buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width;
476 }
477 if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) {
478 buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height;
479 }
480 /* finally, check for empty region */
481 if (buffer->_Xmin > buffer->_Xmax) {
482 buffer->_Xmin = buffer->_Xmax;
483 }
484 if (buffer->_Ymin > buffer->_Ymax) {
485 buffer->_Ymin = buffer->_Ymax;
486 }
487 }
488
489 ASSERT(buffer->_Xmin <= buffer->_Xmax);
490 ASSERT(buffer->_Ymin <= buffer->_Ymax);
491 }
492
493
494 /**
495 * The glGet queries of the framebuffer red/green/blue size, stencil size,
496 * etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can
497 * change depending on the renderbuffer bindings. This function updates
498 * the given framebuffer's Visual from the current renderbuffer bindings.
499 *
500 * This may apply to user-created framebuffers or window system framebuffers.
501 *
502 * Also note: ctx->DrawBuffer->Visual.depthBits might not equal
503 * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits.
504 * The former one is used to convert floating point depth values into
505 * integer Z values.
506 */
507 void
508 _mesa_update_framebuffer_visual(struct gl_framebuffer *fb)
509 {
510 GLuint i;
511
512 _mesa_bzero(&fb->Visual, sizeof(fb->Visual));
513 fb->Visual.rgbMode = GL_TRUE; /* assume this */
514
515 #if 0 /* this _might_ be needed */
516 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
517 /* leave visual fields zero'd */
518 return;
519 }
520 #endif
521
522 /* find first RGB or CI renderbuffer */
523 for (i = 0; i < BUFFER_COUNT; i++) {
524 if (fb->Attachment[i].Renderbuffer) {
525 const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
526 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
527 const gl_format fmt = rb->Format;
528
529 if (baseFormat == GL_RGBA || baseFormat == GL_RGB) {
530 fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
531 fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
532 fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
533 fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
534 fb->Visual.rgbBits = fb->Visual.redBits
535 + fb->Visual.greenBits + fb->Visual.blueBits;
536 fb->Visual.floatMode = GL_FALSE;
537 fb->Visual.samples = rb->NumSamples;
538 break;
539 }
540 else if (baseFormat == GL_COLOR_INDEX) {
541 fb->Visual.indexBits = _mesa_get_format_bits(fmt, GL_INDEX_BITS);
542 fb->Visual.rgbMode = GL_FALSE;
543 break;
544 }
545 }
546 }
547
548 if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
549 const struct gl_renderbuffer *rb =
550 fb->Attachment[BUFFER_DEPTH].Renderbuffer;
551 const gl_format fmt = rb->Format;
552 fb->Visual.haveDepthBuffer = GL_TRUE;
553 fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS);
554 }
555
556 if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
557 const struct gl_renderbuffer *rb =
558 fb->Attachment[BUFFER_STENCIL].Renderbuffer;
559 const gl_format fmt = rb->Format;
560 fb->Visual.haveStencilBuffer = GL_TRUE;
561 fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS);
562 }
563
564 if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) {
565 const struct gl_renderbuffer *rb =
566 fb->Attachment[BUFFER_ACCUM].Renderbuffer;
567 const gl_format fmt = rb->Format;
568 fb->Visual.haveAccumBuffer = GL_TRUE;
569 fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
570 fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
571 fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
572 fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
573 }
574
575 compute_depth_max(fb);
576 }
577
578
579 /**
580 * Update the framebuffer's _DepthBuffer field using the renderbuffer
581 * found at the given attachment index.
582 *
583 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
584 * create and install a depth wrapper/adaptor.
585 *
586 * \param fb the framebuffer whose _DepthBuffer field to update
587 * \param attIndex indicates the renderbuffer to possibly wrap
588 */
589 void
590 _mesa_update_depth_buffer(GLcontext *ctx,
591 struct gl_framebuffer *fb,
592 GLuint attIndex)
593 {
594 struct gl_renderbuffer *depthRb;
595
596 /* only one possiblity for now */
597 ASSERT(attIndex == BUFFER_DEPTH);
598
599 depthRb = fb->Attachment[attIndex].Renderbuffer;
600
601 if (depthRb && depthRb->_BaseFormat == GL_DEPTH_STENCIL) {
602 /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */
603 if (!fb->_DepthBuffer
604 || fb->_DepthBuffer->Wrapped != depthRb
605 || _mesa_get_format_base_format(fb->_DepthBuffer->Format) != GL_DEPTH_COMPONENT) {
606 /* need to update wrapper */
607 struct gl_renderbuffer *wrapper
608 = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb);
609 _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper);
610 ASSERT(fb->_DepthBuffer->Wrapped == depthRb);
611 }
612 }
613 else {
614 /* depthRb may be null */
615 _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb);
616 }
617 }
618
619
620 /**
621 * Update the framebuffer's _StencilBuffer field using the renderbuffer
622 * found at the given attachment index.
623 *
624 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
625 * create and install a stencil wrapper/adaptor.
626 *
627 * \param fb the framebuffer whose _StencilBuffer field to update
628 * \param attIndex indicates the renderbuffer to possibly wrap
629 */
630 void
631 _mesa_update_stencil_buffer(GLcontext *ctx,
632 struct gl_framebuffer *fb,
633 GLuint attIndex)
634 {
635 struct gl_renderbuffer *stencilRb;
636
637 ASSERT(attIndex == BUFFER_DEPTH ||
638 attIndex == BUFFER_STENCIL);
639
640 stencilRb = fb->Attachment[attIndex].Renderbuffer;
641
642 if (stencilRb && stencilRb->_BaseFormat == GL_DEPTH_STENCIL) {
643 /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */
644 if (!fb->_StencilBuffer
645 || fb->_StencilBuffer->Wrapped != stencilRb
646 || _mesa_get_format_base_format(fb->_StencilBuffer->Format) != GL_STENCIL_INDEX) {
647 /* need to update wrapper */
648 struct gl_renderbuffer *wrapper
649 = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb);
650 _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper);
651 ASSERT(fb->_StencilBuffer->Wrapped == stencilRb);
652 }
653 }
654 else {
655 /* stencilRb may be null */
656 _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb);
657 }
658 }
659
660
661 /*
662 * Example DrawBuffers scenarios:
663 *
664 * 1. glDrawBuffer(GL_FRONT_AND_BACK), fixed-func or shader writes to
665 * "gl_FragColor" or program writes to the "result.color" register:
666 *
667 * fragment color output renderbuffer
668 * --------------------- ---------------
669 * color[0] Front, Back
670 *
671 *
672 * 2. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]), shader writes to
673 * gl_FragData[i] or program writes to result.color[i] registers:
674 *
675 * fragment color output renderbuffer
676 * --------------------- ---------------
677 * color[0] Front
678 * color[1] Aux0
679 * color[3] Aux1
680 *
681 *
682 * 3. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]) and shader writes to
683 * gl_FragColor, or fixed function:
684 *
685 * fragment color output renderbuffer
686 * --------------------- ---------------
687 * color[0] Front, Aux0, Aux1
688 *
689 *
690 * In either case, the list of renderbuffers is stored in the
691 * framebuffer->_ColorDrawBuffers[] array and
692 * framebuffer->_NumColorDrawBuffers indicates the number of buffers.
693 * The renderer (like swrast) has to look at the current fragment shader
694 * to see if it writes to gl_FragColor vs. gl_FragData[i] to determine
695 * how to map color outputs to renderbuffers.
696 *
697 * Note that these two calls are equivalent (for fixed function fragment
698 * shading anyway):
699 * a) glDrawBuffer(GL_FRONT_AND_BACK); (assuming non-stereo framebuffer)
700 * b) glDrawBuffers(2, [GL_FRONT_LEFT, GL_BACK_LEFT]);
701 */
702
703
704
705
706 /**
707 * Update the (derived) list of color drawing renderbuffer pointers.
708 * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers
709 * writing colors.
710 */
711 static void
712 update_color_draw_buffers(GLcontext *ctx, struct gl_framebuffer *fb)
713 {
714 GLuint output;
715
716 /* set 0th buffer to NULL now in case _NumColorDrawBuffers is zero */
717 fb->_ColorDrawBuffers[0] = NULL;
718
719 for (output = 0; output < fb->_NumColorDrawBuffers; output++) {
720 GLint buf = fb->_ColorDrawBufferIndexes[output];
721 if (buf >= 0) {
722 fb->_ColorDrawBuffers[output] = fb->Attachment[buf].Renderbuffer;
723 }
724 else {
725 fb->_ColorDrawBuffers[output] = NULL;
726 }
727 }
728 }
729
730
731 /**
732 * Update the (derived) color read renderbuffer pointer.
733 * Unlike the DrawBuffer, we can only read from one (or zero) color buffers.
734 */
735 static void
736 update_color_read_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
737 {
738 (void) ctx;
739 if (fb->_ColorReadBufferIndex == -1 ||
740 fb->DeletePending ||
741 fb->Width == 0 ||
742 fb->Height == 0) {
743 fb->_ColorReadBuffer = NULL; /* legal! */
744 }
745 else {
746 ASSERT(fb->_ColorReadBufferIndex >= 0);
747 ASSERT(fb->_ColorReadBufferIndex < BUFFER_COUNT);
748 fb->_ColorReadBuffer
749 = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer;
750 }
751 }
752
753
754 /**
755 * Update a gl_framebuffer's derived state.
756 *
757 * Specifically, update these framebuffer fields:
758 * _ColorDrawBuffers
759 * _NumColorDrawBuffers
760 * _ColorReadBuffer
761 * _DepthBuffer
762 * _StencilBuffer
763 *
764 * If the framebuffer is user-created, make sure it's complete.
765 *
766 * The following functions (at least) can effect framebuffer state:
767 * glReadBuffer, glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT,
768 * glRenderbufferStorageEXT.
769 */
770 static void
771 update_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
772 {
773 if (fb->Name == 0) {
774 /* This is a window-system framebuffer */
775 /* Need to update the FB's GL_DRAW_BUFFER state to match the
776 * context state (GL_READ_BUFFER too).
777 */
778 if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) {
779 _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers,
780 ctx->Color.DrawBuffer, NULL);
781 }
782 if (fb->ColorReadBuffer != ctx->Pixel.ReadBuffer) {
783
784 }
785 }
786 else {
787 /* This is a user-created framebuffer.
788 * Completeness only matters for user-created framebuffers.
789 */
790 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) {
791 _mesa_test_framebuffer_completeness(ctx, fb);
792 }
793 }
794
795 /* Strictly speaking, we don't need to update the draw-state
796 * if this FB is bound as ctx->ReadBuffer (and conversely, the
797 * read-state if this FB is bound as ctx->DrawBuffer), but no
798 * harm.
799 */
800 update_color_draw_buffers(ctx, fb);
801 update_color_read_buffer(ctx, fb);
802 _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH);
803 _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL);
804
805 compute_depth_max(fb);
806 }
807
808
809 /**
810 * Update state related to the current draw/read framebuffers.
811 */
812 void
813 _mesa_update_framebuffer(GLcontext *ctx)
814 {
815 struct gl_framebuffer *drawFb = ctx->DrawBuffer;
816 struct gl_framebuffer *readFb = ctx->ReadBuffer;
817
818 update_framebuffer(ctx, drawFb);
819 if (readFb != drawFb)
820 update_framebuffer(ctx, readFb);
821 }
822
823
824 /**
825 * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels,
826 * glCopyTex[Sub]Image, etc) exists.
827 * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA,
828 * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL.
829 * \return GL_TRUE if buffer exists, GL_FALSE otherwise
830 */
831 GLboolean
832 _mesa_source_buffer_exists(GLcontext *ctx, GLenum format)
833 {
834 const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment;
835
836 /* If we don't know the framebuffer status, update it now */
837 if (ctx->ReadBuffer->_Status == 0) {
838 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
839 }
840
841 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
842 return GL_FALSE;
843 }
844
845 switch (format) {
846 case GL_COLOR:
847 case GL_RED:
848 case GL_GREEN:
849 case GL_BLUE:
850 case GL_ALPHA:
851 case GL_LUMINANCE:
852 case GL_LUMINANCE_ALPHA:
853 case GL_INTENSITY:
854 case GL_RGB:
855 case GL_BGR:
856 case GL_RGBA:
857 case GL_BGRA:
858 case GL_ABGR_EXT:
859 case GL_COLOR_INDEX:
860 if (ctx->ReadBuffer->_ColorReadBuffer == NULL) {
861 return GL_FALSE;
862 }
863 ASSERT(_mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_RED_BITS) > 0 ||
864 _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_INDEX_BITS) > 0);
865 break;
866 case GL_DEPTH:
867 case GL_DEPTH_COMPONENT:
868 if (!att[BUFFER_DEPTH].Renderbuffer) {
869 return GL_FALSE;
870 }
871 /*ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);*/
872 break;
873 case GL_STENCIL:
874 case GL_STENCIL_INDEX:
875 if (!att[BUFFER_STENCIL].Renderbuffer) {
876 return GL_FALSE;
877 }
878 /*ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);*/
879 break;
880 case GL_DEPTH_STENCIL_EXT:
881 if (!att[BUFFER_DEPTH].Renderbuffer ||
882 !att[BUFFER_STENCIL].Renderbuffer) {
883 return GL_FALSE;
884 }
885 /*
886 ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);
887 ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);
888 */
889 break;
890 default:
891 _mesa_problem(ctx,
892 "Unexpected format 0x%x in _mesa_source_buffer_exists",
893 format);
894 return GL_FALSE;
895 }
896
897 /* OK */
898 return GL_TRUE;
899 }
900
901
902 /**
903 * As above, but for drawing operations.
904 * XXX could do some code merging w/ above function.
905 */
906 GLboolean
907 _mesa_dest_buffer_exists(GLcontext *ctx, GLenum format)
908 {
909 const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
910
911 /* If we don't know the framebuffer status, update it now */
912 if (ctx->DrawBuffer->_Status == 0) {
913 _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer);
914 }
915
916 if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
917 return GL_FALSE;
918 }
919
920 switch (format) {
921 case GL_COLOR:
922 case GL_RED:
923 case GL_GREEN:
924 case GL_BLUE:
925 case GL_ALPHA:
926 case GL_LUMINANCE:
927 case GL_LUMINANCE_ALPHA:
928 case GL_INTENSITY:
929 case GL_RGB:
930 case GL_BGR:
931 case GL_RGBA:
932 case GL_BGRA:
933 case GL_ABGR_EXT:
934 case GL_COLOR_INDEX:
935 /* Nothing special since GL_DRAW_BUFFER could be GL_NONE. */
936 /* Could assert that colorbuffer has RedBits > 0 */
937 break;
938 case GL_DEPTH:
939 case GL_DEPTH_COMPONENT:
940 if (!att[BUFFER_DEPTH].Renderbuffer) {
941 return GL_FALSE;
942 }
943 /*ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);*/
944 break;
945 case GL_STENCIL:
946 case GL_STENCIL_INDEX:
947 if (!att[BUFFER_STENCIL].Renderbuffer) {
948 return GL_FALSE;
949 }
950 /*ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);*/
951 break;
952 case GL_DEPTH_STENCIL_EXT:
953 if (!att[BUFFER_DEPTH].Renderbuffer ||
954 !att[BUFFER_STENCIL].Renderbuffer) {
955 return GL_FALSE;
956 }
957 /*
958 ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);
959 ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);
960 */
961 break;
962 default:
963 _mesa_problem(ctx,
964 "Unexpected format 0x%x in _mesa_dest_buffer_exists",
965 format);
966 return GL_FALSE;
967 }
968
969 /* OK */
970 return GL_TRUE;
971 }
972
973 GLenum
974 _mesa_get_color_read_format(GLcontext *ctx)
975 {
976 switch (ctx->ReadBuffer->_ColorReadBuffer->Format) {
977 case MESA_FORMAT_ARGB8888:
978 return GL_BGRA;
979 case MESA_FORMAT_RGB565:
980 return GL_BGR;
981 default:
982 return GL_RGBA;
983 }
984 }
985
986 GLenum
987 _mesa_get_color_read_type(GLcontext *ctx)
988 {
989 switch (ctx->ReadBuffer->_ColorReadBuffer->Format) {
990 case MESA_FORMAT_ARGB8888:
991 return GL_UNSIGNED_BYTE;
992 case MESA_FORMAT_RGB565:
993 return GL_UNSIGNED_SHORT_5_6_5_REV;
994 default:
995 return GL_UNSIGNED_BYTE;
996 }
997 }