ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fbobject.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  7.1
00004  *
00005  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 
00026 /*
00027  * Authors:
00028  *   Brian Paul
00029  */
00030 
00031 
00032 #include "buffers.h"
00033 #include "context.h"
00034 #include "fbobject.h"
00035 #include "framebuffer.h"
00036 #include "hash.h"
00037 #include "mipmap.h"
00038 #include "renderbuffer.h"
00039 #include "state.h"
00040 #include "teximage.h"
00041 #include "texobj.h"
00042 #include "texstore.h"
00043 
00044 
00054 /*
00055  * When glGenRender/FramebuffersEXT() is called we insert pointers to
00056  * these placeholder objects into the hash table.
00057  * Later, when the object ID is first bound, we replace the placeholder
00058  * with the real frame/renderbuffer.
00059  */
00060 static struct gl_framebuffer DummyFramebuffer;
00061 static struct gl_renderbuffer DummyRenderbuffer;
00062 
00063 
00064 #define IS_CUBE_FACE(TARGET) \
00065    ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \
00066     (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
00067 
00068 
00069 static void
00070 delete_dummy_renderbuffer(struct gl_renderbuffer *rb)
00071 {
00072    /* no op */
00073 }
00074 
00075 static void
00076 delete_dummy_framebuffer(struct gl_framebuffer *fb)
00077 {
00078    /* no op */
00079 }
00080 
00081 
00082 void
00083 _mesa_init_fbobjects(GLcontext *ctx)
00084 {
00085    DummyFramebuffer.Delete = delete_dummy_framebuffer;
00086    DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
00087 }
00088 
00089 
00093 struct gl_renderbuffer *
00094 _mesa_lookup_renderbuffer(GLcontext *ctx, GLuint id)
00095 {
00096    struct gl_renderbuffer *rb;
00097 
00098    if (id == 0)
00099       return NULL;
00100 
00101    rb = (struct gl_renderbuffer *)
00102       _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
00103    return rb;
00104 }
00105 
00106 
00110 struct gl_framebuffer *
00111 _mesa_lookup_framebuffer(GLcontext *ctx, GLuint id)
00112 {
00113    struct gl_framebuffer *fb;
00114 
00115    if (id == 0)
00116       return NULL;
00117 
00118    fb = (struct gl_framebuffer *)
00119       _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
00120    return fb;
00121 }
00122 
00123 
00128 struct gl_renderbuffer_attachment *
00129 _mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
00130                      GLenum attachment)
00131 {
00132    GLuint i;
00133 
00134    switch (attachment) {
00135    case GL_COLOR_ATTACHMENT0_EXT:
00136    case GL_COLOR_ATTACHMENT1_EXT:
00137    case GL_COLOR_ATTACHMENT2_EXT:
00138    case GL_COLOR_ATTACHMENT3_EXT:
00139    case GL_COLOR_ATTACHMENT4_EXT:
00140    case GL_COLOR_ATTACHMENT5_EXT:
00141    case GL_COLOR_ATTACHMENT6_EXT:
00142    case GL_COLOR_ATTACHMENT7_EXT:
00143    case GL_COLOR_ATTACHMENT8_EXT:
00144    case GL_COLOR_ATTACHMENT9_EXT:
00145    case GL_COLOR_ATTACHMENT10_EXT:
00146    case GL_COLOR_ATTACHMENT11_EXT:
00147    case GL_COLOR_ATTACHMENT12_EXT:
00148    case GL_COLOR_ATTACHMENT13_EXT:
00149    case GL_COLOR_ATTACHMENT14_EXT:
00150    case GL_COLOR_ATTACHMENT15_EXT:
00151       i = attachment - GL_COLOR_ATTACHMENT0_EXT;
00152       if (i >= ctx->Const.MaxColorAttachments) {
00153      return NULL;
00154       }
00155       return &fb->Attachment[BUFFER_COLOR0 + i];
00156    case GL_DEPTH_ATTACHMENT_EXT:
00157       return &fb->Attachment[BUFFER_DEPTH];
00158    case GL_STENCIL_ATTACHMENT_EXT:
00159       return &fb->Attachment[BUFFER_STENCIL];
00160    default:
00161       return NULL;
00162    }
00163 }
00164 
00165 
00170 void
00171 _mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
00172 {
00173    if (att->Type == GL_TEXTURE) {
00174       ASSERT(att->Texture);
00175       if (ctx->Driver.FinishRenderTexture) {
00176          /* tell driver we're done rendering to this texobj */
00177          ctx->Driver.FinishRenderTexture(ctx, att);
00178       }
00179       _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
00180       ASSERT(!att->Texture);
00181    }
00182    if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
00183       ASSERT(!att->Texture);
00184       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
00185       ASSERT(!att->Renderbuffer);
00186    }
00187    att->Type = GL_NONE;
00188    att->Complete = GL_TRUE;
00189 }
00190 
00191 
00196 void
00197 _mesa_set_texture_attachment(GLcontext *ctx,
00198                              struct gl_framebuffer *fb,
00199                              struct gl_renderbuffer_attachment *att,
00200                              struct gl_texture_object *texObj,
00201                              GLenum texTarget, GLuint level, GLuint zoffset)
00202 {
00203    if (att->Texture == texObj) {
00204       /* re-attaching same texture */
00205       ASSERT(att->Type == GL_TEXTURE);
00206    }
00207    else {
00208       /* new attachment */
00209       _mesa_remove_attachment(ctx, att);
00210       att->Type = GL_TEXTURE;
00211       assert(!att->Texture);
00212       _mesa_reference_texobj(&att->Texture, texObj);
00213    }
00214 
00215    /* always update these fields */
00216    att->TextureLevel = level;
00217    if (IS_CUBE_FACE(texTarget)) {
00218       att->CubeMapFace = texTarget - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
00219    }
00220    else {
00221       att->CubeMapFace = 0;
00222    }
00223    att->Zoffset = zoffset;
00224    att->Complete = GL_FALSE;
00225 
00226    if (att->Texture->Image[att->CubeMapFace][att->TextureLevel]) {
00227       ctx->Driver.RenderTexture(ctx, fb, att);
00228    }
00229 }
00230 
00231 
00236 void
00237 _mesa_set_renderbuffer_attachment(GLcontext *ctx,
00238                                   struct gl_renderbuffer_attachment *att,
00239                                   struct gl_renderbuffer *rb)
00240 {
00241    /* XXX check if re-doing same attachment, exit early */
00242    _mesa_remove_attachment(ctx, att);
00243    att->Type = GL_RENDERBUFFER_EXT;
00244    att->Texture = NULL; /* just to be safe */
00245    att->Complete = GL_FALSE;
00246    _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
00247 }
00248 
00249 
00254 void
00255 _mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
00256                                GLenum attachment, struct gl_renderbuffer *rb)
00257 {
00258    struct gl_renderbuffer_attachment *att;
00259 
00260    _glthread_LOCK_MUTEX(fb->Mutex);
00261 
00262    att = _mesa_get_attachment(ctx, fb, attachment);
00263    ASSERT(att);
00264    if (rb) {
00265       _mesa_set_renderbuffer_attachment(ctx, att, rb);
00266    }
00267    else {
00268       _mesa_remove_attachment(ctx, att);
00269    }
00270 
00271    _glthread_UNLOCK_MUTEX(fb->Mutex);
00272 }
00273 
00274 
00281 static void
00282 test_attachment_completeness(const GLcontext *ctx, GLenum format,
00283                              struct gl_renderbuffer_attachment *att)
00284 {
00285    assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
00286 
00287    /* assume complete */
00288    att->Complete = GL_TRUE;
00289 
00290    /* Look for reasons why the attachment might be incomplete */
00291    if (att->Type == GL_TEXTURE) {
00292       const struct gl_texture_object *texObj = att->Texture;
00293       struct gl_texture_image *texImage;
00294 
00295       if (!texObj) {
00296          att->Complete = GL_FALSE;
00297          return;
00298       }
00299 
00300       texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
00301       if (!texImage) {
00302          att->Complete = GL_FALSE;
00303          return;
00304       }
00305       if (texImage->Width < 1 || texImage->Height < 1) {
00306          att->Complete = GL_FALSE;
00307          return;
00308       }
00309       if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) {
00310          att->Complete = GL_FALSE;
00311          return;
00312       }
00313 
00314       if (format == GL_COLOR) {
00315          if (texImage->TexFormat->BaseFormat != GL_RGB &&
00316              texImage->TexFormat->BaseFormat != GL_RGBA) {
00317             att->Complete = GL_FALSE;
00318             return;
00319          }
00320       }
00321       else if (format == GL_DEPTH) {
00322          if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
00323             /* OK */
00324          }
00325          else if (ctx->Extensions.EXT_packed_depth_stencil &&
00326                   texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
00327             /* OK */
00328          }
00329          else {
00330             att->Complete = GL_FALSE;
00331             return;
00332          }
00333       }
00334       else {
00335          /* no such thing as stencil textures */
00336          att->Complete = GL_FALSE;
00337          return;
00338       }
00339    }
00340    else if (att->Type == GL_RENDERBUFFER_EXT) {
00341       ASSERT(att->Renderbuffer);
00342       if (!att->Renderbuffer->InternalFormat ||
00343           att->Renderbuffer->Width < 1 ||
00344           att->Renderbuffer->Height < 1) {
00345          att->Complete = GL_FALSE;
00346          return;
00347       }
00348       if (format == GL_COLOR) {
00349          if (att->Renderbuffer->_BaseFormat != GL_RGB &&
00350              att->Renderbuffer->_BaseFormat != GL_RGBA) {
00351             ASSERT(att->Renderbuffer->RedBits);
00352             ASSERT(att->Renderbuffer->GreenBits);
00353             ASSERT(att->Renderbuffer->BlueBits);
00354             att->Complete = GL_FALSE;
00355             return;
00356          }
00357       }
00358       else if (format == GL_DEPTH) {
00359          ASSERT(att->Renderbuffer->DepthBits);
00360          if (att->Renderbuffer->_BaseFormat == GL_DEPTH_COMPONENT) {
00361             /* OK */
00362          }
00363          else if (ctx->Extensions.EXT_packed_depth_stencil &&
00364                   att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
00365             /* OK */
00366          }
00367          else {
00368             att->Complete = GL_FALSE;
00369             return;
00370          }
00371       }
00372       else {
00373          assert(format == GL_STENCIL);
00374          ASSERT(att->Renderbuffer->StencilBits);
00375          if (att->Renderbuffer->_BaseFormat == GL_STENCIL_INDEX) {
00376             /* OK */
00377          }
00378          else if (ctx->Extensions.EXT_packed_depth_stencil &&
00379                   att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
00380             /* OK */
00381          }
00382          else {
00383             att->Complete = GL_FALSE;
00384             return;
00385          }
00386       }
00387    }
00388    else {
00389       ASSERT(att->Type == GL_NONE);
00390       /* complete */
00391       return;
00392    }
00393 }
00394 
00395 
00399 static void
00400 fbo_incomplete(const char *msg, int index)
00401 {
00402    (void) msg;
00403    (void) index;
00404    /*
00405    _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
00406    */
00407 }
00408 
00409 
00416 void
00417 _mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
00418 {
00419    GLuint numImages, width = 0, height = 0;
00420    GLenum intFormat = GL_NONE;
00421    GLuint w = 0, h = 0;
00422    GLint i;
00423    GLuint j;
00424 
00425    assert(fb->Name != 0);
00426 
00427    numImages = 0;
00428    fb->Width = 0;
00429    fb->Height = 0;
00430 
00431    /* Start at -2 to more easily loop over all attachment points */
00432    for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
00433       struct gl_renderbuffer_attachment *att;
00434       GLenum f;
00435 
00436       if (i == -2) {
00437          att = &fb->Attachment[BUFFER_DEPTH];
00438          test_attachment_completeness(ctx, GL_DEPTH, att);
00439          if (!att->Complete) {
00440             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
00441             fbo_incomplete("depth attachment incomplete", -1);
00442             return;
00443          }
00444       }
00445       else if (i == -1) {
00446          att = &fb->Attachment[BUFFER_STENCIL];
00447          test_attachment_completeness(ctx, GL_STENCIL, att);
00448          if (!att->Complete) {
00449             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
00450             fbo_incomplete("stencil attachment incomplete", -1);
00451             return;
00452          }
00453       }
00454       else {
00455          att = &fb->Attachment[BUFFER_COLOR0 + i];
00456          test_attachment_completeness(ctx, GL_COLOR, att);
00457          if (!att->Complete) {
00458             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
00459             fbo_incomplete("color attachment incomplete", i);
00460             return;
00461          }
00462       }
00463 
00464       if (att->Type == GL_TEXTURE) {
00465          const struct gl_texture_image *texImg
00466             = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
00467          w = texImg->Width;
00468          h = texImg->Height;
00469          f = texImg->_BaseFormat;
00470          numImages++;
00471          if (f != GL_RGB && f != GL_RGBA && f != GL_DEPTH_COMPONENT
00472              && f != GL_DEPTH_STENCIL_EXT) {
00473             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
00474             fbo_incomplete("texture attachment incomplete", -1);
00475             return;
00476          }
00477       }
00478       else if (att->Type == GL_RENDERBUFFER_EXT) {
00479          w = att->Renderbuffer->Width;
00480          h = att->Renderbuffer->Height;
00481          f = att->Renderbuffer->InternalFormat;
00482          numImages++;
00483       }
00484       else {
00485          assert(att->Type == GL_NONE);
00486          continue;
00487       }
00488 
00489       if (numImages == 1) {
00490          /* set required width, height and format */
00491          width = w;
00492          height = h;
00493          if (i >= 0)
00494             intFormat = f;
00495       }
00496       else {
00497          /* check that width, height, format are same */
00498          if (w != width || h != height) {
00499             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
00500             fbo_incomplete("width or height mismatch", -1);
00501             return;
00502          }
00503          if (intFormat != GL_NONE && f != intFormat) {
00504             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
00505             fbo_incomplete("format mismatch", -1);
00506             return;
00507          }
00508       }
00509    }
00510 
00511 #ifndef FEATURE_OES_framebuffer_object
00512    /* Check that all DrawBuffers are present */
00513    for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
00514       if (fb->ColorDrawBuffer[j] != GL_NONE) {
00515          const struct gl_renderbuffer_attachment *att
00516             = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
00517          assert(att);
00518          if (att->Type == GL_NONE) {
00519             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
00520             fbo_incomplete("missing drawbuffer", j);
00521             return;
00522          }
00523       }
00524    }
00525 
00526    /* Check that the ReadBuffer is present */
00527    if (fb->ColorReadBuffer != GL_NONE) {
00528       const struct gl_renderbuffer_attachment *att
00529          = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
00530       assert(att);
00531       if (att->Type == GL_NONE) {
00532          fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
00533             fbo_incomplete("missing readbuffer", -1);
00534          return;
00535       }
00536    }
00537 #endif
00538 
00539    if (numImages == 0) {
00540       fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
00541       fbo_incomplete("no attachments", -1);
00542       return;
00543    }
00544 
00545    /*
00546     * If we get here, the framebuffer is complete!
00547     */
00548    fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
00549    fb->Width = w;
00550    fb->Height = h;
00551 }
00552 
00553 
00554 GLboolean GLAPIENTRY
00555 _mesa_IsRenderbufferEXT(GLuint renderbuffer)
00556 {
00557    GET_CURRENT_CONTEXT(ctx);
00558    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
00559    if (renderbuffer) {
00560       struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
00561       if (rb != NULL && rb != &DummyRenderbuffer)
00562          return GL_TRUE;
00563    }
00564    return GL_FALSE;
00565 }
00566 
00567 
00568 void GLAPIENTRY
00569 _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
00570 {
00571    struct gl_renderbuffer *newRb;
00572    GET_CURRENT_CONTEXT(ctx);
00573 
00574    ASSERT_OUTSIDE_BEGIN_END(ctx);
00575 
00576    if (target != GL_RENDERBUFFER_EXT) {
00577          _mesa_error(ctx, GL_INVALID_ENUM,
00578                   "glBindRenderbufferEXT(target)");
00579       return;
00580    }
00581 
00582    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
00583    /* The above doesn't fully flush the drivers in the way that a
00584     * glFlush does, but that is required here:
00585     */
00586    if (ctx->Driver.Flush)
00587       ctx->Driver.Flush(ctx);
00588 
00589 
00590    if (renderbuffer) {
00591       newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
00592       if (newRb == &DummyRenderbuffer) {
00593          /* ID was reserved, but no real renderbuffer object made yet */
00594          newRb = NULL;
00595       }
00596       if (!newRb) {
00597      /* create new renderbuffer object */
00598      newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
00599      if (!newRb) {
00600         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
00601         return;
00602      }
00603          ASSERT(newRb->AllocStorage);
00604          _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
00605          newRb->RefCount = 1; /* referenced by hash table */
00606       }
00607    }
00608    else {
00609       newRb = NULL;
00610    }
00611 
00612    ASSERT(newRb != &DummyRenderbuffer);
00613 
00614    _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
00615 }
00616 
00617 
00618 void GLAPIENTRY
00619 _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
00620 {
00621    GLint i;
00622    GET_CURRENT_CONTEXT(ctx);
00623 
00624    ASSERT_OUTSIDE_BEGIN_END(ctx);
00625    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
00626 
00627    for (i = 0; i < n; i++) {
00628       if (renderbuffers[i] > 0) {
00629      struct gl_renderbuffer *rb;
00630      rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
00631      if (rb) {
00632             /* check if deleting currently bound renderbuffer object */
00633             if (rb == ctx->CurrentRenderbuffer) {
00634                /* bind default */
00635                ASSERT(rb->RefCount >= 2);
00636                _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
00637             }
00638 
00639         /* Remove from hash table immediately, to free the ID.
00640              * But the object will not be freed until it's no longer
00641              * referenced anywhere else.
00642              */
00643         _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
00644 
00645             if (rb != &DummyRenderbuffer) {
00646                /* no longer referenced by hash table */
00647                _mesa_reference_renderbuffer(&rb, NULL);
00648         }
00649      }
00650       }
00651    }
00652 }
00653 
00654 
00655 void GLAPIENTRY
00656 _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
00657 {
00658    GET_CURRENT_CONTEXT(ctx);
00659    GLuint first;
00660    GLint i;
00661 
00662    ASSERT_OUTSIDE_BEGIN_END(ctx);
00663 
00664    if (n < 0) {
00665       _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
00666       return;
00667    }
00668 
00669    if (!renderbuffers)
00670       return;
00671 
00672    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
00673 
00674    for (i = 0; i < n; i++) {
00675       GLuint name = first + i;
00676       renderbuffers[i] = name;
00677       /* insert dummy placeholder into hash table */
00678       _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
00679       _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
00680       _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
00681    }
00682 }
00683 
00684 
00694 GLenum
00695 _mesa_base_fbo_format(GLcontext *ctx, GLenum internalFormat)
00696 {
00697    switch (internalFormat) {
00698    case GL_RGB:
00699    case GL_R3_G3_B2:
00700    case GL_RGB4:
00701    case GL_RGB5:
00702    case GL_RGB8:
00703    case GL_RGB10:
00704    case GL_RGB12:
00705    case GL_RGB16:
00706       return GL_RGB;
00707    case GL_RGBA:
00708    case GL_RGBA2:
00709    case GL_RGBA4:
00710    case GL_RGB5_A1:
00711    case GL_RGBA8:
00712    case GL_RGB10_A2:
00713    case GL_RGBA12:
00714    case GL_RGBA16:
00715       return GL_RGBA;
00716    case GL_STENCIL_INDEX:
00717    case GL_STENCIL_INDEX1_EXT:
00718    case GL_STENCIL_INDEX4_EXT:
00719    case GL_STENCIL_INDEX8_EXT:
00720    case GL_STENCIL_INDEX16_EXT:
00721       return GL_STENCIL_INDEX;
00722    case GL_DEPTH_COMPONENT:
00723    case GL_DEPTH_COMPONENT16:
00724    case GL_DEPTH_COMPONENT24:
00725    case GL_DEPTH_COMPONENT32:
00726       return GL_DEPTH_COMPONENT;
00727    case GL_DEPTH_STENCIL_EXT:
00728    case GL_DEPTH24_STENCIL8_EXT:
00729       if (ctx->Extensions.EXT_packed_depth_stencil)
00730          return GL_DEPTH_STENCIL_EXT;
00731       else
00732          return 0;
00733    /* XXX add floating point formats eventually */
00734    default:
00735       return 0;
00736    }
00737 }
00738 
00739 
00740 void GLAPIENTRY
00741 _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
00742                              GLsizei width, GLsizei height)
00743 {
00744    struct gl_renderbuffer *rb;
00745    GLenum baseFormat;
00746    GET_CURRENT_CONTEXT(ctx);
00747 
00748    ASSERT_OUTSIDE_BEGIN_END(ctx);
00749 
00750    if (target != GL_RENDERBUFFER_EXT) {
00751       _mesa_error(ctx, GL_INVALID_ENUM, "glRenderbufferStorageEXT(target)");
00752       return;
00753    }
00754 
00755    baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
00756    if (baseFormat == 0) {
00757       _mesa_error(ctx, GL_INVALID_ENUM,
00758                   "glRenderbufferStorageEXT(internalFormat)");
00759       return;
00760    }
00761 
00762    if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
00763       _mesa_error(ctx, GL_INVALID_VALUE, "glRenderbufferStorageEXT(width)");
00764       return;
00765    }
00766 
00767    if (height < 1 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
00768       _mesa_error(ctx, GL_INVALID_VALUE, "glRenderbufferStorageEXT(height)");
00769       return;
00770    }
00771 
00772    rb = ctx->CurrentRenderbuffer;
00773 
00774    if (!rb) {
00775       _mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferStorageEXT");
00776       return;
00777    }
00778 
00779    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
00780 
00781    if (rb->InternalFormat == internalFormat &&
00782        rb->Width == (GLuint) width &&
00783        rb->Height == (GLuint) height) {
00784       /* no change in allocation needed */
00785       return;
00786    }
00787 
00788    /* These MUST get set by the AllocStorage func */
00789    rb->_ActualFormat = 0;
00790    rb->RedBits =
00791    rb->GreenBits =
00792    rb->BlueBits =
00793    rb->AlphaBits =
00794    rb->IndexBits =
00795    rb->DepthBits =
00796    rb->StencilBits = 0;
00797 
00798    /* Now allocate the storage */
00799    ASSERT(rb->AllocStorage);
00800    if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
00801       /* No error - check/set fields now */
00802       assert(rb->_ActualFormat);
00803       assert(rb->Width == (GLuint) width);
00804       assert(rb->Height == (GLuint) height);
00805       assert(rb->RedBits || rb->GreenBits || rb->BlueBits || rb->AlphaBits ||
00806              rb->DepthBits || rb->StencilBits || rb->IndexBits);
00807       rb->InternalFormat = internalFormat;
00808       rb->_BaseFormat = baseFormat;
00809    }
00810    else {
00811       /* Probably ran out of memory - clear the fields */
00812       rb->Width = 0;
00813       rb->Height = 0;
00814       rb->InternalFormat = GL_NONE;
00815       rb->_ActualFormat = GL_NONE;
00816       rb->_BaseFormat = GL_NONE;
00817       rb->RedBits =
00818       rb->GreenBits =
00819       rb->BlueBits =
00820       rb->AlphaBits =
00821       rb->IndexBits =
00822       rb->DepthBits =
00823       rb->StencilBits = 0;
00824    }
00825 
00826    /*
00827    test_framebuffer_completeness(ctx, fb);
00828    */
00829    /* XXX if this renderbuffer is attached anywhere, invalidate attachment
00830     * points???
00831     */
00832 }
00833 
00834 
00835 void GLAPIENTRY
00836 _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
00837 {
00838    GET_CURRENT_CONTEXT(ctx);
00839 
00840    ASSERT_OUTSIDE_BEGIN_END(ctx);
00841 
00842    if (target != GL_RENDERBUFFER_EXT) {
00843       _mesa_error(ctx, GL_INVALID_ENUM,
00844                   "glGetRenderbufferParameterivEXT(target)");
00845       return;
00846    }
00847 
00848    if (!ctx->CurrentRenderbuffer) {
00849       _mesa_error(ctx, GL_INVALID_OPERATION,
00850                   "glGetRenderbufferParameterivEXT");
00851       return;
00852    }
00853 
00854    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
00855 
00856    switch (pname) {
00857    case GL_RENDERBUFFER_WIDTH_EXT:
00858       *params = ctx->CurrentRenderbuffer->Width;
00859       return;
00860    case GL_RENDERBUFFER_HEIGHT_EXT:
00861       *params = ctx->CurrentRenderbuffer->Height;
00862       return;
00863    case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
00864       *params = ctx->CurrentRenderbuffer->InternalFormat;
00865       return;
00866    case GL_RENDERBUFFER_RED_SIZE_EXT:
00867       *params = ctx->CurrentRenderbuffer->RedBits;
00868       break;
00869    case GL_RENDERBUFFER_GREEN_SIZE_EXT:
00870       *params = ctx->CurrentRenderbuffer->GreenBits;
00871       break;
00872    case GL_RENDERBUFFER_BLUE_SIZE_EXT:
00873       *params = ctx->CurrentRenderbuffer->BlueBits;
00874       break;
00875    case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
00876       *params = ctx->CurrentRenderbuffer->AlphaBits;
00877       break;
00878    case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
00879       *params = ctx->CurrentRenderbuffer->DepthBits;
00880       break;
00881    case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
00882       *params = ctx->CurrentRenderbuffer->StencilBits;
00883       break;
00884    default:
00885       _mesa_error(ctx, GL_INVALID_ENUM,
00886                   "glGetRenderbufferParameterivEXT(target)");
00887       return;
00888    }
00889 }
00890 
00891 
00892 GLboolean GLAPIENTRY
00893 _mesa_IsFramebufferEXT(GLuint framebuffer)
00894 {
00895    GET_CURRENT_CONTEXT(ctx);
00896    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
00897    if (framebuffer) {
00898       struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
00899       if (rb != NULL && rb != &DummyFramebuffer)
00900          return GL_TRUE;
00901    }
00902    return GL_FALSE;
00903 }
00904 
00905 
00906 static void
00907 check_begin_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
00908 {
00909    GLuint i;
00910    ASSERT(ctx->Driver.RenderTexture);
00911    for (i = 0; i < BUFFER_COUNT; i++) {
00912       struct gl_renderbuffer_attachment *att = fb->Attachment + i;
00913       struct gl_texture_object *texObj = att->Texture;
00914       if (texObj
00915           && att->Texture->Image[att->CubeMapFace][att->TextureLevel]) {
00916          ctx->Driver.RenderTexture(ctx, fb, att);
00917       }
00918    }
00919 }
00920 
00921 
00927 static void
00928 check_end_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
00929 {
00930    if (ctx->Driver.FinishRenderTexture) {
00931       GLuint i;
00932       for (i = 0; i < BUFFER_COUNT; i++) {
00933          struct gl_renderbuffer_attachment *att = fb->Attachment + i;
00934          if (att->Texture && att->Renderbuffer) {
00935             ctx->Driver.FinishRenderTexture(ctx, att);
00936          }
00937       }
00938    }
00939 }
00940 
00941 
00942 void GLAPIENTRY
00943 _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
00944 {
00945    struct gl_framebuffer *newFb, *newFbread;
00946    GLboolean bindReadBuf, bindDrawBuf;
00947    GET_CURRENT_CONTEXT(ctx);
00948 
00949    ASSERT_OUTSIDE_BEGIN_END(ctx);
00950 
00951    if (!ctx->Extensions.EXT_framebuffer_object) {
00952       _mesa_error(ctx, GL_INVALID_OPERATION,
00953                   "glBindFramebufferEXT(unsupported)");
00954       return;
00955    }
00956 
00957    switch (target) {
00958 #if FEATURE_EXT_framebuffer_blit
00959    case GL_DRAW_FRAMEBUFFER_EXT:
00960       if (!ctx->Extensions.EXT_framebuffer_blit) {
00961          _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
00962          return;
00963       }
00964       bindDrawBuf = GL_TRUE;
00965       bindReadBuf = GL_FALSE;
00966       break;
00967    case GL_READ_FRAMEBUFFER_EXT:
00968       if (!ctx->Extensions.EXT_framebuffer_blit) {
00969          _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
00970          return;
00971       }
00972       bindDrawBuf = GL_FALSE;
00973       bindReadBuf = GL_TRUE;
00974       break;
00975 #endif
00976    case GL_FRAMEBUFFER_EXT:
00977       bindDrawBuf = GL_TRUE;
00978       bindReadBuf = GL_TRUE;
00979       break;
00980    default:
00981       _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
00982       return;
00983    }
00984 
00985    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
00986 
00987    if (ctx->Driver.Flush) {  
00988       ctx->Driver.Flush(ctx);
00989    }
00990 
00991    if (framebuffer) {
00992       /* Binding a user-created framebuffer object */
00993       newFb = _mesa_lookup_framebuffer(ctx, framebuffer);
00994       if (newFb == &DummyFramebuffer) {
00995          /* ID was reserved, but no real framebuffer object made yet */
00996          newFb = NULL;
00997       }
00998       if (!newFb) {
00999      /* create new framebuffer object */
01000      newFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
01001      if (!newFb) {
01002         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
01003         return;
01004      }
01005          _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb);
01006       }
01007       newFbread = newFb;
01008    }
01009    else {
01010       /* Binding the window system framebuffer (which was originally set
01011        * with MakeCurrent).
01012        */
01013       newFb = ctx->WinSysDrawBuffer;
01014       newFbread = ctx->WinSysReadBuffer;
01015    }
01016 
01017    ASSERT(newFb);
01018    ASSERT(newFb != &DummyFramebuffer);
01019 
01020    /*
01021     * XXX check if re-binding same buffer and skip some of this code.
01022     */
01023 
01024    if (bindReadBuf) {
01025       _mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread);
01026    }
01027 
01028    if (bindDrawBuf) {
01029       /* check if old FB had any texture attachments */
01030       check_end_texture_render(ctx, ctx->DrawBuffer);
01031 
01032       /* check if time to delete this framebuffer */
01033       _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb);
01034 
01035       if (newFb->Name != 0) {
01036          /* check if newly bound framebuffer has any texture attachments */
01037          check_begin_texture_render(ctx, newFb);
01038       }
01039    }
01040 
01041    if (ctx->Driver.BindFramebuffer) {
01042       ctx->Driver.BindFramebuffer(ctx, target, newFb, newFbread);
01043    }
01044 }
01045 
01046 
01047 void GLAPIENTRY
01048 _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
01049 {
01050    GLint i;
01051    GET_CURRENT_CONTEXT(ctx);
01052 
01053    ASSERT_OUTSIDE_BEGIN_END(ctx);
01054    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
01055    /* The above doesn't fully flush the drivers in the way that a
01056     * glFlush does, but that is required here:
01057     */
01058    if (ctx->Driver.Flush)
01059       ctx->Driver.Flush(ctx);
01060 
01061    for (i = 0; i < n; i++) {
01062       if (framebuffers[i] > 0) {
01063      struct gl_framebuffer *fb;
01064      fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
01065      if (fb) {
01066             ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
01067 
01068             /* check if deleting currently bound framebuffer object */
01069             if (fb == ctx->DrawBuffer) {
01070                /* bind default */
01071                ASSERT(fb->RefCount >= 2);
01072                _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
01073             }
01074 
01075         /* remove from hash table immediately, to free the ID */
01076         _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
01077 
01078             if (fb != &DummyFramebuffer) {
01079                /* But the object will not be freed until it's no longer
01080                 * bound in any context.
01081                 */
01082                _mesa_unreference_framebuffer(&fb);
01083         }
01084      }
01085       }
01086    }
01087 }
01088 
01089 
01090 void GLAPIENTRY
01091 _mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers)
01092 {
01093    GET_CURRENT_CONTEXT(ctx);
01094    GLuint first;
01095    GLint i;
01096 
01097    ASSERT_OUTSIDE_BEGIN_END(ctx);
01098 
01099    if (n < 0) {
01100       _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
01101       return;
01102    }
01103 
01104    if (!framebuffers)
01105       return;
01106 
01107    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
01108 
01109    for (i = 0; i < n; i++) {
01110       GLuint name = first + i;
01111       framebuffers[i] = name;
01112       /* insert dummy placeholder into hash table */
01113       _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
01114       _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
01115       _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
01116    }
01117 }
01118 
01119 
01120 
01121 GLenum GLAPIENTRY
01122 _mesa_CheckFramebufferStatusEXT(GLenum target)
01123 {
01124    struct gl_framebuffer *buffer;
01125    GET_CURRENT_CONTEXT(ctx);
01126 
01127    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
01128 
01129    switch (target) {
01130 #if FEATURE_EXT_framebuffer_blit
01131    case GL_DRAW_FRAMEBUFFER_EXT:
01132       if (!ctx->Extensions.EXT_framebuffer_blit) {
01133          _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
01134          return 0;
01135       }
01136       buffer = ctx->DrawBuffer;
01137       break;
01138    case GL_READ_FRAMEBUFFER_EXT:
01139       if (!ctx->Extensions.EXT_framebuffer_blit) {
01140          _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
01141          return 0;
01142       }
01143       buffer = ctx->ReadBuffer;
01144       break;
01145 #endif
01146    case GL_FRAMEBUFFER_EXT:
01147       buffer = ctx->DrawBuffer;
01148       break;
01149    default:
01150       _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
01151       return 0; /* formerly GL_FRAMEBUFFER_STATUS_ERROR_EXT */
01152    }
01153 
01154    if (buffer->Name == 0) {
01155       /* The window system / default framebuffer is always complete */
01156       return GL_FRAMEBUFFER_COMPLETE_EXT;
01157    }
01158 
01159    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
01160 
01161    _mesa_test_framebuffer_completeness(ctx, buffer);
01162    return buffer->_Status;
01163 }
01164 
01165 
01166 
01170 static void
01171 framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target, 
01172                     GLenum attachment, GLenum textarget, GLuint texture,
01173                     GLint level, GLint zoffset)
01174 {
01175    struct gl_renderbuffer_attachment *att;
01176    struct gl_texture_object *texObj = NULL;
01177    struct gl_framebuffer *fb;
01178 
01179    ASSERT_OUTSIDE_BEGIN_END(ctx);
01180 
01181    if (target != GL_FRAMEBUFFER_EXT) {
01182       _mesa_error(ctx, GL_INVALID_ENUM,
01183                   "glFramebufferTexture%sEXT(target)", caller);
01184       return;
01185    }
01186 
01187    fb = ctx->DrawBuffer;
01188    ASSERT(fb);
01189 
01190    /* check framebuffer binding */
01191    if (fb->Name == 0) {
01192       _mesa_error(ctx, GL_INVALID_OPERATION,
01193                   "glFramebufferTexture%sEXT", caller);
01194       return;
01195    }
01196 
01197 
01198    /* The textarget, level, and zoffset parameters are only validated if
01199     * texture is non-zero.
01200     */
01201    if (texture) {
01202       GLboolean err = GL_TRUE;
01203 
01204       texObj = _mesa_lookup_texture(ctx, texture);
01205       if (texObj != NULL) {
01206          if (textarget == 0) {
01207             err = (texObj->Target != GL_TEXTURE_3D) &&
01208                 (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
01209                 (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT);
01210          }
01211          else {
01212             err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
01213                 ? !IS_CUBE_FACE(textarget)
01214                 : (texObj->Target != textarget);
01215          }
01216       }
01217 
01218       if (err) {
01219          _mesa_error(ctx, GL_INVALID_OPERATION,
01220                      "glFramebufferTexture%sEXT(texture target mismatch)",
01221                      caller);
01222          return;
01223       }
01224 
01225       if (texObj->Target == GL_TEXTURE_3D) {
01226          const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
01227          if (zoffset < 0 || zoffset >= maxSize) {
01228             _mesa_error(ctx, GL_INVALID_VALUE,
01229                         "glFramebufferTexture%sEXT(zoffset)", caller);
01230             return;
01231          }
01232       }
01233       else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
01234                (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
01235          if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) {
01236             _mesa_error(ctx, GL_INVALID_VALUE,
01237                         "glFramebufferTexture%sEXT(layer)", caller);
01238             return;
01239          }
01240       }
01241 
01242 
01243       if ((level < 0) || 
01244           (level >= _mesa_max_texture_levels(ctx, texObj->Target))) {
01245          _mesa_error(ctx, GL_INVALID_VALUE,
01246                      "glFramebufferTexture%sEXT(level)", caller);
01247          return;
01248       }
01249    }
01250 
01251    att = _mesa_get_attachment(ctx, fb, attachment);
01252    if (att == NULL) {
01253       _mesa_error(ctx, GL_INVALID_ENUM,
01254                   "glFramebufferTexture%sEXT(attachment)", caller);
01255       return;
01256    }
01257 
01258    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
01259    /* The above doesn't fully flush the drivers in the way that a
01260     * glFlush does, but that is required here:
01261     */
01262    if (ctx->Driver.Flush)
01263       ctx->Driver.Flush(ctx);
01264 
01265    _glthread_LOCK_MUTEX(fb->Mutex);
01266    if (texObj) {
01267       _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
01268                                    level, zoffset);
01269    }
01270    else {
01271       _mesa_remove_attachment(ctx, att);
01272    }
01273    _glthread_UNLOCK_MUTEX(fb->Mutex);
01274 }
01275 
01276 
01277 
01278 void GLAPIENTRY
01279 _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
01280                               GLenum textarget, GLuint texture, GLint level)
01281 {
01282    GET_CURRENT_CONTEXT(ctx);
01283 
01284    if ((texture != 0) && (textarget != GL_TEXTURE_1D)) {
01285       _mesa_error(ctx, GL_INVALID_ENUM,
01286                   "glFramebufferTexture1DEXT(textarget)");
01287       return;
01288    }
01289 
01290    framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
01291                        level, 0);
01292 }
01293 
01294 
01295 void GLAPIENTRY
01296 _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
01297                               GLenum textarget, GLuint texture, GLint level)
01298 {
01299    GET_CURRENT_CONTEXT(ctx);
01300 
01301    if ((texture != 0) &&
01302        (textarget != GL_TEXTURE_2D) &&
01303        (textarget != GL_TEXTURE_RECTANGLE_ARB) &&
01304        (!IS_CUBE_FACE(textarget))) {
01305       _mesa_error(ctx, GL_INVALID_OPERATION,
01306                   "glFramebufferTexture2DEXT(textarget)");
01307       return;
01308    }
01309 
01310    framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
01311                        level, 0);
01312 }
01313 
01314 
01315 void GLAPIENTRY
01316 _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
01317                               GLenum textarget, GLuint texture,
01318                               GLint level, GLint zoffset)
01319 {
01320    GET_CURRENT_CONTEXT(ctx);
01321 
01322    if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
01323       _mesa_error(ctx, GL_INVALID_ENUM,
01324                   "glFramebufferTexture3DEXT(textarget)");
01325       return;
01326    }
01327 
01328    framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
01329                        level, zoffset);
01330 }
01331 
01332 
01333 void GLAPIENTRY
01334 _mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment,
01335                                  GLuint texture, GLint level, GLint layer)
01336 {
01337    GET_CURRENT_CONTEXT(ctx);
01338 
01339    framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
01340                        level, layer);
01341 }
01342 
01343 
01344 void GLAPIENTRY
01345 _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
01346                                  GLenum renderbufferTarget,
01347                                  GLuint renderbuffer)
01348 {
01349    struct gl_renderbuffer_attachment *att;
01350    struct gl_framebuffer *fb;
01351    struct gl_renderbuffer *rb;
01352    GET_CURRENT_CONTEXT(ctx);
01353 
01354    ASSERT_OUTSIDE_BEGIN_END(ctx);
01355 
01356    switch (target) {
01357 #if FEATURE_EXT_framebuffer_blit
01358    case GL_DRAW_FRAMEBUFFER_EXT:
01359       if (!ctx->Extensions.EXT_framebuffer_blit) {
01360          _mesa_error(ctx, GL_INVALID_ENUM,
01361                      "glFramebufferRenderbufferEXT(target)");
01362          return;
01363       }
01364       fb = ctx->DrawBuffer;
01365       break;
01366    case GL_READ_FRAMEBUFFER_EXT:
01367       if (!ctx->Extensions.EXT_framebuffer_blit) {
01368          _mesa_error(ctx, GL_INVALID_ENUM,
01369                      "glFramebufferRenderbufferEXT(target)");
01370          return;
01371       }
01372       fb = ctx->ReadBuffer;
01373       break;
01374 #endif
01375    case GL_FRAMEBUFFER_EXT:
01376       fb = ctx->DrawBuffer;
01377       break;
01378    default:
01379       _mesa_error(ctx, GL_INVALID_ENUM,
01380                   "glFramebufferRenderbufferEXT(target)");
01381       return;
01382    }
01383 
01384    if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
01385       _mesa_error(ctx, GL_INVALID_ENUM,
01386                   "glFramebufferRenderbufferEXT(renderbufferTarget)");
01387       return;
01388    }
01389 
01390    if (fb->Name == 0) {
01391       /* Can't attach new renderbuffers to a window system framebuffer */
01392       _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
01393       return;
01394    }
01395 
01396    att = _mesa_get_attachment(ctx, fb, attachment);
01397    if (att == NULL) {
01398       _mesa_error(ctx, GL_INVALID_ENUM,
01399                  "glFramebufferRenderbufferEXT(attachment)");
01400       return;
01401    }
01402 
01403    if (renderbuffer) {
01404       rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
01405       if (!rb) {
01406      _mesa_error(ctx, GL_INVALID_OPERATION,
01407              "glFramebufferRenderbufferEXT(renderbuffer)");
01408      return;
01409       }
01410    }
01411    else {
01412       /* remove renderbuffer attachment */
01413       rb = NULL;
01414    }
01415 
01416    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
01417    /* The above doesn't fully flush the drivers in the way that a
01418     * glFlush does, but that is required here:
01419     */
01420    if (ctx->Driver.Flush)
01421       ctx->Driver.Flush(ctx);
01422 
01423    assert(ctx->Driver.FramebufferRenderbuffer);
01424    ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
01425 
01426    /* Some subsequent GL commands may depend on the framebuffer's visual
01427     * after the binding is updated.  Update visual info now.
01428     */
01429    _mesa_update_framebuffer_visual(fb);
01430 }
01431 
01432 
01433 void GLAPIENTRY
01434 _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
01435                                              GLenum pname, GLint *params)
01436 {
01437    const struct gl_renderbuffer_attachment *att;
01438    struct gl_framebuffer *buffer;
01439    GET_CURRENT_CONTEXT(ctx);
01440 
01441    ASSERT_OUTSIDE_BEGIN_END(ctx);
01442 
01443    switch (target) {
01444 #if FEATURE_EXT_framebuffer_blit
01445    case GL_DRAW_FRAMEBUFFER_EXT:
01446       if (!ctx->Extensions.EXT_framebuffer_blit) {
01447          _mesa_error(ctx, GL_INVALID_ENUM,
01448                      "glGetFramebufferAttachmentParameterivEXT(target)");
01449          return;
01450       }
01451       buffer = ctx->DrawBuffer;
01452       break;
01453    case GL_READ_FRAMEBUFFER_EXT:
01454       if (!ctx->Extensions.EXT_framebuffer_blit) {
01455          _mesa_error(ctx, GL_INVALID_ENUM,
01456                      "glGetFramebufferAttachmentParameterivEXT(target)");
01457          return;
01458       }
01459       buffer = ctx->ReadBuffer;
01460       break;
01461 #endif
01462    case GL_FRAMEBUFFER_EXT:
01463       buffer = ctx->DrawBuffer;
01464       break;
01465    default:
01466       _mesa_error(ctx, GL_INVALID_ENUM,
01467                   "glGetFramebufferAttachmentParameterivEXT(target)");
01468       return;
01469    }
01470 
01471    if (buffer->Name == 0) {
01472       _mesa_error(ctx, GL_INVALID_OPERATION,
01473                   "glGetFramebufferAttachmentParameterivEXT");
01474       return;
01475    }
01476 
01477    att = _mesa_get_attachment(ctx, buffer, attachment);
01478    if (att == NULL) {
01479       _mesa_error(ctx, GL_INVALID_ENUM,
01480                   "glGetFramebufferAttachmentParameterivEXT(attachment)");
01481       return;
01482    }
01483 
01484    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
01485    /* The above doesn't fully flush the drivers in the way that a
01486     * glFlush does, but that is required here:
01487     */
01488    if (ctx->Driver.Flush)
01489       ctx->Driver.Flush(ctx);
01490 
01491    switch (pname) {
01492    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
01493       *params = att->Type;
01494       return;
01495    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
01496       if (att->Type == GL_RENDERBUFFER_EXT) {
01497      *params = att->Renderbuffer->Name;
01498       }
01499       else if (att->Type == GL_TEXTURE) {
01500      *params = att->Texture->Name;
01501       }
01502       else {
01503      _mesa_error(ctx, GL_INVALID_ENUM,
01504              "glGetFramebufferAttachmentParameterivEXT(pname)");
01505       }
01506       return;
01507    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
01508       if (att->Type == GL_TEXTURE) {
01509      *params = att->TextureLevel;
01510       }
01511       else {
01512      _mesa_error(ctx, GL_INVALID_ENUM,
01513              "glGetFramebufferAttachmentParameterivEXT(pname)");
01514       }
01515       return;
01516    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
01517       if (att->Type == GL_TEXTURE) {
01518          if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
01519             *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
01520          }
01521          else {
01522             *params = 0;
01523          }
01524       }
01525       else {
01526      _mesa_error(ctx, GL_INVALID_ENUM,
01527              "glGetFramebufferAttachmentParameterivEXT(pname)");
01528       }
01529       return;
01530    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
01531       if (att->Type == GL_TEXTURE) {
01532          if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
01533             *params = att->Zoffset;
01534          }
01535          else {
01536             *params = 0;
01537          }
01538       }
01539       else {
01540      _mesa_error(ctx, GL_INVALID_ENUM,
01541              "glGetFramebufferAttachmentParameterivEXT(pname)");
01542       }
01543       return;
01544    default:
01545       _mesa_error(ctx, GL_INVALID_ENUM,
01546                   "glGetFramebufferAttachmentParameterivEXT(pname)");
01547       return;
01548    }
01549 }
01550 
01551 
01552 void GLAPIENTRY
01553 _mesa_GenerateMipmapEXT(GLenum target)
01554 {
01555    struct gl_texture_unit *texUnit;
01556    struct gl_texture_object *texObj;
01557    GET_CURRENT_CONTEXT(ctx);
01558 
01559    ASSERT_OUTSIDE_BEGIN_END(ctx);
01560    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
01561 
01562    switch (target) {
01563    case GL_TEXTURE_1D:
01564    case GL_TEXTURE_2D:
01565    case GL_TEXTURE_3D:
01566    case GL_TEXTURE_CUBE_MAP:
01567       /* OK, legal value */
01568       break;
01569    default:
01570       _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)");
01571       return;
01572    }
01573 
01574    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
01575    texObj = _mesa_select_tex_object(ctx, texUnit, target);
01576 
01577    _mesa_lock_texture(ctx, texObj);
01578    if (target == GL_TEXTURE_CUBE_MAP) {
01579       int face;
01580 
01581       for (face = 0; face < 6; face++)
01582      ctx->Driver.GenerateMipmap(ctx,
01583                     GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,
01584                     texObj);
01585    } else {
01586       ctx->Driver.GenerateMipmap(ctx, target, texObj);
01587    }
01588    _mesa_unlock_texture(ctx, texObj);
01589 }
01590 
01591 
01592 #if FEATURE_EXT_framebuffer_blit
01593 void GLAPIENTRY
01594 _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
01595                          GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
01596                          GLbitfield mask, GLenum filter)
01597 {
01598    GET_CURRENT_CONTEXT(ctx);
01599 
01600    ASSERT_OUTSIDE_BEGIN_END(ctx);
01601    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
01602 
01603    if (ctx->NewState) {
01604       _mesa_update_state(ctx);
01605    }
01606 
01607    if (!ctx->ReadBuffer) {
01608       /* XXX */
01609    }
01610 
01611    /* check for complete framebuffers */
01612    if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
01613        ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
01614       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
01615                   "glBlitFramebufferEXT(incomplete draw/read buffers)");
01616       return;
01617    }
01618 
01619    if (filter != GL_NEAREST && filter != GL_LINEAR) {
01620       _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)");
01621       return;
01622    }
01623 
01624    if (mask & ~(GL_COLOR_BUFFER_BIT |
01625                 GL_DEPTH_BUFFER_BIT |
01626                 GL_STENCIL_BUFFER_BIT)) {
01627       _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
01628       return;
01629    }
01630 
01631    /* depth/stencil must be blitted with nearest filtering */
01632    if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
01633         && filter != GL_NEAREST) {
01634       _mesa_error(ctx, GL_INVALID_OPERATION,
01635              "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter");
01636       return;
01637    }
01638 
01639    if (mask & GL_STENCIL_BUFFER_BIT) {
01640       struct gl_renderbuffer *readRb = ctx->ReadBuffer->_StencilBuffer;
01641       struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_StencilBuffer;
01642       if (readRb->StencilBits != drawRb->StencilBits) {
01643          _mesa_error(ctx, GL_INVALID_OPERATION,
01644                      "glBlitFramebufferEXT(stencil buffer size mismatch");
01645          return;
01646       }
01647    }
01648 
01649    if (mask & GL_DEPTH_BUFFER_BIT) {
01650       struct gl_renderbuffer *readRb = ctx->ReadBuffer->_DepthBuffer;
01651       struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_DepthBuffer;
01652       if (readRb->DepthBits != drawRb->DepthBits) {
01653          _mesa_error(ctx, GL_INVALID_OPERATION,
01654                      "glBlitFramebufferEXT(depth buffer size mismatch");
01655          return;
01656       }
01657    }
01658 
01659    if (!ctx->Extensions.EXT_framebuffer_blit) {
01660       _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
01661       return;
01662    }
01663 
01664    ASSERT(ctx->Driver.BlitFramebuffer);
01665    ctx->Driver.BlitFramebuffer(ctx,
01666                                srcX0, srcY0, srcX1, srcY1,
01667                                dstX0, dstY0, dstX1, dstY1,
01668                                mask, filter);
01669 }
01670 #endif /* FEATURE_EXT_framebuffer_blit */

Generated on Mon May 28 2012 04:20:01 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.