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