Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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/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_B5G5R5A1_UNORM:
  311.       strb->Base.InternalFormat = GL_RGB5_A1;
  312.       break;
  313.    case PIPE_FORMAT_B4G4R4A4_UNORM:
  314.       strb->Base.InternalFormat = GL_RGBA4;
  315.       break;
  316.    case PIPE_FORMAT_B5G6R5_UNORM:
  317.       strb->Base.InternalFormat = GL_RGB565;
  318.       break;
  319.    case PIPE_FORMAT_Z16_UNORM:
  320.       strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
  321.       break;
  322.    case PIPE_FORMAT_Z32_UNORM:
  323.       strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
  324.       break;
  325.    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
  326.    case PIPE_FORMAT_S8_UINT_Z24_UNORM:
  327.       strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
  328.       break;
  329.    case PIPE_FORMAT_Z24X8_UNORM:
  330.    case PIPE_FORMAT_X8Z24_UNORM:
  331.       strb->Base.InternalFormat = GL_DEPTH_COMPONENT24;
  332.       break;
  333.    case PIPE_FORMAT_S8_UINT:
  334.       strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
  335.       break;
  336.    case PIPE_FORMAT_R16G16B16A16_SNORM:
  337.       /* accum buffer */
  338.       strb->Base.InternalFormat = GL_RGBA16_SNORM;
  339.       break;
  340.    case PIPE_FORMAT_R16G16B16A16_UNORM:
  341.       strb->Base.InternalFormat = GL_RGBA16;
  342.       break;
  343.    case PIPE_FORMAT_R8_UNORM:
  344.       strb->Base.InternalFormat = GL_R8;
  345.       break;
  346.    case PIPE_FORMAT_R8G8_UNORM:
  347.       strb->Base.InternalFormat = GL_RG8;
  348.       break;
  349.    case PIPE_FORMAT_R16_UNORM:
  350.       strb->Base.InternalFormat = GL_R16;
  351.       break;
  352.    case PIPE_FORMAT_R16G16_UNORM:
  353.       strb->Base.InternalFormat = GL_RG16;
  354.       break;
  355.    case PIPE_FORMAT_R32G32B32A32_FLOAT:
  356.       strb->Base.InternalFormat = GL_RGBA32F;
  357.       break;
  358.    case PIPE_FORMAT_R16G16B16A16_FLOAT:
  359.       strb->Base.InternalFormat = GL_RGBA16F;
  360.       break;
  361.    default:
  362.       _mesa_problem(NULL,
  363.                     "Unexpected format %s in st_new_renderbuffer_fb",
  364.                     util_format_name(format));
  365.       free(strb);
  366.       return NULL;
  367.    }
  368.  
  369.    /* st-specific methods */
  370.    strb->Base.Delete = st_renderbuffer_delete;
  371.    strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
  372.  
  373.    /* surface is allocated in st_renderbuffer_alloc_storage() */
  374.    strb->surface = NULL;
  375.  
  376.    return &strb->Base;
  377. }
  378.  
  379.  
  380. /**
  381.  * Called via ctx->Driver.BindFramebufferEXT().
  382.  */
  383. static void
  384. st_bind_framebuffer(struct gl_context *ctx, GLenum target,
  385.                     struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
  386. {
  387.    /* no-op */
  388. }
  389.  
  390.  
  391. /**
  392.  * Called by ctx->Driver.RenderTexture
  393.  */
  394. static void
  395. st_render_texture(struct gl_context *ctx,
  396.                   struct gl_framebuffer *fb,
  397.                   struct gl_renderbuffer_attachment *att)
  398. {
  399.    struct st_context *st = st_context(ctx);
  400.    struct pipe_context *pipe = st->pipe;
  401.    struct gl_renderbuffer *rb = att->Renderbuffer;
  402.    struct st_renderbuffer *strb = st_renderbuffer(rb);
  403.    struct pipe_resource *pt;
  404.    struct st_texture_object *stObj;
  405.    struct pipe_surface surf_tmpl;
  406.  
  407.    if (!st_finalize_texture(ctx, pipe, att->Texture))
  408.       return;
  409.  
  410.    pt = st_get_texobj_resource(att->Texture);
  411.    assert(pt);
  412.  
  413.    /* get the texture for the texture object */
  414.    stObj = st_texture_object(att->Texture);
  415.  
  416.    /* point renderbuffer at texobject */
  417.    strb->rtt = stObj;
  418.    strb->rtt_level = att->TextureLevel;
  419.    strb->rtt_face = att->CubeMapFace;
  420.    strb->rtt_slice = att->Zoffset;
  421.  
  422.    pipe_resource_reference( &strb->texture, pt );
  423.  
  424.    pipe_surface_release(pipe, &strb->surface);
  425.  
  426.    assert(strb->rtt_level <= strb->texture->last_level);
  427.  
  428.    /* new surface for rendering into the texture */
  429.    memset(&surf_tmpl, 0, sizeof(surf_tmpl));
  430.    surf_tmpl.format = ctx->Color.sRGBEnabled
  431.       ? strb->texture->format : util_format_linear(strb->texture->format);
  432.    surf_tmpl.u.tex.level = strb->rtt_level;
  433.    surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
  434.    surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
  435.    strb->surface = pipe->create_surface(pipe,
  436.                                         strb->texture,
  437.                                         &surf_tmpl);
  438.  
  439.    strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
  440.  
  441.    /* Invalidate buffer state so that the pipe's framebuffer state
  442.     * gets updated.
  443.     * That's where the new renderbuffer (which we just created) gets
  444.     * passed to the pipe as a (color/depth) render target.
  445.     */
  446.    st_invalidate_state(ctx, _NEW_BUFFERS);
  447.  
  448.  
  449.    /* Need to trigger a call to update_framebuffer() since we just
  450.     * attached a new renderbuffer.
  451.     */
  452.    ctx->NewState |= _NEW_BUFFERS;
  453. }
  454.  
  455.  
  456. /**
  457.  * Called via ctx->Driver.FinishRenderTexture.
  458.  */
  459. static void
  460. st_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb)
  461. {
  462.    struct st_renderbuffer *strb = st_renderbuffer(rb);
  463.  
  464.    if (!strb)
  465.       return;
  466.  
  467.    strb->rtt = NULL;
  468.  
  469.    /* restore previous framebuffer state */
  470.    st_invalidate_state(ctx, _NEW_BUFFERS);
  471. }
  472.  
  473.  
  474. /** Debug helper */
  475. static void
  476. st_fbo_invalid(const char *reason)
  477. {
  478.    if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
  479.       _mesa_debug(NULL, "Invalid FBO: %s\n", reason);
  480.    }
  481. }
  482.  
  483.  
  484. /**
  485.  * Validate a renderbuffer attachment for a particular set of bindings.
  486.  */
  487. static GLboolean
  488. st_validate_attachment(struct gl_context *ctx,
  489.                        struct pipe_screen *screen,
  490.                        const struct gl_renderbuffer_attachment *att,
  491.                        unsigned bindings)
  492. {
  493.    const struct st_texture_object *stObj = st_texture_object(att->Texture);
  494.    enum pipe_format format;
  495.    gl_format texFormat;
  496.    GLboolean valid;
  497.  
  498.    /* Only validate texture attachments for now, since
  499.     * st_renderbuffer_alloc_storage makes sure that
  500.     * the format is supported.
  501.     */
  502.    if (att->Type != GL_TEXTURE)
  503.       return GL_TRUE;
  504.  
  505.    if (!stObj || !stObj->pt)
  506.       return GL_FALSE;
  507.  
  508.    format = stObj->pt->format;
  509.    texFormat = att->Renderbuffer->TexImage->TexFormat;
  510.  
  511.    /* If the encoding is sRGB and sRGB rendering cannot be enabled,
  512.     * check for linear format support instead.
  513.     * Later when we create a surface, we change the format to a linear one. */
  514.    if (!ctx->Extensions.EXT_framebuffer_sRGB &&
  515.        _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
  516.       const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
  517.       format = st_mesa_format_to_pipe_format(linearFormat);
  518.    }
  519.  
  520.    valid = screen->is_format_supported(screen, format,
  521.                                       PIPE_TEXTURE_2D,
  522.                                       stObj->pt->nr_samples, bindings);
  523.    if (!valid) {
  524.       st_fbo_invalid("Invalid format");
  525.    }
  526.  
  527.    return valid;
  528. }
  529.  
  530.  
  531. /**
  532.  * Check that the framebuffer configuration is valid in terms of what
  533.  * the driver can support.
  534.  *
  535.  * For Gallium we only supports combined Z+stencil, not separate buffers.
  536.  */
  537. static void
  538. st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
  539. {
  540.    struct st_context *st = st_context(ctx);
  541.    struct pipe_screen *screen = st->pipe->screen;
  542.    const struct gl_renderbuffer_attachment *depth =
  543.          &fb->Attachment[BUFFER_DEPTH];
  544.    const struct gl_renderbuffer_attachment *stencil =
  545.          &fb->Attachment[BUFFER_STENCIL];
  546.    GLuint i;
  547.    enum pipe_format first_format = PIPE_FORMAT_NONE;
  548.    boolean mixed_formats =
  549.          screen->get_param(screen, PIPE_CAP_MIXED_COLORBUFFER_FORMATS) != 0;
  550.  
  551.    if (depth->Type && stencil->Type && depth->Type != stencil->Type) {
  552.       st_fbo_invalid("Different Depth/Stencil buffer formats");
  553.       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  554.       return;
  555.    }
  556.    if (depth->Type == GL_RENDERBUFFER_EXT &&
  557.        stencil->Type == GL_RENDERBUFFER_EXT &&
  558.        depth->Renderbuffer != stencil->Renderbuffer) {
  559.       st_fbo_invalid("Separate Depth/Stencil buffers");
  560.       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  561.       return;
  562.    }
  563.    if (depth->Type == GL_TEXTURE &&
  564.        stencil->Type == GL_TEXTURE &&
  565.        depth->Texture != stencil->Texture) {
  566.       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  567.       st_fbo_invalid("Different Depth/Stencil textures");
  568.       return;
  569.    }
  570.  
  571.    if (!st_validate_attachment(ctx,
  572.                                screen,
  573.                                depth,
  574.                                PIPE_BIND_DEPTH_STENCIL)) {
  575.       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  576.       return;
  577.    }
  578.    if (!st_validate_attachment(ctx,
  579.                                screen,
  580.                                stencil,
  581.                                PIPE_BIND_DEPTH_STENCIL)) {
  582.       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  583.       return;
  584.    }
  585.    for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
  586.       struct gl_renderbuffer_attachment *att =
  587.             &fb->Attachment[BUFFER_COLOR0 + i];
  588.       enum pipe_format format;
  589.  
  590.       if (!st_validate_attachment(ctx,
  591.                                   screen,
  592.                                   att,
  593.                                   PIPE_BIND_RENDER_TARGET)) {
  594.          fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  595.          return;
  596.       }
  597.  
  598.       if (!mixed_formats) {
  599.          /* Disallow mixed formats. */
  600.          if (att->Type != GL_NONE) {
  601.             format = st_renderbuffer(att->Renderbuffer)->surface->format;
  602.          } else {
  603.             continue;
  604.          }
  605.  
  606.          if (first_format == PIPE_FORMAT_NONE) {
  607.             first_format = format;
  608.          } else if (format != first_format) {
  609.             fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  610.             st_fbo_invalid("Mixed color formats");
  611.             return;
  612.          }
  613.       }
  614.    }
  615. }
  616.  
  617.  
  618. /**
  619.  * Called via glDrawBuffer.
  620.  */
  621. static void
  622. st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers)
  623. {
  624.    struct st_context *st = st_context(ctx);
  625.    struct gl_framebuffer *fb = ctx->DrawBuffer;
  626.    GLuint i;
  627.  
  628.    (void) count;
  629.    (void) buffers;
  630.  
  631.    /* add the renderbuffers on demand */
  632.    for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
  633.       gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
  634.       st_manager_add_color_renderbuffer(st, fb, idx);
  635.    }
  636. }
  637.  
  638.  
  639. /**
  640.  * Called via glReadBuffer.
  641.  */
  642. static void
  643. st_ReadBuffer(struct gl_context *ctx, GLenum buffer)
  644. {
  645.    struct st_context *st = st_context(ctx);
  646.    struct gl_framebuffer *fb = ctx->ReadBuffer;
  647.  
  648.    (void) buffer;
  649.  
  650.    /* add the renderbuffer on demand */
  651.    st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex);
  652. }
  653.  
  654.  
  655.  
  656. /**
  657.  * Called via ctx->Driver.MapRenderbuffer.
  658.  */
  659. static void
  660. st_MapRenderbuffer(struct gl_context *ctx,
  661.                    struct gl_renderbuffer *rb,
  662.                    GLuint x, GLuint y, GLuint w, GLuint h,
  663.                    GLbitfield mode,
  664.                    GLubyte **mapOut, GLint *rowStrideOut)
  665. {
  666.    struct st_context *st = st_context(ctx);
  667.    struct st_renderbuffer *strb = st_renderbuffer(rb);
  668.    struct pipe_context *pipe = st->pipe;
  669.    const GLboolean invert = rb->Name == 0;
  670.    unsigned usage;
  671.    GLuint y2;
  672.    GLubyte *map;
  673.  
  674.    if (strb->software) {
  675.       /* software-allocated renderbuffer (probably an accum buffer) */
  676.       if (strb->data) {
  677.          GLint bpp = _mesa_get_format_bytes(strb->Base.Format);
  678.          GLint stride = _mesa_format_row_stride(strb->Base.Format,
  679.                                                 strb->Base.Width);
  680.          *mapOut = (GLubyte *) strb->data + y * stride + x * bpp;
  681.          *rowStrideOut = stride;
  682.       }
  683.       else {
  684.          *mapOut = NULL;
  685.          *rowStrideOut = 0;
  686.       }
  687.       return;
  688.    }
  689.  
  690.    usage = 0x0;
  691.    if (mode & GL_MAP_READ_BIT)
  692.       usage |= PIPE_TRANSFER_READ;
  693.    if (mode & GL_MAP_WRITE_BIT)
  694.       usage |= PIPE_TRANSFER_WRITE;
  695.    if (mode & GL_MAP_INVALIDATE_RANGE_BIT)
  696.       usage |= PIPE_TRANSFER_DISCARD_RANGE;
  697.  
  698.    /* Note: y=0=bottom of buffer while y2=0=top of buffer.
  699.     * 'invert' will be true for window-system buffers and false for
  700.     * user-allocated renderbuffers and textures.
  701.     */
  702.    if (invert)
  703.       y2 = strb->Base.Height - y - h;
  704.    else
  705.       y2 = y;
  706.  
  707.     map = pipe_transfer_map(pipe,
  708.                             strb->texture,
  709.                             strb->rtt_level,
  710.                             strb->rtt_face + strb->rtt_slice,
  711.                             usage, x, y2, w, h, &strb->transfer);
  712.    if (map) {
  713.       if (invert) {
  714.          *rowStrideOut = -(int) strb->transfer->stride;
  715.          map += (h - 1) * strb->transfer->stride;
  716.       }
  717.       else {
  718.          *rowStrideOut = strb->transfer->stride;
  719.       }
  720.       *mapOut = map;
  721.    }
  722.    else {
  723.       *mapOut = NULL;
  724.       *rowStrideOut = 0;
  725.    }
  726. }
  727.  
  728.  
  729. /**
  730.  * Called via ctx->Driver.UnmapRenderbuffer.
  731.  */
  732. static void
  733. st_UnmapRenderbuffer(struct gl_context *ctx,
  734.                      struct gl_renderbuffer *rb)
  735. {
  736.    struct st_context *st = st_context(ctx);
  737.    struct st_renderbuffer *strb = st_renderbuffer(rb);
  738.    struct pipe_context *pipe = st->pipe;
  739.  
  740.    if (strb->software) {
  741.       /* software-allocated renderbuffer (probably an accum buffer) */
  742.       return;
  743.    }
  744.  
  745.    pipe_transfer_unmap(pipe, strb->transfer);
  746.    strb->transfer = NULL;
  747. }
  748.  
  749.  
  750.  
  751. void st_init_fbo_functions(struct dd_function_table *functions)
  752. {
  753.    functions->NewFramebuffer = st_new_framebuffer;
  754.    functions->NewRenderbuffer = st_new_renderbuffer;
  755.    functions->BindFramebuffer = st_bind_framebuffer;
  756.    functions->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
  757.    functions->RenderTexture = st_render_texture;
  758.    functions->FinishRenderTexture = st_finish_render_texture;
  759.    functions->ValidateFramebuffer = st_validate_framebuffer;
  760.  
  761.    functions->DrawBuffers = st_DrawBuffers;
  762.    functions->ReadBuffer = st_ReadBuffer;
  763.  
  764.    functions->MapRenderbuffer = st_MapRenderbuffer;
  765.    functions->UnmapRenderbuffer = st_UnmapRenderbuffer;
  766. }
  767.  
  768.  
  769.