image.c revision 848b8605
1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the "Software"), 9848b8605Smrg * to deal in the Software without restriction, including without limitation 10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 12848b8605Smrg * Software is furnished to do so, subject to the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice shall be included 15848b8605Smrg * in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 24848b8605Smrg */ 25848b8605Smrg 26848b8605Smrg 27848b8605Smrg/** 28848b8605Smrg * \file image.c 29848b8605Smrg * Image handling. 30848b8605Smrg */ 31848b8605Smrg 32848b8605Smrg 33848b8605Smrg#include "glheader.h" 34848b8605Smrg#include "colormac.h" 35848b8605Smrg#include "glformats.h" 36848b8605Smrg#include "image.h" 37848b8605Smrg#include "imports.h" 38848b8605Smrg#include "macros.h" 39848b8605Smrg#include "mtypes.h" 40848b8605Smrg 41848b8605Smrg 42848b8605Smrg 43848b8605Smrg/** 44848b8605Smrg * Flip the order of the 2 bytes in each word in the given array. 45848b8605Smrg * 46848b8605Smrg * \param p array. 47848b8605Smrg * \param n number of words. 48848b8605Smrg */ 49848b8605Smrgvoid 50848b8605Smrg_mesa_swap2( GLushort *p, GLuint n ) 51848b8605Smrg{ 52848b8605Smrg GLuint i; 53848b8605Smrg for (i = 0; i < n; i++) { 54848b8605Smrg p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00); 55848b8605Smrg } 56848b8605Smrg} 57848b8605Smrg 58848b8605Smrg 59848b8605Smrg 60848b8605Smrg/* 61848b8605Smrg * Flip the order of the 4 bytes in each word in the given array. 62848b8605Smrg */ 63848b8605Smrgvoid 64848b8605Smrg_mesa_swap4( GLuint *p, GLuint n ) 65848b8605Smrg{ 66848b8605Smrg GLuint i, a, b; 67848b8605Smrg for (i = 0; i < n; i++) { 68848b8605Smrg b = p[i]; 69848b8605Smrg a = (b >> 24) 70848b8605Smrg | ((b >> 8) & 0xff00) 71848b8605Smrg | ((b << 8) & 0xff0000) 72848b8605Smrg | ((b << 24) & 0xff000000); 73848b8605Smrg p[i] = a; 74848b8605Smrg } 75848b8605Smrg} 76848b8605Smrg 77848b8605Smrg 78848b8605Smrg/** 79848b8605Smrg * Return the byte offset of a specific pixel in an image (1D, 2D or 3D). 80848b8605Smrg * 81848b8605Smrg * Pixel unpacking/packing parameters are observed according to \p packing. 82848b8605Smrg * 83848b8605Smrg * \param dimensions either 1, 2 or 3 to indicate dimensionality of image 84848b8605Smrg * \param packing the pixelstore attributes 85848b8605Smrg * \param width the image width 86848b8605Smrg * \param height the image height 87848b8605Smrg * \param format the pixel format (must be validated beforehand) 88848b8605Smrg * \param type the pixel data type (must be validated beforehand) 89848b8605Smrg * \param img which image in the volume (0 for 1D or 2D images) 90848b8605Smrg * \param row row of pixel in the image (0 for 1D images) 91848b8605Smrg * \param column column of pixel in the image 92848b8605Smrg * 93848b8605Smrg * \return offset of pixel. 94848b8605Smrg * 95848b8605Smrg * \sa gl_pixelstore_attrib. 96848b8605Smrg */ 97848b8605SmrgGLintptr 98848b8605Smrg_mesa_image_offset( GLuint dimensions, 99848b8605Smrg const struct gl_pixelstore_attrib *packing, 100848b8605Smrg GLsizei width, GLsizei height, 101848b8605Smrg GLenum format, GLenum type, 102848b8605Smrg GLint img, GLint row, GLint column ) 103848b8605Smrg{ 104848b8605Smrg GLint alignment; /* 1, 2 or 4 */ 105848b8605Smrg GLint pixels_per_row; 106848b8605Smrg GLint rows_per_image; 107848b8605Smrg GLint skiprows; 108848b8605Smrg GLint skippixels; 109848b8605Smrg GLint skipimages; /* for 3-D volume images */ 110848b8605Smrg GLintptr offset; 111848b8605Smrg 112848b8605Smrg ASSERT(dimensions >= 1 && dimensions <= 3); 113848b8605Smrg 114848b8605Smrg alignment = packing->Alignment; 115848b8605Smrg if (packing->RowLength > 0) { 116848b8605Smrg pixels_per_row = packing->RowLength; 117848b8605Smrg } 118848b8605Smrg else { 119848b8605Smrg pixels_per_row = width; 120848b8605Smrg } 121848b8605Smrg if (packing->ImageHeight > 0) { 122848b8605Smrg rows_per_image = packing->ImageHeight; 123848b8605Smrg } 124848b8605Smrg else { 125848b8605Smrg rows_per_image = height; 126848b8605Smrg } 127848b8605Smrg 128848b8605Smrg skippixels = packing->SkipPixels; 129848b8605Smrg /* Note: SKIP_ROWS _is_ used for 1D images */ 130848b8605Smrg skiprows = packing->SkipRows; 131848b8605Smrg /* Note: SKIP_IMAGES is only used for 3D images */ 132848b8605Smrg skipimages = (dimensions == 3) ? packing->SkipImages : 0; 133848b8605Smrg 134848b8605Smrg if (type == GL_BITMAP) { 135848b8605Smrg /* BITMAP data */ 136848b8605Smrg GLint bytes_per_row; 137848b8605Smrg GLint bytes_per_image; 138848b8605Smrg /* components per pixel for color or stencil index: */ 139848b8605Smrg const GLint comp_per_pixel = 1; 140848b8605Smrg 141848b8605Smrg /* The pixel type and format should have been error checked earlier */ 142848b8605Smrg assert(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX); 143848b8605Smrg 144848b8605Smrg bytes_per_row = alignment 145848b8605Smrg * CEILING( comp_per_pixel*pixels_per_row, 8*alignment ); 146848b8605Smrg 147848b8605Smrg bytes_per_image = bytes_per_row * rows_per_image; 148848b8605Smrg 149848b8605Smrg offset = (skipimages + img) * bytes_per_image 150848b8605Smrg + (skiprows + row) * bytes_per_row 151848b8605Smrg + (skippixels + column) / 8; 152848b8605Smrg } 153848b8605Smrg else { 154848b8605Smrg /* Non-BITMAP data */ 155848b8605Smrg GLint bytes_per_pixel, bytes_per_row, remainder, bytes_per_image; 156848b8605Smrg GLint topOfImage; 157848b8605Smrg 158848b8605Smrg bytes_per_pixel = _mesa_bytes_per_pixel( format, type ); 159848b8605Smrg 160848b8605Smrg /* The pixel type and format should have been error checked earlier */ 161848b8605Smrg assert(bytes_per_pixel > 0); 162848b8605Smrg 163848b8605Smrg bytes_per_row = pixels_per_row * bytes_per_pixel; 164848b8605Smrg remainder = bytes_per_row % alignment; 165848b8605Smrg if (remainder > 0) 166848b8605Smrg bytes_per_row += (alignment - remainder); 167848b8605Smrg 168848b8605Smrg ASSERT(bytes_per_row % alignment == 0); 169848b8605Smrg 170848b8605Smrg bytes_per_image = bytes_per_row * rows_per_image; 171848b8605Smrg 172848b8605Smrg if (packing->Invert) { 173848b8605Smrg /* set pixel_addr to the last row */ 174848b8605Smrg topOfImage = bytes_per_row * (height - 1); 175848b8605Smrg bytes_per_row = -bytes_per_row; 176848b8605Smrg } 177848b8605Smrg else { 178848b8605Smrg topOfImage = 0; 179848b8605Smrg } 180848b8605Smrg 181848b8605Smrg /* compute final pixel address */ 182848b8605Smrg offset = (skipimages + img) * bytes_per_image 183848b8605Smrg + topOfImage 184848b8605Smrg + (skiprows + row) * bytes_per_row 185848b8605Smrg + (skippixels + column) * bytes_per_pixel; 186848b8605Smrg } 187848b8605Smrg 188848b8605Smrg return offset; 189848b8605Smrg} 190848b8605Smrg 191848b8605Smrg 192848b8605Smrg/** 193848b8605Smrg * Return the address of a specific pixel in an image (1D, 2D or 3D). 194848b8605Smrg * 195848b8605Smrg * Pixel unpacking/packing parameters are observed according to \p packing. 196848b8605Smrg * 197848b8605Smrg * \param dimensions either 1, 2 or 3 to indicate dimensionality of image 198848b8605Smrg * \param packing the pixelstore attributes 199848b8605Smrg * \param image starting address of image data 200848b8605Smrg * \param width the image width 201848b8605Smrg * \param height the image height 202848b8605Smrg * \param format the pixel format (must be validated beforehand) 203848b8605Smrg * \param type the pixel data type (must be validated beforehand) 204848b8605Smrg * \param img which image in the volume (0 for 1D or 2D images) 205848b8605Smrg * \param row row of pixel in the image (0 for 1D images) 206848b8605Smrg * \param column column of pixel in the image 207848b8605Smrg * 208848b8605Smrg * \return address of pixel. 209848b8605Smrg * 210848b8605Smrg * \sa gl_pixelstore_attrib. 211848b8605Smrg */ 212848b8605SmrgGLvoid * 213848b8605Smrg_mesa_image_address( GLuint dimensions, 214848b8605Smrg const struct gl_pixelstore_attrib *packing, 215848b8605Smrg const GLvoid *image, 216848b8605Smrg GLsizei width, GLsizei height, 217848b8605Smrg GLenum format, GLenum type, 218848b8605Smrg GLint img, GLint row, GLint column ) 219848b8605Smrg{ 220848b8605Smrg const GLubyte *addr = (const GLubyte *) image; 221848b8605Smrg 222848b8605Smrg addr += _mesa_image_offset(dimensions, packing, width, height, 223848b8605Smrg format, type, img, row, column); 224848b8605Smrg 225848b8605Smrg return (GLvoid *) addr; 226848b8605Smrg} 227848b8605Smrg 228848b8605Smrg 229848b8605SmrgGLvoid * 230848b8605Smrg_mesa_image_address1d( const struct gl_pixelstore_attrib *packing, 231848b8605Smrg const GLvoid *image, 232848b8605Smrg GLsizei width, 233848b8605Smrg GLenum format, GLenum type, 234848b8605Smrg GLint column ) 235848b8605Smrg{ 236848b8605Smrg return _mesa_image_address(1, packing, image, width, 1, 237848b8605Smrg format, type, 0, 0, column); 238848b8605Smrg} 239848b8605Smrg 240848b8605Smrg 241848b8605SmrgGLvoid * 242848b8605Smrg_mesa_image_address2d( const struct gl_pixelstore_attrib *packing, 243848b8605Smrg const GLvoid *image, 244848b8605Smrg GLsizei width, GLsizei height, 245848b8605Smrg GLenum format, GLenum type, 246848b8605Smrg GLint row, GLint column ) 247848b8605Smrg{ 248848b8605Smrg return _mesa_image_address(2, packing, image, width, height, 249848b8605Smrg format, type, 0, row, column); 250848b8605Smrg} 251848b8605Smrg 252848b8605Smrg 253848b8605SmrgGLvoid * 254848b8605Smrg_mesa_image_address3d( const struct gl_pixelstore_attrib *packing, 255848b8605Smrg const GLvoid *image, 256848b8605Smrg GLsizei width, GLsizei height, 257848b8605Smrg GLenum format, GLenum type, 258848b8605Smrg GLint img, GLint row, GLint column ) 259848b8605Smrg{ 260848b8605Smrg return _mesa_image_address(3, packing, image, width, height, 261848b8605Smrg format, type, img, row, column); 262848b8605Smrg} 263848b8605Smrg 264848b8605Smrg 265848b8605Smrg 266848b8605Smrg/** 267848b8605Smrg * Compute the stride (in bytes) between image rows. 268848b8605Smrg * 269848b8605Smrg * \param packing the pixelstore attributes 270848b8605Smrg * \param width image width. 271848b8605Smrg * \param format pixel format. 272848b8605Smrg * \param type pixel data type. 273848b8605Smrg * 274848b8605Smrg * \return the stride in bytes for the given parameters, or -1 if error 275848b8605Smrg */ 276848b8605SmrgGLint 277848b8605Smrg_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing, 278848b8605Smrg GLint width, GLenum format, GLenum type ) 279848b8605Smrg{ 280848b8605Smrg GLint bytesPerRow, remainder; 281848b8605Smrg 282848b8605Smrg ASSERT(packing); 283848b8605Smrg 284848b8605Smrg if (type == GL_BITMAP) { 285848b8605Smrg if (packing->RowLength == 0) { 286848b8605Smrg bytesPerRow = (width + 7) / 8; 287848b8605Smrg } 288848b8605Smrg else { 289848b8605Smrg bytesPerRow = (packing->RowLength + 7) / 8; 290848b8605Smrg } 291848b8605Smrg } 292848b8605Smrg else { 293848b8605Smrg /* Non-BITMAP data */ 294848b8605Smrg const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); 295848b8605Smrg if (bytesPerPixel <= 0) 296848b8605Smrg return -1; /* error */ 297848b8605Smrg if (packing->RowLength == 0) { 298848b8605Smrg bytesPerRow = bytesPerPixel * width; 299848b8605Smrg } 300848b8605Smrg else { 301848b8605Smrg bytesPerRow = bytesPerPixel * packing->RowLength; 302848b8605Smrg } 303848b8605Smrg } 304848b8605Smrg 305848b8605Smrg remainder = bytesPerRow % packing->Alignment; 306848b8605Smrg if (remainder > 0) { 307848b8605Smrg bytesPerRow += (packing->Alignment - remainder); 308848b8605Smrg } 309848b8605Smrg 310848b8605Smrg if (packing->Invert) { 311848b8605Smrg /* negate the bytes per row (negative row stride) */ 312848b8605Smrg bytesPerRow = -bytesPerRow; 313848b8605Smrg } 314848b8605Smrg 315848b8605Smrg return bytesPerRow; 316848b8605Smrg} 317848b8605Smrg 318848b8605Smrg 319848b8605Smrg/* 320848b8605Smrg * Compute the stride between images in a 3D texture (in bytes) for the given 321848b8605Smrg * pixel packing parameters and image width, format and type. 322848b8605Smrg */ 323848b8605SmrgGLint 324848b8605Smrg_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing, 325848b8605Smrg GLint width, GLint height, 326848b8605Smrg GLenum format, GLenum type ) 327848b8605Smrg{ 328848b8605Smrg GLint bytesPerRow, bytesPerImage, remainder; 329848b8605Smrg 330848b8605Smrg ASSERT(packing); 331848b8605Smrg 332848b8605Smrg if (type == GL_BITMAP) { 333848b8605Smrg if (packing->RowLength == 0) { 334848b8605Smrg bytesPerRow = (width + 7) / 8; 335848b8605Smrg } 336848b8605Smrg else { 337848b8605Smrg bytesPerRow = (packing->RowLength + 7) / 8; 338848b8605Smrg } 339848b8605Smrg } 340848b8605Smrg else { 341848b8605Smrg const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); 342848b8605Smrg 343848b8605Smrg if (bytesPerPixel <= 0) 344848b8605Smrg return -1; /* error */ 345848b8605Smrg if (packing->RowLength == 0) { 346848b8605Smrg bytesPerRow = bytesPerPixel * width; 347848b8605Smrg } 348848b8605Smrg else { 349848b8605Smrg bytesPerRow = bytesPerPixel * packing->RowLength; 350848b8605Smrg } 351848b8605Smrg } 352848b8605Smrg 353848b8605Smrg remainder = bytesPerRow % packing->Alignment; 354848b8605Smrg if (remainder > 0) 355848b8605Smrg bytesPerRow += (packing->Alignment - remainder); 356848b8605Smrg 357848b8605Smrg if (packing->ImageHeight == 0) 358848b8605Smrg bytesPerImage = bytesPerRow * height; 359848b8605Smrg else 360848b8605Smrg bytesPerImage = bytesPerRow * packing->ImageHeight; 361848b8605Smrg 362848b8605Smrg return bytesPerImage; 363848b8605Smrg} 364848b8605Smrg 365848b8605Smrg 366848b8605Smrg 367848b8605Smrg/** 368848b8605Smrg * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel. 369848b8605Smrg * This is typically used to convert a bitmap into a GLubyte/pixel texture. 370848b8605Smrg * "On" bits will set texels to \p onValue. 371848b8605Smrg * "Off" bits will not modify texels. 372848b8605Smrg * \param width src bitmap width in pixels 373848b8605Smrg * \param height src bitmap height in pixels 374848b8605Smrg * \param unpack bitmap unpacking state 375848b8605Smrg * \param bitmap the src bitmap data 376848b8605Smrg * \param destBuffer start of dest buffer 377848b8605Smrg * \param destStride row stride in dest buffer 378848b8605Smrg * \param onValue if bit is 1, set destBuffer pixel to this value 379848b8605Smrg */ 380848b8605Smrgvoid 381848b8605Smrg_mesa_expand_bitmap(GLsizei width, GLsizei height, 382848b8605Smrg const struct gl_pixelstore_attrib *unpack, 383848b8605Smrg const GLubyte *bitmap, 384848b8605Smrg GLubyte *destBuffer, GLint destStride, 385848b8605Smrg GLubyte onValue) 386848b8605Smrg{ 387848b8605Smrg const GLubyte *srcRow = (const GLubyte *) 388848b8605Smrg _mesa_image_address2d(unpack, bitmap, width, height, 389848b8605Smrg GL_COLOR_INDEX, GL_BITMAP, 0, 0); 390848b8605Smrg const GLint srcStride = _mesa_image_row_stride(unpack, width, 391848b8605Smrg GL_COLOR_INDEX, GL_BITMAP); 392848b8605Smrg GLint row, col; 393848b8605Smrg 394848b8605Smrg#define SET_PIXEL(COL, ROW) \ 395848b8605Smrg destBuffer[(ROW) * destStride + (COL)] = onValue; 396848b8605Smrg 397848b8605Smrg for (row = 0; row < height; row++) { 398848b8605Smrg const GLubyte *src = srcRow; 399848b8605Smrg 400848b8605Smrg if (unpack->LsbFirst) { 401848b8605Smrg /* Lsb first */ 402848b8605Smrg GLubyte mask = 1U << (unpack->SkipPixels & 0x7); 403848b8605Smrg for (col = 0; col < width; col++) { 404848b8605Smrg 405848b8605Smrg if (*src & mask) { 406848b8605Smrg SET_PIXEL(col, row); 407848b8605Smrg } 408848b8605Smrg 409848b8605Smrg if (mask == 128U) { 410848b8605Smrg src++; 411848b8605Smrg mask = 1U; 412848b8605Smrg } 413848b8605Smrg else { 414848b8605Smrg mask = mask << 1; 415848b8605Smrg } 416848b8605Smrg } 417848b8605Smrg 418848b8605Smrg /* get ready for next row */ 419848b8605Smrg if (mask != 1) 420848b8605Smrg src++; 421848b8605Smrg } 422848b8605Smrg else { 423848b8605Smrg /* Msb first */ 424848b8605Smrg GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); 425848b8605Smrg for (col = 0; col < width; col++) { 426848b8605Smrg 427848b8605Smrg if (*src & mask) { 428848b8605Smrg SET_PIXEL(col, row); 429848b8605Smrg } 430848b8605Smrg 431848b8605Smrg if (mask == 1U) { 432848b8605Smrg src++; 433848b8605Smrg mask = 128U; 434848b8605Smrg } 435848b8605Smrg else { 436848b8605Smrg mask = mask >> 1; 437848b8605Smrg } 438848b8605Smrg } 439848b8605Smrg 440848b8605Smrg /* get ready for next row */ 441848b8605Smrg if (mask != 128) 442848b8605Smrg src++; 443848b8605Smrg } 444848b8605Smrg 445848b8605Smrg srcRow += srcStride; 446848b8605Smrg } /* row */ 447848b8605Smrg 448848b8605Smrg#undef SET_PIXEL 449848b8605Smrg} 450848b8605Smrg 451848b8605Smrg 452848b8605Smrg 453848b8605Smrg 454848b8605Smrg/** 455848b8605Smrg * Convert an array of RGBA colors from one datatype to another. 456848b8605Smrg * NOTE: src may equal dst. In that case, we use a temporary buffer. 457848b8605Smrg */ 458848b8605Smrgvoid 459848b8605Smrg_mesa_convert_colors(GLenum srcType, const GLvoid *src, 460848b8605Smrg GLenum dstType, GLvoid *dst, 461848b8605Smrg GLuint count, const GLubyte mask[]) 462848b8605Smrg{ 463848b8605Smrg GLuint *tempBuffer; 464848b8605Smrg const GLboolean useTemp = (src == dst); 465848b8605Smrg 466848b8605Smrg tempBuffer = malloc(count * MAX_PIXEL_BYTES); 467848b8605Smrg if (!tempBuffer) 468848b8605Smrg return; 469848b8605Smrg 470848b8605Smrg ASSERT(srcType != dstType); 471848b8605Smrg 472848b8605Smrg switch (srcType) { 473848b8605Smrg case GL_UNSIGNED_BYTE: 474848b8605Smrg if (dstType == GL_UNSIGNED_SHORT) { 475848b8605Smrg const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src; 476848b8605Smrg GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst); 477848b8605Smrg GLuint i; 478848b8605Smrg for (i = 0; i < count; i++) { 479848b8605Smrg if (!mask || mask[i]) { 480848b8605Smrg dst2[i][RCOMP] = UBYTE_TO_USHORT(src1[i][RCOMP]); 481848b8605Smrg dst2[i][GCOMP] = UBYTE_TO_USHORT(src1[i][GCOMP]); 482848b8605Smrg dst2[i][BCOMP] = UBYTE_TO_USHORT(src1[i][BCOMP]); 483848b8605Smrg dst2[i][ACOMP] = UBYTE_TO_USHORT(src1[i][ACOMP]); 484848b8605Smrg } 485848b8605Smrg } 486848b8605Smrg if (useTemp) 487848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort)); 488848b8605Smrg } 489848b8605Smrg else { 490848b8605Smrg const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src; 491848b8605Smrg GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst); 492848b8605Smrg GLuint i; 493848b8605Smrg ASSERT(dstType == GL_FLOAT); 494848b8605Smrg for (i = 0; i < count; i++) { 495848b8605Smrg if (!mask || mask[i]) { 496848b8605Smrg dst4[i][RCOMP] = UBYTE_TO_FLOAT(src1[i][RCOMP]); 497848b8605Smrg dst4[i][GCOMP] = UBYTE_TO_FLOAT(src1[i][GCOMP]); 498848b8605Smrg dst4[i][BCOMP] = UBYTE_TO_FLOAT(src1[i][BCOMP]); 499848b8605Smrg dst4[i][ACOMP] = UBYTE_TO_FLOAT(src1[i][ACOMP]); 500848b8605Smrg } 501848b8605Smrg } 502848b8605Smrg if (useTemp) 503848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat)); 504848b8605Smrg } 505848b8605Smrg break; 506848b8605Smrg case GL_UNSIGNED_SHORT: 507848b8605Smrg if (dstType == GL_UNSIGNED_BYTE) { 508848b8605Smrg const GLushort (*src2)[4] = (const GLushort (*)[4]) src; 509848b8605Smrg GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst); 510848b8605Smrg GLuint i; 511848b8605Smrg for (i = 0; i < count; i++) { 512848b8605Smrg if (!mask || mask[i]) { 513848b8605Smrg dst1[i][RCOMP] = USHORT_TO_UBYTE(src2[i][RCOMP]); 514848b8605Smrg dst1[i][GCOMP] = USHORT_TO_UBYTE(src2[i][GCOMP]); 515848b8605Smrg dst1[i][BCOMP] = USHORT_TO_UBYTE(src2[i][BCOMP]); 516848b8605Smrg dst1[i][ACOMP] = USHORT_TO_UBYTE(src2[i][ACOMP]); 517848b8605Smrg } 518848b8605Smrg } 519848b8605Smrg if (useTemp) 520848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte)); 521848b8605Smrg } 522848b8605Smrg else { 523848b8605Smrg const GLushort (*src2)[4] = (const GLushort (*)[4]) src; 524848b8605Smrg GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst); 525848b8605Smrg GLuint i; 526848b8605Smrg ASSERT(dstType == GL_FLOAT); 527848b8605Smrg for (i = 0; i < count; i++) { 528848b8605Smrg if (!mask || mask[i]) { 529848b8605Smrg dst4[i][RCOMP] = USHORT_TO_FLOAT(src2[i][RCOMP]); 530848b8605Smrg dst4[i][GCOMP] = USHORT_TO_FLOAT(src2[i][GCOMP]); 531848b8605Smrg dst4[i][BCOMP] = USHORT_TO_FLOAT(src2[i][BCOMP]); 532848b8605Smrg dst4[i][ACOMP] = USHORT_TO_FLOAT(src2[i][ACOMP]); 533848b8605Smrg } 534848b8605Smrg } 535848b8605Smrg if (useTemp) 536848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat)); 537848b8605Smrg } 538848b8605Smrg break; 539848b8605Smrg case GL_FLOAT: 540848b8605Smrg if (dstType == GL_UNSIGNED_BYTE) { 541848b8605Smrg const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src; 542848b8605Smrg GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst); 543848b8605Smrg GLuint i; 544848b8605Smrg for (i = 0; i < count; i++) { 545848b8605Smrg if (!mask || mask[i]) 546848b8605Smrg _mesa_unclamped_float_rgba_to_ubyte(dst1[i], src4[i]); 547848b8605Smrg } 548848b8605Smrg if (useTemp) 549848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte)); 550848b8605Smrg } 551848b8605Smrg else { 552848b8605Smrg const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src; 553848b8605Smrg GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst); 554848b8605Smrg GLuint i; 555848b8605Smrg ASSERT(dstType == GL_UNSIGNED_SHORT); 556848b8605Smrg for (i = 0; i < count; i++) { 557848b8605Smrg if (!mask || mask[i]) { 558848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(dst2[i][RCOMP], src4[i][RCOMP]); 559848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(dst2[i][GCOMP], src4[i][GCOMP]); 560848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(dst2[i][BCOMP], src4[i][BCOMP]); 561848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(dst2[i][ACOMP], src4[i][ACOMP]); 562848b8605Smrg } 563848b8605Smrg } 564848b8605Smrg if (useTemp) 565848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort)); 566848b8605Smrg } 567848b8605Smrg break; 568848b8605Smrg default: 569848b8605Smrg _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors"); 570848b8605Smrg } 571848b8605Smrg 572848b8605Smrg free(tempBuffer); 573848b8605Smrg} 574848b8605Smrg 575848b8605Smrg 576848b8605Smrg 577848b8605Smrg 578848b8605Smrg/** 579848b8605Smrg * Perform basic clipping for glDrawPixels. The image's position and size 580848b8605Smrg * and the unpack SkipPixels and SkipRows are adjusted so that the image 581848b8605Smrg * region is entirely within the window and scissor bounds. 582848b8605Smrg * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1). 583848b8605Smrg * If Pixel.ZoomY is -1, *destY will be changed to be the first row which 584848b8605Smrg * we'll actually write. Beforehand, *destY-1 is the first drawing row. 585848b8605Smrg * 586848b8605Smrg * \return GL_TRUE if image is ready for drawing or 587848b8605Smrg * GL_FALSE if image was completely clipped away (draw nothing) 588848b8605Smrg */ 589848b8605SmrgGLboolean 590848b8605Smrg_mesa_clip_drawpixels(const struct gl_context *ctx, 591848b8605Smrg GLint *destX, GLint *destY, 592848b8605Smrg GLsizei *width, GLsizei *height, 593848b8605Smrg struct gl_pixelstore_attrib *unpack) 594848b8605Smrg{ 595848b8605Smrg const struct gl_framebuffer *buffer = ctx->DrawBuffer; 596848b8605Smrg 597848b8605Smrg if (unpack->RowLength == 0) { 598848b8605Smrg unpack->RowLength = *width; 599848b8605Smrg } 600848b8605Smrg 601848b8605Smrg ASSERT(ctx->Pixel.ZoomX == 1.0F); 602848b8605Smrg ASSERT(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F); 603848b8605Smrg 604848b8605Smrg /* left clipping */ 605848b8605Smrg if (*destX < buffer->_Xmin) { 606848b8605Smrg unpack->SkipPixels += (buffer->_Xmin - *destX); 607848b8605Smrg *width -= (buffer->_Xmin - *destX); 608848b8605Smrg *destX = buffer->_Xmin; 609848b8605Smrg } 610848b8605Smrg /* right clipping */ 611848b8605Smrg if (*destX + *width > buffer->_Xmax) 612848b8605Smrg *width -= (*destX + *width - buffer->_Xmax); 613848b8605Smrg 614848b8605Smrg if (*width <= 0) 615848b8605Smrg return GL_FALSE; 616848b8605Smrg 617848b8605Smrg if (ctx->Pixel.ZoomY == 1.0F) { 618848b8605Smrg /* bottom clipping */ 619848b8605Smrg if (*destY < buffer->_Ymin) { 620848b8605Smrg unpack->SkipRows += (buffer->_Ymin - *destY); 621848b8605Smrg *height -= (buffer->_Ymin - *destY); 622848b8605Smrg *destY = buffer->_Ymin; 623848b8605Smrg } 624848b8605Smrg /* top clipping */ 625848b8605Smrg if (*destY + *height > buffer->_Ymax) 626848b8605Smrg *height -= (*destY + *height - buffer->_Ymax); 627848b8605Smrg } 628848b8605Smrg else { /* upside down */ 629848b8605Smrg /* top clipping */ 630848b8605Smrg if (*destY > buffer->_Ymax) { 631848b8605Smrg unpack->SkipRows += (*destY - buffer->_Ymax); 632848b8605Smrg *height -= (*destY - buffer->_Ymax); 633848b8605Smrg *destY = buffer->_Ymax; 634848b8605Smrg } 635848b8605Smrg /* bottom clipping */ 636848b8605Smrg if (*destY - *height < buffer->_Ymin) 637848b8605Smrg *height -= (buffer->_Ymin - (*destY - *height)); 638848b8605Smrg /* adjust destY so it's the first row to write to */ 639848b8605Smrg (*destY)--; 640848b8605Smrg } 641848b8605Smrg 642848b8605Smrg if (*height <= 0) 643848b8605Smrg return GL_FALSE; 644848b8605Smrg 645848b8605Smrg return GL_TRUE; 646848b8605Smrg} 647848b8605Smrg 648848b8605Smrg 649848b8605Smrg/** 650848b8605Smrg * Perform clipping for glReadPixels. The image's window position 651848b8605Smrg * and size, and the pack skipPixels, skipRows and rowLength are adjusted 652848b8605Smrg * so that the image region is entirely within the window bounds. 653848b8605Smrg * Note: this is different from _mesa_clip_drawpixels() in that the 654848b8605Smrg * scissor box is ignored, and we use the bounds of the current readbuffer 655848b8605Smrg * surface. 656848b8605Smrg * 657848b8605Smrg * \return GL_TRUE if region to read is in bounds 658848b8605Smrg * GL_FALSE if region is completely out of bounds (nothing to read) 659848b8605Smrg */ 660848b8605SmrgGLboolean 661848b8605Smrg_mesa_clip_readpixels(const struct gl_context *ctx, 662848b8605Smrg GLint *srcX, GLint *srcY, 663848b8605Smrg GLsizei *width, GLsizei *height, 664848b8605Smrg struct gl_pixelstore_attrib *pack) 665848b8605Smrg{ 666848b8605Smrg const struct gl_framebuffer *buffer = ctx->ReadBuffer; 667848b8605Smrg 668848b8605Smrg if (pack->RowLength == 0) { 669848b8605Smrg pack->RowLength = *width; 670848b8605Smrg } 671848b8605Smrg 672848b8605Smrg /* left clipping */ 673848b8605Smrg if (*srcX < 0) { 674848b8605Smrg pack->SkipPixels += (0 - *srcX); 675848b8605Smrg *width -= (0 - *srcX); 676848b8605Smrg *srcX = 0; 677848b8605Smrg } 678848b8605Smrg /* right clipping */ 679848b8605Smrg if (*srcX + *width > (GLsizei) buffer->Width) 680848b8605Smrg *width -= (*srcX + *width - buffer->Width); 681848b8605Smrg 682848b8605Smrg if (*width <= 0) 683848b8605Smrg return GL_FALSE; 684848b8605Smrg 685848b8605Smrg /* bottom clipping */ 686848b8605Smrg if (*srcY < 0) { 687848b8605Smrg pack->SkipRows += (0 - *srcY); 688848b8605Smrg *height -= (0 - *srcY); 689848b8605Smrg *srcY = 0; 690848b8605Smrg } 691848b8605Smrg /* top clipping */ 692848b8605Smrg if (*srcY + *height > (GLsizei) buffer->Height) 693848b8605Smrg *height -= (*srcY + *height - buffer->Height); 694848b8605Smrg 695848b8605Smrg if (*height <= 0) 696848b8605Smrg return GL_FALSE; 697848b8605Smrg 698848b8605Smrg return GL_TRUE; 699848b8605Smrg} 700848b8605Smrg 701848b8605Smrg 702848b8605Smrg/** 703848b8605Smrg * Do clipping for a glCopyTexSubImage call. 704848b8605Smrg * The framebuffer source region might extend outside the framebuffer 705848b8605Smrg * bounds. Clip the source region against the framebuffer bounds and 706848b8605Smrg * adjust the texture/dest position and size accordingly. 707848b8605Smrg * 708848b8605Smrg * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise. 709848b8605Smrg */ 710848b8605SmrgGLboolean 711848b8605Smrg_mesa_clip_copytexsubimage(const struct gl_context *ctx, 712848b8605Smrg GLint *destX, GLint *destY, 713848b8605Smrg GLint *srcX, GLint *srcY, 714848b8605Smrg GLsizei *width, GLsizei *height) 715848b8605Smrg{ 716848b8605Smrg const struct gl_framebuffer *fb = ctx->ReadBuffer; 717848b8605Smrg const GLint srcX0 = *srcX, srcY0 = *srcY; 718848b8605Smrg 719848b8605Smrg if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height, 720848b8605Smrg srcX, srcY, width, height)) { 721848b8605Smrg *destX = *destX + *srcX - srcX0; 722848b8605Smrg *destY = *destY + *srcY - srcY0; 723848b8605Smrg 724848b8605Smrg return GL_TRUE; 725848b8605Smrg } 726848b8605Smrg else { 727848b8605Smrg return GL_FALSE; 728848b8605Smrg } 729848b8605Smrg} 730848b8605Smrg 731848b8605Smrg 732848b8605Smrg 733848b8605Smrg/** 734848b8605Smrg * Clip the rectangle defined by (x, y, width, height) against the bounds 735848b8605Smrg * specified by [xmin, xmax) and [ymin, ymax). 736848b8605Smrg * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise. 737848b8605Smrg */ 738848b8605SmrgGLboolean 739848b8605Smrg_mesa_clip_to_region(GLint xmin, GLint ymin, 740848b8605Smrg GLint xmax, GLint ymax, 741848b8605Smrg GLint *x, GLint *y, 742848b8605Smrg GLsizei *width, GLsizei *height ) 743848b8605Smrg{ 744848b8605Smrg /* left clipping */ 745848b8605Smrg if (*x < xmin) { 746848b8605Smrg *width -= (xmin - *x); 747848b8605Smrg *x = xmin; 748848b8605Smrg } 749848b8605Smrg 750848b8605Smrg /* right clipping */ 751848b8605Smrg if (*x + *width > xmax) 752848b8605Smrg *width -= (*x + *width - xmax); 753848b8605Smrg 754848b8605Smrg if (*width <= 0) 755848b8605Smrg return GL_FALSE; 756848b8605Smrg 757848b8605Smrg /* bottom (or top) clipping */ 758848b8605Smrg if (*y < ymin) { 759848b8605Smrg *height -= (ymin - *y); 760848b8605Smrg *y = ymin; 761848b8605Smrg } 762848b8605Smrg 763848b8605Smrg /* top (or bottom) clipping */ 764848b8605Smrg if (*y + *height > ymax) 765848b8605Smrg *height -= (*y + *height - ymax); 766848b8605Smrg 767848b8605Smrg if (*height <= 0) 768848b8605Smrg return GL_FALSE; 769848b8605Smrg 770848b8605Smrg return GL_TRUE; 771848b8605Smrg} 772848b8605Smrg 773848b8605Smrg 774848b8605Smrg/** 775848b8605Smrg * Clip dst coords against Xmax (or Ymax). 776848b8605Smrg */ 777848b8605Smrgstatic inline void 778848b8605Smrgclip_right_or_top(GLint *srcX0, GLint *srcX1, 779848b8605Smrg GLint *dstX0, GLint *dstX1, 780848b8605Smrg GLint maxValue) 781848b8605Smrg{ 782848b8605Smrg GLfloat t, bias; 783848b8605Smrg 784848b8605Smrg if (*dstX1 > maxValue) { 785848b8605Smrg /* X1 outside right edge */ 786848b8605Smrg ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */ 787848b8605Smrg t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); 788848b8605Smrg /* chop off [t, 1] part */ 789848b8605Smrg ASSERT(t >= 0.0 && t <= 1.0); 790848b8605Smrg *dstX1 = maxValue; 791848b8605Smrg bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; 792848b8605Smrg *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); 793848b8605Smrg } 794848b8605Smrg else if (*dstX0 > maxValue) { 795848b8605Smrg /* X0 outside right edge */ 796848b8605Smrg ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */ 797848b8605Smrg t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); 798848b8605Smrg /* chop off [t, 1] part */ 799848b8605Smrg ASSERT(t >= 0.0 && t <= 1.0); 800848b8605Smrg *dstX0 = maxValue; 801848b8605Smrg bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F; 802848b8605Smrg *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); 803848b8605Smrg } 804848b8605Smrg} 805848b8605Smrg 806848b8605Smrg 807848b8605Smrg/** 808848b8605Smrg * Clip dst coords against Xmin (or Ymin). 809848b8605Smrg */ 810848b8605Smrgstatic inline void 811848b8605Smrgclip_left_or_bottom(GLint *srcX0, GLint *srcX1, 812848b8605Smrg GLint *dstX0, GLint *dstX1, 813848b8605Smrg GLint minValue) 814848b8605Smrg{ 815848b8605Smrg GLfloat t, bias; 816848b8605Smrg 817848b8605Smrg if (*dstX0 < minValue) { 818848b8605Smrg /* X0 outside left edge */ 819848b8605Smrg ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */ 820848b8605Smrg t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); 821848b8605Smrg /* chop off [0, t] part */ 822848b8605Smrg ASSERT(t >= 0.0 && t <= 1.0); 823848b8605Smrg *dstX0 = minValue; 824848b8605Smrg bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; 825848b8605Smrg *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); 826848b8605Smrg } 827848b8605Smrg else if (*dstX1 < minValue) { 828848b8605Smrg /* X1 outside left edge */ 829848b8605Smrg ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */ 830848b8605Smrg t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); 831848b8605Smrg /* chop off [0, t] part */ 832848b8605Smrg ASSERT(t >= 0.0 && t <= 1.0); 833848b8605Smrg *dstX1 = minValue; 834848b8605Smrg bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F; 835848b8605Smrg *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); 836848b8605Smrg } 837848b8605Smrg} 838848b8605Smrg 839848b8605Smrg 840848b8605Smrg/** 841848b8605Smrg * Do clipping of blit src/dest rectangles. 842848b8605Smrg * The dest rect is clipped against both the buffer bounds and scissor bounds. 843848b8605Smrg * The src rect is just clipped against the buffer bounds. 844848b8605Smrg * 845848b8605Smrg * When either the src or dest rect is clipped, the other is also clipped 846848b8605Smrg * proportionately! 847848b8605Smrg * 848848b8605Smrg * Note that X0 need not be less than X1 (same for Y) for either the source 849848b8605Smrg * and dest rects. That makes the clipping a little trickier. 850848b8605Smrg * 851848b8605Smrg * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped 852848b8605Smrg */ 853848b8605SmrgGLboolean 854848b8605Smrg_mesa_clip_blit(struct gl_context *ctx, 855848b8605Smrg GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1, 856848b8605Smrg GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1) 857848b8605Smrg{ 858848b8605Smrg const GLint srcXmin = 0; 859848b8605Smrg const GLint srcXmax = ctx->ReadBuffer->Width; 860848b8605Smrg const GLint srcYmin = 0; 861848b8605Smrg const GLint srcYmax = ctx->ReadBuffer->Height; 862848b8605Smrg 863848b8605Smrg /* these include scissor bounds */ 864848b8605Smrg const GLint dstXmin = ctx->DrawBuffer->_Xmin; 865848b8605Smrg const GLint dstXmax = ctx->DrawBuffer->_Xmax; 866848b8605Smrg const GLint dstYmin = ctx->DrawBuffer->_Ymin; 867848b8605Smrg const GLint dstYmax = ctx->DrawBuffer->_Ymax; 868848b8605Smrg 869848b8605Smrg /* 870848b8605Smrg printf("PreClipX: src: %d .. %d dst: %d .. %d\n", 871848b8605Smrg *srcX0, *srcX1, *dstX0, *dstX1); 872848b8605Smrg printf("PreClipY: src: %d .. %d dst: %d .. %d\n", 873848b8605Smrg *srcY0, *srcY1, *dstY0, *dstY1); 874848b8605Smrg */ 875848b8605Smrg 876848b8605Smrg /* trivial rejection tests */ 877848b8605Smrg if (*dstX0 == *dstX1) 878848b8605Smrg return GL_FALSE; /* no width */ 879848b8605Smrg if (*dstX0 <= dstXmin && *dstX1 <= dstXmin) 880848b8605Smrg return GL_FALSE; /* totally out (left) of bounds */ 881848b8605Smrg if (*dstX0 >= dstXmax && *dstX1 >= dstXmax) 882848b8605Smrg return GL_FALSE; /* totally out (right) of bounds */ 883848b8605Smrg 884848b8605Smrg if (*dstY0 == *dstY1) 885848b8605Smrg return GL_FALSE; 886848b8605Smrg if (*dstY0 <= dstYmin && *dstY1 <= dstYmin) 887848b8605Smrg return GL_FALSE; 888848b8605Smrg if (*dstY0 >= dstYmax && *dstY1 >= dstYmax) 889848b8605Smrg return GL_FALSE; 890848b8605Smrg 891848b8605Smrg if (*srcX0 == *srcX1) 892848b8605Smrg return GL_FALSE; 893848b8605Smrg if (*srcX0 <= srcXmin && *srcX1 <= srcXmin) 894848b8605Smrg return GL_FALSE; 895848b8605Smrg if (*srcX0 >= srcXmax && *srcX1 >= srcXmax) 896848b8605Smrg return GL_FALSE; 897848b8605Smrg 898848b8605Smrg if (*srcY0 == *srcY1) 899848b8605Smrg return GL_FALSE; 900848b8605Smrg if (*srcY0 <= srcYmin && *srcY1 <= srcYmin) 901848b8605Smrg return GL_FALSE; 902848b8605Smrg if (*srcY0 >= srcYmax && *srcY1 >= srcYmax) 903848b8605Smrg return GL_FALSE; 904848b8605Smrg 905848b8605Smrg /* 906848b8605Smrg * dest clip 907848b8605Smrg */ 908848b8605Smrg clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax); 909848b8605Smrg clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax); 910848b8605Smrg clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin); 911848b8605Smrg clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin); 912848b8605Smrg 913848b8605Smrg /* 914848b8605Smrg * src clip (just swap src/dst values from above) 915848b8605Smrg */ 916848b8605Smrg clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax); 917848b8605Smrg clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax); 918848b8605Smrg clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin); 919848b8605Smrg clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin); 920848b8605Smrg 921848b8605Smrg /* 922848b8605Smrg printf("PostClipX: src: %d .. %d dst: %d .. %d\n", 923848b8605Smrg *srcX0, *srcX1, *dstX0, *dstX1); 924848b8605Smrg printf("PostClipY: src: %d .. %d dst: %d .. %d\n", 925848b8605Smrg *srcY0, *srcY1, *dstY0, *dstY1); 926848b8605Smrg */ 927848b8605Smrg 928848b8605Smrg ASSERT(*dstX0 >= dstXmin); 929848b8605Smrg ASSERT(*dstX0 <= dstXmax); 930848b8605Smrg ASSERT(*dstX1 >= dstXmin); 931848b8605Smrg ASSERT(*dstX1 <= dstXmax); 932848b8605Smrg 933848b8605Smrg ASSERT(*dstY0 >= dstYmin); 934848b8605Smrg ASSERT(*dstY0 <= dstYmax); 935848b8605Smrg ASSERT(*dstY1 >= dstYmin); 936848b8605Smrg ASSERT(*dstY1 <= dstYmax); 937848b8605Smrg 938848b8605Smrg ASSERT(*srcX0 >= srcXmin); 939848b8605Smrg ASSERT(*srcX0 <= srcXmax); 940848b8605Smrg ASSERT(*srcX1 >= srcXmin); 941848b8605Smrg ASSERT(*srcX1 <= srcXmax); 942848b8605Smrg 943848b8605Smrg ASSERT(*srcY0 >= srcYmin); 944848b8605Smrg ASSERT(*srcY0 <= srcYmax); 945848b8605Smrg ASSERT(*srcY1 >= srcYmin); 946848b8605Smrg ASSERT(*srcY1 <= srcYmax); 947848b8605Smrg 948848b8605Smrg return GL_TRUE; 949848b8605Smrg} 950