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