Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
      5  * Copyright (C) 2009  VMware, Inc.  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  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     23  * OTHER DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 
     27 /**
     28  * \file image.c
     29  * Image handling.
     30  */
     31 
     32 
     33 #include "glheader.h"
     34 #include "colormac.h"
     35 #include "glformats.h"
     36 #include "image.h"
     37 #include "imports.h"
     38 #include "macros.h"
     39 #include "mtypes.h"
     40 
     41 
     42 
     43 /**
     44  * Flip the order of the 2 bytes in each word in the given array (src) and
     45  * store the result in another array (dst). For in-place byte-swapping this
     46  * function can be called with the same array for src and dst.
     47  *
     48  * \param dst the array where byte-swapped data will be stored.
     49  * \param src the array with the source data we want to byte-swap.
     50  * \param n number of words.
     51  */
     52 static void
     53 swap2_copy( GLushort *dst, GLushort *src, GLuint n )
     54 {
     55    GLuint i;
     56    for (i = 0; i < n; i++) {
     57       dst[i] = (src[i] >> 8) | ((src[i] << 8) & 0xff00);
     58    }
     59 }
     60 
     61 void
     62 _mesa_swap2(GLushort *p, GLuint n)
     63 {
     64    swap2_copy(p, p, n);
     65 }
     66 
     67 /*
     68  * Flip the order of the 4 bytes in each word in the given array (src) and
     69  * store the result in another array (dst). For in-place byte-swapping this
     70  * function can be called with the same array for src and dst.
     71  *
     72  * \param dst the array where byte-swapped data will be stored.
     73  * \param src the array with the source data we want to byte-swap.
     74  * \param n number of words.
     75  */
     76 static void
     77 swap4_copy( GLuint *dst, GLuint *src, GLuint n )
     78 {
     79    GLuint i, a, b;
     80    for (i = 0; i < n; i++) {
     81       b = src[i];
     82       a =  (b >> 24)
     83 	| ((b >> 8) & 0xff00)
     84 	| ((b << 8) & 0xff0000)
     85 	| ((b << 24) & 0xff000000);
     86       dst[i] = a;
     87    }
     88 }
     89 
     90 void
     91 _mesa_swap4(GLuint *p, GLuint n)
     92 {
     93    swap4_copy(p, p, n);
     94 }
     95 
     96 /**
     97  * Return the byte offset of a specific pixel in an image (1D, 2D or 3D).
     98  *
     99  * Pixel unpacking/packing parameters are observed according to \p packing.
    100  *
    101  * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
    102  * \param packing  the pixelstore attributes
    103  * \param width  the image width
    104  * \param height  the image height
    105  * \param format  the pixel format (must be validated beforehand)
    106  * \param type  the pixel data type (must be validated beforehand)
    107  * \param img  which image in the volume (0 for 1D or 2D images)
    108  * \param row  row of pixel in the image (0 for 1D images)
    109  * \param column column of pixel in the image
    110  *
    111  * \return offset of pixel.
    112  *
    113  * \sa gl_pixelstore_attrib.
    114  */
    115 GLintptr
    116 _mesa_image_offset( GLuint dimensions,
    117                     const struct gl_pixelstore_attrib *packing,
    118                     GLsizei width, GLsizei height,
    119                     GLenum format, GLenum type,
    120                     GLint img, GLint row, GLint column )
    121 {
    122    GLint alignment;        /* 1, 2 or 4 */
    123    GLint pixels_per_row;
    124    GLint rows_per_image;
    125    GLint skiprows;
    126    GLint skippixels;
    127    GLint skipimages;       /* for 3-D volume images */
    128    GLintptr offset;
    129 
    130    assert(dimensions >= 1 && dimensions <= 3);
    131 
    132    alignment = packing->Alignment;
    133    if (packing->RowLength > 0) {
    134       pixels_per_row = packing->RowLength;
    135    }
    136    else {
    137       pixels_per_row = width;
    138    }
    139    if (packing->ImageHeight > 0) {
    140       rows_per_image = packing->ImageHeight;
    141    }
    142    else {
    143       rows_per_image = height;
    144    }
    145 
    146    skippixels = packing->SkipPixels;
    147    /* Note: SKIP_ROWS _is_ used for 1D images */
    148    skiprows = packing->SkipRows;
    149    /* Note: SKIP_IMAGES is only used for 3D images */
    150    skipimages = (dimensions == 3) ? packing->SkipImages : 0;
    151 
    152    if (type == GL_BITMAP) {
    153       /* BITMAP data */
    154       GLintptr bytes_per_row;
    155       GLintptr bytes_per_image;
    156       /* components per pixel for color or stencil index: */
    157       const GLint comp_per_pixel = 1;
    158 
    159       /* The pixel type and format should have been error checked earlier */
    160       assert(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX);
    161 
    162       bytes_per_row = alignment
    163                     * DIV_ROUND_UP( comp_per_pixel*pixels_per_row, 8*alignment );
    164 
    165       bytes_per_image = bytes_per_row * rows_per_image;
    166 
    167       offset = (skipimages + img) * bytes_per_image
    168                  + (skiprows + row) * bytes_per_row
    169                  + (skippixels + column) / 8;
    170    }
    171    else {
    172       /* Non-BITMAP data */
    173       GLintptr bytes_per_pixel, bytes_per_row, remainder, bytes_per_image;
    174       GLintptr topOfImage;
    175 
    176       bytes_per_pixel = _mesa_bytes_per_pixel( format, type );
    177 
    178       /* The pixel type and format should have been error checked earlier */
    179       assert(bytes_per_pixel > 0);
    180 
    181       bytes_per_row = pixels_per_row * bytes_per_pixel;
    182       remainder = bytes_per_row % alignment;
    183       if (remainder > 0)
    184          bytes_per_row += (alignment - remainder);
    185 
    186       assert(bytes_per_row % alignment == 0);
    187 
    188       bytes_per_image = bytes_per_row * rows_per_image;
    189 
    190       if (packing->Invert) {
    191          /* set pixel_addr to the last row */
    192          topOfImage = bytes_per_row * (height - 1);
    193          bytes_per_row = -bytes_per_row;
    194       }
    195       else {
    196          topOfImage = 0;
    197       }
    198 
    199       /* compute final pixel address */
    200       offset = (skipimages + img) * bytes_per_image
    201                  + topOfImage
    202                  + (skiprows + row) * bytes_per_row
    203                  + (skippixels + column) * bytes_per_pixel;
    204    }
    205 
    206    return offset;
    207 }
    208 
    209 
    210 /**
    211  * Return the address of a specific pixel in an image (1D, 2D or 3D).
    212  *
    213  * Pixel unpacking/packing parameters are observed according to \p packing.
    214  *
    215  * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
    216  * \param packing  the pixelstore attributes
    217  * \param image  starting address of image data
    218  * \param width  the image width
    219  * \param height  the image height
    220  * \param format  the pixel format (must be validated beforehand)
    221  * \param type  the pixel data type (must be validated beforehand)
    222  * \param img  which image in the volume (0 for 1D or 2D images)
    223  * \param row  row of pixel in the image (0 for 1D images)
    224  * \param column column of pixel in the image
    225  *
    226  * \return address of pixel.
    227  *
    228  * \sa gl_pixelstore_attrib.
    229  */
    230 GLvoid *
    231 _mesa_image_address( GLuint dimensions,
    232                      const struct gl_pixelstore_attrib *packing,
    233                      const GLvoid *image,
    234                      GLsizei width, GLsizei height,
    235                      GLenum format, GLenum type,
    236                      GLint img, GLint row, GLint column )
    237 {
    238    const GLubyte *addr = (const GLubyte *) image;
    239 
    240    addr += _mesa_image_offset(dimensions, packing, width, height,
    241                               format, type, img, row, column);
    242 
    243    return (GLvoid *) addr;
    244 }
    245 
    246 
    247 GLvoid *
    248 _mesa_image_address1d( const struct gl_pixelstore_attrib *packing,
    249                        const GLvoid *image,
    250                        GLsizei width,
    251                        GLenum format, GLenum type,
    252                        GLint column )
    253 {
    254    return _mesa_image_address(1, packing, image, width, 1,
    255                               format, type, 0, 0, column);
    256 }
    257 
    258 
    259 GLvoid *
    260 _mesa_image_address2d( const struct gl_pixelstore_attrib *packing,
    261                        const GLvoid *image,
    262                        GLsizei width, GLsizei height,
    263                        GLenum format, GLenum type,
    264                        GLint row, GLint column )
    265 {
    266    return _mesa_image_address(2, packing, image, width, height,
    267                               format, type, 0, row, column);
    268 }
    269 
    270 
    271 GLvoid *
    272 _mesa_image_address3d( const struct gl_pixelstore_attrib *packing,
    273                        const GLvoid *image,
    274                        GLsizei width, GLsizei height,
    275                        GLenum format, GLenum type,
    276                        GLint img, GLint row, GLint column )
    277 {
    278    return _mesa_image_address(3, packing, image, width, height,
    279                               format, type, img, row, column);
    280 }
    281 
    282 
    283 
    284 /**
    285  * Compute the stride (in bytes) between image rows.
    286  *
    287  * \param packing the pixelstore attributes
    288  * \param width image width.
    289  * \param format pixel format.
    290  * \param type pixel data type.
    291  *
    292  * \return the stride in bytes for the given parameters, or -1 if error
    293  */
    294 GLint
    295 _mesa_image_row_stride( const struct gl_pixelstore_attrib *packing,
    296                         GLint width, GLenum format, GLenum type )
    297 {
    298    GLint bytesPerRow, remainder;
    299 
    300    assert(packing);
    301 
    302    if (type == GL_BITMAP) {
    303       if (packing->RowLength == 0) {
    304          bytesPerRow = (width + 7) / 8;
    305       }
    306       else {
    307          bytesPerRow = (packing->RowLength + 7) / 8;
    308       }
    309    }
    310    else {
    311       /* Non-BITMAP data */
    312       const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
    313       if (bytesPerPixel <= 0)
    314          return -1;  /* error */
    315       if (packing->RowLength == 0) {
    316          bytesPerRow = bytesPerPixel * width;
    317       }
    318       else {
    319          bytesPerRow = bytesPerPixel * packing->RowLength;
    320       }
    321    }
    322 
    323    remainder = bytesPerRow % packing->Alignment;
    324    if (remainder > 0) {
    325       bytesPerRow += (packing->Alignment - remainder);
    326    }
    327 
    328    if (packing->Invert) {
    329       /* negate the bytes per row (negative row stride) */
    330       bytesPerRow = -bytesPerRow;
    331    }
    332 
    333    return bytesPerRow;
    334 }
    335 
    336 
    337 /*
    338  * Compute the stride between images in a 3D texture (in bytes) for the given
    339  * pixel packing parameters and image width, format and type.
    340  */
    341 GLint
    342 _mesa_image_image_stride( const struct gl_pixelstore_attrib *packing,
    343                           GLint width, GLint height,
    344                           GLenum format, GLenum type )
    345 {
    346    GLint bytesPerRow, bytesPerImage, remainder;
    347 
    348    assert(packing);
    349 
    350    if (type == GL_BITMAP) {
    351       if (packing->RowLength == 0) {
    352          bytesPerRow = (width + 7) / 8;
    353       }
    354       else {
    355          bytesPerRow = (packing->RowLength + 7) / 8;
    356       }
    357    }
    358    else {
    359       const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
    360 
    361       if (bytesPerPixel <= 0)
    362          return -1;  /* error */
    363       if (packing->RowLength == 0) {
    364          bytesPerRow = bytesPerPixel * width;
    365       }
    366       else {
    367          bytesPerRow = bytesPerPixel * packing->RowLength;
    368       }
    369    }
    370 
    371    remainder = bytesPerRow % packing->Alignment;
    372    if (remainder > 0)
    373       bytesPerRow += (packing->Alignment - remainder);
    374 
    375    if (packing->ImageHeight == 0)
    376       bytesPerImage = bytesPerRow * height;
    377    else
    378       bytesPerImage = bytesPerRow * packing->ImageHeight;
    379 
    380    return bytesPerImage;
    381 }
    382 
    383 
    384 
    385 /**
    386  * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel.
    387  * This is typically used to convert a bitmap into a GLubyte/pixel texture.
    388  * "On" bits will set texels to \p onValue.
    389  * "Off" bits will not modify texels.
    390  * \param width  src bitmap width in pixels
    391  * \param height  src bitmap height in pixels
    392  * \param unpack  bitmap unpacking state
    393  * \param bitmap  the src bitmap data
    394  * \param destBuffer  start of dest buffer
    395  * \param destStride  row stride in dest buffer
    396  * \param onValue  if bit is 1, set destBuffer pixel to this value
    397  */
    398 void
    399 _mesa_expand_bitmap(GLsizei width, GLsizei height,
    400                     const struct gl_pixelstore_attrib *unpack,
    401                     const GLubyte *bitmap,
    402                     GLubyte *destBuffer, GLint destStride,
    403                     GLubyte onValue)
    404 {
    405    const GLubyte *srcRow = (const GLubyte *)
    406       _mesa_image_address2d(unpack, bitmap, width, height,
    407                             GL_COLOR_INDEX, GL_BITMAP, 0, 0);
    408    const GLint srcStride = _mesa_image_row_stride(unpack, width,
    409                                                   GL_COLOR_INDEX, GL_BITMAP);
    410    GLint row, col;
    411    GLubyte *dstRow = destBuffer;
    412 
    413    for (row = 0; row < height; row++) {
    414       const GLubyte *src = srcRow;
    415 
    416       if (unpack->LsbFirst) {
    417          /* Lsb first */
    418          GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
    419          for (col = 0; col < width; col++) {
    420 
    421             if (*src & mask) {
    422                dstRow[col] = onValue;
    423             }
    424 
    425             if (mask == 128U) {
    426                src++;
    427                mask = 1U;
    428             }
    429             else {
    430                mask = mask << 1;
    431             }
    432          }
    433 
    434          /* get ready for next row */
    435          if (mask != 1)
    436             src++;
    437       }
    438       else {
    439          /* Msb first */
    440          GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
    441          for (col = 0; col < width; col++) {
    442 
    443             if (*src & mask) {
    444                dstRow[col] = onValue;
    445             }
    446 
    447             if (mask == 1U) {
    448                src++;
    449                mask = 128U;
    450             }
    451             else {
    452                mask = mask >> 1;
    453             }
    454          }
    455 
    456          /* get ready for next row */
    457          if (mask != 128)
    458             src++;
    459       }
    460 
    461       srcRow += srcStride;
    462       dstRow += destStride;
    463    } /* row */
    464 }
    465 
    466 
    467 
    468 
    469 /**
    470  * Convert an array of RGBA colors from one datatype to another.
    471  * NOTE: src may equal dst.  In that case, we use a temporary buffer.
    472  */
    473 void
    474 _mesa_convert_colors(GLenum srcType, const GLvoid *src,
    475                      GLenum dstType, GLvoid *dst,
    476                      GLuint count, const GLubyte mask[])
    477 {
    478    GLuint *tempBuffer;
    479    const GLboolean useTemp = (src == dst);
    480 
    481    tempBuffer = malloc(count * MAX_PIXEL_BYTES);
    482    if (!tempBuffer)
    483       return;
    484 
    485    assert(srcType != dstType);
    486 
    487    switch (srcType) {
    488    case GL_UNSIGNED_BYTE:
    489       if (dstType == GL_UNSIGNED_SHORT) {
    490          const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
    491          GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
    492          GLuint i;
    493          for (i = 0; i < count; i++) {
    494             if (!mask || mask[i]) {
    495                dst2[i][RCOMP] = UBYTE_TO_USHORT(src1[i][RCOMP]);
    496                dst2[i][GCOMP] = UBYTE_TO_USHORT(src1[i][GCOMP]);
    497                dst2[i][BCOMP] = UBYTE_TO_USHORT(src1[i][BCOMP]);
    498                dst2[i][ACOMP] = UBYTE_TO_USHORT(src1[i][ACOMP]);
    499             }
    500          }
    501          if (useTemp)
    502             memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
    503       }
    504       else {
    505          const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
    506          GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
    507          GLuint i;
    508          assert(dstType == GL_FLOAT);
    509          for (i = 0; i < count; i++) {
    510             if (!mask || mask[i]) {
    511                dst4[i][RCOMP] = UBYTE_TO_FLOAT(src1[i][RCOMP]);
    512                dst4[i][GCOMP] = UBYTE_TO_FLOAT(src1[i][GCOMP]);
    513                dst4[i][BCOMP] = UBYTE_TO_FLOAT(src1[i][BCOMP]);
    514                dst4[i][ACOMP] = UBYTE_TO_FLOAT(src1[i][ACOMP]);
    515             }
    516          }
    517          if (useTemp)
    518             memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
    519       }
    520       break;
    521    case GL_UNSIGNED_SHORT:
    522       if (dstType == GL_UNSIGNED_BYTE) {
    523          const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
    524          GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
    525          GLuint i;
    526          for (i = 0; i < count; i++) {
    527             if (!mask || mask[i]) {
    528                dst1[i][RCOMP] = USHORT_TO_UBYTE(src2[i][RCOMP]);
    529                dst1[i][GCOMP] = USHORT_TO_UBYTE(src2[i][GCOMP]);
    530                dst1[i][BCOMP] = USHORT_TO_UBYTE(src2[i][BCOMP]);
    531                dst1[i][ACOMP] = USHORT_TO_UBYTE(src2[i][ACOMP]);
    532             }
    533          }
    534          if (useTemp)
    535             memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
    536       }
    537       else {
    538          const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
    539          GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
    540          GLuint i;
    541          assert(dstType == GL_FLOAT);
    542          for (i = 0; i < count; i++) {
    543             if (!mask || mask[i]) {
    544                dst4[i][RCOMP] = USHORT_TO_FLOAT(src2[i][RCOMP]);
    545                dst4[i][GCOMP] = USHORT_TO_FLOAT(src2[i][GCOMP]);
    546                dst4[i][BCOMP] = USHORT_TO_FLOAT(src2[i][BCOMP]);
    547                dst4[i][ACOMP] = USHORT_TO_FLOAT(src2[i][ACOMP]);
    548             }
    549          }
    550          if (useTemp)
    551             memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
    552       }
    553       break;
    554    case GL_FLOAT:
    555       if (dstType == GL_UNSIGNED_BYTE) {
    556          const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
    557          GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
    558          GLuint i;
    559          for (i = 0; i < count; i++) {
    560             if (!mask || mask[i])
    561                _mesa_unclamped_float_rgba_to_ubyte(dst1[i], src4[i]);
    562          }
    563          if (useTemp)
    564             memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
    565       }
    566       else {
    567          const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
    568          GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
    569          GLuint i;
    570          assert(dstType == GL_UNSIGNED_SHORT);
    571          for (i = 0; i < count; i++) {
    572             if (!mask || mask[i]) {
    573                UNCLAMPED_FLOAT_TO_USHORT(dst2[i][RCOMP], src4[i][RCOMP]);
    574                UNCLAMPED_FLOAT_TO_USHORT(dst2[i][GCOMP], src4[i][GCOMP]);
    575                UNCLAMPED_FLOAT_TO_USHORT(dst2[i][BCOMP], src4[i][BCOMP]);
    576                UNCLAMPED_FLOAT_TO_USHORT(dst2[i][ACOMP], src4[i][ACOMP]);
    577             }
    578          }
    579          if (useTemp)
    580             memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
    581       }
    582       break;
    583    default:
    584       _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors");
    585    }
    586 
    587    free(tempBuffer);
    588 }
    589 
    590 
    591 
    592 
    593 /**
    594  * Perform basic clipping for glDrawPixels.  The image's position and size
    595  * and the unpack SkipPixels and SkipRows are adjusted so that the image
    596  * region is entirely within the window and scissor bounds.
    597  * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1).
    598  * If Pixel.ZoomY is -1, *destY will be changed to be the first row which
    599  * we'll actually write.  Beforehand, *destY-1 is the first drawing row.
    600  *
    601  * \return  GL_TRUE if image is ready for drawing or
    602  *          GL_FALSE if image was completely clipped away (draw nothing)
    603  */
    604 GLboolean
    605 _mesa_clip_drawpixels(const struct gl_context *ctx,
    606                       GLint *destX, GLint *destY,
    607                       GLsizei *width, GLsizei *height,
    608                       struct gl_pixelstore_attrib *unpack)
    609 {
    610    const struct gl_framebuffer *buffer = ctx->DrawBuffer;
    611 
    612    if (unpack->RowLength == 0) {
    613       unpack->RowLength = *width;
    614    }
    615 
    616    assert(ctx->Pixel.ZoomX == 1.0F);
    617    assert(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F);
    618 
    619    /* left clipping */
    620    if (*destX < buffer->_Xmin) {
    621       unpack->SkipPixels += (buffer->_Xmin - *destX);
    622       *width -= (buffer->_Xmin - *destX);
    623       *destX = buffer->_Xmin;
    624    }
    625    /* right clipping */
    626    if (*destX + *width > buffer->_Xmax)
    627       *width -= (*destX + *width - buffer->_Xmax);
    628 
    629    if (*width <= 0)
    630       return GL_FALSE;
    631 
    632    if (ctx->Pixel.ZoomY == 1.0F) {
    633       /* bottom clipping */
    634       if (*destY < buffer->_Ymin) {
    635          unpack->SkipRows += (buffer->_Ymin - *destY);
    636          *height -= (buffer->_Ymin - *destY);
    637          *destY = buffer->_Ymin;
    638       }
    639       /* top clipping */
    640       if (*destY + *height > buffer->_Ymax)
    641          *height -= (*destY + *height - buffer->_Ymax);
    642    }
    643    else { /* upside down */
    644       /* top clipping */
    645       if (*destY > buffer->_Ymax) {
    646          unpack->SkipRows += (*destY - buffer->_Ymax);
    647          *height -= (*destY - buffer->_Ymax);
    648          *destY = buffer->_Ymax;
    649       }
    650       /* bottom clipping */
    651       if (*destY - *height < buffer->_Ymin)
    652          *height -= (buffer->_Ymin - (*destY - *height));
    653       /* adjust destY so it's the first row to write to */
    654       (*destY)--;
    655    }
    656 
    657    if (*height <= 0)
    658       return GL_FALSE;
    659 
    660    return GL_TRUE;
    661 }
    662 
    663 
    664 /**
    665  * Perform clipping for glReadPixels.  The image's window position
    666  * and size, and the pack skipPixels, skipRows and rowLength are adjusted
    667  * so that the image region is entirely within the window bounds.
    668  * Note: this is different from _mesa_clip_drawpixels() in that the
    669  * scissor box is ignored, and we use the bounds of the current readbuffer
    670  * surface or the attached image.
    671  *
    672  * \return  GL_TRUE if region to read is in bounds
    673  *          GL_FALSE if region is completely out of bounds (nothing to read)
    674  */
    675 GLboolean
    676 _mesa_clip_readpixels(const struct gl_context *ctx,
    677                       GLint *srcX, GLint *srcY,
    678                       GLsizei *width, GLsizei *height,
    679                       struct gl_pixelstore_attrib *pack)
    680 {
    681    const struct gl_framebuffer *buffer = ctx->ReadBuffer;
    682    struct gl_renderbuffer *rb = buffer->_ColorReadBuffer;
    683    GLsizei clip_width;
    684    GLsizei clip_height;
    685 
    686    if (rb) {
    687       clip_width = rb->Width;
    688       clip_height = rb->Height;
    689    } else {
    690       clip_width = buffer->Width;
    691       clip_height = buffer->Height;
    692    }
    693 
    694 
    695    if (pack->RowLength == 0) {
    696       pack->RowLength = *width;
    697    }
    698 
    699    /* left clipping */
    700    if (*srcX < 0) {
    701       pack->SkipPixels += (0 - *srcX);
    702       *width -= (0 - *srcX);
    703       *srcX = 0;
    704    }
    705    /* right clipping */
    706    if (*srcX + *width > clip_width)
    707       *width -= (*srcX + *width - clip_width);
    708 
    709    if (*width <= 0)
    710       return GL_FALSE;
    711 
    712    /* bottom clipping */
    713    if (*srcY < 0) {
    714       pack->SkipRows += (0 - *srcY);
    715       *height -= (0 - *srcY);
    716       *srcY = 0;
    717    }
    718    /* top clipping */
    719    if (*srcY + *height > clip_height)
    720       *height -= (*srcY + *height - clip_height);
    721 
    722    if (*height <= 0)
    723       return GL_FALSE;
    724 
    725    return GL_TRUE;
    726 }
    727 
    728 
    729 /**
    730  * Do clipping for a glCopyTexSubImage call.
    731  * The framebuffer source region might extend outside the framebuffer
    732  * bounds.  Clip the source region against the framebuffer bounds and
    733  * adjust the texture/dest position and size accordingly.
    734  *
    735  * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise.
    736  */
    737 GLboolean
    738 _mesa_clip_copytexsubimage(const struct gl_context *ctx,
    739                            GLint *destX, GLint *destY,
    740                            GLint *srcX, GLint *srcY,
    741                            GLsizei *width, GLsizei *height)
    742 {
    743    const struct gl_framebuffer *fb = ctx->ReadBuffer;
    744    const GLint srcX0 = *srcX, srcY0 = *srcY;
    745 
    746    if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height,
    747                             srcX, srcY, width, height)) {
    748       *destX = *destX + *srcX - srcX0;
    749       *destY = *destY + *srcY - srcY0;
    750 
    751       return GL_TRUE;
    752    }
    753    else {
    754       return GL_FALSE;
    755    }
    756 }
    757 
    758 
    759 
    760 /**
    761  * Clip the rectangle defined by (x, y, width, height) against the bounds
    762  * specified by [xmin, xmax) and [ymin, ymax).
    763  * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise.
    764  */
    765 GLboolean
    766 _mesa_clip_to_region(GLint xmin, GLint ymin,
    767                      GLint xmax, GLint ymax,
    768                      GLint *x, GLint *y,
    769                      GLsizei *width, GLsizei *height )
    770 {
    771    /* left clipping */
    772    if (*x < xmin) {
    773       *width -= (xmin - *x);
    774       *x = xmin;
    775    }
    776 
    777    /* right clipping */
    778    if (*x + *width > xmax)
    779       *width -= (*x + *width - xmax);
    780 
    781    if (*width <= 0)
    782       return GL_FALSE;
    783 
    784    /* bottom (or top) clipping */
    785    if (*y < ymin) {
    786       *height -= (ymin - *y);
    787       *y = ymin;
    788    }
    789 
    790    /* top (or bottom) clipping */
    791    if (*y + *height > ymax)
    792       *height -= (*y + *height - ymax);
    793 
    794    if (*height <= 0)
    795       return GL_FALSE;
    796 
    797    return GL_TRUE;
    798 }
    799 
    800 
    801 /**
    802  * Clip dst coords against Xmax (or Ymax).
    803  */
    804 static inline void
    805 clip_right_or_top(GLint *srcX0, GLint *srcX1,
    806                   GLint *dstX0, GLint *dstX1,
    807                   GLint maxValue)
    808 {
    809    GLfloat t, bias;
    810 
    811    if (*dstX1 > maxValue) {
    812       /* X1 outside right edge */
    813       assert(*dstX0 < maxValue); /* X0 should be inside right edge */
    814       t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
    815       /* chop off [t, 1] part */
    816       assert(t >= 0.0 && t <= 1.0);
    817       *dstX1 = maxValue;
    818       bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
    819       *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
    820    }
    821    else if (*dstX0 > maxValue) {
    822       /* X0 outside right edge */
    823       assert(*dstX1 < maxValue); /* X1 should be inside right edge */
    824       t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
    825       /* chop off [t, 1] part */
    826       assert(t >= 0.0 && t <= 1.0);
    827       *dstX0 = maxValue;
    828       bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F;
    829       *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
    830    }
    831 }
    832 
    833 
    834 /**
    835  * Clip dst coords against Xmin (or Ymin).
    836  */
    837 static inline void
    838 clip_left_or_bottom(GLint *srcX0, GLint *srcX1,
    839                     GLint *dstX0, GLint *dstX1,
    840                     GLint minValue)
    841 {
    842    GLfloat t, bias;
    843 
    844    if (*dstX0 < minValue) {
    845       /* X0 outside left edge */
    846       assert(*dstX1 > minValue); /* X1 should be inside left edge */
    847       t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
    848       /* chop off [0, t] part */
    849       assert(t >= 0.0 && t <= 1.0);
    850       *dstX0 = minValue;
    851       bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
    852       *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
    853    }
    854    else if (*dstX1 < minValue) {
    855       /* X1 outside left edge */
    856       assert(*dstX0 > minValue); /* X0 should be inside left edge */
    857       t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
    858       /* chop off [0, t] part */
    859       assert(t >= 0.0 && t <= 1.0);
    860       *dstX1 = minValue;
    861       bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F;
    862       *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
    863    }
    864 }
    865 
    866 
    867 /**
    868  * Do clipping of blit src/dest rectangles.
    869  * The dest rect is clipped against both the buffer bounds and scissor bounds.
    870  * The src rect is just clipped against the buffer bounds.
    871  *
    872  * When either the src or dest rect is clipped, the other is also clipped
    873  * proportionately!
    874  *
    875  * Note that X0 need not be less than X1 (same for Y) for either the source
    876  * and dest rects.  That makes the clipping a little trickier.
    877  *
    878  * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped
    879  */
    880 GLboolean
    881 _mesa_clip_blit(struct gl_context *ctx,
    882                 const struct gl_framebuffer *readFb,
    883                 const struct gl_framebuffer *drawFb,
    884                 GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
    885                 GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1)
    886 {
    887    const GLint srcXmin = 0;
    888    const GLint srcXmax = readFb->Width;
    889    const GLint srcYmin = 0;
    890    const GLint srcYmax = readFb->Height;
    891 
    892    /* these include scissor bounds */
    893    const GLint dstXmin = drawFb->_Xmin;
    894    const GLint dstXmax = drawFb->_Xmax;
    895    const GLint dstYmin = drawFb->_Ymin;
    896    const GLint dstYmax = drawFb->_Ymax;
    897 
    898    /*
    899    printf("PreClipX:  src: %d .. %d  dst: %d .. %d\n",
    900           *srcX0, *srcX1, *dstX0, *dstX1);
    901    printf("PreClipY:  src: %d .. %d  dst: %d .. %d\n",
    902           *srcY0, *srcY1, *dstY0, *dstY1);
    903    */
    904 
    905    /* trivial rejection tests */
    906    if (*dstX0 == *dstX1)
    907       return GL_FALSE; /* no width */
    908    if (*dstX0 <= dstXmin && *dstX1 <= dstXmin)
    909       return GL_FALSE; /* totally out (left) of bounds */
    910    if (*dstX0 >= dstXmax && *dstX1 >= dstXmax)
    911       return GL_FALSE; /* totally out (right) of bounds */
    912 
    913    if (*dstY0 == *dstY1)
    914       return GL_FALSE;
    915    if (*dstY0 <= dstYmin && *dstY1 <= dstYmin)
    916       return GL_FALSE;
    917    if (*dstY0 >= dstYmax && *dstY1 >= dstYmax)
    918       return GL_FALSE;
    919 
    920    if (*srcX0 == *srcX1)
    921       return GL_FALSE;
    922    if (*srcX0 <= srcXmin && *srcX1 <= srcXmin)
    923       return GL_FALSE;
    924    if (*srcX0 >= srcXmax && *srcX1 >= srcXmax)
    925       return GL_FALSE;
    926 
    927    if (*srcY0 == *srcY1)
    928       return GL_FALSE;
    929    if (*srcY0 <= srcYmin && *srcY1 <= srcYmin)
    930       return GL_FALSE;
    931    if (*srcY0 >= srcYmax && *srcY1 >= srcYmax)
    932       return GL_FALSE;
    933 
    934    /*
    935     * dest clip
    936     */
    937    clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax);
    938    clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax);
    939    clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin);
    940    clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin);
    941 
    942    /*
    943     * src clip (just swap src/dst values from above)
    944     */
    945    clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax);
    946    clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax);
    947    clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin);
    948    clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin);
    949 
    950    /*
    951    printf("PostClipX: src: %d .. %d  dst: %d .. %d\n",
    952           *srcX0, *srcX1, *dstX0, *dstX1);
    953    printf("PostClipY: src: %d .. %d  dst: %d .. %d\n",
    954           *srcY0, *srcY1, *dstY0, *dstY1);
    955    */
    956 
    957    assert(*dstX0 >= dstXmin);
    958    assert(*dstX0 <= dstXmax);
    959    assert(*dstX1 >= dstXmin);
    960    assert(*dstX1 <= dstXmax);
    961 
    962    assert(*dstY0 >= dstYmin);
    963    assert(*dstY0 <= dstYmax);
    964    assert(*dstY1 >= dstYmin);
    965    assert(*dstY1 <= dstYmax);
    966 
    967    assert(*srcX0 >= srcXmin);
    968    assert(*srcX0 <= srcXmax);
    969    assert(*srcX1 >= srcXmin);
    970    assert(*srcX1 <= srcXmax);
    971 
    972    assert(*srcY0 >= srcYmin);
    973    assert(*srcY0 <= srcYmax);
    974    assert(*srcY1 >= srcYmin);
    975    assert(*srcY1 <= srcYmax);
    976 
    977    return GL_TRUE;
    978 }
    979 
    980 /**
    981  * Swap the bytes in a 2D image.
    982  *
    983  * using the packing information this swaps the bytes
    984  * according to the format and type of data being input.
    985  * It takes into a/c various packing parameters like
    986  * Alignment and RowLength.
    987  */
    988 void
    989 _mesa_swap_bytes_2d_image(GLenum format, GLenum type,
    990                           const struct gl_pixelstore_attrib *packing,
    991                           GLsizei width, GLsizei height,
    992                           GLvoid *dst, const GLvoid *src)
    993 {
    994    GLint swapSize = _mesa_sizeof_packed_type(type);
    995 
    996    assert(packing->SwapBytes);
    997 
    998    if (swapSize == 2 || swapSize == 4) {
    999       int swapsPerPixel = _mesa_bytes_per_pixel(format, type) / swapSize;
   1000       int stride = _mesa_image_row_stride(packing, width, format, type);
   1001       int row;
   1002       uint8_t *dstrow;
   1003       const uint8_t *srcrow;
   1004       assert(swapsPerPixel > 0);
   1005       assert(_mesa_bytes_per_pixel(format, type) % swapSize == 0);
   1006       dstrow = dst;
   1007       srcrow = src;
   1008       for (row = 0; row < height; row++) {
   1009          if (swapSize == 2)
   1010             swap2_copy((GLushort *)dstrow, (GLushort *)srcrow, width * swapsPerPixel);
   1011          else if (swapSize == 4)
   1012             swap4_copy((GLuint *)dstrow, (GLuint *)srcrow, width * swapsPerPixel);
   1013          dstrow += stride;
   1014          srcrow += stride;
   1015       }
   1016    }
   1017 }
   1018