Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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