Home | History | Annotate | Download | only in state_tracker
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 
     29 /**
     30  * Framebuffer/renderbuffer functions.
     31  *
     32  * \author Brian Paul
     33  */
     34 
     35 
     36 #include "main/imports.h"
     37 #include "main/context.h"
     38 #include "main/fbobject.h"
     39 #include "main/framebuffer.h"
     40 #include "main/macros.h"
     41 #include "main/mfeatures.h"
     42 #include "main/renderbuffer.h"
     43 
     44 #include "pipe/p_context.h"
     45 #include "pipe/p_defines.h"
     46 #include "pipe/p_screen.h"
     47 #include "st_context.h"
     48 #include "st_cb_fbo.h"
     49 #include "st_cb_flush.h"
     50 #include "st_cb_texture.h"
     51 #include "st_format.h"
     52 #include "st_texture.h"
     53 #include "st_manager.h"
     54 
     55 #include "util/u_format.h"
     56 #include "util/u_inlines.h"
     57 #include "util/u_surface.h"
     58 
     59 
     60 static GLboolean
     61 st_renderbuffer_alloc_sw_storage(struct gl_context * ctx,
     62                                  struct gl_renderbuffer *rb,
     63                                  GLenum internalFormat,
     64                                  GLuint width, GLuint height)
     65 {
     66    struct pipe_screen *screen = st_context(ctx)->pipe->screen;
     67    struct st_renderbuffer *strb = st_renderbuffer(rb);
     68    enum pipe_format format;
     69    size_t size;
     70 
     71    free(strb->data);
     72    strb->data = NULL;
     73 
     74    if (internalFormat == GL_RGBA16_SNORM) {
     75       /* Special case for software accum buffers.  Otherwise, if the
     76        * call to st_choose_renderbuffer_format() fails (because the
     77        * driver doesn't support signed 16-bit/channel colors) we'd
     78        * just return without allocating the software accum buffer.
     79        */
     80       format = PIPE_FORMAT_R16G16B16A16_SNORM;
     81    }
     82    else {
     83       format = st_choose_renderbuffer_format(screen, internalFormat, 0);
     84 
     85       /* Not setting gl_renderbuffer::Format here will cause
     86        * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called.
     87        */
     88       if (format == PIPE_FORMAT_NONE) {
     89          return GL_TRUE;
     90       }
     91    }
     92 
     93    strb->Base.Format = st_pipe_format_to_mesa_format(format);
     94 
     95    size = _mesa_format_image_size(strb->Base.Format, width, height, 1);
     96    strb->data = malloc(size);
     97    return strb->data != NULL;
     98 }
     99 
    100 
    101 /**
    102  * gl_renderbuffer::AllocStorage()
    103  * This is called to allocate the original drawing surface, and
    104  * during window resize.
    105  */
    106 static GLboolean
    107 st_renderbuffer_alloc_storage(struct gl_context * ctx,
    108                               struct gl_renderbuffer *rb,
    109                               GLenum internalFormat,
    110                               GLuint width, GLuint height)
    111 {
    112    struct st_context *st = st_context(ctx);
    113    struct pipe_context *pipe = st->pipe;
    114    struct pipe_screen *screen = st->pipe->screen;
    115    struct st_renderbuffer *strb = st_renderbuffer(rb);
    116    enum pipe_format format = PIPE_FORMAT_NONE;
    117    struct pipe_surface surf_tmpl;
    118    struct pipe_resource templ;
    119 
    120    /* init renderbuffer fields */
    121    strb->Base.Width  = width;
    122    strb->Base.Height = height;
    123    strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
    124    strb->defined = GL_FALSE;  /* undefined contents now */
    125 
    126    if (strb->software) {
    127       return st_renderbuffer_alloc_sw_storage(ctx, rb, internalFormat,
    128                                               width, height);
    129    }
    130 
    131    /* Free the old surface and texture
    132     */
    133    pipe_surface_reference( &strb->surface, NULL );
    134    pipe_resource_reference( &strb->texture, NULL );
    135 
    136    /* Handle multisample renderbuffers first.
    137     *
    138     * From ARB_framebuffer_object:
    139     *   If <samples> is zero, then RENDERBUFFER_SAMPLES is set to zero.
    140     *   Otherwise <samples> represents a request for a desired minimum
    141     *   number of samples. Since different implementations may support
    142     *   different sample counts for multisampled rendering, the actual
    143     *   number of samples allocated for the renderbuffer image is
    144     *   implementation dependent.  However, the resulting value for
    145     *   RENDERBUFFER_SAMPLES is guaranteed to be greater than or equal
    146     *   to <samples> and no more than the next larger sample count supported
    147     *   by the implementation.
    148     *
    149     * So let's find the supported number of samples closest to NumSamples.
    150     * (NumSamples == 1) is treated the same as (NumSamples == 0).
    151     */
    152    if (rb->NumSamples > 1) {
    153       unsigned i;
    154 
    155       for (i = rb->NumSamples; i <= ctx->Const.MaxSamples; i++) {
    156          format = st_choose_renderbuffer_format(screen, internalFormat, i);
    157 
    158          if (format != PIPE_FORMAT_NONE) {
    159             rb->NumSamples = i;
    160             break;
    161          }
    162       }
    163    } else {
    164       format = st_choose_renderbuffer_format(screen, internalFormat, 0);
    165    }
    166 
    167    /* Not setting gl_renderbuffer::Format here will cause
    168     * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called.
    169     */
    170    if (format == PIPE_FORMAT_NONE) {
    171       return GL_TRUE;
    172    }
    173 
    174    strb->Base.Format = st_pipe_format_to_mesa_format(format);
    175 
    176    if (width == 0 || height == 0) {
    177       /* if size is zero, nothing to allocate */
    178       return GL_TRUE;
    179    }
    180 
    181    /* Setup new texture template.
    182     */
    183    memset(&templ, 0, sizeof(templ));
    184    templ.target = st->internal_target;
    185    templ.format = format;
    186    templ.width0 = width;
    187    templ.height0 = height;
    188    templ.depth0 = 1;
    189    templ.array_size = 1;
    190    templ.nr_samples = rb->NumSamples;
    191    if (util_format_is_depth_or_stencil(format)) {
    192       templ.bind = PIPE_BIND_DEPTH_STENCIL;
    193    }
    194    else if (strb->Base.Name != 0) {
    195       /* this is a user-created renderbuffer */
    196       templ.bind = PIPE_BIND_RENDER_TARGET;
    197    }
    198    else {
    199       /* this is a window-system buffer */
    200       templ.bind = (PIPE_BIND_DISPLAY_TARGET |
    201                     PIPE_BIND_RENDER_TARGET);
    202    }
    203 
    204    strb->texture = screen->resource_create(screen, &templ);
    205 
    206    if (!strb->texture)
    207       return FALSE;
    208 
    209    u_surface_default_template(&surf_tmpl, strb->texture, templ.bind);
    210    strb->surface = pipe->create_surface(pipe,
    211                                         strb->texture,
    212                                         &surf_tmpl);
    213    if (strb->surface) {
    214       assert(strb->surface->texture);
    215       assert(strb->surface->format);
    216       assert(strb->surface->width == width);
    217       assert(strb->surface->height == height);
    218    }
    219 
    220    return strb->surface != NULL;
    221 }
    222 
    223 
    224 /**
    225  * gl_renderbuffer::Delete()
    226  */
    227 static void
    228 st_renderbuffer_delete(struct gl_context *ctx, struct gl_renderbuffer *rb)
    229 {
    230    struct st_renderbuffer *strb = st_renderbuffer(rb);
    231    if (ctx) {
    232       struct st_context *st = st_context(ctx);
    233       pipe_surface_release(st->pipe, &strb->surface);
    234    }
    235    pipe_resource_reference(&strb->texture, NULL);
    236    free(strb->data);
    237    _mesa_delete_renderbuffer(ctx, rb);
    238 }
    239 
    240 
    241 /**
    242  * Called via ctx->Driver.NewFramebuffer()
    243  */
    244 static struct gl_framebuffer *
    245 st_new_framebuffer(struct gl_context *ctx, GLuint name)
    246 {
    247    /* XXX not sure we need to subclass gl_framebuffer for pipe */
    248    return _mesa_new_framebuffer(ctx, name);
    249 }
    250 
    251 
    252 /**
    253  * Called via ctx->Driver.NewRenderbuffer()
    254  */
    255 static struct gl_renderbuffer *
    256 st_new_renderbuffer(struct gl_context *ctx, GLuint name)
    257 {
    258    struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer);
    259    if (strb) {
    260       assert(name != 0);
    261       _mesa_init_renderbuffer(&strb->Base, name);
    262       strb->Base.Delete = st_renderbuffer_delete;
    263       strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
    264       return &strb->Base;
    265    }
    266    return NULL;
    267 }
    268 
    269 
    270 /**
    271  * Allocate a renderbuffer for a an on-screen window (not a user-created
    272  * renderbuffer).  The window system code determines the format.
    273  */
    274 struct gl_renderbuffer *
    275 st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
    276 {
    277    struct st_renderbuffer *strb;
    278 
    279    strb = ST_CALLOC_STRUCT(st_renderbuffer);
    280    if (!strb) {
    281       _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
    282       return NULL;
    283    }
    284 
    285    _mesa_init_renderbuffer(&strb->Base, 0);
    286    strb->Base.ClassID = 0x4242; /* just a unique value */
    287    strb->Base.NumSamples = samples;
    288    strb->Base.Format = st_pipe_format_to_mesa_format(format);
    289    strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format);
    290    strb->software = sw;
    291 
    292    switch (format) {
    293    case PIPE_FORMAT_R8G8B8A8_UNORM:
    294    case PIPE_FORMAT_B8G8R8A8_UNORM:
    295    case PIPE_FORMAT_A8R8G8B8_UNORM:
    296       strb->Base.InternalFormat = GL_RGBA8;
    297       break;
    298    case PIPE_FORMAT_R8G8B8X8_UNORM:
    299    case PIPE_FORMAT_B8G8R8X8_UNORM:
    300    case PIPE_FORMAT_X8R8G8B8_UNORM:
    301       strb->Base.InternalFormat = GL_RGB8;
    302       break;
    303    case PIPE_FORMAT_B5G5R5A1_UNORM:
    304       strb->Base.InternalFormat = GL_RGB5_A1;
    305       break;
    306    case PIPE_FORMAT_B4G4R4A4_UNORM:
    307       strb->Base.InternalFormat = GL_RGBA4;
    308       break;
    309    case PIPE_FORMAT_B5G6R5_UNORM:
    310       strb->Base.InternalFormat = GL_RGB565;
    311       break;
    312    case PIPE_FORMAT_Z16_UNORM:
    313       strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
    314       break;
    315    case PIPE_FORMAT_Z32_UNORM:
    316       strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
    317       break;
    318    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
    319    case PIPE_FORMAT_S8_UINT_Z24_UNORM:
    320    case PIPE_FORMAT_Z24X8_UNORM:
    321    case PIPE_FORMAT_X8Z24_UNORM:
    322       strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
    323       break;
    324    case PIPE_FORMAT_S8_UINT:
    325       strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
    326       break;
    327    case PIPE_FORMAT_R16G16B16A16_SNORM:
    328       /* accum buffer */
    329       strb->Base.InternalFormat = GL_RGBA16_SNORM;
    330       break;
    331    case PIPE_FORMAT_R8_UNORM:
    332       strb->Base.InternalFormat = GL_R8;
    333       break;
    334    case PIPE_FORMAT_R8G8_UNORM:
    335       strb->Base.InternalFormat = GL_RG8;
    336       break;
    337    case PIPE_FORMAT_R16_UNORM:
    338       strb->Base.InternalFormat = GL_R16;
    339       break;
    340    case PIPE_FORMAT_R16G16_UNORM:
    341       strb->Base.InternalFormat = GL_RG16;
    342       break;
    343    case PIPE_FORMAT_R32G32B32A32_FLOAT:
    344       strb->Base.InternalFormat = GL_RGBA32F;
    345       break;
    346    case PIPE_FORMAT_R16G16B16A16_FLOAT:
    347       strb->Base.InternalFormat = GL_RGBA16F;
    348       break;
    349    default:
    350       _mesa_problem(NULL,
    351 		    "Unexpected format %s in st_new_renderbuffer_fb",
    352                     util_format_name(format));
    353       free(strb);
    354       return NULL;
    355    }
    356 
    357    /* st-specific methods */
    358    strb->Base.Delete = st_renderbuffer_delete;
    359    strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
    360 
    361    /* surface is allocated in st_renderbuffer_alloc_storage() */
    362    strb->surface = NULL;
    363 
    364    return &strb->Base;
    365 }
    366 
    367 
    368 /**
    369  * Called via ctx->Driver.BindFramebufferEXT().
    370  */
    371 static void
    372 st_bind_framebuffer(struct gl_context *ctx, GLenum target,
    373                     struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
    374 {
    375    /* no-op */
    376 }
    377 
    378 
    379 /**
    380  * Called by ctx->Driver.RenderTexture
    381  */
    382 static void
    383 st_render_texture(struct gl_context *ctx,
    384                   struct gl_framebuffer *fb,
    385                   struct gl_renderbuffer_attachment *att)
    386 {
    387    struct st_context *st = st_context(ctx);
    388    struct pipe_context *pipe = st->pipe;
    389    struct st_renderbuffer *strb;
    390    struct gl_renderbuffer *rb;
    391    struct pipe_resource *pt;
    392    struct st_texture_object *stObj;
    393    const struct gl_texture_image *texImage;
    394    struct pipe_surface surf_tmpl;
    395 
    396    if (!st_finalize_texture(ctx, pipe, att->Texture))
    397       return;
    398 
    399    pt = st_get_texobj_resource(att->Texture);
    400    assert(pt);
    401 
    402    /* get pointer to texture image we're rendeing to */
    403    texImage = _mesa_get_attachment_teximage(att);
    404 
    405    /* create new renderbuffer which wraps the texture image.
    406     * Use the texture's name as the renderbuffer's name so that we have
    407     * something that's non-zero (to determine vertical orientation) and
    408     * possibly helpful for debugging.
    409     */
    410    rb = st_new_renderbuffer(ctx, att->Texture->Name);
    411    if (!rb) {
    412       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
    413       return;
    414    }
    415 
    416    _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
    417    assert(rb->RefCount == 1);
    418    rb->AllocStorage = NULL; /* should not get called */
    419    strb = st_renderbuffer(rb);
    420 
    421    assert(strb->Base.RefCount > 0);
    422 
    423    /* get the texture for the texture object */
    424    stObj = st_texture_object(att->Texture);
    425 
    426    /* point renderbuffer at texobject */
    427    strb->rtt = stObj;
    428    strb->rtt_level = att->TextureLevel;
    429    strb->rtt_face = att->CubeMapFace;
    430    strb->rtt_slice = att->Zoffset;
    431 
    432    rb->Width = texImage->Width2;
    433    rb->Height = texImage->Height2;
    434    rb->_BaseFormat = texImage->_BaseFormat;
    435    rb->InternalFormat = texImage->InternalFormat;
    436 
    437    pipe_resource_reference( &strb->texture, pt );
    438 
    439    pipe_surface_release(pipe, &strb->surface);
    440 
    441    assert(strb->rtt_level <= strb->texture->last_level);
    442 
    443    /* new surface for rendering into the texture */
    444    memset(&surf_tmpl, 0, sizeof(surf_tmpl));
    445    surf_tmpl.format = ctx->Color.sRGBEnabled
    446       ? strb->texture->format : util_format_linear(strb->texture->format);
    447    surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
    448    surf_tmpl.u.tex.level = strb->rtt_level;
    449    surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
    450    surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
    451    strb->surface = pipe->create_surface(pipe,
    452                                         strb->texture,
    453                                         &surf_tmpl);
    454 
    455    strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
    456 
    457    /* Invalidate buffer state so that the pipe's framebuffer state
    458     * gets updated.
    459     * That's where the new renderbuffer (which we just created) gets
    460     * passed to the pipe as a (color/depth) render target.
    461     */
    462    st_invalidate_state(ctx, _NEW_BUFFERS);
    463 
    464 
    465    /* Need to trigger a call to update_framebuffer() since we just
    466     * attached a new renderbuffer.
    467     */
    468    ctx->NewState |= _NEW_BUFFERS;
    469 }
    470 
    471 
    472 /**
    473  * Called via ctx->Driver.FinishRenderTexture.
    474  */
    475 static void
    476 st_finish_render_texture(struct gl_context *ctx,
    477                          struct gl_renderbuffer_attachment *att)
    478 {
    479    struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
    480 
    481    if (!strb)
    482       return;
    483 
    484    strb->rtt = NULL;
    485 
    486    /* restore previous framebuffer state */
    487    st_invalidate_state(ctx, _NEW_BUFFERS);
    488 }
    489 
    490 
    491 /** Debug helper */
    492 static void
    493 st_fbo_invalid(const char *reason)
    494 {
    495    if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
    496       _mesa_debug(NULL, "Invalid FBO: %s\n", reason);
    497    }
    498 }
    499 
    500 
    501 /**
    502  * Validate a renderbuffer attachment for a particular set of bindings.
    503  */
    504 static GLboolean
    505 st_validate_attachment(struct gl_context *ctx,
    506 		       struct pipe_screen *screen,
    507 		       const struct gl_renderbuffer_attachment *att,
    508 		       unsigned bindings)
    509 {
    510    const struct st_texture_object *stObj = st_texture_object(att->Texture);
    511    enum pipe_format format;
    512    gl_format texFormat;
    513    GLboolean valid;
    514 
    515    /* Only validate texture attachments for now, since
    516     * st_renderbuffer_alloc_storage makes sure that
    517     * the format is supported.
    518     */
    519    if (att->Type != GL_TEXTURE)
    520       return GL_TRUE;
    521 
    522    if (!stObj)
    523       return GL_FALSE;
    524 
    525    format = stObj->pt->format;
    526    texFormat = _mesa_get_attachment_teximage_const(att)->TexFormat;
    527 
    528    /* If the encoding is sRGB and sRGB rendering cannot be enabled,
    529     * check for linear format support instead.
    530     * Later when we create a surface, we change the format to a linear one. */
    531    if (!ctx->Extensions.EXT_framebuffer_sRGB &&
    532        _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
    533       const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
    534       format = st_mesa_format_to_pipe_format(linearFormat);
    535    }
    536 
    537    valid = screen->is_format_supported(screen, format,
    538                                       PIPE_TEXTURE_2D,
    539                                       stObj->pt->nr_samples, bindings);
    540    if (!valid) {
    541       st_fbo_invalid("Invalid format");
    542    }
    543 
    544    return valid;
    545 }
    546 
    547 
    548 /**
    549  * Check if two renderbuffer attachments name a combined depth/stencil
    550  * renderbuffer.
    551  */
    552 GLboolean
    553 st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
    554                              const struct gl_renderbuffer_attachment *stencil)
    555 {
    556    assert(depth && stencil);
    557 
    558    if (depth->Type == stencil->Type) {
    559       if (depth->Type == GL_RENDERBUFFER_EXT &&
    560           depth->Renderbuffer == stencil->Renderbuffer)
    561          return GL_TRUE;
    562 
    563       if (depth->Type == GL_TEXTURE &&
    564           depth->Texture == stencil->Texture)
    565          return GL_TRUE;
    566    }
    567 
    568    return GL_FALSE;
    569 }
    570 
    571 
    572 /**
    573  * Check that the framebuffer configuration is valid in terms of what
    574  * the driver can support.
    575  *
    576  * For Gallium we only supports combined Z+stencil, not separate buffers.
    577  */
    578 static void
    579 st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
    580 {
    581    struct st_context *st = st_context(ctx);
    582    struct pipe_screen *screen = st->pipe->screen;
    583    const struct gl_renderbuffer_attachment *depth =
    584          &fb->Attachment[BUFFER_DEPTH];
    585    const struct gl_renderbuffer_attachment *stencil =
    586          &fb->Attachment[BUFFER_STENCIL];
    587    GLuint i;
    588    enum pipe_format first_format = PIPE_FORMAT_NONE;
    589    boolean mixed_formats =
    590          screen->get_param(screen, PIPE_CAP_MIXED_COLORBUFFER_FORMATS) != 0;
    591 
    592    if (depth->Type && stencil->Type && depth->Type != stencil->Type) {
    593       st_fbo_invalid("Different Depth/Stencil buffer formats");
    594       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
    595       return;
    596    }
    597    if (depth->Type == GL_RENDERBUFFER_EXT &&
    598        stencil->Type == GL_RENDERBUFFER_EXT &&
    599        depth->Renderbuffer != stencil->Renderbuffer) {
    600       st_fbo_invalid("Separate Depth/Stencil buffers");
    601       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
    602       return;
    603    }
    604    if (depth->Type == GL_TEXTURE &&
    605        stencil->Type == GL_TEXTURE &&
    606        depth->Texture != stencil->Texture) {
    607       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
    608       st_fbo_invalid("Different Depth/Stencil textures");
    609       return;
    610    }
    611 
    612    if (!st_validate_attachment(ctx,
    613                                screen,
    614                                depth,
    615 			       PIPE_BIND_DEPTH_STENCIL)) {
    616       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
    617       return;
    618    }
    619    if (!st_validate_attachment(ctx,
    620                                screen,
    621                                stencil,
    622 			       PIPE_BIND_DEPTH_STENCIL)) {
    623       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
    624       return;
    625    }
    626    for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
    627       struct gl_renderbuffer_attachment *att =
    628             &fb->Attachment[BUFFER_COLOR0 + i];
    629       enum pipe_format format;
    630 
    631       if (!st_validate_attachment(ctx,
    632                                   screen,
    633 				  att,
    634 				  PIPE_BIND_RENDER_TARGET)) {
    635 	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
    636 	 return;
    637       }
    638 
    639       if (!mixed_formats) {
    640          /* Disallow mixed formats. */
    641          if (att->Type != GL_NONE) {
    642             format = st_renderbuffer(att->Renderbuffer)->surface->format;
    643          } else {
    644             continue;
    645          }
    646 
    647          if (first_format == PIPE_FORMAT_NONE) {
    648             first_format = format;
    649          } else if (format != first_format) {
    650             fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
    651             st_fbo_invalid("Mixed color formats");
    652             return;
    653          }
    654       }
    655    }
    656 }
    657 
    658 
    659 /**
    660  * Called via glDrawBuffer.
    661  */
    662 static void
    663 st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers)
    664 {
    665    struct st_context *st = st_context(ctx);
    666    struct gl_framebuffer *fb = ctx->DrawBuffer;
    667    GLuint i;
    668 
    669    (void) count;
    670    (void) buffers;
    671 
    672    /* add the renderbuffers on demand */
    673    for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
    674       gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
    675       st_manager_add_color_renderbuffer(st, fb, idx);
    676    }
    677 }
    678 
    679 
    680 /**
    681  * Called via glReadBuffer.
    682  */
    683 static void
    684 st_ReadBuffer(struct gl_context *ctx, GLenum buffer)
    685 {
    686    struct st_context *st = st_context(ctx);
    687    struct gl_framebuffer *fb = ctx->ReadBuffer;
    688 
    689    (void) buffer;
    690 
    691    /* add the renderbuffer on demand */
    692    st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex);
    693 }
    694 
    695 
    696 
    697 /**
    698  * Called via ctx->Driver.MapRenderbuffer.
    699  */
    700 static void
    701 st_MapRenderbuffer(struct gl_context *ctx,
    702                    struct gl_renderbuffer *rb,
    703                    GLuint x, GLuint y, GLuint w, GLuint h,
    704                    GLbitfield mode,
    705                    GLubyte **mapOut, GLint *rowStrideOut)
    706 {
    707    struct st_context *st = st_context(ctx);
    708    struct st_renderbuffer *strb = st_renderbuffer(rb);
    709    struct pipe_context *pipe = st->pipe;
    710    const GLboolean invert = rb->Name == 0;
    711    unsigned usage;
    712    GLuint y2;
    713 
    714    if (strb->software) {
    715       /* software-allocated renderbuffer (probably an accum buffer) */
    716       if (strb->data) {
    717          GLint bpp = _mesa_get_format_bytes(strb->Base.Format);
    718          GLint stride = _mesa_format_row_stride(strb->Base.Format,
    719                                                 strb->Base.Width);
    720          *mapOut = (GLubyte *) strb->data + y * stride + x * bpp;
    721          *rowStrideOut = stride;
    722       }
    723       else {
    724          *mapOut = NULL;
    725          *rowStrideOut = 0;
    726       }
    727       return;
    728    }
    729 
    730    usage = 0x0;
    731    if (mode & GL_MAP_READ_BIT)
    732       usage |= PIPE_TRANSFER_READ;
    733    if (mode & GL_MAP_WRITE_BIT)
    734       usage |= PIPE_TRANSFER_WRITE;
    735    if (mode & GL_MAP_INVALIDATE_RANGE_BIT)
    736       usage |= PIPE_TRANSFER_DISCARD_RANGE;
    737 
    738    /* Note: y=0=bottom of buffer while y2=0=top of buffer.
    739     * 'invert' will be true for window-system buffers and false for
    740     * user-allocated renderbuffers and textures.
    741     */
    742    if (invert)
    743       y2 = strb->Base.Height - y - h;
    744    else
    745       y2 = y;
    746 
    747    strb->transfer = pipe_get_transfer(pipe,
    748                                       strb->texture,
    749                                       strb->rtt_level,
    750                                       strb->rtt_face + strb->rtt_slice,
    751                                       usage, x, y2, w, h);
    752    if (strb->transfer) {
    753       GLubyte *map = pipe_transfer_map(pipe, strb->transfer);
    754       if (invert) {
    755          *rowStrideOut = -strb->transfer->stride;
    756          map += (h - 1) * strb->transfer->stride;
    757       }
    758       else {
    759          *rowStrideOut = strb->transfer->stride;
    760       }
    761       *mapOut = map;
    762    }
    763    else {
    764       *mapOut = NULL;
    765       *rowStrideOut = 0;
    766    }
    767 }
    768 
    769 
    770 /**
    771  * Called via ctx->Driver.UnmapRenderbuffer.
    772  */
    773 static void
    774 st_UnmapRenderbuffer(struct gl_context *ctx,
    775                      struct gl_renderbuffer *rb)
    776 {
    777    struct st_context *st = st_context(ctx);
    778    struct st_renderbuffer *strb = st_renderbuffer(rb);
    779    struct pipe_context *pipe = st->pipe;
    780 
    781    if (strb->software) {
    782       /* software-allocated renderbuffer (probably an accum buffer) */
    783       return;
    784    }
    785 
    786    pipe_transfer_unmap(pipe, strb->transfer);
    787    pipe->transfer_destroy(pipe, strb->transfer);
    788    strb->transfer = NULL;
    789 }
    790 
    791 
    792 
    793 void st_init_fbo_functions(struct dd_function_table *functions)
    794 {
    795 #if FEATURE_EXT_framebuffer_object
    796    functions->NewFramebuffer = st_new_framebuffer;
    797    functions->NewRenderbuffer = st_new_renderbuffer;
    798    functions->BindFramebuffer = st_bind_framebuffer;
    799    functions->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
    800    functions->RenderTexture = st_render_texture;
    801    functions->FinishRenderTexture = st_finish_render_texture;
    802    functions->ValidateFramebuffer = st_validate_framebuffer;
    803 #endif
    804 
    805    functions->DrawBuffers = st_DrawBuffers;
    806    functions->ReadBuffer = st_ReadBuffer;
    807 
    808    functions->MapRenderbuffer = st_MapRenderbuffer;
    809    functions->UnmapRenderbuffer = st_UnmapRenderbuffer;
    810 }
    811 
    812 
    813