mesa: move more format helper functions to glformats.c
[mesa.git] / src / mesa / main / image.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.5
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR 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 "mfeatures.h"
40 #include "mtypes.h"
41
42
43
44 /**
45 * Flip the order of the 2 bytes in each word in the given array.
46 *
47 * \param p array.
48 * \param n number of words.
49 */
50 void
51 _mesa_swap2( GLushort *p, GLuint n )
52 {
53 GLuint i;
54 for (i = 0; i < n; i++) {
55 p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00);
56 }
57 }
58
59
60
61 /*
62 * Flip the order of the 4 bytes in each word in the given array.
63 */
64 void
65 _mesa_swap4( GLuint *p, GLuint n )
66 {
67 GLuint i, a, b;
68 for (i = 0; i < n; i++) {
69 b = p[i];
70 a = (b >> 24)
71 | ((b >> 8) & 0xff00)
72 | ((b << 8) & 0xff0000)
73 | ((b << 24) & 0xff000000);
74 p[i] = a;
75 }
76 }
77
78
79 /**
80 * Do error checking of format/type combinations for glReadPixels,
81 * glDrawPixels and glTex[Sub]Image. Note that depending on the format
82 * and type values, we may either generate GL_INVALID_OPERATION or
83 * GL_INVALID_ENUM.
84 *
85 * \param format pixel format.
86 * \param type pixel type.
87 *
88 * \return GL_INVALID_ENUM, GL_INVALID_OPERATION or GL_NO_ERROR
89 */
90 GLenum
91 _mesa_error_check_format_and_type(const struct gl_context *ctx,
92 GLenum format, GLenum type)
93 {
94 /* special type-based checks (see glReadPixels, glDrawPixels error lists) */
95 switch (type) {
96 case GL_BITMAP:
97 if (format != GL_COLOR_INDEX && format != GL_STENCIL_INDEX) {
98 return GL_INVALID_ENUM;
99 }
100 break;
101
102 case GL_UNSIGNED_BYTE_3_3_2:
103 case GL_UNSIGNED_BYTE_2_3_3_REV:
104 case GL_UNSIGNED_SHORT_5_6_5:
105 case GL_UNSIGNED_SHORT_5_6_5_REV:
106 if (format == GL_RGB) {
107 break; /* OK */
108 }
109 if (format == GL_RGB_INTEGER_EXT &&
110 ctx->Extensions.ARB_texture_rgb10_a2ui) {
111 break; /* OK */
112 }
113 return GL_INVALID_OPERATION;
114
115 case GL_UNSIGNED_SHORT_4_4_4_4:
116 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
117 case GL_UNSIGNED_SHORT_5_5_5_1:
118 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
119 case GL_UNSIGNED_INT_8_8_8_8:
120 case GL_UNSIGNED_INT_8_8_8_8_REV:
121 case GL_UNSIGNED_INT_10_10_10_2:
122 case GL_UNSIGNED_INT_2_10_10_10_REV:
123 if (format == GL_RGBA ||
124 format == GL_BGRA ||
125 format == GL_ABGR_EXT) {
126 break; /* OK */
127 }
128 if ((format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT) &&
129 ctx->Extensions.ARB_texture_rgb10_a2ui) {
130 break; /* OK */
131 }
132 return GL_INVALID_OPERATION;
133
134 case GL_UNSIGNED_INT_24_8:
135 if (!ctx->Extensions.EXT_packed_depth_stencil) {
136 return GL_INVALID_ENUM;
137 }
138 if (format != GL_DEPTH_STENCIL) {
139 return GL_INVALID_OPERATION;
140 }
141 return GL_NO_ERROR;
142
143 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
144 if (!ctx->Extensions.ARB_depth_buffer_float) {
145 return GL_INVALID_ENUM;
146 }
147 if (format != GL_DEPTH_STENCIL) {
148 return GL_INVALID_OPERATION;
149 }
150 return GL_NO_ERROR;
151
152 case GL_UNSIGNED_INT_10F_11F_11F_REV:
153 if (!ctx->Extensions.EXT_packed_float) {
154 return GL_INVALID_ENUM;
155 }
156 if (format != GL_RGB) {
157 return GL_INVALID_OPERATION;
158 }
159 return GL_NO_ERROR;
160
161 default:
162 ; /* fall-through */
163 }
164
165 /* now, for each format, check the type for compatibility */
166 switch (format) {
167 case GL_COLOR_INDEX:
168 case GL_STENCIL_INDEX:
169 switch (type) {
170 case GL_BITMAP:
171 case GL_BYTE:
172 case GL_UNSIGNED_BYTE:
173 case GL_SHORT:
174 case GL_UNSIGNED_SHORT:
175 case GL_INT:
176 case GL_UNSIGNED_INT:
177 case GL_FLOAT:
178 return GL_NO_ERROR;
179 case GL_HALF_FLOAT:
180 return ctx->Extensions.ARB_half_float_pixel
181 ? GL_NO_ERROR : GL_INVALID_ENUM;
182 default:
183 return GL_INVALID_ENUM;
184 }
185
186 case GL_RED:
187 case GL_GREEN:
188 case GL_BLUE:
189 case GL_ALPHA:
190 #if 0 /* not legal! see table 3.6 of the 1.5 spec */
191 case GL_INTENSITY:
192 #endif
193 case GL_LUMINANCE:
194 case GL_LUMINANCE_ALPHA:
195 case GL_DEPTH_COMPONENT:
196 switch (type) {
197 case GL_BYTE:
198 case GL_UNSIGNED_BYTE:
199 case GL_SHORT:
200 case GL_UNSIGNED_SHORT:
201 case GL_INT:
202 case GL_UNSIGNED_INT:
203 case GL_FLOAT:
204 return GL_NO_ERROR;
205 case GL_HALF_FLOAT:
206 return ctx->Extensions.ARB_half_float_pixel
207 ? GL_NO_ERROR : GL_INVALID_ENUM;
208 default:
209 return GL_INVALID_ENUM;
210 }
211
212 case GL_RG:
213 if (!ctx->Extensions.ARB_texture_rg)
214 return GL_INVALID_ENUM;
215 switch (type) {
216 case GL_BYTE:
217 case GL_UNSIGNED_BYTE:
218 case GL_SHORT:
219 case GL_UNSIGNED_SHORT:
220 case GL_INT:
221 case GL_UNSIGNED_INT:
222 case GL_FLOAT:
223 return GL_NO_ERROR;
224 case GL_HALF_FLOAT:
225 return ctx->Extensions.ARB_half_float_pixel
226 ? GL_NO_ERROR : GL_INVALID_ENUM;
227 default:
228 return GL_INVALID_ENUM;
229 }
230
231 case GL_RGB:
232 switch (type) {
233 case GL_BYTE:
234 case GL_UNSIGNED_BYTE:
235 case GL_SHORT:
236 case GL_UNSIGNED_SHORT:
237 case GL_INT:
238 case GL_UNSIGNED_INT:
239 case GL_FLOAT:
240 case GL_UNSIGNED_BYTE_3_3_2:
241 case GL_UNSIGNED_BYTE_2_3_3_REV:
242 case GL_UNSIGNED_SHORT_5_6_5:
243 case GL_UNSIGNED_SHORT_5_6_5_REV:
244 return GL_NO_ERROR;
245 case GL_HALF_FLOAT:
246 return ctx->Extensions.ARB_half_float_pixel
247 ? GL_NO_ERROR : GL_INVALID_ENUM;
248 case GL_UNSIGNED_INT_5_9_9_9_REV:
249 return ctx->Extensions.EXT_texture_shared_exponent
250 ? GL_NO_ERROR : GL_INVALID_ENUM;
251 case GL_UNSIGNED_INT_10F_11F_11F_REV:
252 return ctx->Extensions.EXT_packed_float
253 ? GL_NO_ERROR : GL_INVALID_ENUM;
254 default:
255 return GL_INVALID_ENUM;
256 }
257
258 case GL_BGR:
259 switch (type) {
260 /* NOTE: no packed types are supported with BGR. That's
261 * intentional, according to the GL spec.
262 */
263 case GL_BYTE:
264 case GL_UNSIGNED_BYTE:
265 case GL_SHORT:
266 case GL_UNSIGNED_SHORT:
267 case GL_INT:
268 case GL_UNSIGNED_INT:
269 case GL_FLOAT:
270 return GL_NO_ERROR;
271 case GL_HALF_FLOAT:
272 return ctx->Extensions.ARB_half_float_pixel
273 ? GL_NO_ERROR : GL_INVALID_ENUM;
274 default:
275 return GL_INVALID_ENUM;
276 }
277
278 case GL_RGBA:
279 case GL_BGRA:
280 case GL_ABGR_EXT:
281 switch (type) {
282 case GL_BYTE:
283 case GL_UNSIGNED_BYTE:
284 case GL_SHORT:
285 case GL_UNSIGNED_SHORT:
286 case GL_INT:
287 case GL_UNSIGNED_INT:
288 case GL_FLOAT:
289 case GL_UNSIGNED_SHORT_4_4_4_4:
290 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
291 case GL_UNSIGNED_SHORT_5_5_5_1:
292 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
293 case GL_UNSIGNED_INT_8_8_8_8:
294 case GL_UNSIGNED_INT_8_8_8_8_REV:
295 case GL_UNSIGNED_INT_10_10_10_2:
296 case GL_UNSIGNED_INT_2_10_10_10_REV:
297 return GL_NO_ERROR;
298 case GL_HALF_FLOAT:
299 return ctx->Extensions.ARB_half_float_pixel
300 ? GL_NO_ERROR : GL_INVALID_ENUM;
301 default:
302 return GL_INVALID_ENUM;
303 }
304
305 case GL_YCBCR_MESA:
306 if (!ctx->Extensions.MESA_ycbcr_texture)
307 return GL_INVALID_ENUM;
308 if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
309 type == GL_UNSIGNED_SHORT_8_8_REV_MESA)
310 return GL_NO_ERROR;
311 else
312 return GL_INVALID_OPERATION;
313
314 case GL_DEPTH_STENCIL_EXT:
315 if (ctx->Extensions.EXT_packed_depth_stencil &&
316 type == GL_UNSIGNED_INT_24_8)
317 return GL_NO_ERROR;
318 else if (ctx->Extensions.ARB_depth_buffer_float &&
319 type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV)
320 return GL_NO_ERROR;
321 else
322 return GL_INVALID_ENUM;
323
324 case GL_DUDV_ATI:
325 case GL_DU8DV8_ATI:
326 if (!ctx->Extensions.ATI_envmap_bumpmap)
327 return GL_INVALID_ENUM;
328 switch (type) {
329 case GL_BYTE:
330 case GL_UNSIGNED_BYTE:
331 case GL_SHORT:
332 case GL_UNSIGNED_SHORT:
333 case GL_INT:
334 case GL_UNSIGNED_INT:
335 case GL_FLOAT:
336 return GL_NO_ERROR;
337 default:
338 return GL_INVALID_ENUM;
339 }
340
341 /* integer-valued formats */
342 case GL_RED_INTEGER_EXT:
343 case GL_GREEN_INTEGER_EXT:
344 case GL_BLUE_INTEGER_EXT:
345 case GL_ALPHA_INTEGER_EXT:
346 case GL_RG_INTEGER:
347 switch (type) {
348 case GL_BYTE:
349 case GL_UNSIGNED_BYTE:
350 case GL_SHORT:
351 case GL_UNSIGNED_SHORT:
352 case GL_INT:
353 case GL_UNSIGNED_INT:
354 return (ctx->VersionMajor >= 3 ||
355 ctx->Extensions.EXT_texture_integer)
356 ? GL_NO_ERROR : GL_INVALID_ENUM;
357 default:
358 return GL_INVALID_ENUM;
359 }
360
361 case GL_RGB_INTEGER_EXT:
362 switch (type) {
363 case GL_BYTE:
364 case GL_UNSIGNED_BYTE:
365 case GL_SHORT:
366 case GL_UNSIGNED_SHORT:
367 case GL_INT:
368 case GL_UNSIGNED_INT:
369 return (ctx->VersionMajor >= 3 ||
370 ctx->Extensions.EXT_texture_integer)
371 ? GL_NO_ERROR : GL_INVALID_ENUM;
372 case GL_UNSIGNED_BYTE_3_3_2:
373 case GL_UNSIGNED_BYTE_2_3_3_REV:
374 case GL_UNSIGNED_SHORT_5_6_5:
375 case GL_UNSIGNED_SHORT_5_6_5_REV:
376 return ctx->Extensions.ARB_texture_rgb10_a2ui
377 ? GL_NO_ERROR : GL_INVALID_ENUM;
378 default:
379 return GL_INVALID_ENUM;
380 }
381
382 case GL_BGR_INTEGER_EXT:
383 switch (type) {
384 case GL_BYTE:
385 case GL_UNSIGNED_BYTE:
386 case GL_SHORT:
387 case GL_UNSIGNED_SHORT:
388 case GL_INT:
389 case GL_UNSIGNED_INT:
390 /* NOTE: no packed formats w/ BGR format */
391 return (ctx->VersionMajor >= 3 ||
392 ctx->Extensions.EXT_texture_integer)
393 ? GL_NO_ERROR : GL_INVALID_ENUM;
394 default:
395 return GL_INVALID_ENUM;
396 }
397
398 case GL_RGBA_INTEGER_EXT:
399 case GL_BGRA_INTEGER_EXT:
400 switch (type) {
401 case GL_BYTE:
402 case GL_UNSIGNED_BYTE:
403 case GL_SHORT:
404 case GL_UNSIGNED_SHORT:
405 case GL_INT:
406 case GL_UNSIGNED_INT:
407 return (ctx->VersionMajor >= 3 ||
408 ctx->Extensions.EXT_texture_integer)
409 ? GL_NO_ERROR : GL_INVALID_ENUM;
410 case GL_UNSIGNED_SHORT_4_4_4_4:
411 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
412 case GL_UNSIGNED_SHORT_5_5_5_1:
413 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
414 case GL_UNSIGNED_INT_8_8_8_8:
415 case GL_UNSIGNED_INT_8_8_8_8_REV:
416 case GL_UNSIGNED_INT_10_10_10_2:
417 case GL_UNSIGNED_INT_2_10_10_10_REV:
418 return ctx->Extensions.ARB_texture_rgb10_a2ui
419 ? GL_NO_ERROR : GL_INVALID_ENUM;
420 default:
421 return GL_INVALID_ENUM;
422 }
423
424 case GL_LUMINANCE_INTEGER_EXT:
425 case GL_LUMINANCE_ALPHA_INTEGER_EXT:
426 switch (type) {
427 case GL_BYTE:
428 case GL_UNSIGNED_BYTE:
429 case GL_SHORT:
430 case GL_UNSIGNED_SHORT:
431 case GL_INT:
432 case GL_UNSIGNED_INT:
433 return ctx->Extensions.EXT_texture_integer
434 ? GL_NO_ERROR : GL_INVALID_ENUM;
435 default:
436 return GL_INVALID_ENUM;
437 }
438
439 default:
440 return GL_INVALID_ENUM;
441 }
442 return GL_NO_ERROR;
443 }
444
445
446 /**
447 * Return the byte offset of a specific pixel in an image (1D, 2D or 3D).
448 *
449 * Pixel unpacking/packing parameters are observed according to \p packing.
450 *
451 * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
452 * \param packing the pixelstore attributes
453 * \param width the image width
454 * \param height the image height
455 * \param format the pixel format (must be validated beforehand)
456 * \param type the pixel data type (must be validated beforehand)
457 * \param img which image in the volume (0 for 1D or 2D images)
458 * \param row row of pixel in the image (0 for 1D images)
459 * \param column column of pixel in the image
460 *
461 * \return offset of pixel.
462 *
463 * \sa gl_pixelstore_attrib.
464 */
465 GLintptr
466 _mesa_image_offset( GLuint dimensions,
467 const struct gl_pixelstore_attrib *packing,
468 GLsizei width, GLsizei height,
469 GLenum format, GLenum type,
470 GLint img, GLint row, GLint column )
471 {
472 GLint alignment; /* 1, 2 or 4 */
473 GLint pixels_per_row;
474 GLint rows_per_image;
475 GLint skiprows;
476 GLint skippixels;
477 GLint skipimages; /* for 3-D volume images */
478 GLintptr offset;
479
480 ASSERT(dimensions >= 1 && dimensions <= 3);
481
482 alignment = packing->Alignment;
483 if (packing->RowLength > 0) {
484 pixels_per_row = packing->RowLength;
485 }
486 else {
487 pixels_per_row = width;
488 }
489 if (packing->ImageHeight > 0) {
490 rows_per_image = packing->ImageHeight;
491 }
492 else {
493 rows_per_image = height;
494 }
495
496 skippixels = packing->SkipPixels;
497 /* Note: SKIP_ROWS _is_ used for 1D images */
498 skiprows = packing->SkipRows;
499 /* Note: SKIP_IMAGES is only used for 3D images */
500 skipimages = (dimensions == 3) ? packing->SkipImages : 0;
501
502 if (type == GL_BITMAP) {
503 /* BITMAP data */
504 GLint bytes_per_row;
505 GLint bytes_per_image;
506 /* components per pixel for color or stencil index: */
507 const GLint comp_per_pixel = 1;
508
509 /* The pixel type and format should have been error checked earlier */
510 assert(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX);
511
512 bytes_per_row = alignment
513 * CEILING( comp_per_pixel*pixels_per_row, 8*alignment );
514
515 bytes_per_image = bytes_per_row * rows_per_image;
516
517 offset = (skipimages + img) * bytes_per_image
518 + (skiprows + row) * bytes_per_row
519 + (skippixels + column) / 8;
520 }
521 else {
522 /* Non-BITMAP data */
523 GLint bytes_per_pixel, bytes_per_row, remainder, bytes_per_image;
524 GLint topOfImage;
525
526 bytes_per_pixel = _mesa_bytes_per_pixel( format, type );
527
528 /* The pixel type and format should have been error checked earlier */
529 assert(bytes_per_pixel > 0);
530
531 bytes_per_row = pixels_per_row * bytes_per_pixel;
532 remainder = bytes_per_row % alignment;
533 if (remainder > 0)
534 bytes_per_row += (alignment - remainder);
535
536 ASSERT(bytes_per_row % alignment == 0);
537
538 bytes_per_image = bytes_per_row * rows_per_image;
539
540 if (packing->Invert) {
541 /* set pixel_addr to the last row */
542 topOfImage = bytes_per_row * (height - 1);
543 bytes_per_row = -bytes_per_row;
544 }
545 else {
546 topOfImage = 0;
547 }
548
549 /* compute final pixel address */
550 offset = (skipimages + img) * bytes_per_image
551 + topOfImage
552 + (skiprows + row) * bytes_per_row
553 + (skippixels + column) * bytes_per_pixel;
554 }
555
556 return offset;
557 }
558
559
560 /**
561 * Return the address of a specific pixel in an image (1D, 2D or 3D).
562 *
563 * Pixel unpacking/packing parameters are observed according to \p packing.
564 *
565 * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
566 * \param packing the pixelstore attributes
567 * \param image starting address of image data
568 * \param width the image width
569 * \param height the image height
570 * \param format the pixel format (must be validated beforehand)
571 * \param type the pixel data type (must be validated beforehand)
572 * \param img which image in the volume (0 for 1D or 2D images)
573 * \param row row of pixel in the image (0 for 1D images)
574 * \param column column of pixel in the image
575 *
576 * \return address of pixel.
577 *
578 * \sa gl_pixelstore_attrib.
579 */
580 GLvoid *
581 _mesa_image_address( GLuint dimensions,
582 const struct gl_pixelstore_attrib *packing,
583 const GLvoid *image,
584 GLsizei width, GLsizei height,
585 GLenum format, GLenum type,
586 GLint img, GLint row, GLint column )
587 {
588 const GLubyte *addr = (const GLubyte *) image;
589
590 addr += _mesa_image_offset(dimensions, packing, width, height,
591 format, type, img, row, column);
592
593 return (GLvoid *) addr;
594 }
595
596
597 GLvoid *
598 _mesa_image_address1d( const struct gl_pixelstore_attrib *packing,
599 const GLvoid *image,
600 GLsizei width,
601 GLenum format, GLenum type,
602 GLint column )
603 {
604 return _mesa_image_address(1, packing, image, width, 1,
605 format, type, 0, 0, column);
606 }
607
608
609 GLvoid *
610 _mesa_image_address2d( const struct gl_pixelstore_attrib *packing,
611 const GLvoid *image,
612 GLsizei width, GLsizei height,
613 GLenum format, GLenum type,
614 GLint row, GLint column )
615 {
616 return _mesa_image_address(2, packing, image, width, height,
617 format, type, 0, row, column);
618 }
619
620
621 GLvoid *
622 _mesa_image_address3d( const struct gl_pixelstore_attrib *packing,
623 const GLvoid *image,
624 GLsizei width, GLsizei height,
625 GLenum format, GLenum type,
626 GLint img, GLint row, GLint column )
627 {
628 return _mesa_image_address(3, packing, image, width, height,
629 format, type, img, row, column);
630 }
631
632
633
634 /**
635 * Compute the stride (in bytes) between image rows.
636 *
637 * \param packing the pixelstore attributes
638 * \param width image width.
639 * \param format pixel format.
640 * \param type pixel data type.
641 *
642 * \return the stride in bytes for the given parameters, or -1 if error
643 */
644 GLint
645 _mesa_image_row_stride( const struct gl_pixelstore_attrib *packing,
646 GLint width, GLenum format, GLenum type )
647 {
648 GLint bytesPerRow, remainder;
649
650 ASSERT(packing);
651
652 if (type == GL_BITMAP) {
653 if (packing->RowLength == 0) {
654 bytesPerRow = (width + 7) / 8;
655 }
656 else {
657 bytesPerRow = (packing->RowLength + 7) / 8;
658 }
659 }
660 else {
661 /* Non-BITMAP data */
662 const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
663 if (bytesPerPixel <= 0)
664 return -1; /* error */
665 if (packing->RowLength == 0) {
666 bytesPerRow = bytesPerPixel * width;
667 }
668 else {
669 bytesPerRow = bytesPerPixel * packing->RowLength;
670 }
671 }
672
673 remainder = bytesPerRow % packing->Alignment;
674 if (remainder > 0) {
675 bytesPerRow += (packing->Alignment - remainder);
676 }
677
678 if (packing->Invert) {
679 /* negate the bytes per row (negative row stride) */
680 bytesPerRow = -bytesPerRow;
681 }
682
683 return bytesPerRow;
684 }
685
686
687 /*
688 * Compute the stride between images in a 3D texture (in bytes) for the given
689 * pixel packing parameters and image width, format and type.
690 */
691 GLint
692 _mesa_image_image_stride( const struct gl_pixelstore_attrib *packing,
693 GLint width, GLint height,
694 GLenum format, GLenum type )
695 {
696 GLint bytesPerRow, bytesPerImage, remainder;
697
698 ASSERT(packing);
699
700 if (type == GL_BITMAP) {
701 if (packing->RowLength == 0) {
702 bytesPerRow = (width + 7) / 8;
703 }
704 else {
705 bytesPerRow = (packing->RowLength + 7) / 8;
706 }
707 }
708 else {
709 const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
710
711 if (bytesPerPixel <= 0)
712 return -1; /* error */
713 if (packing->RowLength == 0) {
714 bytesPerRow = bytesPerPixel * width;
715 }
716 else {
717 bytesPerRow = bytesPerPixel * packing->RowLength;
718 }
719 }
720
721 remainder = bytesPerRow % packing->Alignment;
722 if (remainder > 0)
723 bytesPerRow += (packing->Alignment - remainder);
724
725 if (packing->ImageHeight == 0)
726 bytesPerImage = bytesPerRow * height;
727 else
728 bytesPerImage = bytesPerRow * packing->ImageHeight;
729
730 return bytesPerImage;
731 }
732
733
734
735 /**
736 * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel.
737 * This is typically used to convert a bitmap into a GLubyte/pixel texture.
738 * "On" bits will set texels to \p onValue.
739 * "Off" bits will not modify texels.
740 * \param width src bitmap width in pixels
741 * \param height src bitmap height in pixels
742 * \param unpack bitmap unpacking state
743 * \param bitmap the src bitmap data
744 * \param destBuffer start of dest buffer
745 * \param destStride row stride in dest buffer
746 * \param onValue if bit is 1, set destBuffer pixel to this value
747 */
748 void
749 _mesa_expand_bitmap(GLsizei width, GLsizei height,
750 const struct gl_pixelstore_attrib *unpack,
751 const GLubyte *bitmap,
752 GLubyte *destBuffer, GLint destStride,
753 GLubyte onValue)
754 {
755 const GLubyte *srcRow = (const GLubyte *)
756 _mesa_image_address2d(unpack, bitmap, width, height,
757 GL_COLOR_INDEX, GL_BITMAP, 0, 0);
758 const GLint srcStride = _mesa_image_row_stride(unpack, width,
759 GL_COLOR_INDEX, GL_BITMAP);
760 GLint row, col;
761
762 #define SET_PIXEL(COL, ROW) \
763 destBuffer[(ROW) * destStride + (COL)] = onValue;
764
765 for (row = 0; row < height; row++) {
766 const GLubyte *src = srcRow;
767
768 if (unpack->LsbFirst) {
769 /* Lsb first */
770 GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
771 for (col = 0; col < width; col++) {
772
773 if (*src & mask) {
774 SET_PIXEL(col, row);
775 }
776
777 if (mask == 128U) {
778 src++;
779 mask = 1U;
780 }
781 else {
782 mask = mask << 1;
783 }
784 }
785
786 /* get ready for next row */
787 if (mask != 1)
788 src++;
789 }
790 else {
791 /* Msb first */
792 GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
793 for (col = 0; col < width; col++) {
794
795 if (*src & mask) {
796 SET_PIXEL(col, row);
797 }
798
799 if (mask == 1U) {
800 src++;
801 mask = 128U;
802 }
803 else {
804 mask = mask >> 1;
805 }
806 }
807
808 /* get ready for next row */
809 if (mask != 128)
810 src++;
811 }
812
813 srcRow += srcStride;
814 } /* row */
815
816 #undef SET_PIXEL
817 }
818
819
820
821
822 /**
823 * Convert an array of RGBA colors from one datatype to another.
824 * NOTE: src may equal dst. In that case, we use a temporary buffer.
825 */
826 void
827 _mesa_convert_colors(GLenum srcType, const GLvoid *src,
828 GLenum dstType, GLvoid *dst,
829 GLuint count, const GLubyte mask[])
830 {
831 GLuint *tempBuffer;
832 const GLboolean useTemp = (src == dst);
833
834 tempBuffer = malloc(count * MAX_PIXEL_BYTES);
835 if (!tempBuffer)
836 return;
837
838 ASSERT(srcType != dstType);
839
840 switch (srcType) {
841 case GL_UNSIGNED_BYTE:
842 if (dstType == GL_UNSIGNED_SHORT) {
843 const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
844 GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
845 GLuint i;
846 for (i = 0; i < count; i++) {
847 if (!mask || mask[i]) {
848 dst2[i][RCOMP] = UBYTE_TO_USHORT(src1[i][RCOMP]);
849 dst2[i][GCOMP] = UBYTE_TO_USHORT(src1[i][GCOMP]);
850 dst2[i][BCOMP] = UBYTE_TO_USHORT(src1[i][BCOMP]);
851 dst2[i][ACOMP] = UBYTE_TO_USHORT(src1[i][ACOMP]);
852 }
853 }
854 if (useTemp)
855 memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
856 }
857 else {
858 const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
859 GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
860 GLuint i;
861 ASSERT(dstType == GL_FLOAT);
862 for (i = 0; i < count; i++) {
863 if (!mask || mask[i]) {
864 dst4[i][RCOMP] = UBYTE_TO_FLOAT(src1[i][RCOMP]);
865 dst4[i][GCOMP] = UBYTE_TO_FLOAT(src1[i][GCOMP]);
866 dst4[i][BCOMP] = UBYTE_TO_FLOAT(src1[i][BCOMP]);
867 dst4[i][ACOMP] = UBYTE_TO_FLOAT(src1[i][ACOMP]);
868 }
869 }
870 if (useTemp)
871 memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
872 }
873 break;
874 case GL_UNSIGNED_SHORT:
875 if (dstType == GL_UNSIGNED_BYTE) {
876 const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
877 GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
878 GLuint i;
879 for (i = 0; i < count; i++) {
880 if (!mask || mask[i]) {
881 dst1[i][RCOMP] = USHORT_TO_UBYTE(src2[i][RCOMP]);
882 dst1[i][GCOMP] = USHORT_TO_UBYTE(src2[i][GCOMP]);
883 dst1[i][BCOMP] = USHORT_TO_UBYTE(src2[i][BCOMP]);
884 dst1[i][ACOMP] = USHORT_TO_UBYTE(src2[i][ACOMP]);
885 }
886 }
887 if (useTemp)
888 memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
889 }
890 else {
891 const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
892 GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
893 GLuint i;
894 ASSERT(dstType == GL_FLOAT);
895 for (i = 0; i < count; i++) {
896 if (!mask || mask[i]) {
897 dst4[i][RCOMP] = USHORT_TO_FLOAT(src2[i][RCOMP]);
898 dst4[i][GCOMP] = USHORT_TO_FLOAT(src2[i][GCOMP]);
899 dst4[i][BCOMP] = USHORT_TO_FLOAT(src2[i][BCOMP]);
900 dst4[i][ACOMP] = USHORT_TO_FLOAT(src2[i][ACOMP]);
901 }
902 }
903 if (useTemp)
904 memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
905 }
906 break;
907 case GL_FLOAT:
908 if (dstType == GL_UNSIGNED_BYTE) {
909 const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
910 GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
911 GLuint i;
912 for (i = 0; i < count; i++) {
913 if (!mask || mask[i])
914 _mesa_unclamped_float_rgba_to_ubyte(dst1[i], src4[i]);
915 }
916 if (useTemp)
917 memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
918 }
919 else {
920 const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
921 GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
922 GLuint i;
923 ASSERT(dstType == GL_UNSIGNED_SHORT);
924 for (i = 0; i < count; i++) {
925 if (!mask || mask[i]) {
926 UNCLAMPED_FLOAT_TO_USHORT(dst2[i][RCOMP], src4[i][RCOMP]);
927 UNCLAMPED_FLOAT_TO_USHORT(dst2[i][GCOMP], src4[i][GCOMP]);
928 UNCLAMPED_FLOAT_TO_USHORT(dst2[i][BCOMP], src4[i][BCOMP]);
929 UNCLAMPED_FLOAT_TO_USHORT(dst2[i][ACOMP], src4[i][ACOMP]);
930 }
931 }
932 if (useTemp)
933 memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
934 }
935 break;
936 default:
937 _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors");
938 }
939
940 free(tempBuffer);
941 }
942
943
944
945
946 /**
947 * Perform basic clipping for glDrawPixels. The image's position and size
948 * and the unpack SkipPixels and SkipRows are adjusted so that the image
949 * region is entirely within the window and scissor bounds.
950 * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1).
951 * If Pixel.ZoomY is -1, *destY will be changed to be the first row which
952 * we'll actually write. Beforehand, *destY-1 is the first drawing row.
953 *
954 * \return GL_TRUE if image is ready for drawing or
955 * GL_FALSE if image was completely clipped away (draw nothing)
956 */
957 GLboolean
958 _mesa_clip_drawpixels(const struct gl_context *ctx,
959 GLint *destX, GLint *destY,
960 GLsizei *width, GLsizei *height,
961 struct gl_pixelstore_attrib *unpack)
962 {
963 const struct gl_framebuffer *buffer = ctx->DrawBuffer;
964
965 if (unpack->RowLength == 0) {
966 unpack->RowLength = *width;
967 }
968
969 ASSERT(ctx->Pixel.ZoomX == 1.0F);
970 ASSERT(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F);
971
972 /* left clipping */
973 if (*destX < buffer->_Xmin) {
974 unpack->SkipPixels += (buffer->_Xmin - *destX);
975 *width -= (buffer->_Xmin - *destX);
976 *destX = buffer->_Xmin;
977 }
978 /* right clipping */
979 if (*destX + *width > buffer->_Xmax)
980 *width -= (*destX + *width - buffer->_Xmax);
981
982 if (*width <= 0)
983 return GL_FALSE;
984
985 if (ctx->Pixel.ZoomY == 1.0F) {
986 /* bottom clipping */
987 if (*destY < buffer->_Ymin) {
988 unpack->SkipRows += (buffer->_Ymin - *destY);
989 *height -= (buffer->_Ymin - *destY);
990 *destY = buffer->_Ymin;
991 }
992 /* top clipping */
993 if (*destY + *height > buffer->_Ymax)
994 *height -= (*destY + *height - buffer->_Ymax);
995 }
996 else { /* upside down */
997 /* top clipping */
998 if (*destY > buffer->_Ymax) {
999 unpack->SkipRows += (*destY - buffer->_Ymax);
1000 *height -= (*destY - buffer->_Ymax);
1001 *destY = buffer->_Ymax;
1002 }
1003 /* bottom clipping */
1004 if (*destY - *height < buffer->_Ymin)
1005 *height -= (buffer->_Ymin - (*destY - *height));
1006 /* adjust destY so it's the first row to write to */
1007 (*destY)--;
1008 }
1009
1010 if (*height <= 0)
1011 return GL_FALSE;
1012
1013 return GL_TRUE;
1014 }
1015
1016
1017 /**
1018 * Perform clipping for glReadPixels. The image's window position
1019 * and size, and the pack skipPixels, skipRows and rowLength are adjusted
1020 * so that the image region is entirely within the window bounds.
1021 * Note: this is different from _mesa_clip_drawpixels() in that the
1022 * scissor box is ignored, and we use the bounds of the current readbuffer
1023 * surface.
1024 *
1025 * \return GL_TRUE if region to read is in bounds
1026 * GL_FALSE if region is completely out of bounds (nothing to read)
1027 */
1028 GLboolean
1029 _mesa_clip_readpixels(const struct gl_context *ctx,
1030 GLint *srcX, GLint *srcY,
1031 GLsizei *width, GLsizei *height,
1032 struct gl_pixelstore_attrib *pack)
1033 {
1034 const struct gl_framebuffer *buffer = ctx->ReadBuffer;
1035
1036 if (pack->RowLength == 0) {
1037 pack->RowLength = *width;
1038 }
1039
1040 /* left clipping */
1041 if (*srcX < 0) {
1042 pack->SkipPixels += (0 - *srcX);
1043 *width -= (0 - *srcX);
1044 *srcX = 0;
1045 }
1046 /* right clipping */
1047 if (*srcX + *width > (GLsizei) buffer->Width)
1048 *width -= (*srcX + *width - buffer->Width);
1049
1050 if (*width <= 0)
1051 return GL_FALSE;
1052
1053 /* bottom clipping */
1054 if (*srcY < 0) {
1055 pack->SkipRows += (0 - *srcY);
1056 *height -= (0 - *srcY);
1057 *srcY = 0;
1058 }
1059 /* top clipping */
1060 if (*srcY + *height > (GLsizei) buffer->Height)
1061 *height -= (*srcY + *height - buffer->Height);
1062
1063 if (*height <= 0)
1064 return GL_FALSE;
1065
1066 return GL_TRUE;
1067 }
1068
1069
1070 /**
1071 * Do clipping for a glCopyTexSubImage call.
1072 * The framebuffer source region might extend outside the framebuffer
1073 * bounds. Clip the source region against the framebuffer bounds and
1074 * adjust the texture/dest position and size accordingly.
1075 *
1076 * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise.
1077 */
1078 GLboolean
1079 _mesa_clip_copytexsubimage(const struct gl_context *ctx,
1080 GLint *destX, GLint *destY,
1081 GLint *srcX, GLint *srcY,
1082 GLsizei *width, GLsizei *height)
1083 {
1084 const struct gl_framebuffer *fb = ctx->ReadBuffer;
1085 const GLint srcX0 = *srcX, srcY0 = *srcY;
1086
1087 if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height,
1088 srcX, srcY, width, height)) {
1089 *destX = *destX + *srcX - srcX0;
1090 *destY = *destY + *srcY - srcY0;
1091
1092 return GL_TRUE;
1093 }
1094 else {
1095 return GL_FALSE;
1096 }
1097 }
1098
1099
1100
1101 /**
1102 * Clip the rectangle defined by (x, y, width, height) against the bounds
1103 * specified by [xmin, xmax) and [ymin, ymax).
1104 * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise.
1105 */
1106 GLboolean
1107 _mesa_clip_to_region(GLint xmin, GLint ymin,
1108 GLint xmax, GLint ymax,
1109 GLint *x, GLint *y,
1110 GLsizei *width, GLsizei *height )
1111 {
1112 /* left clipping */
1113 if (*x < xmin) {
1114 *width -= (xmin - *x);
1115 *x = xmin;
1116 }
1117
1118 /* right clipping */
1119 if (*x + *width > xmax)
1120 *width -= (*x + *width - xmax);
1121
1122 if (*width <= 0)
1123 return GL_FALSE;
1124
1125 /* bottom (or top) clipping */
1126 if (*y < ymin) {
1127 *height -= (ymin - *y);
1128 *y = ymin;
1129 }
1130
1131 /* top (or bottom) clipping */
1132 if (*y + *height > ymax)
1133 *height -= (*y + *height - ymax);
1134
1135 if (*height <= 0)
1136 return GL_FALSE;
1137
1138 return GL_TRUE;
1139 }
1140
1141
1142 /**
1143 * Clip dst coords against Xmax (or Ymax).
1144 */
1145 static inline void
1146 clip_right_or_top(GLint *srcX0, GLint *srcX1,
1147 GLint *dstX0, GLint *dstX1,
1148 GLint maxValue)
1149 {
1150 GLfloat t, bias;
1151
1152 if (*dstX1 > maxValue) {
1153 /* X1 outside right edge */
1154 ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */
1155 t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
1156 /* chop off [t, 1] part */
1157 ASSERT(t >= 0.0 && t <= 1.0);
1158 *dstX1 = maxValue;
1159 bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
1160 *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
1161 }
1162 else if (*dstX0 > maxValue) {
1163 /* X0 outside right edge */
1164 ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */
1165 t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
1166 /* chop off [t, 1] part */
1167 ASSERT(t >= 0.0 && t <= 1.0);
1168 *dstX0 = maxValue;
1169 bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F;
1170 *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
1171 }
1172 }
1173
1174
1175 /**
1176 * Clip dst coords against Xmin (or Ymin).
1177 */
1178 static inline void
1179 clip_left_or_bottom(GLint *srcX0, GLint *srcX1,
1180 GLint *dstX0, GLint *dstX1,
1181 GLint minValue)
1182 {
1183 GLfloat t, bias;
1184
1185 if (*dstX0 < minValue) {
1186 /* X0 outside left edge */
1187 ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */
1188 t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
1189 /* chop off [0, t] part */
1190 ASSERT(t >= 0.0 && t <= 1.0);
1191 *dstX0 = minValue;
1192 bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; /* flipped??? */
1193 *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
1194 }
1195 else if (*dstX1 < minValue) {
1196 /* X1 outside left edge */
1197 ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */
1198 t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
1199 /* chop off [0, t] part */
1200 ASSERT(t >= 0.0 && t <= 1.0);
1201 *dstX1 = minValue;
1202 bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
1203 *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
1204 }
1205 }
1206
1207
1208 /**
1209 * Do clipping of blit src/dest rectangles.
1210 * The dest rect is clipped against both the buffer bounds and scissor bounds.
1211 * The src rect is just clipped against the buffer bounds.
1212 *
1213 * When either the src or dest rect is clipped, the other is also clipped
1214 * proportionately!
1215 *
1216 * Note that X0 need not be less than X1 (same for Y) for either the source
1217 * and dest rects. That makes the clipping a little trickier.
1218 *
1219 * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped
1220 */
1221 GLboolean
1222 _mesa_clip_blit(struct gl_context *ctx,
1223 GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
1224 GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1)
1225 {
1226 const GLint srcXmin = 0;
1227 const GLint srcXmax = ctx->ReadBuffer->Width;
1228 const GLint srcYmin = 0;
1229 const GLint srcYmax = ctx->ReadBuffer->Height;
1230
1231 /* these include scissor bounds */
1232 const GLint dstXmin = ctx->DrawBuffer->_Xmin;
1233 const GLint dstXmax = ctx->DrawBuffer->_Xmax;
1234 const GLint dstYmin = ctx->DrawBuffer->_Ymin;
1235 const GLint dstYmax = ctx->DrawBuffer->_Ymax;
1236
1237 /*
1238 printf("PreClipX: src: %d .. %d dst: %d .. %d\n",
1239 *srcX0, *srcX1, *dstX0, *dstX1);
1240 printf("PreClipY: src: %d .. %d dst: %d .. %d\n",
1241 *srcY0, *srcY1, *dstY0, *dstY1);
1242 */
1243
1244 /* trivial rejection tests */
1245 if (*dstX0 == *dstX1)
1246 return GL_FALSE; /* no width */
1247 if (*dstX0 <= dstXmin && *dstX1 <= dstXmin)
1248 return GL_FALSE; /* totally out (left) of bounds */
1249 if (*dstX0 >= dstXmax && *dstX1 >= dstXmax)
1250 return GL_FALSE; /* totally out (right) of bounds */
1251
1252 if (*dstY0 == *dstY1)
1253 return GL_FALSE;
1254 if (*dstY0 <= dstYmin && *dstY1 <= dstYmin)
1255 return GL_FALSE;
1256 if (*dstY0 >= dstYmax && *dstY1 >= dstYmax)
1257 return GL_FALSE;
1258
1259 if (*srcX0 == *srcX1)
1260 return GL_FALSE;
1261 if (*srcX0 <= srcXmin && *srcX1 <= srcXmin)
1262 return GL_FALSE;
1263 if (*srcX0 >= srcXmax && *srcX1 >= srcXmax)
1264 return GL_FALSE;
1265
1266 if (*srcY0 == *srcY1)
1267 return GL_FALSE;
1268 if (*srcY0 <= srcYmin && *srcY1 <= srcYmin)
1269 return GL_FALSE;
1270 if (*srcY0 >= srcYmax && *srcY1 >= srcYmax)
1271 return GL_FALSE;
1272
1273 /*
1274 * dest clip
1275 */
1276 clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax);
1277 clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax);
1278 clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin);
1279 clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin);
1280
1281 /*
1282 * src clip (just swap src/dst values from above)
1283 */
1284 clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax);
1285 clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax);
1286 clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin);
1287 clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin);
1288
1289 /*
1290 printf("PostClipX: src: %d .. %d dst: %d .. %d\n",
1291 *srcX0, *srcX1, *dstX0, *dstX1);
1292 printf("PostClipY: src: %d .. %d dst: %d .. %d\n",
1293 *srcY0, *srcY1, *dstY0, *dstY1);
1294 */
1295
1296 ASSERT(*dstX0 >= dstXmin);
1297 ASSERT(*dstX0 <= dstXmax);
1298 ASSERT(*dstX1 >= dstXmin);
1299 ASSERT(*dstX1 <= dstXmax);
1300
1301 ASSERT(*dstY0 >= dstYmin);
1302 ASSERT(*dstY0 <= dstYmax);
1303 ASSERT(*dstY1 >= dstYmin);
1304 ASSERT(*dstY1 <= dstYmax);
1305
1306 ASSERT(*srcX0 >= srcXmin);
1307 ASSERT(*srcX0 <= srcXmax);
1308 ASSERT(*srcX1 >= srcXmin);
1309 ASSERT(*srcX1 <= srcXmax);
1310
1311 ASSERT(*srcY0 >= srcYmin);
1312 ASSERT(*srcY0 <= srcYmax);
1313 ASSERT(*srcY1 >= srcYmin);
1314 ASSERT(*srcY1 <= srcYmax);
1315
1316 return GL_TRUE;
1317 }