Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.1
  4.  *
  5.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  6.  * Copyright (C) 1999-2009  VMware, Inc.  All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice shall be included
  16.  * in all copies or substantial portions 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 MERCHANTABILITY,
  20.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  21.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  22.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  23.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26.  
  27. /*
  28.  * GL_EXT/ARB_framebuffer_object extensions
  29.  *
  30.  * Authors:
  31.  *   Brian Paul
  32.  */
  33.  
  34.  
  35. #include "buffers.h"
  36. #include "context.h"
  37. #include "enums.h"
  38. #include "fbobject.h"
  39. #include "formats.h"
  40. #include "framebuffer.h"
  41. #include "hash.h"
  42. #include "macros.h"
  43. #include "renderbuffer.h"
  44. #include "state.h"
  45. #include "teximage.h"
  46. #include "texobj.h"
  47.  
  48.  
  49. /** Set this to 1 to help debug FBO incompleteness problems */
  50. #define DEBUG_FBO 0
  51.  
  52. /** Set this to 1 to debug/log glBlitFramebuffer() calls */
  53. #define DEBUG_BLIT 0
  54.  
  55.  
  56. /**
  57.  * Notes:
  58.  *
  59.  * None of the GL_EXT_framebuffer_object functions are compiled into
  60.  * display lists.
  61.  */
  62.  
  63.  
  64.  
  65. /*
  66.  * When glGenRender/FramebuffersEXT() is called we insert pointers to
  67.  * these placeholder objects into the hash table.
  68.  * Later, when the object ID is first bound, we replace the placeholder
  69.  * with the real frame/renderbuffer.
  70.  */
  71. static struct gl_framebuffer DummyFramebuffer;
  72. static struct gl_renderbuffer DummyRenderbuffer;
  73.  
  74. /* We bind this framebuffer when applications pass a NULL
  75.  * drawable/surface in make current. */
  76. static struct gl_framebuffer IncompleteFramebuffer;
  77.  
  78.  
  79. #define IS_CUBE_FACE(TARGET) \
  80.    ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \
  81.     (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
  82.  
  83.  
  84. static void
  85. delete_dummy_renderbuffer(struct gl_renderbuffer *rb)
  86. {
  87.    /* no op */
  88. }
  89.  
  90. static void
  91. delete_dummy_framebuffer(struct gl_framebuffer *fb)
  92. {
  93.    /* no op */
  94. }
  95.  
  96.  
  97. void
  98. _mesa_init_fbobjects(struct gl_context *ctx)
  99. {
  100.    _glthread_INIT_MUTEX(DummyFramebuffer.Mutex);
  101.    _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex);
  102.    _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex);
  103.    DummyFramebuffer.Delete = delete_dummy_framebuffer;
  104.    DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
  105.    IncompleteFramebuffer.Delete = delete_dummy_framebuffer;
  106. }
  107.  
  108. struct gl_framebuffer *
  109. _mesa_get_incomplete_framebuffer(void)
  110. {
  111.    return &IncompleteFramebuffer;
  112. }
  113.  
  114. /**
  115.  * Helper routine for getting a gl_renderbuffer.
  116.  */
  117. struct gl_renderbuffer *
  118. _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
  119. {
  120.    struct gl_renderbuffer *rb;
  121.  
  122.    if (id == 0)
  123.       return NULL;
  124.  
  125.    rb = (struct gl_renderbuffer *)
  126.       _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
  127.    return rb;
  128. }
  129.  
  130.  
  131. /**
  132.  * Helper routine for getting a gl_framebuffer.
  133.  */
  134. struct gl_framebuffer *
  135. _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
  136. {
  137.    struct gl_framebuffer *fb;
  138.  
  139.    if (id == 0)
  140.       return NULL;
  141.  
  142.    fb = (struct gl_framebuffer *)
  143.       _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
  144.    return fb;
  145. }
  146.  
  147.  
  148. /**
  149.  * Mark the given framebuffer as invalid.  This will force the
  150.  * test for framebuffer completeness to be done before the framebuffer
  151.  * is used.
  152.  */
  153. static void
  154. invalidate_framebuffer(struct gl_framebuffer *fb)
  155. {
  156.    fb->_Status = 0; /* "indeterminate" */
  157. }
  158.  
  159.  
  160. /**
  161.  * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
  162.  * gl_renderbuffer_attachment object.
  163.  * This function is only used for user-created FB objects, not the
  164.  * default / window-system FB object.
  165.  * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
  166.  * the depth buffer attachment point.
  167.  */
  168. struct gl_renderbuffer_attachment *
  169. _mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
  170.                      GLenum attachment)
  171. {
  172.    GLuint i;
  173.  
  174.    assert(fb->Name > 0);
  175.  
  176.    switch (attachment) {
  177.    case GL_COLOR_ATTACHMENT0_EXT:
  178.    case GL_COLOR_ATTACHMENT1_EXT:
  179.    case GL_COLOR_ATTACHMENT2_EXT:
  180.    case GL_COLOR_ATTACHMENT3_EXT:
  181.    case GL_COLOR_ATTACHMENT4_EXT:
  182.    case GL_COLOR_ATTACHMENT5_EXT:
  183.    case GL_COLOR_ATTACHMENT6_EXT:
  184.    case GL_COLOR_ATTACHMENT7_EXT:
  185.    case GL_COLOR_ATTACHMENT8_EXT:
  186.    case GL_COLOR_ATTACHMENT9_EXT:
  187.    case GL_COLOR_ATTACHMENT10_EXT:
  188.    case GL_COLOR_ATTACHMENT11_EXT:
  189.    case GL_COLOR_ATTACHMENT12_EXT:
  190.    case GL_COLOR_ATTACHMENT13_EXT:
  191.    case GL_COLOR_ATTACHMENT14_EXT:
  192.    case GL_COLOR_ATTACHMENT15_EXT:
  193.       i = attachment - GL_COLOR_ATTACHMENT0_EXT;
  194.       if (i >= ctx->Const.MaxColorAttachments) {
  195.          return NULL;
  196.       }
  197.       return &fb->Attachment[BUFFER_COLOR0 + i];
  198.    case GL_DEPTH_STENCIL_ATTACHMENT:
  199.       /* fall-through */
  200.    case GL_DEPTH_BUFFER:
  201.       /* fall-through / new in GL 3.0 */
  202.    case GL_DEPTH_ATTACHMENT_EXT:
  203.       return &fb->Attachment[BUFFER_DEPTH];
  204.    case GL_STENCIL_BUFFER:
  205.       /* fall-through / new in GL 3.0 */
  206.    case GL_STENCIL_ATTACHMENT_EXT:
  207.       return &fb->Attachment[BUFFER_STENCIL];
  208.    default:
  209.       return NULL;
  210.    }
  211. }
  212.  
  213.  
  214. /**
  215.  * As above, but only used for getting attachments of the default /
  216.  * window-system framebuffer (not user-created framebuffer objects).
  217.  */
  218. static struct gl_renderbuffer_attachment *
  219. _mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
  220.                          GLenum attachment)
  221. {
  222.    assert(fb->Name == 0);
  223.  
  224.    switch (attachment) {
  225.    case GL_FRONT_LEFT:
  226.       return &fb->Attachment[BUFFER_FRONT_LEFT];
  227.    case GL_FRONT_RIGHT:
  228.       return &fb->Attachment[BUFFER_FRONT_RIGHT];
  229.    case GL_BACK_LEFT:
  230.       return &fb->Attachment[BUFFER_BACK_LEFT];
  231.    case GL_BACK_RIGHT:
  232.       return &fb->Attachment[BUFFER_BACK_RIGHT];
  233.    case GL_AUX0:
  234.       if (fb->Visual.numAuxBuffers == 1) {
  235.          return &fb->Attachment[BUFFER_AUX0];
  236.       }
  237.       return NULL;
  238.    case GL_DEPTH_BUFFER:
  239.       /* fall-through / new in GL 3.0 */
  240.    case GL_DEPTH_ATTACHMENT_EXT:
  241.       return &fb->Attachment[BUFFER_DEPTH];
  242.    case GL_STENCIL_BUFFER:
  243.       /* fall-through / new in GL 3.0 */
  244.    case GL_STENCIL_ATTACHMENT_EXT:
  245.       return &fb->Attachment[BUFFER_STENCIL];
  246.    default:
  247.       return NULL;
  248.    }
  249. }
  250.  
  251.  
  252.  
  253. /**
  254.  * Remove any texture or renderbuffer attached to the given attachment
  255.  * point.  Update reference counts, etc.
  256.  */
  257. void
  258. _mesa_remove_attachment(struct gl_context *ctx,
  259.                         struct gl_renderbuffer_attachment *att)
  260. {
  261.    if (att->Type == GL_TEXTURE) {
  262.       ASSERT(att->Texture);
  263.       if (ctx->Driver.FinishRenderTexture) {
  264.          /* tell driver that we're done rendering to this texture. */
  265.          ctx->Driver.FinishRenderTexture(ctx, att);
  266.       }
  267.       _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
  268.       ASSERT(!att->Texture);
  269.    }
  270.    if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
  271.       ASSERT(!att->Texture);
  272.       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
  273.       ASSERT(!att->Renderbuffer);
  274.    }
  275.    att->Type = GL_NONE;
  276.    att->Complete = GL_TRUE;
  277. }
  278.  
  279.  
  280. /**
  281.  * Bind a texture object to an attachment point.
  282.  * The previous binding, if any, will be removed first.
  283.  */
  284. void
  285. _mesa_set_texture_attachment(struct gl_context *ctx,
  286.                              struct gl_framebuffer *fb,
  287.                              struct gl_renderbuffer_attachment *att,
  288.                              struct gl_texture_object *texObj,
  289.                              GLenum texTarget, GLuint level, GLuint zoffset)
  290. {
  291.    if (att->Texture == texObj) {
  292.       /* re-attaching same texture */
  293.       ASSERT(att->Type == GL_TEXTURE);
  294.       if (ctx->Driver.FinishRenderTexture)
  295.          ctx->Driver.FinishRenderTexture(ctx, att);
  296.    }
  297.    else {
  298.       /* new attachment */
  299.       if (ctx->Driver.FinishRenderTexture && att->Texture)
  300.          ctx->Driver.FinishRenderTexture(ctx, att);
  301.       _mesa_remove_attachment(ctx, att);
  302.       att->Type = GL_TEXTURE;
  303.       assert(!att->Texture);
  304.       _mesa_reference_texobj(&att->Texture, texObj);
  305.    }
  306.  
  307.    /* always update these fields */
  308.    att->TextureLevel = level;
  309.    att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
  310.    att->Zoffset = zoffset;
  311.    att->Complete = GL_FALSE;
  312.  
  313.    if (att->Texture->Image[att->CubeMapFace][att->TextureLevel]) {
  314.       ctx->Driver.RenderTexture(ctx, fb, att);
  315.    }
  316.  
  317.    invalidate_framebuffer(fb);
  318. }
  319.  
  320.  
  321. /**
  322.  * Bind a renderbuffer to an attachment point.
  323.  * The previous binding, if any, will be removed first.
  324.  */
  325. void
  326. _mesa_set_renderbuffer_attachment(struct gl_context *ctx,
  327.                                   struct gl_renderbuffer_attachment *att,
  328.                                   struct gl_renderbuffer *rb)
  329. {
  330.    /* XXX check if re-doing same attachment, exit early */
  331.    _mesa_remove_attachment(ctx, att);
  332.    att->Type = GL_RENDERBUFFER_EXT;
  333.    att->Texture = NULL; /* just to be safe */
  334.    att->Complete = GL_FALSE;
  335.    _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
  336. }
  337.  
  338.  
  339. /**
  340.  * Fallback for ctx->Driver.FramebufferRenderbuffer()
  341.  * Attach a renderbuffer object to a framebuffer object.
  342.  */
  343. void
  344. _mesa_framebuffer_renderbuffer(struct gl_context *ctx,
  345.                                struct gl_framebuffer *fb,
  346.                                GLenum attachment, struct gl_renderbuffer *rb)
  347. {
  348.    struct gl_renderbuffer_attachment *att;
  349.  
  350.    _glthread_LOCK_MUTEX(fb->Mutex);
  351.  
  352.    att = _mesa_get_attachment(ctx, fb, attachment);
  353.    ASSERT(att);
  354.    if (rb) {
  355.       _mesa_set_renderbuffer_attachment(ctx, att, rb);
  356.       if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
  357.          /* do stencil attachment here (depth already done above) */
  358.          att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
  359.          assert(att);
  360.          _mesa_set_renderbuffer_attachment(ctx, att, rb);
  361.       }
  362.    }
  363.    else {
  364.       _mesa_remove_attachment(ctx, att);
  365.    }
  366.  
  367.    invalidate_framebuffer(fb);
  368.  
  369.    _glthread_UNLOCK_MUTEX(fb->Mutex);
  370. }
  371.  
  372.  
  373. /**
  374.  * For debug only.
  375.  */
  376. static void
  377. att_incomplete(const char *msg)
  378. {
  379. #if DEBUG_FBO
  380.    _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
  381. #else
  382.    (void) msg;
  383. #endif
  384. }
  385.  
  386.  
  387. /**
  388.  * For debug only.
  389.  */
  390. static void
  391. fbo_incomplete(const char *msg, int index)
  392. {
  393. #if DEBUG_FBO
  394.    _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
  395. #else
  396.    (void) msg;
  397.    (void) index;
  398. #endif
  399. }
  400.  
  401.  
  402. /**
  403.  * Is the given base format a legal format for a color renderbuffer?
  404.  */
  405. static GLboolean
  406. is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
  407. {
  408.    switch (baseFormat) {
  409.    case GL_RGB:
  410.    case GL_RGBA:
  411.       return GL_TRUE;
  412.    case GL_LUMINANCE:
  413.    case GL_LUMINANCE_ALPHA:
  414.    case GL_INTENSITY:
  415.    case GL_ALPHA:
  416.       return ctx->Extensions.ARB_framebuffer_object;
  417.    case GL_RED:
  418.    case GL_RG:
  419.       return ctx->Extensions.ARB_texture_rg;
  420.    default:
  421.       return GL_FALSE;
  422.    }
  423. }
  424.  
  425.  
  426. /**
  427.  * Is the given base format a legal format for a depth/stencil renderbuffer?
  428.  */
  429. static GLboolean
  430. is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
  431. {
  432.    switch (baseFormat) {
  433.    case GL_DEPTH_COMPONENT:
  434.    case GL_DEPTH_STENCIL_EXT:
  435.       return GL_TRUE;
  436.    default:
  437.       return GL_FALSE;
  438.    }
  439. }
  440.  
  441.  
  442. /**
  443.  * Test if an attachment point is complete and update its Complete field.
  444.  * \param format if GL_COLOR, this is a color attachment point,
  445.  *               if GL_DEPTH, this is a depth component attachment point,
  446.  *               if GL_STENCIL, this is a stencil component attachment point.
  447.  */
  448. static void
  449. test_attachment_completeness(const struct gl_context *ctx, GLenum format,
  450.                              struct gl_renderbuffer_attachment *att)
  451. {
  452.    assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
  453.  
  454.    /* assume complete */
  455.    att->Complete = GL_TRUE;
  456.  
  457.    /* Look for reasons why the attachment might be incomplete */
  458.    if (att->Type == GL_TEXTURE) {
  459.       const struct gl_texture_object *texObj = att->Texture;
  460.       struct gl_texture_image *texImage;
  461.       GLenum baseFormat;
  462.  
  463.       if (!texObj) {
  464.          att_incomplete("no texobj");
  465.          att->Complete = GL_FALSE;
  466.          return;
  467.       }
  468.  
  469.       texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
  470.       if (!texImage) {
  471.          att_incomplete("no teximage");
  472.          att->Complete = GL_FALSE;
  473.          return;
  474.       }
  475.       if (texImage->Width < 1 || texImage->Height < 1) {
  476.          att_incomplete("teximage width/height=0");
  477.          printf("texobj = %u\n", texObj->Name);
  478.          printf("level = %d\n", att->TextureLevel);
  479.          att->Complete = GL_FALSE;
  480.          return;
  481.       }
  482.       if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) {
  483.          att_incomplete("bad z offset");
  484.          att->Complete = GL_FALSE;
  485.          return;
  486.       }
  487.  
  488.       baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
  489.  
  490.       if (format == GL_COLOR) {
  491.          if (!is_legal_color_format(ctx, baseFormat)) {
  492.             att_incomplete("bad format");
  493.             att->Complete = GL_FALSE;
  494.             return;
  495.          }
  496.          if (_mesa_is_format_compressed(texImage->TexFormat)) {
  497.             att_incomplete("compressed internalformat");
  498.             att->Complete = GL_FALSE;
  499.             return;
  500.          }
  501.       }
  502.       else if (format == GL_DEPTH) {
  503.          if (baseFormat == GL_DEPTH_COMPONENT) {
  504.             /* OK */
  505.          }
  506.          else if (ctx->Extensions.EXT_packed_depth_stencil &&
  507.                   ctx->Extensions.ARB_depth_texture &&
  508.                   baseFormat == GL_DEPTH_STENCIL_EXT) {
  509.             /* OK */
  510.          }
  511.          else {
  512.             att->Complete = GL_FALSE;
  513.             att_incomplete("bad depth format");
  514.             return;
  515.          }
  516.       }
  517.       else {
  518.          ASSERT(format == GL_STENCIL);
  519.          if (ctx->Extensions.EXT_packed_depth_stencil &&
  520.              ctx->Extensions.ARB_depth_texture &&
  521.              baseFormat == GL_DEPTH_STENCIL_EXT) {
  522.             /* OK */
  523.          }
  524.          else {
  525.             /* no such thing as stencil-only textures */
  526.             att_incomplete("illegal stencil texture");
  527.             att->Complete = GL_FALSE;
  528.             return;
  529.          }
  530.       }
  531.    }
  532.    else if (att->Type == GL_RENDERBUFFER_EXT) {
  533.       const GLenum baseFormat =
  534.          _mesa_get_format_base_format(att->Renderbuffer->Format);
  535.  
  536.       ASSERT(att->Renderbuffer);
  537.       if (!att->Renderbuffer->InternalFormat ||
  538.           att->Renderbuffer->Width < 1 ||
  539.           att->Renderbuffer->Height < 1) {
  540.          att_incomplete("0x0 renderbuffer");
  541.          att->Complete = GL_FALSE;
  542.          return;
  543.       }
  544.       if (format == GL_COLOR) {
  545.          if (baseFormat != GL_RGB &&
  546.              baseFormat != GL_RGBA) {
  547.             att_incomplete("bad renderbuffer color format");
  548.             att->Complete = GL_FALSE;
  549.             return;
  550.          }
  551.       }
  552.       else if (format == GL_DEPTH) {
  553.          if (baseFormat == GL_DEPTH_COMPONENT) {
  554.             /* OK */
  555.          }
  556.          else if (ctx->Extensions.EXT_packed_depth_stencil &&
  557.                   baseFormat == GL_DEPTH_STENCIL_EXT) {
  558.             /* OK */
  559.          }
  560.          else {
  561.             att_incomplete("bad renderbuffer depth format");
  562.             att->Complete = GL_FALSE;
  563.             return;
  564.          }
  565.       }
  566.       else {
  567.          assert(format == GL_STENCIL);
  568.          if (baseFormat == GL_STENCIL_INDEX) {
  569.             /* OK */
  570.          }
  571.          else if (ctx->Extensions.EXT_packed_depth_stencil &&
  572.                   baseFormat == GL_DEPTH_STENCIL_EXT) {
  573.             /* OK */
  574.          }
  575.          else {
  576.             att->Complete = GL_FALSE;
  577.             att_incomplete("bad renderbuffer stencil format");
  578.             return;
  579.          }
  580.       }
  581.    }
  582.    else {
  583.       ASSERT(att->Type == GL_NONE);
  584.       /* complete */
  585.       return;
  586.    }
  587. }
  588.  
  589.  
  590. /**
  591.  * Test if the given framebuffer object is complete and update its
  592.  * Status field with the results.
  593.  * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
  594.  * driver to make hardware-specific validation/completeness checks.
  595.  * Also update the framebuffer's Width and Height fields if the
  596.  * framebuffer is complete.
  597.  */
  598. void
  599. _mesa_test_framebuffer_completeness(struct gl_context *ctx,
  600.                                     struct gl_framebuffer *fb)
  601. {
  602.    GLuint numImages;
  603.    GLenum intFormat = GL_NONE; /* color buffers' internal format */
  604.    GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
  605.    GLint numSamples = -1;
  606.    GLint i;
  607.    GLuint j;
  608.  
  609.    assert(fb->Name != 0);
  610.  
  611.    numImages = 0;
  612.    fb->Width = 0;
  613.    fb->Height = 0;
  614.  
  615.    /* Start at -2 to more easily loop over all attachment points.
  616.     *  -2: depth buffer
  617.     *  -1: stencil buffer
  618.     * >=0: color buffer
  619.     */
  620.    for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
  621.       struct gl_renderbuffer_attachment *att;
  622.       GLenum f;
  623.       gl_format mesaFormat;
  624.  
  625.       /*
  626.        * XXX for ARB_fbo, only check color buffers that are named by
  627.        * GL_READ_BUFFER and GL_DRAW_BUFFERi.
  628.        */
  629.  
  630.       /* check for attachment completeness
  631.        */
  632.       if (i == -2) {
  633.          att = &fb->Attachment[BUFFER_DEPTH];
  634.          test_attachment_completeness(ctx, GL_DEPTH, att);
  635.          if (!att->Complete) {
  636.             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
  637.             fbo_incomplete("depth attachment incomplete", -1);
  638.             return;
  639.          }
  640.       }
  641.       else if (i == -1) {
  642.          att = &fb->Attachment[BUFFER_STENCIL];
  643.          test_attachment_completeness(ctx, GL_STENCIL, att);
  644.          if (!att->Complete) {
  645.             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
  646.             fbo_incomplete("stencil attachment incomplete", -1);
  647.             return;
  648.          }
  649.       }
  650.       else {
  651.          att = &fb->Attachment[BUFFER_COLOR0 + i];
  652.          test_attachment_completeness(ctx, GL_COLOR, att);
  653.          if (!att->Complete) {
  654.             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
  655.             fbo_incomplete("color attachment incomplete", i);
  656.             return;
  657.          }
  658.       }
  659.  
  660.       /* get width, height, format of the renderbuffer/texture
  661.        */
  662.       if (att->Type == GL_TEXTURE) {
  663.          const struct gl_texture_image *texImg
  664.             = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
  665.          minWidth = MIN2(minWidth, texImg->Width);
  666.          maxWidth = MAX2(maxWidth, texImg->Width);
  667.          minHeight = MIN2(minHeight, texImg->Height);
  668.          maxHeight = MAX2(maxHeight, texImg->Height);
  669.          f = texImg->_BaseFormat;
  670.          mesaFormat = texImg->TexFormat;
  671.          numImages++;
  672.          if (!is_legal_color_format(ctx, f) &&
  673.              !is_legal_depth_format(ctx, f)) {
  674.             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
  675.             fbo_incomplete("texture attachment incomplete", -1);
  676.             return;
  677.          }
  678.       }
  679.       else if (att->Type == GL_RENDERBUFFER_EXT) {
  680.          minWidth = MIN2(minWidth, att->Renderbuffer->Width);
  681.          maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
  682.          minHeight = MIN2(minHeight, att->Renderbuffer->Height);
  683.          maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
  684.          f = att->Renderbuffer->InternalFormat;
  685.          mesaFormat = att->Renderbuffer->Format;
  686.          numImages++;
  687.       }
  688.       else {
  689.          assert(att->Type == GL_NONE);
  690.          continue;
  691.       }
  692.  
  693.       if (numSamples < 0) {
  694.          /* first buffer */
  695.          numSamples = att->Renderbuffer->NumSamples;
  696.       }
  697.  
  698.       /* check if integer color */
  699.       fb->_IntegerColor = _mesa_is_format_integer_color(mesaFormat);
  700.  
  701.       /* Error-check width, height, format, samples
  702.        */
  703.       if (numImages == 1) {
  704.          /* save format, num samples */
  705.          if (i >= 0) {
  706.             intFormat = f;
  707.          }
  708.       }
  709.       else {
  710.          if (!ctx->Extensions.ARB_framebuffer_object) {
  711.             /* check that width, height, format are same */
  712.             if (minWidth != maxWidth || minHeight != maxHeight) {
  713.                fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
  714.                fbo_incomplete("width or height mismatch", -1);
  715.                return;
  716.             }
  717.             /* check that all color buffer have same format */
  718.             if (intFormat != GL_NONE && f != intFormat) {
  719.                fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
  720.                fbo_incomplete("format mismatch", -1);
  721.                return;
  722.             }
  723.          }
  724.          if (att->Renderbuffer &&
  725.              att->Renderbuffer->NumSamples != numSamples) {
  726.             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
  727.             fbo_incomplete("inconsistant number of samples", i);
  728.             return;
  729.          }            
  730.  
  731.       }
  732.    }
  733.  
  734. #if FEATURE_GL
  735.    if (ctx->API == API_OPENGL) {
  736.       /* Check that all DrawBuffers are present */
  737.       for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
  738.          if (fb->ColorDrawBuffer[j] != GL_NONE) {
  739.             const struct gl_renderbuffer_attachment *att
  740.                = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
  741.             assert(att);
  742.             if (att->Type == GL_NONE) {
  743.                fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
  744.                fbo_incomplete("missing drawbuffer", j);
  745.                return;
  746.             }
  747.          }
  748.       }
  749.  
  750.       /* Check that the ReadBuffer is present */
  751.       if (fb->ColorReadBuffer != GL_NONE) {
  752.          const struct gl_renderbuffer_attachment *att
  753.             = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
  754.          assert(att);
  755.          if (att->Type == GL_NONE) {
  756.             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
  757.             fbo_incomplete("missing readbuffer", -1);
  758.             return;
  759.          }
  760.       }
  761.    }
  762. #else
  763.    (void) j;
  764. #endif
  765.  
  766.    if (numImages == 0) {
  767.       fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
  768.       fbo_incomplete("no attachments", -1);
  769.       return;
  770.    }
  771.  
  772.    /* Provisionally set status = COMPLETE ... */
  773.    fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
  774.  
  775.    /* ... but the driver may say the FB is incomplete.
  776.     * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
  777.     * if anything.
  778.     */
  779.    if (ctx->Driver.ValidateFramebuffer) {
  780.       ctx->Driver.ValidateFramebuffer(ctx, fb);
  781.       if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
  782.          fbo_incomplete("driver marked FBO as incomplete", -1);
  783.       }
  784.    }
  785.  
  786.    if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) {
  787.       /*
  788.        * Note that if ARB_framebuffer_object is supported and the attached
  789.        * renderbuffers/textures are different sizes, the framebuffer
  790.        * width/height will be set to the smallest width/height.
  791.        */
  792.       fb->Width = minWidth;
  793.       fb->Height = minHeight;
  794.  
  795.       /* finally, update the visual info for the framebuffer */
  796.       _mesa_update_framebuffer_visual(fb);
  797.    }
  798. }
  799.  
  800.  
  801. GLboolean GLAPIENTRY
  802. _mesa_IsRenderbufferEXT(GLuint renderbuffer)
  803. {
  804.    GET_CURRENT_CONTEXT(ctx);
  805.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
  806.    if (renderbuffer) {
  807.       struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
  808.       if (rb != NULL && rb != &DummyRenderbuffer)
  809.          return GL_TRUE;
  810.    }
  811.    return GL_FALSE;
  812. }
  813.  
  814.  
  815. void GLAPIENTRY
  816. _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
  817. {
  818.    struct gl_renderbuffer *newRb;
  819.    GET_CURRENT_CONTEXT(ctx);
  820.  
  821.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  822.  
  823.    if (target != GL_RENDERBUFFER_EXT) {
  824.       _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
  825.       return;
  826.    }
  827.  
  828.    /* No need to flush here since the render buffer binding has no
  829.     * effect on rendering state.
  830.     */
  831.  
  832.    if (renderbuffer) {
  833.       newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
  834.       if (newRb == &DummyRenderbuffer) {
  835.          /* ID was reserved, but no real renderbuffer object made yet */
  836.          newRb = NULL;
  837.       }
  838.       else if (!newRb && ctx->Extensions.ARB_framebuffer_object) {
  839.          /* All RB IDs must be Gen'd */
  840.          _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
  841.          return;
  842.       }
  843.  
  844.       if (!newRb) {
  845.          /* create new renderbuffer object */
  846.          newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
  847.          if (!newRb) {
  848.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
  849.             return;
  850.          }
  851.          ASSERT(newRb->AllocStorage);
  852.          _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
  853.          newRb->RefCount = 1; /* referenced by hash table */
  854.       }
  855.    }
  856.    else {
  857.       newRb = NULL;
  858.    }
  859.  
  860.    ASSERT(newRb != &DummyRenderbuffer);
  861.  
  862.    _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
  863. }
  864.  
  865.  
  866. /**
  867.  * If the given renderbuffer is anywhere attached to the framebuffer, detach
  868.  * the renderbuffer.
  869.  * This is used when a renderbuffer object is deleted.
  870.  * The spec calls for unbinding.
  871.  */
  872. static void
  873. detach_renderbuffer(struct gl_context *ctx,
  874.                     struct gl_framebuffer *fb,
  875.                     struct gl_renderbuffer *rb)
  876. {
  877.    GLuint i;
  878.    for (i = 0; i < BUFFER_COUNT; i++) {
  879.       if (fb->Attachment[i].Renderbuffer == rb) {
  880.          _mesa_remove_attachment(ctx, &fb->Attachment[i]);
  881.       }
  882.    }
  883.    invalidate_framebuffer(fb);
  884. }
  885.  
  886.  
  887. void GLAPIENTRY
  888. _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
  889. {
  890.    GLint i;
  891.    GET_CURRENT_CONTEXT(ctx);
  892.  
  893.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  894.    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
  895.  
  896.    for (i = 0; i < n; i++) {
  897.       if (renderbuffers[i] > 0) {
  898.          struct gl_renderbuffer *rb;
  899.          rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
  900.          if (rb) {
  901.             /* check if deleting currently bound renderbuffer object */
  902.             if (rb == ctx->CurrentRenderbuffer) {
  903.                /* bind default */
  904.                ASSERT(rb->RefCount >= 2);
  905.                _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
  906.             }
  907.  
  908.             if (ctx->DrawBuffer->Name) {
  909.                detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
  910.             }
  911.             if (ctx->ReadBuffer->Name && ctx->ReadBuffer != ctx->DrawBuffer) {
  912.                detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
  913.             }
  914.  
  915.             /* Remove from hash table immediately, to free the ID.
  916.              * But the object will not be freed until it's no longer
  917.              * referenced anywhere else.
  918.              */
  919.             _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
  920.  
  921.             if (rb != &DummyRenderbuffer) {
  922.                /* no longer referenced by hash table */
  923.                _mesa_reference_renderbuffer(&rb, NULL);
  924.             }
  925.          }
  926.       }
  927.    }
  928. }
  929.  
  930.  
  931. void GLAPIENTRY
  932. _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
  933. {
  934.    GET_CURRENT_CONTEXT(ctx);
  935.    GLuint first;
  936.    GLint i;
  937.  
  938.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  939.  
  940.    if (n < 0) {
  941.       _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
  942.       return;
  943.    }
  944.  
  945.    if (!renderbuffers)
  946.       return;
  947.  
  948.    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
  949.  
  950.    for (i = 0; i < n; i++) {
  951.       GLuint name = first + i;
  952.       renderbuffers[i] = name;
  953.       /* insert dummy placeholder into hash table */
  954.       _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
  955.       _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
  956.       _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
  957.    }
  958. }
  959.  
  960.  
  961. /**
  962.  * Given an internal format token for a render buffer, return the
  963.  * corresponding base format.
  964.  * This is very similar to _mesa_base_tex_format() but the set of valid
  965.  * internal formats is somewhat different.
  966.  *
  967.  * \return one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT
  968.  *  GL_DEPTH_STENCIL_EXT or zero if error.
  969.  *
  970.  * XXX in the future when we support red-only and red-green formats
  971.  * we'll also return GL_RED and GL_RG.
  972.  */
  973. GLenum
  974. _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
  975. {
  976.    switch (internalFormat) {
  977.    case GL_ALPHA:
  978.    case GL_ALPHA4:
  979.    case GL_ALPHA8:
  980.    case GL_ALPHA12:
  981.    case GL_ALPHA16:
  982.       return GL_ALPHA;
  983.    case GL_RGB:
  984.    case GL_R3_G3_B2:
  985.    case GL_RGB4:
  986.    case GL_RGB5:
  987.    case GL_RGB8:
  988.    case GL_RGB10:
  989.    case GL_RGB12:
  990.    case GL_RGB16:
  991.       return GL_RGB;
  992.    case GL_RGBA:
  993.    case GL_RGBA2:
  994.    case GL_RGBA4:
  995.    case GL_RGB5_A1:
  996.    case GL_RGBA8:
  997.    case GL_RGB10_A2:
  998.    case GL_RGBA12:
  999.    case GL_RGBA16:
  1000.    case GL_RGBA16_SNORM:
  1001.       return GL_RGBA;
  1002.    case GL_STENCIL_INDEX:
  1003.    case GL_STENCIL_INDEX1_EXT:
  1004.    case GL_STENCIL_INDEX4_EXT:
  1005.    case GL_STENCIL_INDEX8_EXT:
  1006.    case GL_STENCIL_INDEX16_EXT:
  1007.       return GL_STENCIL_INDEX;
  1008.    case GL_DEPTH_COMPONENT:
  1009.    case GL_DEPTH_COMPONENT16:
  1010.    case GL_DEPTH_COMPONENT24:
  1011.    case GL_DEPTH_COMPONENT32:
  1012.       return GL_DEPTH_COMPONENT;
  1013.    case GL_DEPTH_STENCIL_EXT:
  1014.    case GL_DEPTH24_STENCIL8_EXT:
  1015.       if (ctx->Extensions.EXT_packed_depth_stencil)
  1016.          return GL_DEPTH_STENCIL_EXT;
  1017.       else
  1018.          return 0;
  1019.    /* XXX add floating point formats eventually */
  1020.    default:
  1021.       return 0;
  1022.    }
  1023. }
  1024.  
  1025.  
  1026. /** sentinal value, see below */
  1027. #define NO_SAMPLES 1000
  1028.  
  1029.  
  1030. /**
  1031.  * Helper function used by _mesa_RenderbufferStorageEXT() and
  1032.  * _mesa_RenderbufferStorageMultisample().
  1033.  * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT().
  1034.  */
  1035. static void
  1036. renderbuffer_storage(GLenum target, GLenum internalFormat,
  1037.                      GLsizei width, GLsizei height, GLsizei samples)
  1038. {
  1039.    const char *func = samples == NO_SAMPLES ?
  1040.       "glRenderbufferStorage" : "RenderbufferStorageMultisample";
  1041.    struct gl_renderbuffer *rb;
  1042.    GLenum baseFormat;
  1043.    GET_CURRENT_CONTEXT(ctx);
  1044.  
  1045.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  1046.  
  1047.    if (target != GL_RENDERBUFFER_EXT) {
  1048.       _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
  1049.       return;
  1050.    }
  1051.  
  1052.    baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
  1053.    if (baseFormat == 0) {
  1054.       _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func);
  1055.       return;
  1056.    }
  1057.  
  1058.    if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
  1059.       _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
  1060.       return;
  1061.    }
  1062.  
  1063.    if (height < 1 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
  1064.       _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
  1065.       return;
  1066.    }
  1067.  
  1068.    if (samples == NO_SAMPLES) {
  1069.       /* NumSamples == 0 indicates non-multisampling */
  1070.       samples = 0;
  1071.    }
  1072.    else if (samples > (GLsizei) ctx->Const.MaxSamples) {
  1073.       /* note: driver may choose to use more samples than what's requested */
  1074.       _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func);
  1075.       return;
  1076.    }
  1077.  
  1078.    rb = ctx->CurrentRenderbuffer;
  1079.    if (!rb) {
  1080.       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
  1081.       return;
  1082.    }
  1083.  
  1084.    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
  1085.  
  1086.    if (rb->InternalFormat == internalFormat &&
  1087.        rb->Width == (GLuint) width &&
  1088.        rb->Height == (GLuint) height) {
  1089.       /* no change in allocation needed */
  1090.       return;
  1091.    }
  1092.  
  1093.    /* These MUST get set by the AllocStorage func */
  1094.    rb->Format = MESA_FORMAT_NONE;
  1095.    rb->NumSamples = samples;
  1096.  
  1097.    /* Now allocate the storage */
  1098.    ASSERT(rb->AllocStorage);
  1099.    if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
  1100.       /* No error - check/set fields now */
  1101.       assert(rb->Format != MESA_FORMAT_NONE);
  1102.       assert(rb->Width == (GLuint) width);
  1103.       assert(rb->Height == (GLuint) height);
  1104.       rb->InternalFormat = internalFormat;
  1105.       rb->_BaseFormat = baseFormat;
  1106.       assert(rb->_BaseFormat != 0);
  1107.    }
  1108.    else {
  1109.       /* Probably ran out of memory - clear the fields */
  1110.       rb->Width = 0;
  1111.       rb->Height = 0;
  1112.       rb->Format = MESA_FORMAT_NONE;
  1113.       rb->InternalFormat = GL_NONE;
  1114.       rb->_BaseFormat = GL_NONE;
  1115.       rb->NumSamples = 0;
  1116.    }
  1117.  
  1118.    /*
  1119.    test_framebuffer_completeness(ctx, fb);
  1120.    */
  1121.    /* XXX if this renderbuffer is attached anywhere, invalidate attachment
  1122.     * points???
  1123.     */
  1124. }
  1125.  
  1126.  
  1127. #if FEATURE_OES_EGL_image
  1128. void GLAPIENTRY
  1129. _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
  1130. {
  1131.    struct gl_renderbuffer *rb;
  1132.    GET_CURRENT_CONTEXT(ctx);
  1133.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  1134.  
  1135.    if (!ctx->Extensions.OES_EGL_image) {
  1136.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1137.                   "glEGLImageTargetRenderbufferStorageOES(unsupported)");
  1138.       return;
  1139.    }
  1140.  
  1141.    if (target != GL_RENDERBUFFER) {
  1142.       _mesa_error(ctx, GL_INVALID_ENUM,
  1143.                   "EGLImageTargetRenderbufferStorageOES");
  1144.       return;
  1145.    }
  1146.  
  1147.    rb = ctx->CurrentRenderbuffer;
  1148.    if (!rb) {
  1149.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1150.                   "EGLImageTargetRenderbufferStorageOES");
  1151.       return;
  1152.    }
  1153.  
  1154.    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
  1155.  
  1156.    ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
  1157. }
  1158. #endif
  1159.  
  1160.  
  1161. /**
  1162.  * Helper function for _mesa_GetRenderbufferParameterivEXT() and
  1163.  * _mesa_GetFramebufferAttachmentParameterivEXT()
  1164.  * We have to be careful to respect the base format.  For example, if a
  1165.  * renderbuffer/texture was created with internalFormat=GL_RGB but the
  1166.  * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
  1167.  * we need to return zero.
  1168.  */
  1169. static GLint
  1170. get_component_bits(GLenum pname, GLenum baseFormat, gl_format format)
  1171. {
  1172.    switch (pname) {
  1173.    case GL_RENDERBUFFER_RED_SIZE_EXT:
  1174.    case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
  1175.    case GL_RENDERBUFFER_GREEN_SIZE_EXT:
  1176.    case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
  1177.    case GL_RENDERBUFFER_BLUE_SIZE_EXT:
  1178.    case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
  1179.       if (baseFormat == GL_RGB || baseFormat == GL_RGBA)
  1180.          return _mesa_get_format_bits(format, pname);
  1181.       else
  1182.          return 0;
  1183.    case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
  1184.    case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
  1185.       if (baseFormat == GL_RGBA || baseFormat == GL_ALPHA)
  1186.          return _mesa_get_format_bits(format, pname);
  1187.       else
  1188.          return 0;
  1189.    case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
  1190.    case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
  1191.       if (baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL)
  1192.          return _mesa_get_format_bits(format, pname);
  1193.       else
  1194.          return 0;
  1195.    case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
  1196.    case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
  1197.       if (baseFormat == GL_STENCIL_INDEX || baseFormat == GL_DEPTH_STENCIL)
  1198.          return _mesa_get_format_bits(format, pname);
  1199.       else
  1200.          return 0;
  1201.    default:
  1202.       return 0;
  1203.    }
  1204. }
  1205.  
  1206.  
  1207.  
  1208. void GLAPIENTRY
  1209. _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
  1210.                              GLsizei width, GLsizei height)
  1211. {
  1212.    /* GL_ARB_fbo says calling this function is equivalent to calling
  1213.     * glRenderbufferStorageMultisample() with samples=0.  We pass in
  1214.     * a token value here just for error reporting purposes.
  1215.     */
  1216.    renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
  1217. }
  1218.  
  1219.  
  1220. void GLAPIENTRY
  1221. _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
  1222.                                      GLenum internalFormat,
  1223.                                      GLsizei width, GLsizei height)
  1224. {
  1225.    renderbuffer_storage(target, internalFormat, width, height, samples);
  1226. }
  1227.  
  1228.  
  1229. /**
  1230.  * OpenGL ES version of glRenderBufferStorage.
  1231.  */
  1232. void GLAPIENTRY
  1233. _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
  1234.                            GLsizei width, GLsizei height)
  1235. {
  1236.    switch (internalFormat) {
  1237.    case GL_RGB565:
  1238.       /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
  1239.       /* choose a closest format */
  1240.       internalFormat = GL_RGB5;
  1241.       break;
  1242.    default:
  1243.       break;
  1244.    }
  1245.  
  1246.    renderbuffer_storage(target, internalFormat, width, height, 0);
  1247. }
  1248.  
  1249.  
  1250. void GLAPIENTRY
  1251. _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
  1252. {
  1253.    struct gl_renderbuffer *rb;
  1254.    GET_CURRENT_CONTEXT(ctx);
  1255.  
  1256.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  1257.  
  1258.    if (target != GL_RENDERBUFFER_EXT) {
  1259.       _mesa_error(ctx, GL_INVALID_ENUM,
  1260.                   "glGetRenderbufferParameterivEXT(target)");
  1261.       return;
  1262.    }
  1263.  
  1264.    rb = ctx->CurrentRenderbuffer;
  1265.    if (!rb) {
  1266.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1267.                   "glGetRenderbufferParameterivEXT");
  1268.       return;
  1269.    }
  1270.  
  1271.    /* No need to flush here since we're just quering state which is
  1272.     * not effected by rendering.
  1273.     */
  1274.  
  1275.    switch (pname) {
  1276.    case GL_RENDERBUFFER_WIDTH_EXT:
  1277.       *params = rb->Width;
  1278.       return;
  1279.    case GL_RENDERBUFFER_HEIGHT_EXT:
  1280.       *params = rb->Height;
  1281.       return;
  1282.    case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
  1283.       *params = rb->InternalFormat;
  1284.       return;
  1285.    case GL_RENDERBUFFER_RED_SIZE_EXT:
  1286.    case GL_RENDERBUFFER_GREEN_SIZE_EXT:
  1287.    case GL_RENDERBUFFER_BLUE_SIZE_EXT:
  1288.    case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
  1289.    case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
  1290.    case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
  1291.       *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
  1292.       break;
  1293.    case GL_RENDERBUFFER_SAMPLES:
  1294.       if (ctx->Extensions.ARB_framebuffer_object) {
  1295.          *params = rb->NumSamples;
  1296.          break;
  1297.       }
  1298.       /* fallthrough */
  1299.    default:
  1300.       _mesa_error(ctx, GL_INVALID_ENUM,
  1301.                   "glGetRenderbufferParameterivEXT(target)");
  1302.       return;
  1303.    }
  1304. }
  1305.  
  1306.  
  1307. GLboolean GLAPIENTRY
  1308. _mesa_IsFramebufferEXT(GLuint framebuffer)
  1309. {
  1310.    GET_CURRENT_CONTEXT(ctx);
  1311.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
  1312.    if (framebuffer) {
  1313.       struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
  1314.       if (rb != NULL && rb != &DummyFramebuffer)
  1315.          return GL_TRUE;
  1316.    }
  1317.    return GL_FALSE;
  1318. }
  1319.  
  1320.  
  1321. /**
  1322.  * Check if any of the attachments of the given framebuffer are textures
  1323.  * (render to texture).  Call ctx->Driver.RenderTexture() for such
  1324.  * attachments.
  1325.  */
  1326. static void
  1327. check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
  1328. {
  1329.    GLuint i;
  1330.    ASSERT(ctx->Driver.RenderTexture);
  1331.  
  1332.    if (fb->Name == 0)
  1333.       return; /* can't render to texture with winsys framebuffers */
  1334.  
  1335.    for (i = 0; i < BUFFER_COUNT; i++) {
  1336.       struct gl_renderbuffer_attachment *att = fb->Attachment + i;
  1337.       struct gl_texture_object *texObj = att->Texture;
  1338.       if (texObj
  1339.           && texObj->Image[att->CubeMapFace][att->TextureLevel]) {
  1340.          ctx->Driver.RenderTexture(ctx, fb, att);
  1341.       }
  1342.    }
  1343. }
  1344.  
  1345.  
  1346. /**
  1347.  * Examine all the framebuffer's attachments to see if any are textures.
  1348.  * If so, call ctx->Driver.FinishRenderTexture() for each texture to
  1349.  * notify the device driver that the texture image may have changed.
  1350.  */
  1351. static void
  1352. check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
  1353. {
  1354.    if (fb->Name == 0)
  1355.       return; /* can't render to texture with winsys framebuffers */
  1356.  
  1357.    if (ctx->Driver.FinishRenderTexture) {
  1358.       GLuint i;
  1359.       for (i = 0; i < BUFFER_COUNT; i++) {
  1360.          struct gl_renderbuffer_attachment *att = fb->Attachment + i;
  1361.          if (att->Texture && att->Renderbuffer) {
  1362.             ctx->Driver.FinishRenderTexture(ctx, att);
  1363.          }
  1364.       }
  1365.    }
  1366. }
  1367.  
  1368.  
  1369. void GLAPIENTRY
  1370. _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
  1371. {
  1372.    struct gl_framebuffer *newDrawFb, *newReadFb;
  1373.    struct gl_framebuffer *oldDrawFb, *oldReadFb;
  1374.    GLboolean bindReadBuf, bindDrawBuf;
  1375.    GET_CURRENT_CONTEXT(ctx);
  1376.  
  1377. #ifdef DEBUG
  1378.    if (ctx->Extensions.ARB_framebuffer_object) {
  1379.       ASSERT(ctx->Extensions.EXT_framebuffer_object);
  1380.       ASSERT(ctx->Extensions.EXT_framebuffer_blit);
  1381.    }
  1382. #endif
  1383.  
  1384.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  1385.  
  1386.    if (!ctx->Extensions.EXT_framebuffer_object) {
  1387.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1388.                   "glBindFramebufferEXT(unsupported)");
  1389.       return;
  1390.    }
  1391.  
  1392.    switch (target) {
  1393. #if FEATURE_EXT_framebuffer_blit
  1394.    case GL_DRAW_FRAMEBUFFER_EXT:
  1395.       if (!ctx->Extensions.EXT_framebuffer_blit) {
  1396.          _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
  1397.          return;
  1398.       }
  1399.       bindDrawBuf = GL_TRUE;
  1400.       bindReadBuf = GL_FALSE;
  1401.       break;
  1402.    case GL_READ_FRAMEBUFFER_EXT:
  1403.       if (!ctx->Extensions.EXT_framebuffer_blit) {
  1404.          _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
  1405.          return;
  1406.       }
  1407.       bindDrawBuf = GL_FALSE;
  1408.       bindReadBuf = GL_TRUE;
  1409.       break;
  1410. #endif
  1411.    case GL_FRAMEBUFFER_EXT:
  1412.       bindDrawBuf = GL_TRUE;
  1413.       bindReadBuf = GL_TRUE;
  1414.       break;
  1415.    default:
  1416.       _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
  1417.       return;
  1418.    }
  1419.  
  1420.    if (framebuffer) {
  1421.       /* Binding a user-created framebuffer object */
  1422.       newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
  1423.       if (newDrawFb == &DummyFramebuffer) {
  1424.          /* ID was reserved, but no real framebuffer object made yet */
  1425.          newDrawFb = NULL;
  1426.       }
  1427.       else if (!newDrawFb && ctx->Extensions.ARB_framebuffer_object) {
  1428.          /* All FBO IDs must be Gen'd */
  1429.          _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
  1430.          return;
  1431.       }
  1432.  
  1433.       if (!newDrawFb) {
  1434.          /* create new framebuffer object */
  1435.          newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
  1436.          if (!newDrawFb) {
  1437.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
  1438.             return;
  1439.          }
  1440.          _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
  1441.       }
  1442.       newReadFb = newDrawFb;
  1443.    }
  1444.    else {
  1445.       /* Binding the window system framebuffer (which was originally set
  1446.        * with MakeCurrent).
  1447.        */
  1448.       newDrawFb = ctx->WinSysDrawBuffer;
  1449.       newReadFb = ctx->WinSysReadBuffer;
  1450.    }
  1451.  
  1452.    ASSERT(newDrawFb);
  1453.    ASSERT(newDrawFb != &DummyFramebuffer);
  1454.  
  1455.    /* save pointers to current/old framebuffers */
  1456.    oldDrawFb = ctx->DrawBuffer;
  1457.    oldReadFb = ctx->ReadBuffer;
  1458.  
  1459.    /* check if really changing bindings */
  1460.    if (oldDrawFb == newDrawFb)
  1461.       bindDrawBuf = GL_FALSE;
  1462.    if (oldReadFb == newReadFb)
  1463.       bindReadBuf = GL_FALSE;
  1464.  
  1465.    /*
  1466.     * OK, now bind the new Draw/Read framebuffers, if they're changing.
  1467.     *
  1468.     * We also check if we're beginning and/or ending render-to-texture.
  1469.     * When a framebuffer with texture attachments is unbound, call
  1470.     * ctx->Driver.FinishRenderTexture().
  1471.     * When a framebuffer with texture attachments is bound, call
  1472.     * ctx->Driver.RenderTexture().
  1473.     *
  1474.     * Note that if the ReadBuffer has texture attachments we don't consider
  1475.     * that a render-to-texture case.
  1476.     */
  1477.    if (bindReadBuf) {
  1478.       FLUSH_VERTICES(ctx, _NEW_BUFFERS);
  1479.  
  1480.       /* check if old readbuffer was render-to-texture */
  1481.       check_end_texture_render(ctx, oldReadFb);
  1482.  
  1483.       _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
  1484.    }
  1485.  
  1486.    if (bindDrawBuf) {
  1487.       FLUSH_VERTICES(ctx, _NEW_BUFFERS);
  1488.  
  1489.       /* check if old read/draw buffers were render-to-texture */
  1490.       if (!bindReadBuf)
  1491.          check_end_texture_render(ctx, oldReadFb);
  1492.  
  1493.       if (oldDrawFb != oldReadFb)
  1494.          check_end_texture_render(ctx, oldDrawFb);
  1495.  
  1496.       /* check if newly bound framebuffer has any texture attachments */
  1497.       check_begin_texture_render(ctx, newDrawFb);
  1498.  
  1499.       _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
  1500.    }
  1501.  
  1502.    if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
  1503.       ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb);
  1504.    }
  1505. }
  1506.  
  1507.  
  1508. void GLAPIENTRY
  1509. _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
  1510. {
  1511.    GLint i;
  1512.    GET_CURRENT_CONTEXT(ctx);
  1513.  
  1514.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  1515.    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
  1516.  
  1517.    for (i = 0; i < n; i++) {
  1518.       if (framebuffers[i] > 0) {
  1519.          struct gl_framebuffer *fb;
  1520.          fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
  1521.          if (fb) {
  1522.             ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
  1523.  
  1524.             /* check if deleting currently bound framebuffer object */
  1525.             if (ctx->Extensions.EXT_framebuffer_blit) {
  1526.                /* separate draw/read binding points */
  1527.                if (fb == ctx->DrawBuffer) {
  1528.                   /* bind default */
  1529.                   ASSERT(fb->RefCount >= 2);
  1530.                   _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
  1531.                }
  1532.                if (fb == ctx->ReadBuffer) {
  1533.                   /* bind default */
  1534.                   ASSERT(fb->RefCount >= 2);
  1535.                   _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
  1536.                }
  1537.             }
  1538.             else {
  1539.                /* only one binding point for read/draw buffers */
  1540.                if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) {
  1541.                   /* bind default */
  1542.                   ASSERT(fb->RefCount >= 2);
  1543.                   _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  1544.                }    
  1545.             }
  1546.  
  1547.             /* remove from hash table immediately, to free the ID */
  1548.             _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
  1549.  
  1550.             if (fb != &DummyFramebuffer) {
  1551.                /* But the object will not be freed until it's no longer
  1552.                 * bound in any context.
  1553.                 */
  1554.                _mesa_reference_framebuffer(&fb, NULL);
  1555.             }
  1556.          }
  1557.       }
  1558.    }
  1559. }
  1560.  
  1561.  
  1562. void GLAPIENTRY
  1563. _mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers)
  1564. {
  1565.    GET_CURRENT_CONTEXT(ctx);
  1566.    GLuint first;
  1567.    GLint i;
  1568.  
  1569.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  1570.  
  1571.    if (n < 0) {
  1572.       _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
  1573.       return;
  1574.    }
  1575.  
  1576.    if (!framebuffers)
  1577.       return;
  1578.  
  1579.    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
  1580.  
  1581.    for (i = 0; i < n; i++) {
  1582.       GLuint name = first + i;
  1583.       framebuffers[i] = name;
  1584.       /* insert dummy placeholder into hash table */
  1585.       _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
  1586.       _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
  1587.       _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
  1588.    }
  1589. }
  1590.  
  1591.  
  1592.  
  1593. GLenum GLAPIENTRY
  1594. _mesa_CheckFramebufferStatusEXT(GLenum target)
  1595. {
  1596.    struct gl_framebuffer *buffer;
  1597.    GET_CURRENT_CONTEXT(ctx);
  1598.  
  1599.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
  1600.  
  1601.    switch (target) {
  1602. #if FEATURE_EXT_framebuffer_blit
  1603.    case GL_DRAW_FRAMEBUFFER_EXT:
  1604.       if (!ctx->Extensions.EXT_framebuffer_blit) {
  1605.          _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
  1606.          return 0;
  1607.       }
  1608.       buffer = ctx->DrawBuffer;
  1609.       break;
  1610.    case GL_READ_FRAMEBUFFER_EXT:
  1611.       if (!ctx->Extensions.EXT_framebuffer_blit) {
  1612.          _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
  1613.          return 0;
  1614.       }
  1615.       buffer = ctx->ReadBuffer;
  1616.       break;
  1617. #endif
  1618.    case GL_FRAMEBUFFER_EXT:
  1619.       buffer = ctx->DrawBuffer;
  1620.       break;
  1621.    default:
  1622.       _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
  1623.       return 0; /* formerly GL_FRAMEBUFFER_STATUS_ERROR_EXT */
  1624.    }
  1625.  
  1626.    if (buffer->Name == 0) {
  1627.       /* The window system / default framebuffer is always complete */
  1628.       return GL_FRAMEBUFFER_COMPLETE_EXT;
  1629.    }
  1630.  
  1631.    /* No need to flush here */
  1632.  
  1633.    if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
  1634.       _mesa_test_framebuffer_completeness(ctx, buffer);
  1635.    }
  1636.  
  1637.    return buffer->_Status;
  1638. }
  1639.  
  1640.  
  1641.  
  1642. /**
  1643.  * Common code called by glFramebufferTexture1D/2D/3DEXT().
  1644.  */
  1645. static void
  1646. framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
  1647.                     GLenum attachment, GLenum textarget, GLuint texture,
  1648.                     GLint level, GLint zoffset)
  1649. {
  1650.    struct gl_renderbuffer_attachment *att;
  1651.    struct gl_texture_object *texObj = NULL;
  1652.    struct gl_framebuffer *fb;
  1653.    GLboolean error = GL_FALSE;
  1654.  
  1655.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  1656.  
  1657.    switch (target) {
  1658.    case GL_READ_FRAMEBUFFER_EXT:
  1659.       error = !ctx->Extensions.EXT_framebuffer_blit;
  1660.       fb = ctx->ReadBuffer;
  1661.       break;
  1662.    case GL_DRAW_FRAMEBUFFER_EXT:
  1663.       error = !ctx->Extensions.EXT_framebuffer_blit;
  1664.       /* fall-through */
  1665.    case GL_FRAMEBUFFER_EXT:
  1666.       fb = ctx->DrawBuffer;
  1667.       break;
  1668.    default:
  1669.       error = GL_TRUE;
  1670.    }
  1671.  
  1672.    if (error) {
  1673.       _mesa_error(ctx, GL_INVALID_ENUM,
  1674.                   "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
  1675.       return;
  1676.    }
  1677.  
  1678.    ASSERT(fb);
  1679.  
  1680.    /* check framebuffer binding */
  1681.    if (fb->Name == 0) {
  1682.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1683.                   "glFramebufferTexture%sEXT", caller);
  1684.       return;
  1685.    }
  1686.  
  1687.  
  1688.    /* The textarget, level, and zoffset parameters are only validated if
  1689.     * texture is non-zero.
  1690.     */
  1691.    if (texture) {
  1692.       GLboolean err = GL_TRUE;
  1693.  
  1694.       texObj = _mesa_lookup_texture(ctx, texture);
  1695.       if (texObj != NULL) {
  1696.          if (textarget == 0) {
  1697.             /* XXX what's the purpose of this? */
  1698.             err = (texObj->Target != GL_TEXTURE_3D) &&
  1699.                 (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
  1700.                 (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT);
  1701.          }
  1702.          else {
  1703.             err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
  1704.                 ? !IS_CUBE_FACE(textarget)
  1705.                 : (texObj->Target != textarget);
  1706.          }
  1707.       }
  1708.       else {
  1709.          /* can't render to a non-existant texture */
  1710.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1711.                      "glFramebufferTexture%sEXT(non existant texture)",
  1712.                      caller);
  1713.          return;
  1714.       }
  1715.  
  1716.       if (err) {
  1717.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1718.                      "glFramebufferTexture%sEXT(texture target mismatch)",
  1719.                      caller);
  1720.          return;
  1721.       }
  1722.  
  1723.       if (texObj->Target == GL_TEXTURE_3D) {
  1724.          const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
  1725.          if (zoffset < 0 || zoffset >= maxSize) {
  1726.             _mesa_error(ctx, GL_INVALID_VALUE,
  1727.                         "glFramebufferTexture%sEXT(zoffset)", caller);
  1728.             return;
  1729.          }
  1730.       }
  1731.       else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
  1732.                (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
  1733.          if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) {
  1734.             _mesa_error(ctx, GL_INVALID_VALUE,
  1735.                         "glFramebufferTexture%sEXT(layer)", caller);
  1736.             return;
  1737.          }
  1738.       }
  1739.  
  1740.       if ((level < 0) ||
  1741.           (level >= _mesa_max_texture_levels(ctx, texObj->Target))) {
  1742.          _mesa_error(ctx, GL_INVALID_VALUE,
  1743.                      "glFramebufferTexture%sEXT(level)", caller);
  1744.          return;
  1745.       }
  1746.    }
  1747.  
  1748.    att = _mesa_get_attachment(ctx, fb, attachment);
  1749.    if (att == NULL) {
  1750.       _mesa_error(ctx, GL_INVALID_ENUM,
  1751.                   "glFramebufferTexture%sEXT(attachment)", caller);
  1752.       return;
  1753.    }
  1754.  
  1755.    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
  1756.  
  1757.    _glthread_LOCK_MUTEX(fb->Mutex);
  1758.    if (texObj) {
  1759.       _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
  1760.                                    level, zoffset);
  1761.       /* Set the render-to-texture flag.  We'll check this flag in
  1762.        * glTexImage() and friends to determine if we need to revalidate
  1763.        * any FBOs that might be rendering into this texture.
  1764.        * This flag never gets cleared since it's non-trivial to determine
  1765.        * when all FBOs might be done rendering to this texture.  That's OK
  1766.        * though since it's uncommon to render to a texture then repeatedly
  1767.        * call glTexImage() to change images in the texture.
  1768.        */
  1769.       texObj->_RenderToTexture = GL_TRUE;
  1770.    }
  1771.    else {
  1772.       _mesa_remove_attachment(ctx, att);
  1773.    }
  1774.  
  1775.    invalidate_framebuffer(fb);
  1776.  
  1777.    _glthread_UNLOCK_MUTEX(fb->Mutex);
  1778. }
  1779.  
  1780.  
  1781.  
  1782. void GLAPIENTRY
  1783. _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
  1784.                               GLenum textarget, GLuint texture, GLint level)
  1785. {
  1786.    GET_CURRENT_CONTEXT(ctx);
  1787.  
  1788.    if ((texture != 0) && (textarget != GL_TEXTURE_1D)) {
  1789.       _mesa_error(ctx, GL_INVALID_ENUM,
  1790.                   "glFramebufferTexture1DEXT(textarget)");
  1791.       return;
  1792.    }
  1793.  
  1794.    framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
  1795.                        level, 0);
  1796. }
  1797.  
  1798.  
  1799. void GLAPIENTRY
  1800. _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
  1801.                               GLenum textarget, GLuint texture, GLint level)
  1802. {
  1803.    GET_CURRENT_CONTEXT(ctx);
  1804.  
  1805.    if ((texture != 0) &&
  1806.        (textarget != GL_TEXTURE_2D) &&
  1807.        (textarget != GL_TEXTURE_RECTANGLE_ARB) &&
  1808.        (!IS_CUBE_FACE(textarget))) {
  1809.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1810.                   "glFramebufferTexture2DEXT(textarget=0x%x)", textarget);
  1811.       return;
  1812.    }
  1813.  
  1814.    framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
  1815.                        level, 0);
  1816. }
  1817.  
  1818.  
  1819. void GLAPIENTRY
  1820. _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
  1821.                               GLenum textarget, GLuint texture,
  1822.                               GLint level, GLint zoffset)
  1823. {
  1824.    GET_CURRENT_CONTEXT(ctx);
  1825.  
  1826.    if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
  1827.       _mesa_error(ctx, GL_INVALID_ENUM,
  1828.                   "glFramebufferTexture3DEXT(textarget)");
  1829.       return;
  1830.    }
  1831.  
  1832.    framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
  1833.                        level, zoffset);
  1834. }
  1835.  
  1836.  
  1837. void GLAPIENTRY
  1838. _mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment,
  1839.                                  GLuint texture, GLint level, GLint layer)
  1840. {
  1841.    GET_CURRENT_CONTEXT(ctx);
  1842.  
  1843.    framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
  1844.                        level, layer);
  1845. }
  1846.  
  1847.  
  1848. void GLAPIENTRY
  1849. _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
  1850.                                  GLenum renderbufferTarget,
  1851.                                  GLuint renderbuffer)
  1852. {
  1853.    struct gl_renderbuffer_attachment *att;
  1854.    struct gl_framebuffer *fb;
  1855.    struct gl_renderbuffer *rb;
  1856.    GET_CURRENT_CONTEXT(ctx);
  1857.  
  1858.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  1859.  
  1860.    switch (target) {
  1861. #if FEATURE_EXT_framebuffer_blit
  1862.    case GL_DRAW_FRAMEBUFFER_EXT:
  1863.       if (!ctx->Extensions.EXT_framebuffer_blit) {
  1864.          _mesa_error(ctx, GL_INVALID_ENUM,
  1865.                      "glFramebufferRenderbufferEXT(target)");
  1866.          return;
  1867.       }
  1868.       fb = ctx->DrawBuffer;
  1869.       break;
  1870.    case GL_READ_FRAMEBUFFER_EXT:
  1871.       if (!ctx->Extensions.EXT_framebuffer_blit) {
  1872.          _mesa_error(ctx, GL_INVALID_ENUM,
  1873.                      "glFramebufferRenderbufferEXT(target)");
  1874.          return;
  1875.       }
  1876.       fb = ctx->ReadBuffer;
  1877.       break;
  1878. #endif
  1879.    case GL_FRAMEBUFFER_EXT:
  1880.       fb = ctx->DrawBuffer;
  1881.       break;
  1882.    default:
  1883.       _mesa_error(ctx, GL_INVALID_ENUM,
  1884.                   "glFramebufferRenderbufferEXT(target)");
  1885.       return;
  1886.    }
  1887.  
  1888.    if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
  1889.       _mesa_error(ctx, GL_INVALID_ENUM,
  1890.                   "glFramebufferRenderbufferEXT(renderbufferTarget)");
  1891.       return;
  1892.    }
  1893.  
  1894.    if (fb->Name == 0) {
  1895.       /* Can't attach new renderbuffers to a window system framebuffer */
  1896.       _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
  1897.       return;
  1898.    }
  1899.  
  1900.    att = _mesa_get_attachment(ctx, fb, attachment);
  1901.    if (att == NULL) {
  1902.       _mesa_error(ctx, GL_INVALID_ENUM,
  1903.                   "glFramebufferRenderbufferEXT(invalid attachment %s)",
  1904.                   _mesa_lookup_enum_by_nr(attachment));
  1905.       return;
  1906.    }
  1907.  
  1908.    if (renderbuffer) {
  1909.       rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
  1910.       if (!rb) {
  1911.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1912.                      "glFramebufferRenderbufferEXT(non-existant"
  1913.                      " renderbuffer %u)", renderbuffer);
  1914.          return;
  1915.       }
  1916.       else if (rb == &DummyRenderbuffer) {
  1917.          /* This is what NVIDIA does */
  1918.          _mesa_error(ctx, GL_INVALID_VALUE,
  1919.                      "glFramebufferRenderbufferEXT(renderbuffer %u)",
  1920.                      renderbuffer);
  1921.          return;
  1922.       }
  1923.    }
  1924.    else {
  1925.       /* remove renderbuffer attachment */
  1926.       rb = NULL;
  1927.    }
  1928.  
  1929.    if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
  1930.        rb && rb->Format != MESA_FORMAT_NONE) {
  1931.       /* make sure the renderbuffer is a depth/stencil format */
  1932.       const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
  1933.       if (baseFormat != GL_DEPTH_STENCIL) {
  1934.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1935.                      "glFramebufferRenderbufferEXT(renderbuffer"
  1936.                      " is not DEPTH_STENCIL format)");
  1937.          return;
  1938.       }
  1939.    }
  1940.  
  1941.  
  1942.    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
  1943.  
  1944.    assert(ctx->Driver.FramebufferRenderbuffer);
  1945.    ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
  1946.  
  1947.    /* Some subsequent GL commands may depend on the framebuffer's visual
  1948.     * after the binding is updated.  Update visual info now.
  1949.     */
  1950.    _mesa_update_framebuffer_visual(fb);
  1951. }
  1952.  
  1953.  
  1954. void GLAPIENTRY
  1955. _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
  1956.                                              GLenum pname, GLint *params)
  1957. {
  1958.    const struct gl_renderbuffer_attachment *att;
  1959.    struct gl_framebuffer *buffer;
  1960.    GET_CURRENT_CONTEXT(ctx);
  1961.  
  1962.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  1963.  
  1964.    switch (target) {
  1965. #if FEATURE_EXT_framebuffer_blit
  1966.    case GL_DRAW_FRAMEBUFFER_EXT:
  1967.       if (!ctx->Extensions.EXT_framebuffer_blit) {
  1968.          _mesa_error(ctx, GL_INVALID_ENUM,
  1969.                      "glGetFramebufferAttachmentParameterivEXT(target)");
  1970.          return;
  1971.       }
  1972.       buffer = ctx->DrawBuffer;
  1973.       break;
  1974.    case GL_READ_FRAMEBUFFER_EXT:
  1975.       if (!ctx->Extensions.EXT_framebuffer_blit) {
  1976.          _mesa_error(ctx, GL_INVALID_ENUM,
  1977.                      "glGetFramebufferAttachmentParameterivEXT(target)");
  1978.          return;
  1979.       }
  1980.       buffer = ctx->ReadBuffer;
  1981.       break;
  1982. #endif
  1983.    case GL_FRAMEBUFFER_EXT:
  1984.       buffer = ctx->DrawBuffer;
  1985.       break;
  1986.    default:
  1987.       _mesa_error(ctx, GL_INVALID_ENUM,
  1988.                   "glGetFramebufferAttachmentParameterivEXT(target)");
  1989.       return;
  1990.    }
  1991.  
  1992.    if (buffer->Name == 0) {
  1993.       /* the default / window-system FBO */
  1994.       att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
  1995.    }
  1996.    else {
  1997.       /* user-created framebuffer FBO */
  1998.       att = _mesa_get_attachment(ctx, buffer, attachment);
  1999.    }
  2000.  
  2001.    if (att == NULL) {
  2002.       _mesa_error(ctx, GL_INVALID_ENUM,
  2003.                   "glGetFramebufferAttachmentParameterivEXT(attachment)");
  2004.       return;
  2005.    }
  2006.  
  2007.    if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
  2008.       /* the depth and stencil attachments must point to the same buffer */
  2009.       const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
  2010.       depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
  2011.       stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
  2012.       if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
  2013.          _mesa_error(ctx, GL_INVALID_OPERATION,
  2014.                      "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
  2015.                      " attachments differ)");
  2016.          return;
  2017.       }
  2018.    }
  2019.  
  2020.    /* No need to flush here */
  2021.  
  2022.    switch (pname) {
  2023.    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
  2024.       *params = buffer->Name == 0 ? GL_FRAMEBUFFER_DEFAULT : att->Type;
  2025.       return;
  2026.    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
  2027.       if (att->Type == GL_RENDERBUFFER_EXT) {
  2028.          *params = att->Renderbuffer->Name;
  2029.       }
  2030.       else if (att->Type == GL_TEXTURE) {
  2031.          *params = att->Texture->Name;
  2032.       }
  2033.       else {
  2034.          assert(att->Type == GL_NONE);
  2035.          *params = 0;
  2036.       }
  2037.       return;
  2038.    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
  2039.       if (att->Type == GL_TEXTURE) {
  2040.          *params = att->TextureLevel;
  2041.       }
  2042.       else {
  2043.          _mesa_error(ctx, GL_INVALID_ENUM,
  2044.                      "glGetFramebufferAttachmentParameterivEXT(pname)");
  2045.       }
  2046.       return;
  2047.    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
  2048.       if (att->Type == GL_TEXTURE) {
  2049.          if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
  2050.             *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
  2051.          }
  2052.          else {
  2053.             *params = 0;
  2054.          }
  2055.       }
  2056.       else {
  2057.          _mesa_error(ctx, GL_INVALID_ENUM,
  2058.                      "glGetFramebufferAttachmentParameterivEXT(pname)");
  2059.       }
  2060.       return;
  2061.    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
  2062.       if (att->Type == GL_TEXTURE) {
  2063.          if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
  2064.             *params = att->Zoffset;
  2065.          }
  2066.          else {
  2067.             *params = 0;
  2068.          }
  2069.       }
  2070.       else {
  2071.          _mesa_error(ctx, GL_INVALID_ENUM,
  2072.                      "glGetFramebufferAttachmentParameterivEXT(pname)");
  2073.       }
  2074.       return;
  2075.    case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
  2076.       if (!ctx->Extensions.ARB_framebuffer_object) {
  2077.          _mesa_error(ctx, GL_INVALID_ENUM,
  2078.                      "glGetFramebufferAttachmentParameterivEXT(pname)");
  2079.       }
  2080.       else {
  2081.          *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
  2082.       }
  2083.       return;
  2084.    case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
  2085.       if (!ctx->Extensions.ARB_framebuffer_object) {
  2086.          _mesa_error(ctx, GL_INVALID_ENUM,
  2087.                      "glGetFramebufferAttachmentParameterivEXT(pname)");
  2088.          return;
  2089.       }
  2090.       else {
  2091.          gl_format format = att->Renderbuffer->Format;
  2092.          if (format == MESA_FORMAT_CI8 || format == MESA_FORMAT_S8) {
  2093.             /* special cases */
  2094.             *params = GL_INDEX;
  2095.          }
  2096.          else {
  2097.             *params = _mesa_get_format_datatype(format);
  2098.          }
  2099.       }
  2100.       return;
  2101.    case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
  2102.    case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
  2103.    case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
  2104.    case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
  2105.    case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
  2106.    case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
  2107.       if (!ctx->Extensions.ARB_framebuffer_object) {
  2108.          _mesa_error(ctx, GL_INVALID_ENUM,
  2109.                      "glGetFramebufferAttachmentParameterivEXT(pname)");
  2110.       }
  2111.       else if (att->Texture) {
  2112.          const struct gl_texture_image *texImage =
  2113.             _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target,
  2114.                                    att->TextureLevel);
  2115.          if (texImage) {
  2116.             *params = get_component_bits(pname, texImage->_BaseFormat,
  2117.                                          texImage->TexFormat);
  2118.          }
  2119.          else {
  2120.             *params = 0;
  2121.          }
  2122.       }
  2123.       else if (att->Renderbuffer) {
  2124.          *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
  2125.                                       att->Renderbuffer->Format);
  2126.       }
  2127.       else {
  2128.          *params = 0;
  2129.       }
  2130.       return;
  2131.    default:
  2132.       _mesa_error(ctx, GL_INVALID_ENUM,
  2133.                   "glGetFramebufferAttachmentParameterivEXT(pname)");
  2134.       return;
  2135.    }
  2136. }
  2137.  
  2138.  
  2139. void GLAPIENTRY
  2140. _mesa_GenerateMipmapEXT(GLenum target)
  2141. {
  2142.    struct gl_texture_object *texObj;
  2143.    GET_CURRENT_CONTEXT(ctx);
  2144.  
  2145.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  2146.    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
  2147.  
  2148.    switch (target) {
  2149.    case GL_TEXTURE_1D:
  2150.    case GL_TEXTURE_2D:
  2151.    case GL_TEXTURE_3D:
  2152.    case GL_TEXTURE_CUBE_MAP:
  2153.       /* OK, legal value */
  2154.       break;
  2155.    default:
  2156.       /* XXX need to implement GL_TEXTURE_1D_ARRAY and GL_TEXTURE_2D_ARRAY */
  2157.       _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)");
  2158.       return;
  2159.    }
  2160.  
  2161.    texObj = _mesa_get_current_tex_object(ctx, target);
  2162.  
  2163.    if (texObj->BaseLevel >= texObj->MaxLevel) {
  2164.       /* nothing to do */
  2165.       return;
  2166.    }
  2167.  
  2168.    if (texObj->Target == GL_TEXTURE_CUBE_MAP &&
  2169.        !_mesa_cube_complete(texObj)) {
  2170.       _mesa_error(ctx, GL_INVALID_OPERATION,
  2171.                   "glGenerateMipmap(incomplete cube map)");
  2172.       return;
  2173.    }
  2174.  
  2175.    _mesa_lock_texture(ctx, texObj);
  2176.    if (target == GL_TEXTURE_CUBE_MAP) {
  2177.       GLuint face;
  2178.       for (face = 0; face < 6; face++)
  2179.          ctx->Driver.GenerateMipmap(ctx,
  2180.                                     GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,
  2181.                                     texObj);
  2182.    }
  2183.    else {
  2184.       ctx->Driver.GenerateMipmap(ctx, target, texObj);
  2185.    }
  2186.    _mesa_unlock_texture(ctx, texObj);
  2187. }
  2188.  
  2189.  
  2190. #if FEATURE_EXT_framebuffer_blit
  2191.  
  2192. static const struct gl_renderbuffer_attachment *
  2193. find_attachment(const struct gl_framebuffer *fb, const struct gl_renderbuffer *rb)
  2194. {
  2195.    GLuint i;
  2196.    for (i = 0; i < Elements(fb->Attachment); i++) {
  2197.       if (fb->Attachment[i].Renderbuffer == rb)
  2198.          return &fb->Attachment[i];
  2199.    }
  2200.    return NULL;
  2201. }
  2202.  
  2203.  
  2204.  
  2205. /**
  2206.  * Blit rectangular region, optionally from one framebuffer to another.
  2207.  *
  2208.  * Note, if the src buffer is multisampled and the dest is not, this is
  2209.  * when the samples must be resolved to a single color.
  2210.  */
  2211. void GLAPIENTRY
  2212. _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
  2213.                          GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
  2214.                          GLbitfield mask, GLenum filter)
  2215. {
  2216.    const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
  2217.                                      GL_DEPTH_BUFFER_BIT |
  2218.                                      GL_STENCIL_BUFFER_BIT);
  2219.    const struct gl_framebuffer *readFb, *drawFb;
  2220.    const struct gl_renderbuffer *colorReadRb, *colorDrawRb;
  2221.    GET_CURRENT_CONTEXT(ctx);
  2222.  
  2223.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  2224.    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
  2225.  
  2226.    if (ctx->NewState) {
  2227.       _mesa_update_state(ctx);
  2228.    }
  2229.  
  2230.    readFb = ctx->ReadBuffer;
  2231.    drawFb = ctx->DrawBuffer;
  2232.  
  2233.    if (!readFb || !drawFb) {
  2234.       /* This will normally never happen but someday we may want to
  2235.        * support MakeCurrent() with no drawables.
  2236.        */
  2237.       return;
  2238.    }
  2239.  
  2240.    /* check for complete framebuffers */
  2241.    if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
  2242.        readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
  2243.       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
  2244.                   "glBlitFramebufferEXT(incomplete draw/read buffers)");
  2245.       return;
  2246.    }
  2247.  
  2248.    if (filter != GL_NEAREST && filter != GL_LINEAR) {
  2249.       _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)");
  2250.       return;
  2251.    }
  2252.  
  2253.    if (mask & ~legalMaskBits) {
  2254.       _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
  2255.       return;
  2256.    }
  2257.  
  2258.    /* depth/stencil must be blitted with nearest filtering */
  2259.    if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
  2260.         && filter != GL_NEAREST) {
  2261.       _mesa_error(ctx, GL_INVALID_OPERATION,
  2262.              "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter");
  2263.       return;
  2264.    }
  2265.  
  2266.    /* get color read/draw renderbuffers */
  2267.    if (mask & GL_COLOR_BUFFER_BIT) {
  2268.       colorReadRb = readFb->_ColorReadBuffer;
  2269.       colorDrawRb = drawFb->_ColorDrawBuffers[0];
  2270.    }
  2271.    else {
  2272.       colorReadRb = colorDrawRb = NULL;
  2273.    }
  2274.  
  2275.    if (mask & GL_STENCIL_BUFFER_BIT) {
  2276.       struct gl_renderbuffer *readRb = readFb->_StencilBuffer;
  2277.       struct gl_renderbuffer *drawRb = drawFb->_StencilBuffer;
  2278.       if (!readRb ||
  2279.           !drawRb ||
  2280.           _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
  2281.           _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
  2282.          _mesa_error(ctx, GL_INVALID_OPERATION,
  2283.                      "glBlitFramebufferEXT(stencil buffer size mismatch");
  2284.          return;
  2285.       }
  2286.    }
  2287.  
  2288.    if (mask & GL_DEPTH_BUFFER_BIT) {
  2289.       struct gl_renderbuffer *readRb = readFb->_DepthBuffer;
  2290.       struct gl_renderbuffer *drawRb = drawFb->_DepthBuffer;
  2291.       if (!readRb ||
  2292.           !drawRb ||
  2293.           _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
  2294.           _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) {
  2295.          _mesa_error(ctx, GL_INVALID_OPERATION,
  2296.                      "glBlitFramebufferEXT(depth buffer size mismatch");
  2297.          return;
  2298.       }
  2299.    }
  2300.  
  2301.    if (readFb->Visual.samples > 0 &&
  2302.        drawFb->Visual.samples > 0 &&
  2303.        readFb->Visual.samples != drawFb->Visual.samples) {
  2304.       _mesa_error(ctx, GL_INVALID_OPERATION,
  2305.                   "glBlitFramebufferEXT(mismatched samples");
  2306.       return;
  2307.    }
  2308.  
  2309.    /* extra checks for multisample copies... */
  2310.    if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
  2311.       /* src and dest region sizes must be the same */
  2312.       if (srcX1 - srcX0 != dstX1 - dstX0 ||
  2313.           srcY1 - srcY0 != dstY1 - dstY0) {
  2314.          _mesa_error(ctx, GL_INVALID_OPERATION,
  2315.                 "glBlitFramebufferEXT(bad src/dst multisample region sizes");
  2316.          return;
  2317.       }
  2318.  
  2319.       /* color formats must match */
  2320.       if (colorReadRb &&
  2321.           colorDrawRb &&
  2322.           colorReadRb->Format != colorDrawRb->Format) {
  2323.          _mesa_error(ctx, GL_INVALID_OPERATION,
  2324.                 "glBlitFramebufferEXT(bad src/dst multisample pixel formats");
  2325.          return;
  2326.       }
  2327.    }
  2328.  
  2329.    if (!ctx->Extensions.EXT_framebuffer_blit) {
  2330.       _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
  2331.       return;
  2332.    }
  2333.  
  2334.    /* Debug code */
  2335.    if (DEBUG_BLIT) {
  2336.       printf("glBlitFramebuffer(%d, %d, %d, %d,  %d, %d, %d, %d,"
  2337.              " 0x%x, 0x%x)\n",
  2338.              srcX0, srcY0, srcX1, srcY1,
  2339.              dstX0, dstY0, dstX1, dstY1,
  2340.              mask, filter);
  2341.       if (colorReadRb) {
  2342.          const struct gl_renderbuffer_attachment *att;
  2343.  
  2344.          att = find_attachment(readFb, colorReadRb);
  2345.          printf("  Src FBO %u  RB %u (%dx%d)  ",
  2346.                 readFb->Name, colorReadRb->Name,
  2347.                 colorReadRb->Width, colorReadRb->Height);
  2348.          if (att && att->Texture) {
  2349.             printf("Tex %u  tgt 0x%x  level %u  face %u",
  2350.                    att->Texture->Name,
  2351.                    att->Texture->Target,
  2352.                    att->TextureLevel,
  2353.                    att->CubeMapFace);
  2354.          }
  2355.          printf("\n");
  2356.  
  2357.          att = find_attachment(drawFb, colorDrawRb);
  2358.          printf("  Dst FBO %u  RB %u (%dx%d)  ",
  2359.                 drawFb->Name, colorDrawRb->Name,
  2360.                 colorDrawRb->Width, colorDrawRb->Height);
  2361.          if (att && att->Texture) {
  2362.             printf("Tex %u  tgt 0x%x  level %u  face %u",
  2363.                    att->Texture->Name,
  2364.                    att->Texture->Target,
  2365.                    att->TextureLevel,
  2366.                    att->CubeMapFace);
  2367.          }
  2368.          printf("\n");
  2369.       }
  2370.    }
  2371.  
  2372.    ASSERT(ctx->Driver.BlitFramebuffer);
  2373.    ctx->Driver.BlitFramebuffer(ctx,
  2374.                                srcX0, srcY0, srcX1, srcY1,
  2375.                                dstX0, dstY0, dstX1, dstY1,
  2376.                                mask, filter);
  2377. }
  2378. #endif /* FEATURE_EXT_framebuffer_blit */
  2379.  
  2380. #if FEATURE_ARB_geometry_shader4
  2381. void GLAPIENTRY
  2382. _mesa_FramebufferTextureARB(GLenum target, GLenum attachment,
  2383.                             GLuint texture, GLint level)
  2384. {
  2385.    GET_CURRENT_CONTEXT(ctx);
  2386.    _mesa_error(ctx, GL_INVALID_OPERATION,
  2387.                "glFramebufferTextureARB "
  2388.                "not implemented!");
  2389. }
  2390.  
  2391. void GLAPIENTRY
  2392. _mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment,
  2393.                                 GLuint texture, GLint level, GLenum face)
  2394. {
  2395.    GET_CURRENT_CONTEXT(ctx);
  2396.    _mesa_error(ctx, GL_INVALID_OPERATION,
  2397.                "glFramebufferTextureFaceARB "
  2398.                "not implemented!");
  2399. }
  2400. #endif /* FEATURE_ARB_geometry_shader4 */
  2401.