Home | History | Annotate | Download | only in swrast
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  6.5
      4  *
      5  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 
     26 /**
     27  * Functions for allocating/managing software-based renderbuffers.
     28  * Also, routines for reading/writing software-based renderbuffer data as
     29  * ubytes, ushorts, uints, etc.
     30  */
     31 
     32 
     33 #include "main/glheader.h"
     34 #include "main/imports.h"
     35 #include "main/context.h"
     36 #include "main/fbobject.h"
     37 #include "main/formats.h"
     38 #include "main/mtypes.h"
     39 #include "main/renderbuffer.h"
     40 #include "swrast/s_context.h"
     41 #include "swrast/s_renderbuffer.h"
     42 
     43 
     44 /**
     45  * This is a software fallback for the gl_renderbuffer->AllocStorage
     46  * function.
     47  * Device drivers will typically override this function for the buffers
     48  * which it manages (typically color buffers, Z and stencil).
     49  * Other buffers (like software accumulation and aux buffers) which the driver
     50  * doesn't manage can be handled with this function.
     51  *
     52  * This one multi-purpose function can allocate stencil, depth, accum, color
     53  * or color-index buffers!
     54  */
     55 static GLboolean
     56 soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
     57                           GLenum internalFormat,
     58                           GLuint width, GLuint height)
     59 {
     60    struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
     61    GLuint bpp;
     62 
     63    switch (internalFormat) {
     64    case GL_RGB:
     65    case GL_R3_G3_B2:
     66    case GL_RGB4:
     67    case GL_RGB5:
     68    case GL_RGB8:
     69    case GL_RGB10:
     70    case GL_RGB12:
     71    case GL_RGB16:
     72       rb->Format = MESA_FORMAT_RGB888;
     73       break;
     74    case GL_RGBA:
     75    case GL_RGBA2:
     76    case GL_RGBA4:
     77    case GL_RGB5_A1:
     78    case GL_RGBA8:
     79 #if 1
     80    case GL_RGB10_A2:
     81    case GL_RGBA12:
     82 #endif
     83       if (_mesa_little_endian())
     84          rb->Format = MESA_FORMAT_RGBA8888_REV;
     85       else
     86          rb->Format = MESA_FORMAT_RGBA8888;
     87       break;
     88    case GL_RGBA16:
     89    case GL_RGBA16_SNORM:
     90       /* for accum buffer */
     91       rb->Format = MESA_FORMAT_SIGNED_RGBA_16;
     92       break;
     93    case GL_STENCIL_INDEX:
     94    case GL_STENCIL_INDEX1_EXT:
     95    case GL_STENCIL_INDEX4_EXT:
     96    case GL_STENCIL_INDEX8_EXT:
     97    case GL_STENCIL_INDEX16_EXT:
     98       rb->Format = MESA_FORMAT_S8;
     99       break;
    100    case GL_DEPTH_COMPONENT:
    101    case GL_DEPTH_COMPONENT16:
    102       rb->Format = MESA_FORMAT_Z16;
    103       break;
    104    case GL_DEPTH_COMPONENT24:
    105       rb->Format = MESA_FORMAT_X8_Z24;
    106       break;
    107    case GL_DEPTH_COMPONENT32:
    108       rb->Format = MESA_FORMAT_Z32;
    109       break;
    110    case GL_DEPTH_STENCIL_EXT:
    111    case GL_DEPTH24_STENCIL8_EXT:
    112       rb->Format = MESA_FORMAT_Z24_S8;
    113       break;
    114    default:
    115       /* unsupported format */
    116       return GL_FALSE;
    117    }
    118 
    119    bpp = _mesa_get_format_bytes(rb->Format);
    120 
    121    /* free old buffer storage */
    122    if (srb->Buffer) {
    123       free(srb->Buffer);
    124       srb->Buffer = NULL;
    125    }
    126 
    127    srb->RowStride = width * bpp;
    128 
    129    if (width > 0 && height > 0) {
    130       /* allocate new buffer storage */
    131       srb->Buffer = malloc(srb->RowStride * height);
    132 
    133       if (srb->Buffer == NULL) {
    134          rb->Width = 0;
    135          rb->Height = 0;
    136          _mesa_error(ctx, GL_OUT_OF_MEMORY,
    137                      "software renderbuffer allocation (%d x %d x %d)",
    138                      width, height, bpp);
    139          return GL_FALSE;
    140       }
    141    }
    142 
    143    rb->Width = width;
    144    rb->Height = height;
    145    rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
    146 
    147    if (rb->Name == 0 &&
    148        internalFormat == GL_RGBA16_SNORM &&
    149        rb->_BaseFormat == 0) {
    150       /* NOTE: This is a special case just for accumulation buffers.
    151        * This is a very limited use case- there's no snorm texturing or
    152        * rendering going on.
    153        */
    154       rb->_BaseFormat = GL_RGBA;
    155    }
    156    else {
    157       /* the internalFormat should have been error checked long ago */
    158       ASSERT(rb->_BaseFormat);
    159    }
    160 
    161    return GL_TRUE;
    162 }
    163 
    164 
    165 /**
    166  * Called via gl_renderbuffer::Delete()
    167  */
    168 static void
    169 soft_renderbuffer_delete(struct gl_context *ctx, struct gl_renderbuffer *rb)
    170 {
    171    struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
    172 
    173    free(srb->Buffer);
    174    srb->Buffer = NULL;
    175    _mesa_delete_renderbuffer(ctx, rb);
    176 }
    177 
    178 
    179 void
    180 _swrast_map_soft_renderbuffer(struct gl_context *ctx,
    181                               struct gl_renderbuffer *rb,
    182                               GLuint x, GLuint y, GLuint w, GLuint h,
    183                               GLbitfield mode,
    184                               GLubyte **out_map,
    185                               GLint *out_stride)
    186 {
    187    struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
    188    GLubyte *map = srb->Buffer;
    189    int cpp = _mesa_get_format_bytes(rb->Format);
    190    int stride = rb->Width * cpp;
    191 
    192    if (!map) {
    193       *out_map = NULL;
    194       *out_stride = 0;
    195    }
    196 
    197    map += y * stride;
    198    map += x * cpp;
    199 
    200    *out_map = map;
    201    *out_stride = stride;
    202 }
    203 
    204 
    205 void
    206 _swrast_unmap_soft_renderbuffer(struct gl_context *ctx,
    207                                 struct gl_renderbuffer *rb)
    208 {
    209 }
    210 
    211 
    212 
    213 /**
    214  * Allocate a software-based renderbuffer.  This is called via the
    215  * ctx->Driver.NewRenderbuffer() function when the user creates a new
    216  * renderbuffer.
    217  * This would not be used for hardware-based renderbuffers.
    218  */
    219 struct gl_renderbuffer *
    220 _swrast_new_soft_renderbuffer(struct gl_context *ctx, GLuint name)
    221 {
    222    struct swrast_renderbuffer *srb = CALLOC_STRUCT(swrast_renderbuffer);
    223    if (srb) {
    224       _mesa_init_renderbuffer(&srb->Base, name);
    225       srb->Base.AllocStorage = soft_renderbuffer_storage;
    226       srb->Base.Delete = soft_renderbuffer_delete;
    227    }
    228    return &srb->Base;
    229 }
    230 
    231 
    232 /**
    233  * Add software-based color renderbuffers to the given framebuffer.
    234  * This is a helper routine for device drivers when creating a
    235  * window system framebuffer (not a user-created render/framebuffer).
    236  * Once this function is called, you can basically forget about this
    237  * renderbuffer; core Mesa will handle all the buffer management and
    238  * rendering!
    239  */
    240 static GLboolean
    241 add_color_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
    242                         GLuint rgbBits, GLuint alphaBits,
    243                         GLboolean frontLeft, GLboolean backLeft,
    244                         GLboolean frontRight, GLboolean backRight)
    245 {
    246    gl_buffer_index b;
    247 
    248    if (rgbBits > 16 || alphaBits > 16) {
    249       _mesa_problem(ctx,
    250                     "Unsupported bit depth in add_color_renderbuffers");
    251       return GL_FALSE;
    252    }
    253 
    254    assert(MAX_COLOR_ATTACHMENTS >= 4);
    255 
    256    for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
    257       struct gl_renderbuffer *rb;
    258 
    259       if (b == BUFFER_FRONT_LEFT && !frontLeft)
    260          continue;
    261       else if (b == BUFFER_BACK_LEFT && !backLeft)
    262          continue;
    263       else if (b == BUFFER_FRONT_RIGHT && !frontRight)
    264          continue;
    265       else if (b == BUFFER_BACK_RIGHT && !backRight)
    266          continue;
    267 
    268       assert(fb->Attachment[b].Renderbuffer == NULL);
    269 
    270       rb = ctx->Driver.NewRenderbuffer(ctx, 0);
    271       if (!rb) {
    272          _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
    273          return GL_FALSE;
    274       }
    275 
    276       rb->InternalFormat = GL_RGBA;
    277 
    278       rb->AllocStorage = soft_renderbuffer_storage;
    279       _mesa_add_renderbuffer(fb, b, rb);
    280    }
    281 
    282    return GL_TRUE;
    283 }
    284 
    285 
    286 /**
    287  * Add a software-based depth renderbuffer to the given framebuffer.
    288  * This is a helper routine for device drivers when creating a
    289  * window system framebuffer (not a user-created render/framebuffer).
    290  * Once this function is called, you can basically forget about this
    291  * renderbuffer; core Mesa will handle all the buffer management and
    292  * rendering!
    293  */
    294 static GLboolean
    295 add_depth_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
    296                        GLuint depthBits)
    297 {
    298    struct gl_renderbuffer *rb;
    299 
    300    if (depthBits > 32) {
    301       _mesa_problem(ctx,
    302                     "Unsupported depthBits in add_depth_renderbuffer");
    303       return GL_FALSE;
    304    }
    305 
    306    assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
    307 
    308    rb = _swrast_new_soft_renderbuffer(ctx, 0);
    309    if (!rb) {
    310       _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
    311       return GL_FALSE;
    312    }
    313 
    314    if (depthBits <= 16) {
    315       rb->InternalFormat = GL_DEPTH_COMPONENT16;
    316    }
    317    else if (depthBits <= 24) {
    318       rb->InternalFormat = GL_DEPTH_COMPONENT24;
    319    }
    320    else {
    321       rb->InternalFormat = GL_DEPTH_COMPONENT32;
    322    }
    323 
    324    rb->AllocStorage = soft_renderbuffer_storage;
    325    _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
    326 
    327    return GL_TRUE;
    328 }
    329 
    330 
    331 /**
    332  * Add a software-based stencil renderbuffer to the given framebuffer.
    333  * This is a helper routine for device drivers when creating a
    334  * window system framebuffer (not a user-created render/framebuffer).
    335  * Once this function is called, you can basically forget about this
    336  * renderbuffer; core Mesa will handle all the buffer management and
    337  * rendering!
    338  */
    339 static GLboolean
    340 add_stencil_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
    341                          GLuint stencilBits)
    342 {
    343    struct gl_renderbuffer *rb;
    344 
    345    if (stencilBits > 16) {
    346       _mesa_problem(ctx,
    347                   "Unsupported stencilBits in add_stencil_renderbuffer");
    348       return GL_FALSE;
    349    }
    350 
    351    assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
    352 
    353    rb = _swrast_new_soft_renderbuffer(ctx, 0);
    354    if (!rb) {
    355       _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
    356       return GL_FALSE;
    357    }
    358 
    359    assert(stencilBits <= 8);
    360    rb->InternalFormat = GL_STENCIL_INDEX8;
    361 
    362    rb->AllocStorage = soft_renderbuffer_storage;
    363    _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
    364 
    365    return GL_TRUE;
    366 }
    367 
    368 
    369 static GLboolean
    370 add_depth_stencil_renderbuffer(struct gl_context *ctx,
    371                                struct gl_framebuffer *fb)
    372 {
    373    struct gl_renderbuffer *rb;
    374 
    375    assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
    376    assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
    377 
    378    rb = _swrast_new_soft_renderbuffer(ctx, 0);
    379    if (!rb) {
    380       _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth+stencil buffer");
    381       return GL_FALSE;
    382    }
    383 
    384    rb->InternalFormat = GL_DEPTH_STENCIL;
    385 
    386    rb->AllocStorage = soft_renderbuffer_storage;
    387    _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
    388    _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
    389 
    390    return GL_TRUE;
    391 }
    392 
    393 
    394 /**
    395  * Add a software-based accumulation renderbuffer to the given framebuffer.
    396  * This is a helper routine for device drivers when creating a
    397  * window system framebuffer (not a user-created render/framebuffer).
    398  * Once this function is called, you can basically forget about this
    399  * renderbuffer; core Mesa will handle all the buffer management and
    400  * rendering!
    401  */
    402 static GLboolean
    403 add_accum_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
    404                        GLuint redBits, GLuint greenBits,
    405                        GLuint blueBits, GLuint alphaBits)
    406 {
    407    struct gl_renderbuffer *rb;
    408 
    409    if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
    410       _mesa_problem(ctx,
    411                     "Unsupported accumBits in add_accum_renderbuffer");
    412       return GL_FALSE;
    413    }
    414 
    415    assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
    416 
    417    rb = _swrast_new_soft_renderbuffer(ctx, 0);
    418    if (!rb) {
    419       _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
    420       return GL_FALSE;
    421    }
    422 
    423    rb->InternalFormat = GL_RGBA16_SNORM;
    424    rb->AllocStorage = soft_renderbuffer_storage;
    425    _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
    426 
    427    return GL_TRUE;
    428 }
    429 
    430 
    431 
    432 /**
    433  * Add a software-based aux renderbuffer to the given framebuffer.
    434  * This is a helper routine for device drivers when creating a
    435  * window system framebuffer (not a user-created render/framebuffer).
    436  * Once this function is called, you can basically forget about this
    437  * renderbuffer; core Mesa will handle all the buffer management and
    438  * rendering!
    439  *
    440  * NOTE: color-index aux buffers not supported.
    441  */
    442 static GLboolean
    443 add_aux_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
    444                       GLuint colorBits, GLuint numBuffers)
    445 {
    446    GLuint i;
    447 
    448    if (colorBits > 16) {
    449       _mesa_problem(ctx,
    450                     "Unsupported colorBits in add_aux_renderbuffers");
    451       return GL_FALSE;
    452    }
    453 
    454    assert(numBuffers <= MAX_AUX_BUFFERS);
    455 
    456    for (i = 0; i < numBuffers; i++) {
    457       struct gl_renderbuffer *rb = _swrast_new_soft_renderbuffer(ctx, 0);
    458 
    459       assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
    460 
    461       if (!rb) {
    462          _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating aux buffer");
    463          return GL_FALSE;
    464       }
    465 
    466       assert (colorBits <= 8);
    467       rb->InternalFormat = GL_RGBA;
    468 
    469       rb->AllocStorage = soft_renderbuffer_storage;
    470       _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
    471    }
    472    return GL_TRUE;
    473 }
    474 
    475 
    476 /**
    477  * Create/attach software-based renderbuffers to the given framebuffer.
    478  * This is a helper routine for device drivers.  Drivers can just as well
    479  * call the individual _mesa_add_*_renderbuffer() routines directly.
    480  */
    481 void
    482 _swrast_add_soft_renderbuffers(struct gl_framebuffer *fb,
    483                                GLboolean color,
    484                                GLboolean depth,
    485                                GLboolean stencil,
    486                                GLboolean accum,
    487                                GLboolean alpha,
    488                                GLboolean aux)
    489 {
    490    GLboolean frontLeft = GL_TRUE;
    491    GLboolean backLeft = fb->Visual.doubleBufferMode;
    492    GLboolean frontRight = fb->Visual.stereoMode;
    493    GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
    494 
    495    if (color) {
    496       assert(fb->Visual.redBits == fb->Visual.greenBits);
    497       assert(fb->Visual.redBits == fb->Visual.blueBits);
    498       add_color_renderbuffers(NULL, fb,
    499                               fb->Visual.redBits,
    500                               fb->Visual.alphaBits,
    501                               frontLeft, backLeft,
    502                               frontRight, backRight);
    503    }
    504 
    505 #if 0
    506    /* This is pretty much for debugging purposes only since there's a perf
    507     * hit for using combined depth/stencil in swrast.
    508     */
    509    if (depth && fb->Visual.depthBits == 24 &&
    510        stencil && fb->Visual.stencilBits == 8) {
    511       /* use combined depth/stencil buffer */
    512       add_depth_stencil_renderbuffer(NULL, fb);
    513    }
    514    else
    515 #else
    516    (void) add_depth_stencil_renderbuffer;
    517 #endif
    518    {
    519       if (depth) {
    520          assert(fb->Visual.depthBits > 0);
    521          add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
    522       }
    523 
    524       if (stencil) {
    525          assert(fb->Visual.stencilBits > 0);
    526          add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
    527       }
    528    }
    529 
    530    if (accum) {
    531       assert(fb->Visual.accumRedBits > 0);
    532       assert(fb->Visual.accumGreenBits > 0);
    533       assert(fb->Visual.accumBlueBits > 0);
    534       add_accum_renderbuffer(NULL, fb,
    535                              fb->Visual.accumRedBits,
    536                              fb->Visual.accumGreenBits,
    537                              fb->Visual.accumBlueBits,
    538                              fb->Visual.accumAlphaBits);
    539    }
    540 
    541    if (aux) {
    542       assert(fb->Visual.numAuxBuffers > 0);
    543       add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
    544                             fb->Visual.numAuxBuffers);
    545    }
    546 
    547 #if 0
    548    if (multisample) {
    549       /* maybe someday */
    550    }
    551 #endif
    552 }
    553 
    554 
    555 
    556 static void
    557 map_attachment(struct gl_context *ctx,
    558                  struct gl_framebuffer *fb,
    559                  gl_buffer_index buffer)
    560 {
    561    struct gl_texture_object *texObj = fb->Attachment[buffer].Texture;
    562    struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer;
    563    struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
    564 
    565    if (texObj) {
    566       /* map texture image (render to texture) */
    567       const GLuint level = fb->Attachment[buffer].TextureLevel;
    568       const GLuint face = fb->Attachment[buffer].CubeMapFace;
    569       const GLuint slice = fb->Attachment[buffer].Zoffset;
    570       struct gl_texture_image *texImage = texObj->Image[face][level];
    571       if (texImage) {
    572          ctx->Driver.MapTextureImage(ctx, texImage, slice,
    573                                      0, 0, texImage->Width, texImage->Height,
    574                                      GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
    575                                      &srb->Map, &srb->RowStride);
    576       }
    577    }
    578    else if (rb) {
    579       /* Map ordinary renderbuffer */
    580       ctx->Driver.MapRenderbuffer(ctx, rb,
    581                                   0, 0, rb->Width, rb->Height,
    582                                   GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
    583                                   &srb->Map, &srb->RowStride);
    584    }
    585 
    586    assert(srb->Map);
    587 }
    588 
    589 
    590 static void
    591 unmap_attachment(struct gl_context *ctx,
    592                    struct gl_framebuffer *fb,
    593                    gl_buffer_index buffer)
    594 {
    595    struct gl_texture_object *texObj = fb->Attachment[buffer].Texture;
    596    struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer;
    597    struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
    598 
    599    if (texObj) {
    600       /* unmap texture image (render to texture) */
    601       const GLuint level = fb->Attachment[buffer].TextureLevel;
    602       const GLuint face = fb->Attachment[buffer].CubeMapFace;
    603       const GLuint slice = fb->Attachment[buffer].Zoffset;
    604       struct gl_texture_image *texImage = texObj->Image[face][level];
    605       if (texImage) {
    606          ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
    607       }
    608    }
    609    else if (rb) {
    610       /* unmap ordinary renderbuffer */
    611       ctx->Driver.UnmapRenderbuffer(ctx, rb);
    612    }
    613 
    614    srb->Map = NULL;
    615 }
    616 
    617 
    618 /**
    619  * Determine what type to use (ubyte vs. float) for span colors for the
    620  * given renderbuffer.
    621  * See also _swrast_write_rgba_span().
    622  */
    623 static void
    624 find_renderbuffer_colortype(struct gl_renderbuffer *rb)
    625 {
    626    struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
    627    GLuint rbMaxBits = _mesa_get_format_max_bits(rb->Format);
    628    GLenum rbDatatype = _mesa_get_format_datatype(rb->Format);
    629 
    630    if (rbDatatype == GL_UNSIGNED_NORMALIZED && rbMaxBits <= 8) {
    631       /* the buffer's values fit in GLubyte values */
    632       srb->ColorType = GL_UNSIGNED_BYTE;
    633    }
    634    else {
    635       /* use floats otherwise */
    636       srb->ColorType = GL_FLOAT;
    637    }
    638 }
    639 
    640 
    641 /**
    642  * Map the renderbuffers we'll use for tri/line/point rendering.
    643  */
    644 void
    645 _swrast_map_renderbuffers(struct gl_context *ctx)
    646 {
    647    struct gl_framebuffer *fb = ctx->DrawBuffer;
    648    struct gl_renderbuffer *depthRb, *stencilRb;
    649    GLuint buf;
    650 
    651    depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
    652    if (depthRb) {
    653       /* map depth buffer */
    654       map_attachment(ctx, fb, BUFFER_DEPTH);
    655    }
    656 
    657    stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
    658    if (stencilRb && stencilRb != depthRb) {
    659       /* map stencil buffer */
    660       map_attachment(ctx, fb, BUFFER_STENCIL);
    661    }
    662 
    663    for (buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
    664       map_attachment(ctx, fb, fb->_ColorDrawBufferIndexes[buf]);
    665       find_renderbuffer_colortype(fb->_ColorDrawBuffers[buf]);
    666    }
    667 }
    668 
    669 
    670 /**
    671  * Unmap renderbuffers after rendering.
    672  */
    673 void
    674 _swrast_unmap_renderbuffers(struct gl_context *ctx)
    675 {
    676    struct gl_framebuffer *fb = ctx->DrawBuffer;
    677    struct gl_renderbuffer *depthRb, *stencilRb;
    678    GLuint buf;
    679 
    680    depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
    681    if (depthRb) {
    682       /* map depth buffer */
    683       unmap_attachment(ctx, fb, BUFFER_DEPTH);
    684    }
    685 
    686    stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
    687    if (stencilRb && stencilRb != depthRb) {
    688       /* map stencil buffer */
    689       unmap_attachment(ctx, fb, BUFFER_STENCIL);
    690    }
    691 
    692    for (buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
    693       unmap_attachment(ctx, fb, fb->_ColorDrawBufferIndexes[buf]);
    694    }
    695 }
    696