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/** 44b8e80941Smrg * Flip the order of the 2 bytes in each word in the given array (src) and 45b8e80941Smrg * store the result in another array (dst). For in-place byte-swapping this 46b8e80941Smrg * function can be called with the same array for src and dst. 47848b8605Smrg * 48b8e80941Smrg * \param dst the array where byte-swapped data will be stored. 49b8e80941Smrg * \param src the array with the source data we want to byte-swap. 50848b8605Smrg * \param n number of words. 51848b8605Smrg */ 52b8e80941Smrgstatic void 53b8e80941Smrgswap2_copy( GLushort *dst, GLushort *src, GLuint n ) 54848b8605Smrg{ 55848b8605Smrg GLuint i; 56848b8605Smrg for (i = 0; i < n; i++) { 57b8e80941Smrg dst[i] = (src[i] >> 8) | ((src[i] << 8) & 0xff00); 58848b8605Smrg } 59848b8605Smrg} 60848b8605Smrg 61b8e80941Smrgvoid 62b8e80941Smrg_mesa_swap2(GLushort *p, GLuint n) 63b8e80941Smrg{ 64b8e80941Smrg swap2_copy(p, p, n); 65b8e80941Smrg} 66848b8605Smrg 67848b8605Smrg/* 68b8e80941Smrg * Flip the order of the 4 bytes in each word in the given array (src) and 69b8e80941Smrg * store the result in another array (dst). For in-place byte-swapping this 70b8e80941Smrg * function can be called with the same array for src and dst. 71b8e80941Smrg * 72b8e80941Smrg * \param dst the array where byte-swapped data will be stored. 73b8e80941Smrg * \param src the array with the source data we want to byte-swap. 74b8e80941Smrg * \param n number of words. 75848b8605Smrg */ 76b8e80941Smrgstatic void 77b8e80941Smrgswap4_copy( GLuint *dst, GLuint *src, GLuint n ) 78848b8605Smrg{ 79848b8605Smrg GLuint i, a, b; 80848b8605Smrg for (i = 0; i < n; i++) { 81b8e80941Smrg b = src[i]; 82848b8605Smrg a = (b >> 24) 83848b8605Smrg | ((b >> 8) & 0xff00) 84848b8605Smrg | ((b << 8) & 0xff0000) 85848b8605Smrg | ((b << 24) & 0xff000000); 86b8e80941Smrg dst[i] = a; 87848b8605Smrg } 88848b8605Smrg} 89848b8605Smrg 90b8e80941Smrgvoid 91b8e80941Smrg_mesa_swap4(GLuint *p, GLuint n) 92b8e80941Smrg{ 93b8e80941Smrg swap4_copy(p, p, n); 94b8e80941Smrg} 95848b8605Smrg 96848b8605Smrg/** 97848b8605Smrg * Return the byte offset of a specific pixel in an image (1D, 2D or 3D). 98848b8605Smrg * 99848b8605Smrg * Pixel unpacking/packing parameters are observed according to \p packing. 100848b8605Smrg * 101848b8605Smrg * \param dimensions either 1, 2 or 3 to indicate dimensionality of image 102848b8605Smrg * \param packing the pixelstore attributes 103848b8605Smrg * \param width the image width 104848b8605Smrg * \param height the image height 105848b8605Smrg * \param format the pixel format (must be validated beforehand) 106848b8605Smrg * \param type the pixel data type (must be validated beforehand) 107848b8605Smrg * \param img which image in the volume (0 for 1D or 2D images) 108848b8605Smrg * \param row row of pixel in the image (0 for 1D images) 109848b8605Smrg * \param column column of pixel in the image 110848b8605Smrg * 111848b8605Smrg * \return offset of pixel. 112848b8605Smrg * 113848b8605Smrg * \sa gl_pixelstore_attrib. 114848b8605Smrg */ 115848b8605SmrgGLintptr 116848b8605Smrg_mesa_image_offset( GLuint dimensions, 117848b8605Smrg const struct gl_pixelstore_attrib *packing, 118848b8605Smrg GLsizei width, GLsizei height, 119848b8605Smrg GLenum format, GLenum type, 120848b8605Smrg GLint img, GLint row, GLint column ) 121848b8605Smrg{ 122848b8605Smrg GLint alignment; /* 1, 2 or 4 */ 123848b8605Smrg GLint pixels_per_row; 124848b8605Smrg GLint rows_per_image; 125848b8605Smrg GLint skiprows; 126848b8605Smrg GLint skippixels; 127848b8605Smrg GLint skipimages; /* for 3-D volume images */ 128848b8605Smrg GLintptr offset; 129848b8605Smrg 130b8e80941Smrg assert(dimensions >= 1 && dimensions <= 3); 131848b8605Smrg 132848b8605Smrg alignment = packing->Alignment; 133848b8605Smrg if (packing->RowLength > 0) { 134848b8605Smrg pixels_per_row = packing->RowLength; 135848b8605Smrg } 136848b8605Smrg else { 137848b8605Smrg pixels_per_row = width; 138848b8605Smrg } 139848b8605Smrg if (packing->ImageHeight > 0) { 140848b8605Smrg rows_per_image = packing->ImageHeight; 141848b8605Smrg } 142848b8605Smrg else { 143848b8605Smrg rows_per_image = height; 144848b8605Smrg } 145848b8605Smrg 146848b8605Smrg skippixels = packing->SkipPixels; 147848b8605Smrg /* Note: SKIP_ROWS _is_ used for 1D images */ 148848b8605Smrg skiprows = packing->SkipRows; 149848b8605Smrg /* Note: SKIP_IMAGES is only used for 3D images */ 150848b8605Smrg skipimages = (dimensions == 3) ? packing->SkipImages : 0; 151848b8605Smrg 152848b8605Smrg if (type == GL_BITMAP) { 153848b8605Smrg /* BITMAP data */ 154b8e80941Smrg GLintptr bytes_per_row; 155b8e80941Smrg GLintptr bytes_per_image; 156848b8605Smrg /* components per pixel for color or stencil index: */ 157848b8605Smrg const GLint comp_per_pixel = 1; 158848b8605Smrg 159848b8605Smrg /* The pixel type and format should have been error checked earlier */ 160848b8605Smrg assert(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX); 161848b8605Smrg 162848b8605Smrg bytes_per_row = alignment 163b8e80941Smrg * DIV_ROUND_UP( comp_per_pixel*pixels_per_row, 8*alignment ); 164848b8605Smrg 165848b8605Smrg bytes_per_image = bytes_per_row * rows_per_image; 166848b8605Smrg 167848b8605Smrg offset = (skipimages + img) * bytes_per_image 168848b8605Smrg + (skiprows + row) * bytes_per_row 169848b8605Smrg + (skippixels + column) / 8; 170848b8605Smrg } 171848b8605Smrg else { 172848b8605Smrg /* Non-BITMAP data */ 173b8e80941Smrg GLintptr bytes_per_pixel, bytes_per_row, remainder, bytes_per_image; 174b8e80941Smrg GLintptr topOfImage; 175848b8605Smrg 176848b8605Smrg bytes_per_pixel = _mesa_bytes_per_pixel( format, type ); 177848b8605Smrg 178848b8605Smrg /* The pixel type and format should have been error checked earlier */ 179848b8605Smrg assert(bytes_per_pixel > 0); 180848b8605Smrg 181848b8605Smrg bytes_per_row = pixels_per_row * bytes_per_pixel; 182848b8605Smrg remainder = bytes_per_row % alignment; 183848b8605Smrg if (remainder > 0) 184848b8605Smrg bytes_per_row += (alignment - remainder); 185848b8605Smrg 186b8e80941Smrg assert(bytes_per_row % alignment == 0); 187848b8605Smrg 188848b8605Smrg bytes_per_image = bytes_per_row * rows_per_image; 189848b8605Smrg 190848b8605Smrg if (packing->Invert) { 191848b8605Smrg /* set pixel_addr to the last row */ 192848b8605Smrg topOfImage = bytes_per_row * (height - 1); 193848b8605Smrg bytes_per_row = -bytes_per_row; 194848b8605Smrg } 195848b8605Smrg else { 196848b8605Smrg topOfImage = 0; 197848b8605Smrg } 198848b8605Smrg 199848b8605Smrg /* compute final pixel address */ 200848b8605Smrg offset = (skipimages + img) * bytes_per_image 201848b8605Smrg + topOfImage 202848b8605Smrg + (skiprows + row) * bytes_per_row 203848b8605Smrg + (skippixels + column) * bytes_per_pixel; 204848b8605Smrg } 205848b8605Smrg 206848b8605Smrg return offset; 207848b8605Smrg} 208848b8605Smrg 209848b8605Smrg 210848b8605Smrg/** 211848b8605Smrg * Return the address of a specific pixel in an image (1D, 2D or 3D). 212848b8605Smrg * 213848b8605Smrg * Pixel unpacking/packing parameters are observed according to \p packing. 214848b8605Smrg * 215848b8605Smrg * \param dimensions either 1, 2 or 3 to indicate dimensionality of image 216848b8605Smrg * \param packing the pixelstore attributes 217848b8605Smrg * \param image starting address of image data 218848b8605Smrg * \param width the image width 219848b8605Smrg * \param height the image height 220848b8605Smrg * \param format the pixel format (must be validated beforehand) 221848b8605Smrg * \param type the pixel data type (must be validated beforehand) 222848b8605Smrg * \param img which image in the volume (0 for 1D or 2D images) 223848b8605Smrg * \param row row of pixel in the image (0 for 1D images) 224848b8605Smrg * \param column column of pixel in the image 225848b8605Smrg * 226848b8605Smrg * \return address of pixel. 227848b8605Smrg * 228848b8605Smrg * \sa gl_pixelstore_attrib. 229848b8605Smrg */ 230848b8605SmrgGLvoid * 231848b8605Smrg_mesa_image_address( GLuint dimensions, 232848b8605Smrg const struct gl_pixelstore_attrib *packing, 233848b8605Smrg const GLvoid *image, 234848b8605Smrg GLsizei width, GLsizei height, 235848b8605Smrg GLenum format, GLenum type, 236848b8605Smrg GLint img, GLint row, GLint column ) 237848b8605Smrg{ 238848b8605Smrg const GLubyte *addr = (const GLubyte *) image; 239848b8605Smrg 240848b8605Smrg addr += _mesa_image_offset(dimensions, packing, width, height, 241848b8605Smrg format, type, img, row, column); 242848b8605Smrg 243848b8605Smrg return (GLvoid *) addr; 244848b8605Smrg} 245848b8605Smrg 246848b8605Smrg 247848b8605SmrgGLvoid * 248848b8605Smrg_mesa_image_address1d( const struct gl_pixelstore_attrib *packing, 249848b8605Smrg const GLvoid *image, 250848b8605Smrg GLsizei width, 251848b8605Smrg GLenum format, GLenum type, 252848b8605Smrg GLint column ) 253848b8605Smrg{ 254848b8605Smrg return _mesa_image_address(1, packing, image, width, 1, 255848b8605Smrg format, type, 0, 0, column); 256848b8605Smrg} 257848b8605Smrg 258848b8605Smrg 259848b8605SmrgGLvoid * 260848b8605Smrg_mesa_image_address2d( const struct gl_pixelstore_attrib *packing, 261848b8605Smrg const GLvoid *image, 262848b8605Smrg GLsizei width, GLsizei height, 263848b8605Smrg GLenum format, GLenum type, 264848b8605Smrg GLint row, GLint column ) 265848b8605Smrg{ 266848b8605Smrg return _mesa_image_address(2, packing, image, width, height, 267848b8605Smrg format, type, 0, row, column); 268848b8605Smrg} 269848b8605Smrg 270848b8605Smrg 271848b8605SmrgGLvoid * 272848b8605Smrg_mesa_image_address3d( const struct gl_pixelstore_attrib *packing, 273848b8605Smrg const GLvoid *image, 274848b8605Smrg GLsizei width, GLsizei height, 275848b8605Smrg GLenum format, GLenum type, 276848b8605Smrg GLint img, GLint row, GLint column ) 277848b8605Smrg{ 278848b8605Smrg return _mesa_image_address(3, packing, image, width, height, 279848b8605Smrg format, type, img, row, column); 280848b8605Smrg} 281848b8605Smrg 282848b8605Smrg 283848b8605Smrg 284848b8605Smrg/** 285848b8605Smrg * Compute the stride (in bytes) between image rows. 286848b8605Smrg * 287848b8605Smrg * \param packing the pixelstore attributes 288848b8605Smrg * \param width image width. 289848b8605Smrg * \param format pixel format. 290848b8605Smrg * \param type pixel data type. 291848b8605Smrg * 292848b8605Smrg * \return the stride in bytes for the given parameters, or -1 if error 293848b8605Smrg */ 294848b8605SmrgGLint 295848b8605Smrg_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing, 296848b8605Smrg GLint width, GLenum format, GLenum type ) 297848b8605Smrg{ 298848b8605Smrg GLint bytesPerRow, remainder; 299848b8605Smrg 300b8e80941Smrg assert(packing); 301848b8605Smrg 302848b8605Smrg if (type == GL_BITMAP) { 303848b8605Smrg if (packing->RowLength == 0) { 304848b8605Smrg bytesPerRow = (width + 7) / 8; 305848b8605Smrg } 306848b8605Smrg else { 307848b8605Smrg bytesPerRow = (packing->RowLength + 7) / 8; 308848b8605Smrg } 309848b8605Smrg } 310848b8605Smrg else { 311848b8605Smrg /* Non-BITMAP data */ 312848b8605Smrg const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); 313848b8605Smrg if (bytesPerPixel <= 0) 314848b8605Smrg return -1; /* error */ 315848b8605Smrg if (packing->RowLength == 0) { 316848b8605Smrg bytesPerRow = bytesPerPixel * width; 317848b8605Smrg } 318848b8605Smrg else { 319848b8605Smrg bytesPerRow = bytesPerPixel * packing->RowLength; 320848b8605Smrg } 321848b8605Smrg } 322848b8605Smrg 323848b8605Smrg remainder = bytesPerRow % packing->Alignment; 324848b8605Smrg if (remainder > 0) { 325848b8605Smrg bytesPerRow += (packing->Alignment - remainder); 326848b8605Smrg } 327848b8605Smrg 328848b8605Smrg if (packing->Invert) { 329848b8605Smrg /* negate the bytes per row (negative row stride) */ 330848b8605Smrg bytesPerRow = -bytesPerRow; 331848b8605Smrg } 332848b8605Smrg 333848b8605Smrg return bytesPerRow; 334848b8605Smrg} 335848b8605Smrg 336848b8605Smrg 337848b8605Smrg/* 338848b8605Smrg * Compute the stride between images in a 3D texture (in bytes) for the given 339848b8605Smrg * pixel packing parameters and image width, format and type. 340848b8605Smrg */ 341848b8605SmrgGLint 342848b8605Smrg_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing, 343848b8605Smrg GLint width, GLint height, 344848b8605Smrg GLenum format, GLenum type ) 345848b8605Smrg{ 346848b8605Smrg GLint bytesPerRow, bytesPerImage, remainder; 347848b8605Smrg 348b8e80941Smrg assert(packing); 349848b8605Smrg 350848b8605Smrg if (type == GL_BITMAP) { 351848b8605Smrg if (packing->RowLength == 0) { 352848b8605Smrg bytesPerRow = (width + 7) / 8; 353848b8605Smrg } 354848b8605Smrg else { 355848b8605Smrg bytesPerRow = (packing->RowLength + 7) / 8; 356848b8605Smrg } 357848b8605Smrg } 358848b8605Smrg else { 359848b8605Smrg const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); 360848b8605Smrg 361848b8605Smrg if (bytesPerPixel <= 0) 362848b8605Smrg return -1; /* error */ 363848b8605Smrg if (packing->RowLength == 0) { 364848b8605Smrg bytesPerRow = bytesPerPixel * width; 365848b8605Smrg } 366848b8605Smrg else { 367848b8605Smrg bytesPerRow = bytesPerPixel * packing->RowLength; 368848b8605Smrg } 369848b8605Smrg } 370848b8605Smrg 371848b8605Smrg remainder = bytesPerRow % packing->Alignment; 372848b8605Smrg if (remainder > 0) 373848b8605Smrg bytesPerRow += (packing->Alignment - remainder); 374848b8605Smrg 375848b8605Smrg if (packing->ImageHeight == 0) 376848b8605Smrg bytesPerImage = bytesPerRow * height; 377848b8605Smrg else 378848b8605Smrg bytesPerImage = bytesPerRow * packing->ImageHeight; 379848b8605Smrg 380848b8605Smrg return bytesPerImage; 381848b8605Smrg} 382848b8605Smrg 383848b8605Smrg 384848b8605Smrg 385848b8605Smrg/** 386848b8605Smrg * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel. 387848b8605Smrg * This is typically used to convert a bitmap into a GLubyte/pixel texture. 388848b8605Smrg * "On" bits will set texels to \p onValue. 389848b8605Smrg * "Off" bits will not modify texels. 390848b8605Smrg * \param width src bitmap width in pixels 391848b8605Smrg * \param height src bitmap height in pixels 392848b8605Smrg * \param unpack bitmap unpacking state 393848b8605Smrg * \param bitmap the src bitmap data 394848b8605Smrg * \param destBuffer start of dest buffer 395848b8605Smrg * \param destStride row stride in dest buffer 396848b8605Smrg * \param onValue if bit is 1, set destBuffer pixel to this value 397848b8605Smrg */ 398848b8605Smrgvoid 399848b8605Smrg_mesa_expand_bitmap(GLsizei width, GLsizei height, 400848b8605Smrg const struct gl_pixelstore_attrib *unpack, 401848b8605Smrg const GLubyte *bitmap, 402848b8605Smrg GLubyte *destBuffer, GLint destStride, 403848b8605Smrg GLubyte onValue) 404848b8605Smrg{ 405848b8605Smrg const GLubyte *srcRow = (const GLubyte *) 406848b8605Smrg _mesa_image_address2d(unpack, bitmap, width, height, 407848b8605Smrg GL_COLOR_INDEX, GL_BITMAP, 0, 0); 408848b8605Smrg const GLint srcStride = _mesa_image_row_stride(unpack, width, 409848b8605Smrg GL_COLOR_INDEX, GL_BITMAP); 410848b8605Smrg GLint row, col; 411b8e80941Smrg GLubyte *dstRow = destBuffer; 412848b8605Smrg 413848b8605Smrg for (row = 0; row < height; row++) { 414848b8605Smrg const GLubyte *src = srcRow; 415848b8605Smrg 416848b8605Smrg if (unpack->LsbFirst) { 417848b8605Smrg /* Lsb first */ 418848b8605Smrg GLubyte mask = 1U << (unpack->SkipPixels & 0x7); 419848b8605Smrg for (col = 0; col < width; col++) { 420848b8605Smrg 421848b8605Smrg if (*src & mask) { 422b8e80941Smrg dstRow[col] = onValue; 423848b8605Smrg } 424848b8605Smrg 425848b8605Smrg if (mask == 128U) { 426848b8605Smrg src++; 427848b8605Smrg mask = 1U; 428848b8605Smrg } 429848b8605Smrg else { 430848b8605Smrg mask = mask << 1; 431848b8605Smrg } 432848b8605Smrg } 433848b8605Smrg 434848b8605Smrg /* get ready for next row */ 435848b8605Smrg if (mask != 1) 436848b8605Smrg src++; 437848b8605Smrg } 438848b8605Smrg else { 439848b8605Smrg /* Msb first */ 440848b8605Smrg GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); 441848b8605Smrg for (col = 0; col < width; col++) { 442848b8605Smrg 443848b8605Smrg if (*src & mask) { 444b8e80941Smrg dstRow[col] = onValue; 445848b8605Smrg } 446848b8605Smrg 447848b8605Smrg if (mask == 1U) { 448848b8605Smrg src++; 449848b8605Smrg mask = 128U; 450848b8605Smrg } 451848b8605Smrg else { 452848b8605Smrg mask = mask >> 1; 453848b8605Smrg } 454848b8605Smrg } 455848b8605Smrg 456848b8605Smrg /* get ready for next row */ 457848b8605Smrg if (mask != 128) 458848b8605Smrg src++; 459848b8605Smrg } 460848b8605Smrg 461848b8605Smrg srcRow += srcStride; 462b8e80941Smrg dstRow += destStride; 463848b8605Smrg } /* row */ 464848b8605Smrg} 465848b8605Smrg 466848b8605Smrg 467848b8605Smrg 468848b8605Smrg 469848b8605Smrg/** 470848b8605Smrg * Convert an array of RGBA colors from one datatype to another. 471848b8605Smrg * NOTE: src may equal dst. In that case, we use a temporary buffer. 472848b8605Smrg */ 473848b8605Smrgvoid 474848b8605Smrg_mesa_convert_colors(GLenum srcType, const GLvoid *src, 475848b8605Smrg GLenum dstType, GLvoid *dst, 476848b8605Smrg GLuint count, const GLubyte mask[]) 477848b8605Smrg{ 478848b8605Smrg GLuint *tempBuffer; 479848b8605Smrg const GLboolean useTemp = (src == dst); 480848b8605Smrg 481848b8605Smrg tempBuffer = malloc(count * MAX_PIXEL_BYTES); 482848b8605Smrg if (!tempBuffer) 483848b8605Smrg return; 484848b8605Smrg 485b8e80941Smrg assert(srcType != dstType); 486848b8605Smrg 487848b8605Smrg switch (srcType) { 488848b8605Smrg case GL_UNSIGNED_BYTE: 489848b8605Smrg if (dstType == GL_UNSIGNED_SHORT) { 490848b8605Smrg const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src; 491848b8605Smrg GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst); 492848b8605Smrg GLuint i; 493848b8605Smrg for (i = 0; i < count; i++) { 494848b8605Smrg if (!mask || mask[i]) { 495848b8605Smrg dst2[i][RCOMP] = UBYTE_TO_USHORT(src1[i][RCOMP]); 496848b8605Smrg dst2[i][GCOMP] = UBYTE_TO_USHORT(src1[i][GCOMP]); 497848b8605Smrg dst2[i][BCOMP] = UBYTE_TO_USHORT(src1[i][BCOMP]); 498848b8605Smrg dst2[i][ACOMP] = UBYTE_TO_USHORT(src1[i][ACOMP]); 499848b8605Smrg } 500848b8605Smrg } 501848b8605Smrg if (useTemp) 502848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort)); 503848b8605Smrg } 504848b8605Smrg else { 505848b8605Smrg const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src; 506848b8605Smrg GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst); 507848b8605Smrg GLuint i; 508b8e80941Smrg assert(dstType == GL_FLOAT); 509848b8605Smrg for (i = 0; i < count; i++) { 510848b8605Smrg if (!mask || mask[i]) { 511848b8605Smrg dst4[i][RCOMP] = UBYTE_TO_FLOAT(src1[i][RCOMP]); 512848b8605Smrg dst4[i][GCOMP] = UBYTE_TO_FLOAT(src1[i][GCOMP]); 513848b8605Smrg dst4[i][BCOMP] = UBYTE_TO_FLOAT(src1[i][BCOMP]); 514848b8605Smrg dst4[i][ACOMP] = UBYTE_TO_FLOAT(src1[i][ACOMP]); 515848b8605Smrg } 516848b8605Smrg } 517848b8605Smrg if (useTemp) 518848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat)); 519848b8605Smrg } 520848b8605Smrg break; 521848b8605Smrg case GL_UNSIGNED_SHORT: 522848b8605Smrg if (dstType == GL_UNSIGNED_BYTE) { 523848b8605Smrg const GLushort (*src2)[4] = (const GLushort (*)[4]) src; 524848b8605Smrg GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst); 525848b8605Smrg GLuint i; 526848b8605Smrg for (i = 0; i < count; i++) { 527848b8605Smrg if (!mask || mask[i]) { 528848b8605Smrg dst1[i][RCOMP] = USHORT_TO_UBYTE(src2[i][RCOMP]); 529848b8605Smrg dst1[i][GCOMP] = USHORT_TO_UBYTE(src2[i][GCOMP]); 530848b8605Smrg dst1[i][BCOMP] = USHORT_TO_UBYTE(src2[i][BCOMP]); 531848b8605Smrg dst1[i][ACOMP] = USHORT_TO_UBYTE(src2[i][ACOMP]); 532848b8605Smrg } 533848b8605Smrg } 534848b8605Smrg if (useTemp) 535848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte)); 536848b8605Smrg } 537848b8605Smrg else { 538848b8605Smrg const GLushort (*src2)[4] = (const GLushort (*)[4]) src; 539848b8605Smrg GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst); 540848b8605Smrg GLuint i; 541b8e80941Smrg assert(dstType == GL_FLOAT); 542848b8605Smrg for (i = 0; i < count; i++) { 543848b8605Smrg if (!mask || mask[i]) { 544848b8605Smrg dst4[i][RCOMP] = USHORT_TO_FLOAT(src2[i][RCOMP]); 545848b8605Smrg dst4[i][GCOMP] = USHORT_TO_FLOAT(src2[i][GCOMP]); 546848b8605Smrg dst4[i][BCOMP] = USHORT_TO_FLOAT(src2[i][BCOMP]); 547848b8605Smrg dst4[i][ACOMP] = USHORT_TO_FLOAT(src2[i][ACOMP]); 548848b8605Smrg } 549848b8605Smrg } 550848b8605Smrg if (useTemp) 551848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat)); 552848b8605Smrg } 553848b8605Smrg break; 554848b8605Smrg case GL_FLOAT: 555848b8605Smrg if (dstType == GL_UNSIGNED_BYTE) { 556848b8605Smrg const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src; 557848b8605Smrg GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst); 558848b8605Smrg GLuint i; 559848b8605Smrg for (i = 0; i < count; i++) { 560848b8605Smrg if (!mask || mask[i]) 561848b8605Smrg _mesa_unclamped_float_rgba_to_ubyte(dst1[i], src4[i]); 562848b8605Smrg } 563848b8605Smrg if (useTemp) 564848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte)); 565848b8605Smrg } 566848b8605Smrg else { 567848b8605Smrg const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src; 568848b8605Smrg GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst); 569848b8605Smrg GLuint i; 570b8e80941Smrg assert(dstType == GL_UNSIGNED_SHORT); 571848b8605Smrg for (i = 0; i < count; i++) { 572848b8605Smrg if (!mask || mask[i]) { 573848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(dst2[i][RCOMP], src4[i][RCOMP]); 574848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(dst2[i][GCOMP], src4[i][GCOMP]); 575848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(dst2[i][BCOMP], src4[i][BCOMP]); 576848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(dst2[i][ACOMP], src4[i][ACOMP]); 577848b8605Smrg } 578848b8605Smrg } 579848b8605Smrg if (useTemp) 580848b8605Smrg memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort)); 581848b8605Smrg } 582848b8605Smrg break; 583848b8605Smrg default: 584b8e80941Smrg unreachable("Invalid datatype in _mesa_convert_colors"); 585848b8605Smrg } 586848b8605Smrg 587848b8605Smrg free(tempBuffer); 588848b8605Smrg} 589848b8605Smrg 590848b8605Smrg 591848b8605Smrg 592848b8605Smrg 593848b8605Smrg/** 594848b8605Smrg * Perform basic clipping for glDrawPixels. The image's position and size 595848b8605Smrg * and the unpack SkipPixels and SkipRows are adjusted so that the image 596848b8605Smrg * region is entirely within the window and scissor bounds. 597848b8605Smrg * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1). 598848b8605Smrg * If Pixel.ZoomY is -1, *destY will be changed to be the first row which 599848b8605Smrg * we'll actually write. Beforehand, *destY-1 is the first drawing row. 600848b8605Smrg * 601848b8605Smrg * \return GL_TRUE if image is ready for drawing or 602848b8605Smrg * GL_FALSE if image was completely clipped away (draw nothing) 603848b8605Smrg */ 604848b8605SmrgGLboolean 605848b8605Smrg_mesa_clip_drawpixels(const struct gl_context *ctx, 606848b8605Smrg GLint *destX, GLint *destY, 607848b8605Smrg GLsizei *width, GLsizei *height, 608848b8605Smrg struct gl_pixelstore_attrib *unpack) 609848b8605Smrg{ 610848b8605Smrg const struct gl_framebuffer *buffer = ctx->DrawBuffer; 611848b8605Smrg 612848b8605Smrg if (unpack->RowLength == 0) { 613848b8605Smrg unpack->RowLength = *width; 614848b8605Smrg } 615848b8605Smrg 616b8e80941Smrg assert(ctx->Pixel.ZoomX == 1.0F); 617b8e80941Smrg assert(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F); 618848b8605Smrg 619848b8605Smrg /* left clipping */ 620848b8605Smrg if (*destX < buffer->_Xmin) { 621848b8605Smrg unpack->SkipPixels += (buffer->_Xmin - *destX); 622848b8605Smrg *width -= (buffer->_Xmin - *destX); 623848b8605Smrg *destX = buffer->_Xmin; 624848b8605Smrg } 625848b8605Smrg /* right clipping */ 626848b8605Smrg if (*destX + *width > buffer->_Xmax) 627848b8605Smrg *width -= (*destX + *width - buffer->_Xmax); 628848b8605Smrg 629848b8605Smrg if (*width <= 0) 630848b8605Smrg return GL_FALSE; 631848b8605Smrg 632848b8605Smrg if (ctx->Pixel.ZoomY == 1.0F) { 633848b8605Smrg /* bottom clipping */ 634848b8605Smrg if (*destY < buffer->_Ymin) { 635848b8605Smrg unpack->SkipRows += (buffer->_Ymin - *destY); 636848b8605Smrg *height -= (buffer->_Ymin - *destY); 637848b8605Smrg *destY = buffer->_Ymin; 638848b8605Smrg } 639848b8605Smrg /* top clipping */ 640848b8605Smrg if (*destY + *height > buffer->_Ymax) 641848b8605Smrg *height -= (*destY + *height - buffer->_Ymax); 642848b8605Smrg } 643848b8605Smrg else { /* upside down */ 644848b8605Smrg /* top clipping */ 645848b8605Smrg if (*destY > buffer->_Ymax) { 646848b8605Smrg unpack->SkipRows += (*destY - buffer->_Ymax); 647848b8605Smrg *height -= (*destY - buffer->_Ymax); 648848b8605Smrg *destY = buffer->_Ymax; 649848b8605Smrg } 650848b8605Smrg /* bottom clipping */ 651848b8605Smrg if (*destY - *height < buffer->_Ymin) 652848b8605Smrg *height -= (buffer->_Ymin - (*destY - *height)); 653848b8605Smrg /* adjust destY so it's the first row to write to */ 654848b8605Smrg (*destY)--; 655848b8605Smrg } 656848b8605Smrg 657848b8605Smrg if (*height <= 0) 658848b8605Smrg return GL_FALSE; 659848b8605Smrg 660848b8605Smrg return GL_TRUE; 661848b8605Smrg} 662848b8605Smrg 663848b8605Smrg 664848b8605Smrg/** 665848b8605Smrg * Perform clipping for glReadPixels. The image's window position 666848b8605Smrg * and size, and the pack skipPixels, skipRows and rowLength are adjusted 667848b8605Smrg * so that the image region is entirely within the window bounds. 668848b8605Smrg * Note: this is different from _mesa_clip_drawpixels() in that the 669848b8605Smrg * scissor box is ignored, and we use the bounds of the current readbuffer 670b8e80941Smrg * surface or the attached image. 671848b8605Smrg * 672848b8605Smrg * \return GL_TRUE if region to read is in bounds 673848b8605Smrg * GL_FALSE if region is completely out of bounds (nothing to read) 674848b8605Smrg */ 675848b8605SmrgGLboolean 676848b8605Smrg_mesa_clip_readpixels(const struct gl_context *ctx, 677848b8605Smrg GLint *srcX, GLint *srcY, 678848b8605Smrg GLsizei *width, GLsizei *height, 679848b8605Smrg struct gl_pixelstore_attrib *pack) 680848b8605Smrg{ 681848b8605Smrg const struct gl_framebuffer *buffer = ctx->ReadBuffer; 682b8e80941Smrg struct gl_renderbuffer *rb = buffer->_ColorReadBuffer; 683b8e80941Smrg GLsizei clip_width; 684b8e80941Smrg GLsizei clip_height; 685b8e80941Smrg 686b8e80941Smrg if (rb) { 687b8e80941Smrg clip_width = rb->Width; 688b8e80941Smrg clip_height = rb->Height; 689b8e80941Smrg } else { 690b8e80941Smrg clip_width = buffer->Width; 691b8e80941Smrg clip_height = buffer->Height; 692b8e80941Smrg } 693b8e80941Smrg 694848b8605Smrg 695848b8605Smrg if (pack->RowLength == 0) { 696848b8605Smrg pack->RowLength = *width; 697848b8605Smrg } 698848b8605Smrg 699848b8605Smrg /* left clipping */ 700848b8605Smrg if (*srcX < 0) { 701848b8605Smrg pack->SkipPixels += (0 - *srcX); 702848b8605Smrg *width -= (0 - *srcX); 703848b8605Smrg *srcX = 0; 704848b8605Smrg } 705848b8605Smrg /* right clipping */ 706b8e80941Smrg if (*srcX + *width > clip_width) 707b8e80941Smrg *width -= (*srcX + *width - clip_width); 708848b8605Smrg 709848b8605Smrg if (*width <= 0) 710848b8605Smrg return GL_FALSE; 711848b8605Smrg 712848b8605Smrg /* bottom clipping */ 713848b8605Smrg if (*srcY < 0) { 714848b8605Smrg pack->SkipRows += (0 - *srcY); 715848b8605Smrg *height -= (0 - *srcY); 716848b8605Smrg *srcY = 0; 717848b8605Smrg } 718848b8605Smrg /* top clipping */ 719b8e80941Smrg if (*srcY + *height > clip_height) 720b8e80941Smrg *height -= (*srcY + *height - clip_height); 721848b8605Smrg 722848b8605Smrg if (*height <= 0) 723848b8605Smrg return GL_FALSE; 724848b8605Smrg 725848b8605Smrg return GL_TRUE; 726848b8605Smrg} 727848b8605Smrg 728848b8605Smrg 729848b8605Smrg/** 730848b8605Smrg * Do clipping for a glCopyTexSubImage call. 731848b8605Smrg * The framebuffer source region might extend outside the framebuffer 732848b8605Smrg * bounds. Clip the source region against the framebuffer bounds and 733848b8605Smrg * adjust the texture/dest position and size accordingly. 734848b8605Smrg * 735848b8605Smrg * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise. 736848b8605Smrg */ 737848b8605SmrgGLboolean 738848b8605Smrg_mesa_clip_copytexsubimage(const struct gl_context *ctx, 739848b8605Smrg GLint *destX, GLint *destY, 740848b8605Smrg GLint *srcX, GLint *srcY, 741848b8605Smrg GLsizei *width, GLsizei *height) 742848b8605Smrg{ 743848b8605Smrg const struct gl_framebuffer *fb = ctx->ReadBuffer; 744848b8605Smrg const GLint srcX0 = *srcX, srcY0 = *srcY; 745848b8605Smrg 746848b8605Smrg if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height, 747848b8605Smrg srcX, srcY, width, height)) { 748848b8605Smrg *destX = *destX + *srcX - srcX0; 749848b8605Smrg *destY = *destY + *srcY - srcY0; 750848b8605Smrg 751848b8605Smrg return GL_TRUE; 752848b8605Smrg } 753848b8605Smrg else { 754848b8605Smrg return GL_FALSE; 755848b8605Smrg } 756848b8605Smrg} 757848b8605Smrg 758848b8605Smrg 759848b8605Smrg 760848b8605Smrg/** 761848b8605Smrg * Clip the rectangle defined by (x, y, width, height) against the bounds 762848b8605Smrg * specified by [xmin, xmax) and [ymin, ymax). 763848b8605Smrg * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise. 764848b8605Smrg */ 765848b8605SmrgGLboolean 766848b8605Smrg_mesa_clip_to_region(GLint xmin, GLint ymin, 767848b8605Smrg GLint xmax, GLint ymax, 768848b8605Smrg GLint *x, GLint *y, 769848b8605Smrg GLsizei *width, GLsizei *height ) 770848b8605Smrg{ 771848b8605Smrg /* left clipping */ 772848b8605Smrg if (*x < xmin) { 773848b8605Smrg *width -= (xmin - *x); 774848b8605Smrg *x = xmin; 775848b8605Smrg } 776848b8605Smrg 777848b8605Smrg /* right clipping */ 778848b8605Smrg if (*x + *width > xmax) 779848b8605Smrg *width -= (*x + *width - xmax); 780848b8605Smrg 781848b8605Smrg if (*width <= 0) 782848b8605Smrg return GL_FALSE; 783848b8605Smrg 784848b8605Smrg /* bottom (or top) clipping */ 785848b8605Smrg if (*y < ymin) { 786848b8605Smrg *height -= (ymin - *y); 787848b8605Smrg *y = ymin; 788848b8605Smrg } 789848b8605Smrg 790848b8605Smrg /* top (or bottom) clipping */ 791848b8605Smrg if (*y + *height > ymax) 792848b8605Smrg *height -= (*y + *height - ymax); 793848b8605Smrg 794848b8605Smrg if (*height <= 0) 795848b8605Smrg return GL_FALSE; 796848b8605Smrg 797848b8605Smrg return GL_TRUE; 798848b8605Smrg} 799848b8605Smrg 800848b8605Smrg 801848b8605Smrg/** 802848b8605Smrg * Clip dst coords against Xmax (or Ymax). 803848b8605Smrg */ 804848b8605Smrgstatic inline void 805848b8605Smrgclip_right_or_top(GLint *srcX0, GLint *srcX1, 806848b8605Smrg GLint *dstX0, GLint *dstX1, 807848b8605Smrg GLint maxValue) 808848b8605Smrg{ 809848b8605Smrg GLfloat t, bias; 810848b8605Smrg 811848b8605Smrg if (*dstX1 > maxValue) { 812848b8605Smrg /* X1 outside right edge */ 813b8e80941Smrg assert(*dstX0 < maxValue); /* X0 should be inside right edge */ 814848b8605Smrg t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); 815848b8605Smrg /* chop off [t, 1] part */ 816b8e80941Smrg assert(t >= 0.0 && t <= 1.0); 817848b8605Smrg *dstX1 = maxValue; 818848b8605Smrg bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; 819848b8605Smrg *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); 820848b8605Smrg } 821848b8605Smrg else if (*dstX0 > maxValue) { 822848b8605Smrg /* X0 outside right edge */ 823b8e80941Smrg assert(*dstX1 < maxValue); /* X1 should be inside right edge */ 824848b8605Smrg t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); 825848b8605Smrg /* chop off [t, 1] part */ 826b8e80941Smrg assert(t >= 0.0 && t <= 1.0); 827848b8605Smrg *dstX0 = maxValue; 828848b8605Smrg bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F; 829848b8605Smrg *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); 830848b8605Smrg } 831848b8605Smrg} 832848b8605Smrg 833848b8605Smrg 834848b8605Smrg/** 835848b8605Smrg * Clip dst coords against Xmin (or Ymin). 836848b8605Smrg */ 837848b8605Smrgstatic inline void 838848b8605Smrgclip_left_or_bottom(GLint *srcX0, GLint *srcX1, 839848b8605Smrg GLint *dstX0, GLint *dstX1, 840848b8605Smrg GLint minValue) 841848b8605Smrg{ 842848b8605Smrg GLfloat t, bias; 843848b8605Smrg 844848b8605Smrg if (*dstX0 < minValue) { 845848b8605Smrg /* X0 outside left edge */ 846b8e80941Smrg assert(*dstX1 > minValue); /* X1 should be inside left edge */ 847848b8605Smrg t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); 848848b8605Smrg /* chop off [0, t] part */ 849b8e80941Smrg assert(t >= 0.0 && t <= 1.0); 850848b8605Smrg *dstX0 = minValue; 851848b8605Smrg bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; 852848b8605Smrg *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); 853848b8605Smrg } 854848b8605Smrg else if (*dstX1 < minValue) { 855848b8605Smrg /* X1 outside left edge */ 856b8e80941Smrg assert(*dstX0 > minValue); /* X0 should be inside left edge */ 857848b8605Smrg t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); 858848b8605Smrg /* chop off [0, t] part */ 859b8e80941Smrg assert(t >= 0.0 && t <= 1.0); 860848b8605Smrg *dstX1 = minValue; 861848b8605Smrg bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F; 862848b8605Smrg *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); 863848b8605Smrg } 864848b8605Smrg} 865848b8605Smrg 866848b8605Smrg 867848b8605Smrg/** 868848b8605Smrg * Do clipping of blit src/dest rectangles. 869848b8605Smrg * The dest rect is clipped against both the buffer bounds and scissor bounds. 870848b8605Smrg * The src rect is just clipped against the buffer bounds. 871848b8605Smrg * 872848b8605Smrg * When either the src or dest rect is clipped, the other is also clipped 873848b8605Smrg * proportionately! 874848b8605Smrg * 875848b8605Smrg * Note that X0 need not be less than X1 (same for Y) for either the source 876848b8605Smrg * and dest rects. That makes the clipping a little trickier. 877848b8605Smrg * 878848b8605Smrg * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped 879848b8605Smrg */ 880848b8605SmrgGLboolean 881848b8605Smrg_mesa_clip_blit(struct gl_context *ctx, 882b8e80941Smrg const struct gl_framebuffer *readFb, 883b8e80941Smrg const struct gl_framebuffer *drawFb, 884848b8605Smrg GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1, 885848b8605Smrg GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1) 886848b8605Smrg{ 887848b8605Smrg const GLint srcXmin = 0; 888b8e80941Smrg const GLint srcXmax = readFb->Width; 889848b8605Smrg const GLint srcYmin = 0; 890b8e80941Smrg const GLint srcYmax = readFb->Height; 891848b8605Smrg 892848b8605Smrg /* these include scissor bounds */ 893b8e80941Smrg const GLint dstXmin = drawFb->_Xmin; 894b8e80941Smrg const GLint dstXmax = drawFb->_Xmax; 895b8e80941Smrg const GLint dstYmin = drawFb->_Ymin; 896b8e80941Smrg const GLint dstYmax = drawFb->_Ymax; 897848b8605Smrg 898848b8605Smrg /* 899848b8605Smrg printf("PreClipX: src: %d .. %d dst: %d .. %d\n", 900848b8605Smrg *srcX0, *srcX1, *dstX0, *dstX1); 901848b8605Smrg printf("PreClipY: src: %d .. %d dst: %d .. %d\n", 902848b8605Smrg *srcY0, *srcY1, *dstY0, *dstY1); 903848b8605Smrg */ 904848b8605Smrg 905848b8605Smrg /* trivial rejection tests */ 906848b8605Smrg if (*dstX0 == *dstX1) 907848b8605Smrg return GL_FALSE; /* no width */ 908848b8605Smrg if (*dstX0 <= dstXmin && *dstX1 <= dstXmin) 909848b8605Smrg return GL_FALSE; /* totally out (left) of bounds */ 910848b8605Smrg if (*dstX0 >= dstXmax && *dstX1 >= dstXmax) 911848b8605Smrg return GL_FALSE; /* totally out (right) of bounds */ 912848b8605Smrg 913848b8605Smrg if (*dstY0 == *dstY1) 914848b8605Smrg return GL_FALSE; 915848b8605Smrg if (*dstY0 <= dstYmin && *dstY1 <= dstYmin) 916848b8605Smrg return GL_FALSE; 917848b8605Smrg if (*dstY0 >= dstYmax && *dstY1 >= dstYmax) 918848b8605Smrg return GL_FALSE; 919848b8605Smrg 920848b8605Smrg if (*srcX0 == *srcX1) 921848b8605Smrg return GL_FALSE; 922848b8605Smrg if (*srcX0 <= srcXmin && *srcX1 <= srcXmin) 923848b8605Smrg return GL_FALSE; 924848b8605Smrg if (*srcX0 >= srcXmax && *srcX1 >= srcXmax) 925848b8605Smrg return GL_FALSE; 926848b8605Smrg 927848b8605Smrg if (*srcY0 == *srcY1) 928848b8605Smrg return GL_FALSE; 929848b8605Smrg if (*srcY0 <= srcYmin && *srcY1 <= srcYmin) 930848b8605Smrg return GL_FALSE; 931848b8605Smrg if (*srcY0 >= srcYmax && *srcY1 >= srcYmax) 932848b8605Smrg return GL_FALSE; 933848b8605Smrg 934848b8605Smrg /* 935848b8605Smrg * dest clip 936848b8605Smrg */ 937848b8605Smrg clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax); 938848b8605Smrg clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax); 939848b8605Smrg clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin); 940848b8605Smrg clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin); 941848b8605Smrg 942848b8605Smrg /* 943848b8605Smrg * src clip (just swap src/dst values from above) 944848b8605Smrg */ 945848b8605Smrg clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax); 946848b8605Smrg clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax); 947848b8605Smrg clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin); 948848b8605Smrg clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin); 949848b8605Smrg 950848b8605Smrg /* 951848b8605Smrg printf("PostClipX: src: %d .. %d dst: %d .. %d\n", 952848b8605Smrg *srcX0, *srcX1, *dstX0, *dstX1); 953848b8605Smrg printf("PostClipY: src: %d .. %d dst: %d .. %d\n", 954848b8605Smrg *srcY0, *srcY1, *dstY0, *dstY1); 955848b8605Smrg */ 956848b8605Smrg 957b8e80941Smrg assert(*dstX0 >= dstXmin); 958b8e80941Smrg assert(*dstX0 <= dstXmax); 959b8e80941Smrg assert(*dstX1 >= dstXmin); 960b8e80941Smrg assert(*dstX1 <= dstXmax); 961848b8605Smrg 962b8e80941Smrg assert(*dstY0 >= dstYmin); 963b8e80941Smrg assert(*dstY0 <= dstYmax); 964b8e80941Smrg assert(*dstY1 >= dstYmin); 965b8e80941Smrg assert(*dstY1 <= dstYmax); 966848b8605Smrg 967b8e80941Smrg assert(*srcX0 >= srcXmin); 968b8e80941Smrg assert(*srcX0 <= srcXmax); 969b8e80941Smrg assert(*srcX1 >= srcXmin); 970b8e80941Smrg assert(*srcX1 <= srcXmax); 971848b8605Smrg 972b8e80941Smrg assert(*srcY0 >= srcYmin); 973b8e80941Smrg assert(*srcY0 <= srcYmax); 974b8e80941Smrg assert(*srcY1 >= srcYmin); 975b8e80941Smrg assert(*srcY1 <= srcYmax); 976848b8605Smrg 977848b8605Smrg return GL_TRUE; 978848b8605Smrg} 979b8e80941Smrg 980b8e80941Smrg/** 981b8e80941Smrg * Swap the bytes in a 2D image. 982b8e80941Smrg * 983b8e80941Smrg * using the packing information this swaps the bytes 984b8e80941Smrg * according to the format and type of data being input. 985b8e80941Smrg * It takes into a/c various packing parameters like 986b8e80941Smrg * Alignment and RowLength. 987b8e80941Smrg */ 988b8e80941Smrgvoid 989b8e80941Smrg_mesa_swap_bytes_2d_image(GLenum format, GLenum type, 990b8e80941Smrg const struct gl_pixelstore_attrib *packing, 991b8e80941Smrg GLsizei width, GLsizei height, 992b8e80941Smrg GLvoid *dst, const GLvoid *src) 993b8e80941Smrg{ 994b8e80941Smrg GLint swapSize = _mesa_sizeof_packed_type(type); 995b8e80941Smrg 996b8e80941Smrg assert(packing->SwapBytes); 997b8e80941Smrg 998b8e80941Smrg if (swapSize == 2 || swapSize == 4) { 999b8e80941Smrg int swapsPerPixel = _mesa_bytes_per_pixel(format, type) / swapSize; 1000b8e80941Smrg int stride = _mesa_image_row_stride(packing, width, format, type); 1001b8e80941Smrg int row; 1002b8e80941Smrg uint8_t *dstrow; 1003b8e80941Smrg const uint8_t *srcrow; 1004b8e80941Smrg assert(swapsPerPixel > 0); 1005b8e80941Smrg assert(_mesa_bytes_per_pixel(format, type) % swapSize == 0); 1006b8e80941Smrg dstrow = dst; 1007b8e80941Smrg srcrow = src; 1008b8e80941Smrg for (row = 0; row < height; row++) { 1009b8e80941Smrg if (swapSize == 2) 1010b8e80941Smrg swap2_copy((GLushort *)dstrow, (GLushort *)srcrow, width * swapsPerPixel); 1011b8e80941Smrg else if (swapSize == 4) 1012b8e80941Smrg swap4_copy((GLuint *)dstrow, (GLuint *)srcrow, width * swapsPerPixel); 1013b8e80941Smrg dstrow += stride; 1014b8e80941Smrg srcrow += stride; 1015b8e80941Smrg } 1016b8e80941Smrg } 1017b8e80941Smrg} 1018