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