Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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