2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "main/glheader.h"
27 #include "main/condrender.h"
28 #include "main/image.h"
29 #include "main/macros.h"
30 #include "main/format_unpack.h"
31 #include "main/format_pack.h"
32 #include "main/condrender.h"
33 #include "s_context.h"
36 #define ABS(X) ((X) < 0 ? -(X) : (X))
40 * Generate a row resampler function for GL_NEAREST mode.
42 #define RESAMPLE(NAME, PIXELTYPE, SIZE) \
44 NAME(GLint srcWidth, GLint dstWidth, \
45 const GLvoid *srcBuffer, GLvoid *dstBuffer, \
48 const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
49 PIXELTYPE *dst = (PIXELTYPE *) dstBuffer; \
53 for (dstCol = 0; dstCol < dstWidth; dstCol++) { \
54 GLint srcCol = (dstCol * srcWidth) / dstWidth; \
55 assert(srcCol >= 0); \
56 assert(srcCol < srcWidth); \
57 srcCol = srcWidth - 1 - srcCol; /* flip */ \
59 dst[dstCol] = src[srcCol]; \
61 else if (SIZE == 2) { \
62 dst[dstCol*2+0] = src[srcCol*2+0]; \
63 dst[dstCol*2+1] = src[srcCol*2+1]; \
65 else if (SIZE == 4) { \
66 dst[dstCol*4+0] = src[srcCol*4+0]; \
67 dst[dstCol*4+1] = src[srcCol*4+1]; \
68 dst[dstCol*4+2] = src[srcCol*4+2]; \
69 dst[dstCol*4+3] = src[srcCol*4+3]; \
74 for (dstCol = 0; dstCol < dstWidth; dstCol++) { \
75 GLint srcCol = (dstCol * srcWidth) / dstWidth; \
76 assert(srcCol >= 0); \
77 assert(srcCol < srcWidth); \
79 dst[dstCol] = src[srcCol]; \
81 else if (SIZE == 2) { \
82 dst[dstCol*2+0] = src[srcCol*2+0]; \
83 dst[dstCol*2+1] = src[srcCol*2+1]; \
85 else if (SIZE == 4) { \
86 dst[dstCol*4+0] = src[srcCol*4+0]; \
87 dst[dstCol*4+1] = src[srcCol*4+1]; \
88 dst[dstCol*4+2] = src[srcCol*4+2]; \
89 dst[dstCol*4+3] = src[srcCol*4+3]; \
96 * Resamplers for 1, 2, 4, 8 and 16-byte pixels.
98 RESAMPLE(resample_row_1
, GLubyte
, 1)
99 RESAMPLE(resample_row_2
, GLushort
, 1)
100 RESAMPLE(resample_row_4
, GLuint
, 1)
101 RESAMPLE(resample_row_8
, GLuint
, 2)
102 RESAMPLE(resample_row_16
, GLuint
, 4)
106 * Blit color, depth or stencil with GL_NEAREST filtering.
109 blit_nearest(struct gl_context
*ctx
,
110 struct gl_framebuffer
*readFb
,
111 struct gl_framebuffer
*drawFb
,
112 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
113 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
116 struct gl_renderbuffer
*readRb
, *drawRb
= NULL
;
117 struct gl_renderbuffer_attachment
*readAtt
= NULL
, *drawAtt
= NULL
;
118 GLuint numDrawBuffers
= 0;
121 const GLint srcWidth
= ABS(srcX1
- srcX0
);
122 const GLint dstWidth
= ABS(dstX1
- dstX0
);
123 const GLint srcHeight
= ABS(srcY1
- srcY0
);
124 const GLint dstHeight
= ABS(dstY1
- dstY0
);
126 const GLint srcXpos
= MIN2(srcX0
, srcX1
);
127 const GLint srcYpos
= MIN2(srcY0
, srcY1
);
128 const GLint dstXpos
= MIN2(dstX0
, dstX1
);
129 const GLint dstYpos
= MIN2(dstY0
, dstY1
);
131 const GLboolean invertX
= (srcX1
< srcX0
) ^ (dstX1
< dstX0
);
132 const GLboolean invertY
= (srcY1
< srcY0
) ^ (dstY1
< dstY0
);
140 GLubyte
*srcMap
, *dstMap
;
141 GLint srcRowStride
, dstRowStride
;
145 GLvoid
*srcBuffer
, *dstBuffer
;
148 typedef void (*resample_func
)(GLint srcWidth
, GLint dstWidth
,
149 const GLvoid
*srcBuffer
, GLvoid
*dstBuffer
,
151 resample_func resampleRow
;
154 case GL_COLOR_BUFFER_BIT
:
155 readAtt
= &readFb
->Attachment
[readFb
->_ColorReadBufferIndex
];
156 readRb
= readFb
->_ColorReadBuffer
;
157 numDrawBuffers
= drawFb
->_NumColorDrawBuffers
;
159 case GL_DEPTH_BUFFER_BIT
:
160 readAtt
= &readFb
->Attachment
[BUFFER_DEPTH
];
161 drawAtt
= &drawFb
->Attachment
[BUFFER_DEPTH
];
162 readRb
= readAtt
->Renderbuffer
;
163 drawRb
= drawAtt
->Renderbuffer
;
166 /* Note that for depth/stencil, the formats of src/dst must match. By
167 * using the core helpers for pack/unpack, we avoid needing to handle
168 * masking for things like DEPTH copies of Z24S8.
170 if (readRb
->Format
== MESA_FORMAT_Z_FLOAT32
||
171 readRb
->Format
== MESA_FORMAT_Z32_FLOAT_S8X24_UINT
) {
172 mode
= UNPACK_Z_FLOAT
;
178 case GL_STENCIL_BUFFER_BIT
:
179 readAtt
= &readFb
->Attachment
[BUFFER_STENCIL
];
180 drawAtt
= &drawFb
->Attachment
[BUFFER_STENCIL
];
181 readRb
= readAtt
->Renderbuffer
;
182 drawRb
= drawAtt
->Renderbuffer
;
188 _mesa_problem(ctx
, "unexpected buffer in blit_nearest()");
192 /* allocate the src/dst row buffers */
193 srcBuffer
= malloc(MAX_PIXEL_BYTES
* srcWidth
);
194 dstBuffer
= malloc(MAX_PIXEL_BYTES
* dstWidth
);
195 if (!srcBuffer
|| !dstBuffer
)
198 /* Blit to all the draw buffers */
199 for (i
= 0; i
< numDrawBuffers
; i
++) {
200 if (buffer
== GL_COLOR_BUFFER_BIT
) {
201 gl_buffer_index idx
= drawFb
->_ColorDrawBufferIndexes
[i
];
202 if (idx
== BUFFER_NONE
)
204 drawAtt
= &drawFb
->Attachment
[idx
];
205 drawRb
= drawAtt
->Renderbuffer
;
210 if (readRb
->Format
== drawRb
->Format
) {
212 pixelSize
= _mesa_get_format_bytes(readRb
->Format
);
214 mode
= UNPACK_RGBA_FLOAT
;
219 /* choose row resampler */
222 resampleRow
= resample_row_1
;
225 resampleRow
= resample_row_2
;
228 resampleRow
= resample_row_4
;
231 resampleRow
= resample_row_8
;
234 resampleRow
= resample_row_16
;
237 _mesa_problem(ctx
, "unexpected pixel size (%d) in blit_nearest",
242 if ((readRb
== drawRb
) ||
243 (readAtt
->Texture
&& drawAtt
->Texture
&&
244 (readAtt
->Texture
== drawAtt
->Texture
))) {
245 /* map whole buffer for read/write */
246 /* XXX we could be clever and just map the union region of the
247 * source and dest rects.
251 GLint formatSize
= _mesa_get_format_bytes(readRb
->Format
);
253 ctx
->Driver
.MapRenderbuffer(ctx
, readRb
, 0, 0,
254 readRb
->Width
, readRb
->Height
,
255 GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
,
256 &map
, &rowStride
, readFb
->FlipY
);
261 srcMap
= map
+ srcYpos
* rowStride
+ srcXpos
* formatSize
;
262 dstMap
= map
+ dstYpos
* rowStride
+ dstXpos
* formatSize
;
264 /* this handles overlapping copies */
266 /* copy in reverse (top->down) order */
267 srcMap
+= rowStride
* (readRb
->Height
- 1);
268 dstMap
+= rowStride
* (readRb
->Height
- 1);
269 srcRowStride
= -rowStride
;
270 dstRowStride
= -rowStride
;
273 /* copy in normal (bottom->up) order */
274 srcRowStride
= rowStride
;
275 dstRowStride
= rowStride
;
279 /* different src/dst buffers */
280 ctx
->Driver
.MapRenderbuffer(ctx
, readRb
,
283 GL_MAP_READ_BIT
, &srcMap
, &srcRowStride
,
288 ctx
->Driver
.MapRenderbuffer(ctx
, drawRb
,
291 GL_MAP_WRITE_BIT
, &dstMap
, &dstRowStride
,
294 ctx
->Driver
.UnmapRenderbuffer(ctx
, readRb
);
299 for (dstRow
= 0; dstRow
< dstHeight
; dstRow
++) {
300 GLfloat srcRowF
= (dstRow
+ 0.5F
) / dstHeight
* srcHeight
- 0.5F
;
301 GLint srcRow
= IROUND(srcRowF
);
302 GLubyte
*dstRowStart
= dstMap
+ dstRowStride
* dstRow
;
305 assert(srcRow
< srcHeight
);
308 srcRow
= srcHeight
- 1 - srcRow
;
311 /* get pixel row from source and resample to match dest width */
312 if (prevY
!= srcRow
) {
313 GLubyte
*srcRowStart
= srcMap
+ srcRowStride
* srcRow
;
317 memcpy(srcBuffer
, srcRowStart
, pixelSize
* srcWidth
);
319 case UNPACK_RGBA_FLOAT
:
320 _mesa_unpack_rgba_row(readRb
->Format
, srcWidth
, srcRowStart
,
324 _mesa_unpack_float_z_row(readRb
->Format
, srcWidth
, srcRowStart
,
328 _mesa_unpack_uint_z_row(readRb
->Format
, srcWidth
, srcRowStart
,
332 _mesa_unpack_ubyte_stencil_row(readRb
->Format
, srcWidth
,
333 srcRowStart
, srcBuffer
);
337 (*resampleRow
)(srcWidth
, dstWidth
, srcBuffer
, dstBuffer
, invertX
);
341 /* store pixel row in destination */
344 memcpy(dstRowStart
, dstBuffer
, pixelSize
* dstWidth
);
346 case UNPACK_RGBA_FLOAT
:
347 _mesa_pack_float_rgba_row(drawRb
->Format
, dstWidth
, dstBuffer
,
351 _mesa_pack_float_z_row(drawRb
->Format
, dstWidth
, dstBuffer
,
355 _mesa_pack_uint_z_row(drawRb
->Format
, dstWidth
, dstBuffer
,
359 _mesa_pack_ubyte_stencil_row(drawRb
->Format
, dstWidth
, dstBuffer
,
365 ctx
->Driver
.UnmapRenderbuffer(ctx
, readRb
);
366 if (drawRb
!= readRb
) {
367 ctx
->Driver
.UnmapRenderbuffer(ctx
, drawRb
);
379 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBlitFrameBuffer");
384 #define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
386 static inline GLfloat
387 lerp_2d(GLfloat a
, GLfloat b
,
388 GLfloat v00
, GLfloat v10
, GLfloat v01
, GLfloat v11
)
390 const GLfloat temp0
= LERP(a
, v00
, v10
);
391 const GLfloat temp1
= LERP(a
, v01
, v11
);
392 return LERP(b
, temp0
, temp1
);
397 * Bilinear interpolation of two source rows.
401 resample_linear_row_ub(GLint srcWidth
, GLint dstWidth
,
402 const GLvoid
*srcBuffer0
, const GLvoid
*srcBuffer1
,
403 GLvoid
*dstBuffer
, GLboolean flip
, GLfloat rowWeight
)
405 const GLubyte (*srcColor0
)[4] = (const GLubyte (*)[4]) srcBuffer0
;
406 const GLubyte (*srcColor1
)[4] = (const GLubyte (*)[4]) srcBuffer1
;
407 GLubyte (*dstColor
)[4] = (GLubyte (*)[4]) dstBuffer
;
410 for (dstCol
= 0; dstCol
< dstWidth
; dstCol
++) {
411 const GLfloat srcCol
= (dstCol
+ 0.5F
) / dstWidth
* srcWidth
- 0.5F
;
412 GLint srcCol0
= MAX2(0, IFLOOR(srcCol
));
413 GLint srcCol1
= srcCol0
+ 1;
414 GLfloat colWeight
= srcCol
- srcCol0
; /* fractional part of srcCol */
415 GLfloat red
, green
, blue
, alpha
;
417 assert(srcCol0
< srcWidth
);
418 assert(srcCol1
<= srcWidth
);
420 if (srcCol1
== srcWidth
) {
421 /* last column fudge */
427 srcCol0
= srcWidth
- 1 - srcCol0
;
428 srcCol1
= srcWidth
- 1 - srcCol1
;
431 red
= lerp_2d(colWeight
, rowWeight
,
432 srcColor0
[srcCol0
][RCOMP
], srcColor0
[srcCol1
][RCOMP
],
433 srcColor1
[srcCol0
][RCOMP
], srcColor1
[srcCol1
][RCOMP
]);
434 green
= lerp_2d(colWeight
, rowWeight
,
435 srcColor0
[srcCol0
][GCOMP
], srcColor0
[srcCol1
][GCOMP
],
436 srcColor1
[srcCol0
][GCOMP
], srcColor1
[srcCol1
][GCOMP
]);
437 blue
= lerp_2d(colWeight
, rowWeight
,
438 srcColor0
[srcCol0
][BCOMP
], srcColor0
[srcCol1
][BCOMP
],
439 srcColor1
[srcCol0
][BCOMP
], srcColor1
[srcCol1
][BCOMP
]);
440 alpha
= lerp_2d(colWeight
, rowWeight
,
441 srcColor0
[srcCol0
][ACOMP
], srcColor0
[srcCol1
][ACOMP
],
442 srcColor1
[srcCol0
][ACOMP
], srcColor1
[srcCol1
][ACOMP
]);
444 dstColor
[dstCol
][RCOMP
] = IFLOOR(red
);
445 dstColor
[dstCol
][GCOMP
] = IFLOOR(green
);
446 dstColor
[dstCol
][BCOMP
] = IFLOOR(blue
);
447 dstColor
[dstCol
][ACOMP
] = IFLOOR(alpha
);
453 * Bilinear interpolation of two source rows. floating point pixels.
456 resample_linear_row_float(GLint srcWidth
, GLint dstWidth
,
457 const GLvoid
*srcBuffer0
, const GLvoid
*srcBuffer1
,
458 GLvoid
*dstBuffer
, GLboolean flip
, GLfloat rowWeight
)
460 const GLfloat (*srcColor0
)[4] = (const GLfloat (*)[4]) srcBuffer0
;
461 const GLfloat (*srcColor1
)[4] = (const GLfloat (*)[4]) srcBuffer1
;
462 GLfloat (*dstColor
)[4] = (GLfloat (*)[4]) dstBuffer
;
465 for (dstCol
= 0; dstCol
< dstWidth
; dstCol
++) {
466 const GLfloat srcCol
= (dstCol
+ 0.5F
) / dstWidth
* srcWidth
- 0.5F
;
467 GLint srcCol0
= MAX2(0, IFLOOR(srcCol
));
468 GLint srcCol1
= srcCol0
+ 1;
469 GLfloat colWeight
= srcCol
- srcCol0
; /* fractional part of srcCol */
470 GLfloat red
, green
, blue
, alpha
;
472 assert(srcCol0
< srcWidth
);
473 assert(srcCol1
<= srcWidth
);
475 if (srcCol1
== srcWidth
) {
476 /* last column fudge */
482 srcCol0
= srcWidth
- 1 - srcCol0
;
483 srcCol1
= srcWidth
- 1 - srcCol1
;
486 red
= lerp_2d(colWeight
, rowWeight
,
487 srcColor0
[srcCol0
][RCOMP
], srcColor0
[srcCol1
][RCOMP
],
488 srcColor1
[srcCol0
][RCOMP
], srcColor1
[srcCol1
][RCOMP
]);
489 green
= lerp_2d(colWeight
, rowWeight
,
490 srcColor0
[srcCol0
][GCOMP
], srcColor0
[srcCol1
][GCOMP
],
491 srcColor1
[srcCol0
][GCOMP
], srcColor1
[srcCol1
][GCOMP
]);
492 blue
= lerp_2d(colWeight
, rowWeight
,
493 srcColor0
[srcCol0
][BCOMP
], srcColor0
[srcCol1
][BCOMP
],
494 srcColor1
[srcCol0
][BCOMP
], srcColor1
[srcCol1
][BCOMP
]);
495 alpha
= lerp_2d(colWeight
, rowWeight
,
496 srcColor0
[srcCol0
][ACOMP
], srcColor0
[srcCol1
][ACOMP
],
497 srcColor1
[srcCol0
][ACOMP
], srcColor1
[srcCol1
][ACOMP
]);
499 dstColor
[dstCol
][RCOMP
] = red
;
500 dstColor
[dstCol
][GCOMP
] = green
;
501 dstColor
[dstCol
][BCOMP
] = blue
;
502 dstColor
[dstCol
][ACOMP
] = alpha
;
509 * Bilinear filtered blit (color only, non-integer values).
512 blit_linear(struct gl_context
*ctx
,
513 struct gl_framebuffer
*readFb
,
514 struct gl_framebuffer
*drawFb
,
515 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
516 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
)
518 struct gl_renderbuffer
*readRb
= readFb
->_ColorReadBuffer
;
519 struct gl_renderbuffer_attachment
*readAtt
=
520 &readFb
->Attachment
[readFb
->_ColorReadBufferIndex
];
522 const GLint srcWidth
= ABS(srcX1
- srcX0
);
523 const GLint dstWidth
= ABS(dstX1
- dstX0
);
524 const GLint srcHeight
= ABS(srcY1
- srcY0
);
525 const GLint dstHeight
= ABS(dstY1
- dstY0
);
527 const GLint srcXpos
= MIN2(srcX0
, srcX1
);
528 const GLint srcYpos
= MIN2(srcY0
, srcY1
);
529 const GLint dstXpos
= MIN2(dstX0
, dstX1
);
530 const GLint dstYpos
= MIN2(dstY0
, dstY1
);
532 const GLboolean invertX
= (srcX1
< srcX0
) ^ (dstX1
< dstX0
);
533 const GLboolean invertY
= (srcY1
< srcY0
) ^ (dstY1
< dstY0
);
538 GLvoid
*srcBuffer0
, *srcBuffer1
;
539 GLint srcBufferY0
= -1, srcBufferY1
= -1;
542 mesa_format readFormat
= _mesa_get_srgb_format_linear(readRb
->Format
);
543 GLuint bpp
= _mesa_get_format_bytes(readFormat
);
547 GLubyte
*srcMap
, *dstMap
;
548 GLint srcRowStride
, dstRowStride
;
552 /* Determine datatype for resampling */
553 if (_mesa_get_format_max_bits(readFormat
) == 8 &&
554 _mesa_get_format_datatype(readFormat
) == GL_UNSIGNED_NORMALIZED
) {
555 pixelType
= GL_UNSIGNED_BYTE
;
556 pixelSize
= 4 * sizeof(GLubyte
);
559 pixelType
= GL_FLOAT
;
560 pixelSize
= 4 * sizeof(GLfloat
);
563 /* Allocate the src/dst row buffers.
564 * Keep two adjacent src rows around for bilinear sampling.
566 srcBuffer0
= malloc(pixelSize
* srcWidth
);
567 srcBuffer1
= malloc(pixelSize
* srcWidth
);
568 dstBuffer
= malloc(pixelSize
* dstWidth
);
569 if (!srcBuffer0
|| !srcBuffer1
|| !dstBuffer
) {
573 for (i
= 0; i
< drawFb
->_NumColorDrawBuffers
; i
++) {
574 gl_buffer_index idx
= drawFb
->_ColorDrawBufferIndexes
[i
];
575 struct gl_renderbuffer_attachment
*drawAtt
;
576 struct gl_renderbuffer
*drawRb
;
577 mesa_format drawFormat
;
579 if (idx
== BUFFER_NONE
)
582 drawAtt
= &drawFb
->Attachment
[idx
];
583 drawRb
= drawAtt
->Renderbuffer
;
587 drawFormat
= _mesa_get_srgb_format_linear(drawRb
->Format
);
590 * Map src / dst renderbuffers
592 if ((readRb
== drawRb
) ||
593 (readAtt
->Texture
&& drawAtt
->Texture
&&
594 (readAtt
->Texture
== drawAtt
->Texture
))) {
595 /* map whole buffer for read/write */
596 ctx
->Driver
.MapRenderbuffer(ctx
, readRb
,
597 0, 0, readRb
->Width
, readRb
->Height
,
598 GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
,
599 &srcMap
, &srcRowStride
,
606 dstRowStride
= srcRowStride
;
609 /* different src/dst buffers */
610 /* XXX with a bit of work we could just map the regions to be
611 * read/written instead of the whole buffers.
613 ctx
->Driver
.MapRenderbuffer(ctx
, readRb
,
614 0, 0, readRb
->Width
, readRb
->Height
,
615 GL_MAP_READ_BIT
, &srcMap
, &srcRowStride
,
620 ctx
->Driver
.MapRenderbuffer(ctx
, drawRb
,
621 0, 0, drawRb
->Width
, drawRb
->Height
,
622 GL_MAP_WRITE_BIT
, &dstMap
, &dstRowStride
,
625 ctx
->Driver
.UnmapRenderbuffer(ctx
, readRb
);
630 for (dstRow
= 0; dstRow
< dstHeight
; dstRow
++) {
631 const GLint dstY
= dstYpos
+ dstRow
;
632 GLfloat srcRow
= (dstRow
+ 0.5F
) / dstHeight
* srcHeight
- 0.5F
;
633 GLint srcRow0
= MAX2(0, IFLOOR(srcRow
));
634 GLint srcRow1
= srcRow0
+ 1;
635 GLfloat rowWeight
= srcRow
- srcRow0
; /* fractional part of srcRow */
637 if (srcRow1
== srcHeight
) {
644 srcRow0
= srcHeight
- 1 - srcRow0
;
645 srcRow1
= srcHeight
- 1 - srcRow1
;
648 srcY0
= srcYpos
+ srcRow0
;
649 srcY1
= srcYpos
+ srcRow1
;
651 /* get the two source rows */
652 if (srcY0
== srcBufferY0
&& srcY1
== srcBufferY1
) {
653 /* use same source row buffers again */
655 else if (srcY0
== srcBufferY1
) {
656 /* move buffer1 into buffer0 by swapping pointers */
657 GLvoid
*tmp
= srcBuffer0
;
658 srcBuffer0
= srcBuffer1
;
662 GLubyte
*src
= srcMap
+ srcY1
* srcRowStride
+ srcXpos
* bpp
;
663 if (pixelType
== GL_UNSIGNED_BYTE
) {
664 _mesa_unpack_ubyte_rgba_row(readFormat
, srcWidth
,
668 _mesa_unpack_rgba_row(readFormat
, srcWidth
,
676 /* get both new rows */
678 GLubyte
*src0
= srcMap
+ srcY0
* srcRowStride
+ srcXpos
* bpp
;
679 GLubyte
*src1
= srcMap
+ srcY1
* srcRowStride
+ srcXpos
* bpp
;
680 if (pixelType
== GL_UNSIGNED_BYTE
) {
681 _mesa_unpack_ubyte_rgba_row(readFormat
, srcWidth
,
683 _mesa_unpack_ubyte_rgba_row(readFormat
, srcWidth
,
687 _mesa_unpack_rgba_row(readFormat
, srcWidth
, src0
, srcBuffer0
);
688 _mesa_unpack_rgba_row(readFormat
, srcWidth
, src1
, srcBuffer1
);
695 if (pixelType
== GL_UNSIGNED_BYTE
) {
696 resample_linear_row_ub(srcWidth
, dstWidth
, srcBuffer0
, srcBuffer1
,
697 dstBuffer
, invertX
, rowWeight
);
700 resample_linear_row_float(srcWidth
, dstWidth
, srcBuffer0
, srcBuffer1
,
701 dstBuffer
, invertX
, rowWeight
);
704 /* store pixel row in destination */
706 GLubyte
*dst
= dstMap
+ dstY
* dstRowStride
+ dstXpos
* bpp
;
707 if (pixelType
== GL_UNSIGNED_BYTE
) {
708 _mesa_pack_ubyte_rgba_row(drawFormat
, dstWidth
, dstBuffer
, dst
);
711 _mesa_pack_float_rgba_row(drawFormat
, dstWidth
, dstBuffer
, dst
);
716 ctx
->Driver
.UnmapRenderbuffer(ctx
, readRb
);
717 if (drawRb
!= readRb
) {
718 ctx
->Driver
.UnmapRenderbuffer(ctx
, drawRb
);
731 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBlitFramebuffer");
737 * Software fallback for glBlitFramebufferEXT().
740 _swrast_BlitFramebuffer(struct gl_context
*ctx
,
741 struct gl_framebuffer
*readFb
,
742 struct gl_framebuffer
*drawFb
,
743 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
744 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
745 GLbitfield mask
, GLenum filter
)
747 static const GLbitfield buffers
[3] = {
750 GL_STENCIL_BUFFER_BIT
752 static const GLenum buffer_enums
[3] = {
759 /* Page 679 of OpenGL 4.4 spec says:
760 * "Added BlitFramebuffer to commands affected by conditional rendering in
761 * section 10.10 (Bug 9562)."
763 if (!_mesa_check_conditional_render(ctx
))
764 return; /* Do not blit */
766 if (!_mesa_clip_blit(ctx
, readFb
, drawFb
, &srcX0
, &srcY0
, &srcX1
, &srcY1
,
767 &dstX0
, &dstY0
, &dstX1
, &dstY1
)) {
771 if (SWRAST_CONTEXT(ctx
)->NewState
)
772 _swrast_validate_derived(ctx
);
774 /* First, try covering whatever buffers possible using the fast 1:1 copy
777 if (srcX1
- srcX0
== dstX1
- dstX0
&&
778 srcY1
- srcY0
== dstY1
- dstY0
&&
783 for (i
= 0; i
< 3; i
++) {
784 if (mask
& buffers
[i
]) {
785 if (swrast_fast_copy_pixels(ctx
,
788 srcX1
- srcX0
, srcY1
- srcY0
,
800 if (filter
== GL_NEAREST
) {
801 for (i
= 0; i
< 3; i
++) {
802 if (mask
& buffers
[i
]) {
803 blit_nearest(ctx
, readFb
, drawFb
, srcX0
, srcY0
, srcX1
, srcY1
,
804 dstX0
, dstY0
, dstX1
, dstY1
, buffers
[i
]);
809 assert(filter
== GL_LINEAR
);
810 if (mask
& GL_COLOR_BUFFER_BIT
) { /* depth/stencil not allowed */
811 blit_linear(ctx
, readFb
, drawFb
, srcX0
, srcY0
, srcX1
, srcY1
,
812 dstX0
, dstY0
, dstX1
, dstY1
);