2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include "main/glheader.h"
27 #include "main/macros.h"
28 #include "s_context.h"
31 #define ABS(X) ((X) < 0 ? -(X) : (X))
35 * Generate a row resampler function for GL_NEAREST mode.
37 #define RESAMPLE(NAME, PIXELTYPE, SIZE) \
39 NAME(GLint srcWidth, GLint dstWidth, \
40 const GLvoid *srcBuffer, GLvoid *dstBuffer, \
43 const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
44 PIXELTYPE *dst = (PIXELTYPE *) dstBuffer; \
48 for (dstCol = 0; dstCol < dstWidth; dstCol++) { \
49 GLint srcCol = (dstCol * srcWidth) / dstWidth; \
50 ASSERT(srcCol >= 0); \
51 ASSERT(srcCol < srcWidth); \
52 srcCol = srcWidth - 1 - srcCol; /* flip */ \
54 dst[dstCol] = src[srcCol]; \
56 else if (SIZE == 2) { \
57 dst[dstCol*2+0] = src[srcCol*2+0]; \
58 dst[dstCol*2+1] = src[srcCol*2+1]; \
60 else if (SIZE == 4) { \
61 dst[dstCol*4+0] = src[srcCol*4+0]; \
62 dst[dstCol*4+1] = src[srcCol*4+1]; \
63 dst[dstCol*4+2] = src[srcCol*4+2]; \
64 dst[dstCol*4+3] = src[srcCol*4+3]; \
69 for (dstCol = 0; dstCol < dstWidth; dstCol++) { \
70 GLint srcCol = (dstCol * srcWidth) / dstWidth; \
71 ASSERT(srcCol >= 0); \
72 ASSERT(srcCol < srcWidth); \
74 dst[dstCol] = src[srcCol]; \
76 else if (SIZE == 2) { \
77 dst[dstCol*2+0] = src[srcCol*2+0]; \
78 dst[dstCol*2+1] = src[srcCol*2+1]; \
80 else if (SIZE == 4) { \
81 dst[dstCol*4+0] = src[srcCol*4+0]; \
82 dst[dstCol*4+1] = src[srcCol*4+1]; \
83 dst[dstCol*4+2] = src[srcCol*4+2]; \
84 dst[dstCol*4+3] = src[srcCol*4+3]; \
91 * Resamplers for 1, 2, 4, 8 and 16-byte pixels.
93 RESAMPLE(resample_row_1
, GLubyte
, 1)
94 RESAMPLE(resample_row_2
, GLushort
, 1)
95 RESAMPLE(resample_row_4
, GLuint
, 1)
96 RESAMPLE(resample_row_8
, GLuint
, 2)
97 RESAMPLE(resample_row_16
, GLuint
, 4)
101 * Blit color, depth or stencil with GL_NEAREST filtering.
104 blit_nearest(GLcontext
*ctx
,
105 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
106 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
109 struct gl_renderbuffer
*readRb
, *drawRb
;
111 const GLint srcWidth
= ABS(srcX1
- srcX0
);
112 const GLint dstWidth
= ABS(dstX1
- dstX0
);
113 const GLint srcHeight
= ABS(srcY1
- srcY0
);
114 const GLint dstHeight
= ABS(dstY1
- dstY0
);
116 const GLint srcXpos
= MIN2(srcX0
, srcX1
);
117 const GLint srcYpos
= MIN2(srcY0
, srcY1
);
118 const GLint dstXpos
= MIN2(dstX0
, dstX1
);
119 const GLint dstYpos
= MIN2(dstY0
, dstY1
);
121 const GLboolean invertX
= (srcX1
< srcX0
) ^ (dstX1
< dstX0
);
122 const GLboolean invertY
= (srcY1
< srcY0
) ^ (dstY1
< dstY0
);
126 GLint comps
, pixelSize
;
127 GLvoid
*srcBuffer
, *dstBuffer
;
130 typedef void (*resample_func
)(GLint srcWidth
, GLint dstWidth
,
131 const GLvoid
*srcBuffer
, GLvoid
*dstBuffer
,
133 resample_func resampleRow
;
136 case GL_COLOR_BUFFER_BIT
:
137 readRb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
138 drawRb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0];
141 case GL_DEPTH_BUFFER_BIT
:
142 readRb
= ctx
->ReadBuffer
->_DepthBuffer
;
143 drawRb
= ctx
->DrawBuffer
->_DepthBuffer
;
146 case GL_STENCIL_BUFFER_BIT
:
147 readRb
= ctx
->ReadBuffer
->_StencilBuffer
;
148 drawRb
= ctx
->DrawBuffer
->_StencilBuffer
;
152 _mesa_problem(ctx
, "unexpected buffer in blit_nearest()");
156 switch (readRb
->DataType
) {
157 case GL_UNSIGNED_BYTE
:
158 pixelSize
= comps
* sizeof(GLubyte
);
160 case GL_UNSIGNED_SHORT
:
161 pixelSize
= comps
* sizeof(GLushort
);
163 case GL_UNSIGNED_INT
:
164 pixelSize
= comps
* sizeof(GLuint
);
167 pixelSize
= comps
* sizeof(GLfloat
);
170 _mesa_problem(ctx
, "unexpected buffer type (0x%x) in blit_nearest",
175 /* choose row resampler */
178 resampleRow
= resample_row_1
;
181 resampleRow
= resample_row_2
;
184 resampleRow
= resample_row_4
;
187 resampleRow
= resample_row_8
;
190 resampleRow
= resample_row_16
;
193 _mesa_problem(ctx
, "unexpected pixel size (%d) in blit_nearest",
198 /* allocate the src/dst row buffers */
199 srcBuffer
= _mesa_malloc(pixelSize
* srcWidth
);
201 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBlitFrameBufferEXT");
204 dstBuffer
= _mesa_malloc(pixelSize
* dstWidth
);
206 _mesa_free(srcBuffer
);
207 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBlitFrameBufferEXT");
211 for (dstRow
= 0; dstRow
< dstHeight
; dstRow
++) {
212 const GLint dstY
= dstYpos
+ dstRow
;
213 GLint srcRow
= (dstRow
* srcHeight
) / dstHeight
;
217 ASSERT(srcRow
< srcHeight
);
220 srcRow
= srcHeight
- 1 - srcRow
;
223 srcY
= srcYpos
+ srcRow
;
225 /* get pixel row from source and resample to match dest width */
227 readRb
->GetRow(ctx
, readRb
, srcWidth
, srcXpos
, srcY
, srcBuffer
);
228 (*resampleRow
)(srcWidth
, dstWidth
, srcBuffer
, dstBuffer
, invertX
);
232 /* store pixel row in destination */
233 drawRb
->PutRow(ctx
, drawRb
, dstWidth
, dstXpos
, dstY
, dstBuffer
, NULL
);
236 _mesa_free(srcBuffer
);
237 _mesa_free(dstBuffer
);
242 #define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
244 static INLINE GLfloat
245 lerp_2d(GLfloat a
, GLfloat b
,
246 GLfloat v00
, GLfloat v10
, GLfloat v01
, GLfloat v11
)
248 const GLfloat temp0
= LERP(a
, v00
, v10
);
249 const GLfloat temp1
= LERP(a
, v01
, v11
);
250 return LERP(b
, temp0
, temp1
);
255 * Bilinear interpolation of two source rows.
259 resample_linear_row_ub(GLint srcWidth
, GLint dstWidth
,
260 const GLvoid
*srcBuffer0
, const GLvoid
*srcBuffer1
,
261 GLvoid
*dstBuffer
, GLboolean flip
, GLfloat rowWeight
)
263 const GLubyte (*srcColor0
)[4] = (const GLubyte (*)[4]) srcBuffer0
;
264 const GLubyte (*srcColor1
)[4] = (const GLubyte (*)[4]) srcBuffer1
;
265 GLubyte (*dstColor
)[4] = (GLubyte (*)[4]) dstBuffer
;
266 const GLfloat dstWidthF
= (GLfloat
) dstWidth
;
269 for (dstCol
= 0; dstCol
< dstWidth
; dstCol
++) {
270 const GLfloat srcCol
= (dstCol
* srcWidth
) / dstWidthF
;
271 GLint srcCol0
= IFLOOR(srcCol
);
272 GLint srcCol1
= srcCol0
+ 1;
273 GLfloat colWeight
= srcCol
- srcCol0
; /* fractional part of srcCol */
274 GLfloat red
, green
, blue
, alpha
;
276 ASSERT(srcCol0
>= 0);
277 ASSERT(srcCol0
< srcWidth
);
278 ASSERT(srcCol1
<= srcWidth
);
280 if (srcCol1
== srcWidth
) {
281 /* last column fudge */
287 srcCol0
= srcWidth
- 1 - srcCol0
;
288 srcCol1
= srcWidth
- 1 - srcCol1
;
291 red
= lerp_2d(colWeight
, rowWeight
,
292 srcColor0
[srcCol0
][RCOMP
], srcColor0
[srcCol1
][RCOMP
],
293 srcColor1
[srcCol0
][RCOMP
], srcColor1
[srcCol1
][RCOMP
]);
294 green
= lerp_2d(colWeight
, rowWeight
,
295 srcColor0
[srcCol0
][GCOMP
], srcColor0
[srcCol1
][GCOMP
],
296 srcColor1
[srcCol0
][GCOMP
], srcColor1
[srcCol1
][GCOMP
]);
297 blue
= lerp_2d(colWeight
, rowWeight
,
298 srcColor0
[srcCol0
][BCOMP
], srcColor0
[srcCol1
][BCOMP
],
299 srcColor1
[srcCol0
][BCOMP
], srcColor1
[srcCol1
][BCOMP
]);
300 alpha
= lerp_2d(colWeight
, rowWeight
,
301 srcColor0
[srcCol0
][ACOMP
], srcColor0
[srcCol1
][ACOMP
],
302 srcColor1
[srcCol0
][ACOMP
], srcColor1
[srcCol1
][ACOMP
]);
304 dstColor
[dstCol
][RCOMP
] = IFLOOR(red
);
305 dstColor
[dstCol
][GCOMP
] = IFLOOR(green
);
306 dstColor
[dstCol
][BCOMP
] = IFLOOR(blue
);
307 dstColor
[dstCol
][ACOMP
] = IFLOOR(alpha
);
314 * Bilinear filtered blit (color only).
317 blit_linear(GLcontext
*ctx
,
318 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
319 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
)
321 struct gl_renderbuffer
*readRb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
322 struct gl_renderbuffer
*drawRb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0];
324 const GLint srcWidth
= ABS(srcX1
- srcX0
);
325 const GLint dstWidth
= ABS(dstX1
- dstX0
);
326 const GLint srcHeight
= ABS(srcY1
- srcY0
);
327 const GLint dstHeight
= ABS(dstY1
- dstY0
);
328 const GLfloat dstHeightF
= (GLfloat
) dstHeight
;
330 const GLint srcXpos
= MIN2(srcX0
, srcX1
);
331 const GLint srcYpos
= MIN2(srcY0
, srcY1
);
332 const GLint dstXpos
= MIN2(dstX0
, dstX1
);
333 const GLint dstYpos
= MIN2(dstY0
, dstY1
);
335 const GLboolean invertX
= (srcX1
< srcX0
) ^ (dstX1
< dstX0
);
336 const GLboolean invertY
= (srcY1
< srcY0
) ^ (dstY1
< dstY0
);
341 GLvoid
*srcBuffer0
, *srcBuffer1
;
342 GLint srcBufferY0
= -1, srcBufferY1
= -1;
345 switch (readRb
->DataType
) {
346 case GL_UNSIGNED_BYTE
:
347 pixelSize
= 4 * sizeof(GLubyte
);
349 case GL_UNSIGNED_SHORT
:
350 pixelSize
= 4 * sizeof(GLushort
);
352 case GL_UNSIGNED_INT
:
353 pixelSize
= 4 * sizeof(GLuint
);
356 pixelSize
= 4 * sizeof(GLfloat
);
359 _mesa_problem(ctx
, "unexpected buffer type (0x%x) in blit_nearest",
364 /* Allocate the src/dst row buffers.
365 * Keep two adjacent src rows around for bilinear sampling.
367 srcBuffer0
= _mesa_malloc(pixelSize
* srcWidth
);
369 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBlitFrameBufferEXT");
372 srcBuffer1
= _mesa_malloc(pixelSize
* srcWidth
);
374 _mesa_free(srcBuffer0
);
375 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBlitFrameBufferEXT");
378 dstBuffer
= _mesa_malloc(pixelSize
* dstWidth
);
380 _mesa_free(srcBuffer0
);
381 _mesa_free(srcBuffer1
);
382 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBlitFrameBufferEXT");
386 for (dstRow
= 0; dstRow
< dstHeight
; dstRow
++) {
387 const GLint dstY
= dstYpos
+ dstRow
;
388 const GLfloat srcRow
= (dstRow
* srcHeight
) / dstHeightF
;
389 GLint srcRow0
= IFLOOR(srcRow
);
390 GLint srcRow1
= srcRow0
+ 1;
391 GLfloat rowWeight
= srcRow
- srcRow0
; /* fractional part of srcRow */
394 ASSERT(srcRow
< srcHeight
);
396 if (srcRow1
== srcHeight
) {
403 srcRow0
= srcHeight
- 1 - srcRow0
;
404 srcRow1
= srcHeight
- 1 - srcRow1
;
407 srcY0
= srcYpos
+ srcRow0
;
408 srcY1
= srcYpos
+ srcRow1
;
410 /* get the two source rows */
411 if (srcY0
== srcBufferY0
&& srcY1
== srcBufferY1
) {
412 /* use same source row buffers again */
414 else if (srcY0
== srcBufferY1
) {
415 /* move buffer1 into buffer0 by swapping pointers */
416 GLvoid
*tmp
= srcBuffer0
;
417 srcBuffer0
= srcBuffer1
;
420 readRb
->GetRow(ctx
, readRb
, srcWidth
, srcXpos
, srcY1
, srcBuffer1
);
425 /* get both new rows */
426 readRb
->GetRow(ctx
, readRb
, srcWidth
, srcXpos
, srcY0
, srcBuffer0
);
427 readRb
->GetRow(ctx
, readRb
, srcWidth
, srcXpos
, srcY1
, srcBuffer1
);
432 if (readRb
->DataType
== GL_UNSIGNED_BYTE
) {
433 resample_linear_row_ub(srcWidth
, dstWidth
, srcBuffer0
, srcBuffer1
,
434 dstBuffer
, invertX
, rowWeight
);
437 _mesa_problem(ctx
, "Unsupported color channel type in sw blit");
441 /* store pixel row in destination */
442 drawRb
->PutRow(ctx
, drawRb
, dstWidth
, dstXpos
, dstY
, dstBuffer
, NULL
);
445 _mesa_free(srcBuffer0
);
446 _mesa_free(srcBuffer1
);
447 _mesa_free(dstBuffer
);
452 * Simple case: Blit color, depth or stencil with no scaling or flipping.
453 * XXX we could easily support vertical flipping here.
456 simple_blit(GLcontext
*ctx
,
457 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
458 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
461 struct gl_renderbuffer
*readRb
, *drawRb
;
462 const GLint width
= srcX1
- srcX0
;
463 const GLint height
= srcY1
- srcY0
;
464 GLint row
, srcY
, dstY
, yStep
;
465 GLint comps
, bytesPerRow
;
468 /* only one buffer */
469 ASSERT(_mesa_bitcount(buffer
) == 1);
470 /* no flipping checks */
471 ASSERT(srcX0
< srcX1
);
472 ASSERT(srcY0
< srcY1
);
473 ASSERT(dstX0
< dstX1
);
474 ASSERT(dstY0
< dstY1
);
476 ASSERT(srcX1
- srcX0
== dstX1
- dstX0
);
477 ASSERT(srcY1
- srcY0
== dstY1
- dstY0
);
479 /* determine if copy should be bottom-to-top or top-to-bottom */
481 /* src above dst: copy bottom-to-top */
487 /* src below dst: copy top-to-bottom */
494 case GL_COLOR_BUFFER_BIT
:
495 readRb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
496 drawRb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0];
499 case GL_DEPTH_BUFFER_BIT
:
500 readRb
= ctx
->ReadBuffer
->_DepthBuffer
;
501 drawRb
= ctx
->DrawBuffer
->_DepthBuffer
;
504 case GL_STENCIL_BUFFER_BIT
:
505 readRb
= ctx
->ReadBuffer
->_StencilBuffer
;
506 drawRb
= ctx
->DrawBuffer
->_StencilBuffer
;
510 _mesa_problem(ctx
, "unexpected buffer in simple_blit()");
514 ASSERT(readRb
->DataType
== drawRb
->DataType
);
516 /* compute bytes per row */
517 switch (readRb
->DataType
) {
518 case GL_UNSIGNED_BYTE
:
519 bytesPerRow
= comps
* width
* sizeof(GLubyte
);
521 case GL_UNSIGNED_SHORT
:
522 bytesPerRow
= comps
* width
* sizeof(GLushort
);
524 case GL_UNSIGNED_INT
:
525 bytesPerRow
= comps
* width
* sizeof(GLuint
);
528 bytesPerRow
= comps
* width
* sizeof(GLfloat
);
531 _mesa_problem(ctx
, "unexpected buffer type in simple_blit");
535 /* allocate the row buffer */
536 rowBuffer
= _mesa_malloc(bytesPerRow
);
538 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBlitFrameBufferEXT");
542 for (row
= 0; row
< height
; row
++) {
543 readRb
->GetRow(ctx
, readRb
, width
, srcX0
, srcY
, rowBuffer
);
544 drawRb
->PutRow(ctx
, drawRb
, width
, dstX0
, dstY
, rowBuffer
, NULL
);
549 _mesa_free(rowBuffer
);
554 * Clip dst coords against Xmax (or Ymax).
557 clip_right_or_top(GLint
*srcX0
, GLint
*srcX1
,
558 GLint
*dstX0
, GLint
*dstX1
,
563 if (*dstX1
> maxValue
) {
564 /* X1 outside right edge */
565 ASSERT(*dstX0
< maxValue
); /* X0 should be inside right edge */
566 t
= (GLfloat
) (maxValue
- *dstX0
) / (GLfloat
) (*dstX1
- *dstX0
);
567 /* chop off [t, 1] part */
568 ASSERT(t
>= 0.0 && t
<= 1.0);
570 bias
= (*srcX0
< *srcX1
) ? 0.5 : -0.5;
571 *srcX1
= *srcX0
+ (GLint
) (t
* (*srcX1
- *srcX0
) + bias
);
573 else if (*dstX0
> maxValue
) {
574 /* X0 outside right edge */
575 ASSERT(*dstX1
< maxValue
); /* X1 should be inside right edge */
576 t
= (GLfloat
) (maxValue
- *dstX1
) / (GLfloat
) (*dstX0
- *dstX1
);
577 /* chop off [t, 1] part */
578 ASSERT(t
>= 0.0 && t
<= 1.0);
580 bias
= (*srcX0
< *srcX1
) ? -0.5 : 0.5;
581 *srcX0
= *srcX1
+ (GLint
) (t
* (*srcX0
- *srcX1
) + bias
);
587 * Clip dst coords against Xmin (or Ymin).
590 clip_left_or_bottom(GLint
*srcX0
, GLint
*srcX1
,
591 GLint
*dstX0
, GLint
*dstX1
,
596 if (*dstX0
< minValue
) {
597 /* X0 outside left edge */
598 ASSERT(*dstX1
> minValue
); /* X1 should be inside left edge */
599 t
= (GLfloat
) (minValue
- *dstX0
) / (GLfloat
) (*dstX1
- *dstX0
);
600 /* chop off [0, t] part */
601 ASSERT(t
>= 0.0 && t
<= 1.0);
603 bias
= (*srcX0
< *srcX1
) ? 0.5 : -0.5; /* flipped??? */
604 *srcX0
= *srcX0
+ (GLint
) (t
* (*srcX1
- *srcX0
) + bias
);
606 else if (*dstX1
< minValue
) {
607 /* X1 outside left edge */
608 ASSERT(*dstX0
> minValue
); /* X0 should be inside left edge */
609 t
= (GLfloat
) (minValue
- *dstX1
) / (GLfloat
) (*dstX0
- *dstX1
);
610 /* chop off [0, t] part */
611 ASSERT(t
>= 0.0 && t
<= 1.0);
613 bias
= (*srcX0
< *srcX1
) ? 0.5 : -0.5;
614 *srcX1
= *srcX1
+ (GLint
) (t
* (*srcX0
- *srcX1
) + bias
);
620 * Do clipping of blit src/dest rectangles.
621 * The dest rect is clipped against both the buffer bounds and scissor bounds.
622 * The src rect is just clipped against the buffer bounds.
624 * When either the src or dest rect is clipped, the other is also clipped
627 * Note that X0 need not be less than X1 (same for Y) for either the source
628 * and dest rects. That makes the clipping a little trickier.
630 * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped
633 clip_blit(GLcontext
*ctx
,
634 GLint
*srcX0
, GLint
*srcY0
, GLint
*srcX1
, GLint
*srcY1
,
635 GLint
*dstX0
, GLint
*dstY0
, GLint
*dstX1
, GLint
*dstY1
)
637 const GLint srcXmin
= 0;
638 const GLint srcXmax
= ctx
->ReadBuffer
->Width
;
639 const GLint srcYmin
= 0;
640 const GLint srcYmax
= ctx
->ReadBuffer
->Height
;
642 /* these include scissor bounds */
643 const GLint dstXmin
= ctx
->DrawBuffer
->_Xmin
;
644 const GLint dstXmax
= ctx
->DrawBuffer
->_Xmax
;
645 const GLint dstYmin
= ctx
->DrawBuffer
->_Ymin
;
646 const GLint dstYmax
= ctx
->DrawBuffer
->_Ymax
;
649 printf("PreClipX: src: %d .. %d dst: %d .. %d\n",
650 *srcX0, *srcX1, *dstX0, *dstX1);
651 printf("PreClipY: src: %d .. %d dst: %d .. %d\n",
652 *srcY0, *srcY1, *dstY0, *dstY1);
655 /* trivial rejection tests */
656 if (*dstX0
== *dstX1
)
657 return GL_FALSE
; /* no width */
658 if (*dstX0
<= dstXmin
&& *dstX1
<= dstXmin
)
659 return GL_FALSE
; /* totally out (left) of bounds */
660 if (*dstX0
>= dstXmax
&& *dstX1
>= dstXmax
)
661 return GL_FALSE
; /* totally out (right) of bounds */
663 if (*dstY0
== *dstY1
)
665 if (*dstY0
<= dstYmin
&& *dstY1
<= dstYmin
)
667 if (*dstY0
>= dstYmax
&& *dstY1
>= dstYmax
)
670 if (*srcX0
== *srcX1
)
672 if (*srcX0
<= srcXmin
&& *srcX1
<= srcXmin
)
674 if (*srcX0
>= srcXmax
&& *srcX1
>= srcXmax
)
677 if (*srcY0
== *srcY1
)
679 if (*srcY0
<= srcYmin
&& *srcY1
<= srcYmin
)
681 if (*srcY0
>= srcYmax
&& *srcY1
>= srcYmax
)
687 clip_right_or_top(srcX0
, srcX1
, dstX0
, dstX1
, dstXmax
);
688 clip_right_or_top(srcY0
, srcY1
, dstY0
, dstY1
, dstYmax
);
689 clip_left_or_bottom(srcX0
, srcX1
, dstX0
, dstX1
, dstXmin
);
690 clip_left_or_bottom(srcY0
, srcY1
, dstY0
, dstY1
, dstYmin
);
693 * src clip (just swap src/dst values from above)
695 clip_right_or_top(dstX0
, dstX1
, srcX0
, srcX1
, srcXmax
);
696 clip_right_or_top(dstY0
, dstY1
, srcY0
, srcY1
, srcYmax
);
697 clip_left_or_bottom(dstX0
, dstX1
, srcX0
, srcX1
, srcXmin
);
698 clip_left_or_bottom(dstY0
, dstY1
, srcY0
, srcY1
, srcYmin
);
701 printf("PostClipX: src: %d .. %d dst: %d .. %d\n",
702 *srcX0, *srcX1, *dstX0, *dstX1);
703 printf("PostClipY: src: %d .. %d dst: %d .. %d\n",
704 *srcY0, *srcY1, *dstY0, *dstY1);
707 ASSERT(*dstX0
>= dstXmin
);
708 ASSERT(*dstX0
<= dstXmax
);
709 ASSERT(*dstX1
>= dstXmin
);
710 ASSERT(*dstX1
<= dstXmax
);
712 ASSERT(*dstY0
>= dstYmin
);
713 ASSERT(*dstY0
<= dstYmax
);
714 ASSERT(*dstY1
>= dstYmin
);
715 ASSERT(*dstY1
<= dstYmax
);
717 ASSERT(*srcX0
>= srcXmin
);
718 ASSERT(*srcX0
<= srcXmax
);
719 ASSERT(*srcX1
>= srcXmin
);
720 ASSERT(*srcX1
<= srcXmax
);
722 ASSERT(*srcY0
>= srcYmin
);
723 ASSERT(*srcY0
<= srcYmax
);
724 ASSERT(*srcY1
>= srcYmin
);
725 ASSERT(*srcY1
<= srcYmax
);
732 * Software fallback for glBlitFramebufferEXT().
735 _swrast_BlitFramebuffer(GLcontext
*ctx
,
736 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
737 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
738 GLbitfield mask
, GLenum filter
)
740 static const GLint buffers
[3] = {
743 GL_STENCIL_BUFFER_BIT
747 if (!ctx
->DrawBuffer
->_NumColorDrawBuffers
)
750 if (!clip_blit(ctx
, &srcX0
, &srcY0
, &srcX1
, &srcY1
,
751 &dstX0
, &dstY0
, &dstX1
, &dstY1
)) {
755 swrast_render_start(ctx
);
757 if (srcX1
- srcX0
== dstX1
- dstX0
&&
758 srcY1
- srcY0
== dstY1
- dstY0
&&
763 /* no stretching or flipping.
764 * filter doesn't matter.
766 for (i
= 0; i
< 3; i
++) {
767 if (mask
& buffers
[i
]) {
768 simple_blit(ctx
, srcX0
, srcY0
, srcX1
, srcY1
,
769 dstX0
, dstY0
, dstX1
, dstY1
, buffers
[i
]);
774 if (filter
== GL_NEAREST
) {
775 for (i
= 0; i
< 3; i
++) {
776 if (mask
& buffers
[i
]) {
777 blit_nearest(ctx
, srcX0
, srcY0
, srcX1
, srcY1
,
778 dstX0
, dstY0
, dstX1
, dstY1
, buffers
[i
]);
783 ASSERT(filter
== GL_LINEAR
);
784 if (mask
& GL_COLOR_BUFFER_BIT
) { /* depth/stencil not allowed */
785 blit_linear(ctx
, srcX0
, srcY0
, srcX1
, srcY1
,
786 dstX0
, dstY0
, dstX1
, dstY1
);
791 swrast_render_finish(ctx
);