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
SWcontext *swrast = SWRAST_CONTEXT(ctx);
741
static const GLint buffers[3] = {
744
GL_STENCIL_BUFFER_BIT
748
if (!ctx->DrawBuffer->_NumColorDrawBuffers)
751
if (!clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
752
&dstX0, &dstY0, &dstX1, &dstY1)) {
756
RENDER_START(swrast, ctx);
758
if (srcX1 - srcX0 == dstX1 - dstX0 &&
759
srcY1 - srcY0 == dstY1 - dstY0 &&
764
/* no stretching or flipping.
765
* filter doesn't matter.
767
for (i = 0; i < 3; i++) {
768
if (mask & buffers[i]) {
769
simple_blit(ctx, srcX0, srcY0, srcX1, srcY1,
770
dstX0, dstY0, dstX1, dstY1, buffers[i]);
775
if (filter == GL_NEAREST) {
776
for (i = 0; i < 3; i++) {
777
if (mask & buffers[i]) {
778
blit_nearest(ctx, srcX0, srcY0, srcX1, srcY1,
779
dstX0, dstY0, dstX1, dstY1, buffers[i]);
784
ASSERT(filter == GL_LINEAR);
785
if (mask & GL_COLOR_BUFFER_BIT) { /* depth/stencil not allowed */
786
blit_linear(ctx, srcX0, srcY0, srcX1, srcY1,
787
dstX0, dstY0, dstX1, dstY1);
792
RENDER_FINISH(swrast, ctx);