Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygens_blit.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 6.5 00004 * 00005 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00026 #include "main/glheader.h" 00027 #include "main/macros.h" 00028 #include "s_context.h" 00029 00030 00031 #define ABS(X) ((X) < 0 ? -(X) : (X)) 00032 00033 00037 #define RESAMPLE(NAME, PIXELTYPE, SIZE) \ 00038 static void \ 00039 NAME(GLint srcWidth, GLint dstWidth, \ 00040 const GLvoid *srcBuffer, GLvoid *dstBuffer, \ 00041 GLboolean flip) \ 00042 { \ 00043 const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\ 00044 PIXELTYPE *dst = (PIXELTYPE *) dstBuffer; \ 00045 GLint dstCol; \ 00046 \ 00047 if (flip) { \ 00048 for (dstCol = 0; dstCol < dstWidth; dstCol++) { \ 00049 GLint srcCol = (dstCol * srcWidth) / dstWidth; \ 00050 ASSERT(srcCol >= 0); \ 00051 ASSERT(srcCol < srcWidth); \ 00052 srcCol = srcWidth - 1 - srcCol; /* flip */ \ 00053 if (SIZE == 1) { \ 00054 dst[dstCol] = src[srcCol]; \ 00055 } \ 00056 else if (SIZE == 2) { \ 00057 dst[dstCol*2+0] = src[srcCol*2+0]; \ 00058 dst[dstCol*2+1] = src[srcCol*2+1]; \ 00059 } \ 00060 else if (SIZE == 4) { \ 00061 dst[dstCol*4+0] = src[srcCol*4+0]; \ 00062 dst[dstCol*4+1] = src[srcCol*4+1]; \ 00063 dst[dstCol*4+2] = src[srcCol*4+2]; \ 00064 dst[dstCol*4+3] = src[srcCol*4+3]; \ 00065 } \ 00066 } \ 00067 } \ 00068 else { \ 00069 for (dstCol = 0; dstCol < dstWidth; dstCol++) { \ 00070 GLint srcCol = (dstCol * srcWidth) / dstWidth; \ 00071 ASSERT(srcCol >= 0); \ 00072 ASSERT(srcCol < srcWidth); \ 00073 if (SIZE == 1) { \ 00074 dst[dstCol] = src[srcCol]; \ 00075 } \ 00076 else if (SIZE == 2) { \ 00077 dst[dstCol*2+0] = src[srcCol*2+0]; \ 00078 dst[dstCol*2+1] = src[srcCol*2+1]; \ 00079 } \ 00080 else if (SIZE == 4) { \ 00081 dst[dstCol*4+0] = src[srcCol*4+0]; \ 00082 dst[dstCol*4+1] = src[srcCol*4+1]; \ 00083 dst[dstCol*4+2] = src[srcCol*4+2]; \ 00084 dst[dstCol*4+3] = src[srcCol*4+3]; \ 00085 } \ 00086 } \ 00087 } \ 00088 } 00089 00093 RESAMPLE(resample_row_1, GLubyte, 1) 00094 RESAMPLE(resample_row_2, GLushort, 1) 00095 RESAMPLE(resample_row_4, GLuint, 1) 00096 RESAMPLE(resample_row_8, GLuint, 2) 00097 RESAMPLE(resample_row_16, GLuint, 4) 00098 00099 00103 static void 00104 blit_nearest(GLcontext *ctx, 00105 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 00106 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 00107 GLenum buffer) 00108 { 00109 struct gl_renderbuffer *readRb, *drawRb; 00110 00111 const GLint srcWidth = ABS(srcX1 - srcX0); 00112 const GLint dstWidth = ABS(dstX1 - dstX0); 00113 const GLint srcHeight = ABS(srcY1 - srcY0); 00114 const GLint dstHeight = ABS(dstY1 - dstY0); 00115 00116 const GLint srcXpos = MIN2(srcX0, srcX1); 00117 const GLint srcYpos = MIN2(srcY0, srcY1); 00118 const GLint dstXpos = MIN2(dstX0, dstX1); 00119 const GLint dstYpos = MIN2(dstY0, dstY1); 00120 00121 const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0); 00122 const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0); 00123 00124 GLint dstRow; 00125 00126 GLint comps, pixelSize; 00127 GLvoid *srcBuffer, *dstBuffer; 00128 GLint prevY = -1; 00129 00130 typedef void (*resample_func)(GLint srcWidth, GLint dstWidth, 00131 const GLvoid *srcBuffer, GLvoid *dstBuffer, 00132 GLboolean flip); 00133 resample_func resampleRow; 00134 00135 switch (buffer) { 00136 case GL_COLOR_BUFFER_BIT: 00137 readRb = ctx->ReadBuffer->_ColorReadBuffer; 00138 drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0]; 00139 comps = 4; 00140 break; 00141 case GL_DEPTH_BUFFER_BIT: 00142 readRb = ctx->ReadBuffer->_DepthBuffer; 00143 drawRb = ctx->DrawBuffer->_DepthBuffer; 00144 comps = 1; 00145 break; 00146 case GL_STENCIL_BUFFER_BIT: 00147 readRb = ctx->ReadBuffer->_StencilBuffer; 00148 drawRb = ctx->DrawBuffer->_StencilBuffer; 00149 comps = 1; 00150 break; 00151 default: 00152 _mesa_problem(ctx, "unexpected buffer in blit_nearest()"); 00153 return; 00154 } 00155 00156 switch (readRb->DataType) { 00157 case GL_UNSIGNED_BYTE: 00158 pixelSize = comps * sizeof(GLubyte); 00159 break; 00160 case GL_UNSIGNED_SHORT: 00161 pixelSize = comps * sizeof(GLushort); 00162 break; 00163 case GL_UNSIGNED_INT: 00164 pixelSize = comps * sizeof(GLuint); 00165 break; 00166 case GL_FLOAT: 00167 pixelSize = comps * sizeof(GLfloat); 00168 break; 00169 default: 00170 _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest", 00171 readRb->DataType); 00172 return; 00173 } 00174 00175 /* choose row resampler */ 00176 switch (pixelSize) { 00177 case 1: 00178 resampleRow = resample_row_1; 00179 break; 00180 case 2: 00181 resampleRow = resample_row_2; 00182 break; 00183 case 4: 00184 resampleRow = resample_row_4; 00185 break; 00186 case 8: 00187 resampleRow = resample_row_8; 00188 break; 00189 case 16: 00190 resampleRow = resample_row_16; 00191 break; 00192 default: 00193 _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest", 00194 pixelSize); 00195 return; 00196 } 00197 00198 /* allocate the src/dst row buffers */ 00199 srcBuffer = _mesa_malloc(pixelSize * srcWidth); 00200 if (!srcBuffer) { 00201 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); 00202 return; 00203 } 00204 dstBuffer = _mesa_malloc(pixelSize * dstWidth); 00205 if (!dstBuffer) { 00206 _mesa_free(srcBuffer); 00207 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); 00208 return; 00209 } 00210 00211 for (dstRow = 0; dstRow < dstHeight; dstRow++) { 00212 const GLint dstY = dstYpos + dstRow; 00213 GLint srcRow = (dstRow * srcHeight) / dstHeight; 00214 GLint srcY; 00215 00216 ASSERT(srcRow >= 0); 00217 ASSERT(srcRow < srcHeight); 00218 00219 if (invertY) { 00220 srcRow = srcHeight - 1 - srcRow; 00221 } 00222 00223 srcY = srcYpos + srcRow; 00224 00225 /* get pixel row from source and resample to match dest width */ 00226 if (prevY != srcY) { 00227 readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY, srcBuffer); 00228 (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX); 00229 prevY = srcY; 00230 } 00231 00232 /* store pixel row in destination */ 00233 drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL); 00234 } 00235 00236 _mesa_free(srcBuffer); 00237 _mesa_free(dstBuffer); 00238 } 00239 00240 00241 00242 #define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) ) 00243 00244 static INLINE GLfloat 00245 lerp_2d(GLfloat a, GLfloat b, 00246 GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11) 00247 { 00248 const GLfloat temp0 = LERP(a, v00, v10); 00249 const GLfloat temp1 = LERP(a, v01, v11); 00250 return LERP(b, temp0, temp1); 00251 } 00252 00253 00258 static void 00259 resample_linear_row_ub(GLint srcWidth, GLint dstWidth, 00260 const GLvoid *srcBuffer0, const GLvoid *srcBuffer1, 00261 GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight) 00262 { 00263 const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0; 00264 const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1; 00265 GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer; 00266 const GLfloat dstWidthF = (GLfloat) dstWidth; 00267 GLint dstCol; 00268 00269 for (dstCol = 0; dstCol < dstWidth; dstCol++) { 00270 const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF; 00271 GLint srcCol0 = IFLOOR(srcCol); 00272 GLint srcCol1 = srcCol0 + 1; 00273 GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */ 00274 GLfloat red, green, blue, alpha; 00275 00276 ASSERT(srcCol0 >= 0); 00277 ASSERT(srcCol0 < srcWidth); 00278 ASSERT(srcCol1 <= srcWidth); 00279 00280 if (srcCol1 == srcWidth) { 00281 /* last column fudge */ 00282 srcCol1--; 00283 colWeight = 0.0; 00284 } 00285 00286 if (flip) { 00287 srcCol0 = srcWidth - 1 - srcCol0; 00288 srcCol1 = srcWidth - 1 - srcCol1; 00289 } 00290 00291 red = lerp_2d(colWeight, rowWeight, 00292 srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP], 00293 srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]); 00294 green = lerp_2d(colWeight, rowWeight, 00295 srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP], 00296 srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]); 00297 blue = lerp_2d(colWeight, rowWeight, 00298 srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP], 00299 srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]); 00300 alpha = lerp_2d(colWeight, rowWeight, 00301 srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP], 00302 srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]); 00303 00304 dstColor[dstCol][RCOMP] = IFLOOR(red); 00305 dstColor[dstCol][GCOMP] = IFLOOR(green); 00306 dstColor[dstCol][BCOMP] = IFLOOR(blue); 00307 dstColor[dstCol][ACOMP] = IFLOOR(alpha); 00308 } 00309 } 00310 00311 00312 00316 static void 00317 blit_linear(GLcontext *ctx, 00318 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 00319 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) 00320 { 00321 struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer; 00322 struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0]; 00323 00324 const GLint srcWidth = ABS(srcX1 - srcX0); 00325 const GLint dstWidth = ABS(dstX1 - dstX0); 00326 const GLint srcHeight = ABS(srcY1 - srcY0); 00327 const GLint dstHeight = ABS(dstY1 - dstY0); 00328 const GLfloat dstHeightF = (GLfloat) dstHeight; 00329 00330 const GLint srcXpos = MIN2(srcX0, srcX1); 00331 const GLint srcYpos = MIN2(srcY0, srcY1); 00332 const GLint dstXpos = MIN2(dstX0, dstX1); 00333 const GLint dstYpos = MIN2(dstY0, dstY1); 00334 00335 const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0); 00336 const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0); 00337 00338 GLint dstRow; 00339 00340 GLint pixelSize; 00341 GLvoid *srcBuffer0, *srcBuffer1; 00342 GLint srcBufferY0 = -1, srcBufferY1 = -1; 00343 GLvoid *dstBuffer; 00344 00345 switch (readRb->DataType) { 00346 case GL_UNSIGNED_BYTE: 00347 pixelSize = 4 * sizeof(GLubyte); 00348 break; 00349 case GL_UNSIGNED_SHORT: 00350 pixelSize = 4 * sizeof(GLushort); 00351 break; 00352 case GL_UNSIGNED_INT: 00353 pixelSize = 4 * sizeof(GLuint); 00354 break; 00355 case GL_FLOAT: 00356 pixelSize = 4 * sizeof(GLfloat); 00357 break; 00358 default: 00359 _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest", 00360 readRb->DataType); 00361 return; 00362 } 00363 00364 /* Allocate the src/dst row buffers. 00365 * Keep two adjacent src rows around for bilinear sampling. 00366 */ 00367 srcBuffer0 = _mesa_malloc(pixelSize * srcWidth); 00368 if (!srcBuffer0) { 00369 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); 00370 return; 00371 } 00372 srcBuffer1 = _mesa_malloc(pixelSize * srcWidth); 00373 if (!srcBuffer1) { 00374 _mesa_free(srcBuffer0); 00375 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); 00376 return; 00377 } 00378 dstBuffer = _mesa_malloc(pixelSize * dstWidth); 00379 if (!dstBuffer) { 00380 _mesa_free(srcBuffer0); 00381 _mesa_free(srcBuffer1); 00382 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); 00383 return; 00384 } 00385 00386 for (dstRow = 0; dstRow < dstHeight; dstRow++) { 00387 const GLint dstY = dstYpos + dstRow; 00388 const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF; 00389 GLint srcRow0 = IFLOOR(srcRow); 00390 GLint srcRow1 = srcRow0 + 1; 00391 GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */ 00392 00393 ASSERT(srcRow >= 0); 00394 ASSERT(srcRow < srcHeight); 00395 00396 if (srcRow1 == srcHeight) { 00397 /* last row fudge */ 00398 srcRow1 = srcRow0; 00399 rowWeight = 0.0; 00400 } 00401 00402 if (invertY) { 00403 srcRow0 = srcHeight - 1 - srcRow0; 00404 srcRow1 = srcHeight - 1 - srcRow1; 00405 } 00406 00407 srcY0 = srcYpos + srcRow0; 00408 srcY1 = srcYpos + srcRow1; 00409 00410 /* get the two source rows */ 00411 if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) { 00412 /* use same source row buffers again */ 00413 } 00414 else if (srcY0 == srcBufferY1) { 00415 /* move buffer1 into buffer0 by swapping pointers */ 00416 GLvoid *tmp = srcBuffer0; 00417 srcBuffer0 = srcBuffer1; 00418 srcBuffer1 = tmp; 00419 /* get y1 row */ 00420 readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1); 00421 srcBufferY0 = srcY0; 00422 srcBufferY1 = srcY1; 00423 } 00424 else { 00425 /* get both new rows */ 00426 readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0, srcBuffer0); 00427 readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1); 00428 srcBufferY0 = srcY0; 00429 srcBufferY1 = srcY1; 00430 } 00431 00432 if (readRb->DataType == GL_UNSIGNED_BYTE) { 00433 resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1, 00434 dstBuffer, invertX, rowWeight); 00435 } 00436 else { 00437 _mesa_problem(ctx, "Unsupported color channel type in sw blit"); 00438 break; 00439 } 00440 00441 /* store pixel row in destination */ 00442 drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL); 00443 } 00444 00445 _mesa_free(srcBuffer0); 00446 _mesa_free(srcBuffer1); 00447 _mesa_free(dstBuffer); 00448 } 00449 00450 00455 static void 00456 simple_blit(GLcontext *ctx, 00457 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 00458 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 00459 GLenum buffer) 00460 { 00461 struct gl_renderbuffer *readRb, *drawRb; 00462 const GLint width = srcX1 - srcX0; 00463 const GLint height = srcY1 - srcY0; 00464 GLint row, srcY, dstY, yStep; 00465 GLint comps, bytesPerRow; 00466 void *rowBuffer; 00467 00468 /* only one buffer */ 00469 ASSERT(_mesa_bitcount(buffer) == 1); 00470 /* no flipping checks */ 00471 ASSERT(srcX0 < srcX1); 00472 ASSERT(srcY0 < srcY1); 00473 ASSERT(dstX0 < dstX1); 00474 ASSERT(dstY0 < dstY1); 00475 /* size checks */ 00476 ASSERT(srcX1 - srcX0 == dstX1 - dstX0); 00477 ASSERT(srcY1 - srcY0 == dstY1 - dstY0); 00478 00479 /* determine if copy should be bottom-to-top or top-to-bottom */ 00480 if (srcY0 > dstY0) { 00481 /* src above dst: copy bottom-to-top */ 00482 yStep = 1; 00483 srcY = srcY0; 00484 dstY = dstY0; 00485 } 00486 else { 00487 /* src below dst: copy top-to-bottom */ 00488 yStep = -1; 00489 srcY = srcY1 - 1; 00490 dstY = dstY1 - 1; 00491 } 00492 00493 switch (buffer) { 00494 case GL_COLOR_BUFFER_BIT: 00495 readRb = ctx->ReadBuffer->_ColorReadBuffer; 00496 drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0]; 00497 comps = 4; 00498 break; 00499 case GL_DEPTH_BUFFER_BIT: 00500 readRb = ctx->ReadBuffer->_DepthBuffer; 00501 drawRb = ctx->DrawBuffer->_DepthBuffer; 00502 comps = 1; 00503 break; 00504 case GL_STENCIL_BUFFER_BIT: 00505 readRb = ctx->ReadBuffer->_StencilBuffer; 00506 drawRb = ctx->DrawBuffer->_StencilBuffer; 00507 comps = 1; 00508 break; 00509 default: 00510 _mesa_problem(ctx, "unexpected buffer in simple_blit()"); 00511 return; 00512 } 00513 00514 ASSERT(readRb->DataType == drawRb->DataType); 00515 00516 /* compute bytes per row */ 00517 switch (readRb->DataType) { 00518 case GL_UNSIGNED_BYTE: 00519 bytesPerRow = comps * width * sizeof(GLubyte); 00520 break; 00521 case GL_UNSIGNED_SHORT: 00522 bytesPerRow = comps * width * sizeof(GLushort); 00523 break; 00524 case GL_UNSIGNED_INT: 00525 bytesPerRow = comps * width * sizeof(GLuint); 00526 break; 00527 case GL_FLOAT: 00528 bytesPerRow = comps * width * sizeof(GLfloat); 00529 break; 00530 default: 00531 _mesa_problem(ctx, "unexpected buffer type in simple_blit"); 00532 return; 00533 } 00534 00535 /* allocate the row buffer */ 00536 rowBuffer = _mesa_malloc(bytesPerRow); 00537 if (!rowBuffer) { 00538 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); 00539 return; 00540 } 00541 00542 for (row = 0; row < height; row++) { 00543 readRb->GetRow(ctx, readRb, width, srcX0, srcY, rowBuffer); 00544 drawRb->PutRow(ctx, drawRb, width, dstX0, dstY, rowBuffer, NULL); 00545 srcY += yStep; 00546 dstY += yStep; 00547 } 00548 00549 _mesa_free(rowBuffer); 00550 } 00551 00552 00556 static INLINE void 00557 clip_right_or_top(GLint *srcX0, GLint *srcX1, 00558 GLint *dstX0, GLint *dstX1, 00559 GLint maxValue) 00560 { 00561 GLfloat t, bias; 00562 00563 if (*dstX1 > maxValue) { 00564 /* X1 outside right edge */ 00565 ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */ 00566 t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); 00567 /* chop off [t, 1] part */ 00568 ASSERT(t >= 0.0 && t <= 1.0); 00569 *dstX1 = maxValue; 00570 bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; 00571 *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); 00572 } 00573 else if (*dstX0 > maxValue) { 00574 /* X0 outside right edge */ 00575 ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */ 00576 t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); 00577 /* chop off [t, 1] part */ 00578 ASSERT(t >= 0.0 && t <= 1.0); 00579 *dstX0 = maxValue; 00580 bias = (*srcX0 < *srcX1) ? -0.5 : 0.5; 00581 *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); 00582 } 00583 } 00584 00585 00589 static INLINE void 00590 clip_left_or_bottom(GLint *srcX0, GLint *srcX1, 00591 GLint *dstX0, GLint *dstX1, 00592 GLint minValue) 00593 { 00594 GLfloat t, bias; 00595 00596 if (*dstX0 < minValue) { 00597 /* X0 outside left edge */ 00598 ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */ 00599 t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); 00600 /* chop off [0, t] part */ 00601 ASSERT(t >= 0.0 && t <= 1.0); 00602 *dstX0 = minValue; 00603 bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; /* flipped??? */ 00604 *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); 00605 } 00606 else if (*dstX1 < minValue) { 00607 /* X1 outside left edge */ 00608 ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */ 00609 t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); 00610 /* chop off [0, t] part */ 00611 ASSERT(t >= 0.0 && t <= 1.0); 00612 *dstX1 = minValue; 00613 bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; 00614 *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); 00615 } 00616 } 00617 00618 00632 static GLboolean 00633 clip_blit(GLcontext *ctx, 00634 GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1, 00635 GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1) 00636 { 00637 const GLint srcXmin = 0; 00638 const GLint srcXmax = ctx->ReadBuffer->Width; 00639 const GLint srcYmin = 0; 00640 const GLint srcYmax = ctx->ReadBuffer->Height; 00641 00642 /* these include scissor bounds */ 00643 const GLint dstXmin = ctx->DrawBuffer->_Xmin; 00644 const GLint dstXmax = ctx->DrawBuffer->_Xmax; 00645 const GLint dstYmin = ctx->DrawBuffer->_Ymin; 00646 const GLint dstYmax = ctx->DrawBuffer->_Ymax; 00647 00648 /* 00649 printf("PreClipX: src: %d .. %d dst: %d .. %d\n", 00650 *srcX0, *srcX1, *dstX0, *dstX1); 00651 printf("PreClipY: src: %d .. %d dst: %d .. %d\n", 00652 *srcY0, *srcY1, *dstY0, *dstY1); 00653 */ 00654 00655 /* trivial rejection tests */ 00656 if (*dstX0 == *dstX1) 00657 return GL_FALSE; /* no width */ 00658 if (*dstX0 <= dstXmin && *dstX1 <= dstXmin) 00659 return GL_FALSE; /* totally out (left) of bounds */ 00660 if (*dstX0 >= dstXmax && *dstX1 >= dstXmax) 00661 return GL_FALSE; /* totally out (right) of bounds */ 00662 00663 if (*dstY0 == *dstY1) 00664 return GL_FALSE; 00665 if (*dstY0 <= dstYmin && *dstY1 <= dstYmin) 00666 return GL_FALSE; 00667 if (*dstY0 >= dstYmax && *dstY1 >= dstYmax) 00668 return GL_FALSE; 00669 00670 if (*srcX0 == *srcX1) 00671 return GL_FALSE; 00672 if (*srcX0 <= srcXmin && *srcX1 <= srcXmin) 00673 return GL_FALSE; 00674 if (*srcX0 >= srcXmax && *srcX1 >= srcXmax) 00675 return GL_FALSE; 00676 00677 if (*srcY0 == *srcY1) 00678 return GL_FALSE; 00679 if (*srcY0 <= srcYmin && *srcY1 <= srcYmin) 00680 return GL_FALSE; 00681 if (*srcY0 >= srcYmax && *srcY1 >= srcYmax) 00682 return GL_FALSE; 00683 00684 /* 00685 * dest clip 00686 */ 00687 clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax); 00688 clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax); 00689 clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin); 00690 clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin); 00691 00692 /* 00693 * src clip (just swap src/dst values from above) 00694 */ 00695 clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax); 00696 clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax); 00697 clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin); 00698 clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin); 00699 00700 /* 00701 printf("PostClipX: src: %d .. %d dst: %d .. %d\n", 00702 *srcX0, *srcX1, *dstX0, *dstX1); 00703 printf("PostClipY: src: %d .. %d dst: %d .. %d\n", 00704 *srcY0, *srcY1, *dstY0, *dstY1); 00705 */ 00706 00707 ASSERT(*dstX0 >= dstXmin); 00708 ASSERT(*dstX0 <= dstXmax); 00709 ASSERT(*dstX1 >= dstXmin); 00710 ASSERT(*dstX1 <= dstXmax); 00711 00712 ASSERT(*dstY0 >= dstYmin); 00713 ASSERT(*dstY0 <= dstYmax); 00714 ASSERT(*dstY1 >= dstYmin); 00715 ASSERT(*dstY1 <= dstYmax); 00716 00717 ASSERT(*srcX0 >= srcXmin); 00718 ASSERT(*srcX0 <= srcXmax); 00719 ASSERT(*srcX1 >= srcXmin); 00720 ASSERT(*srcX1 <= srcXmax); 00721 00722 ASSERT(*srcY0 >= srcYmin); 00723 ASSERT(*srcY0 <= srcYmax); 00724 ASSERT(*srcY1 >= srcYmin); 00725 ASSERT(*srcY1 <= srcYmax); 00726 00727 return GL_TRUE; 00728 } 00729 00730 00734 void 00735 _swrast_BlitFramebuffer(GLcontext *ctx, 00736 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 00737 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 00738 GLbitfield mask, GLenum filter) 00739 { 00740 SWcontext *swrast = SWRAST_CONTEXT(ctx); 00741 static const GLint buffers[3] = { 00742 GL_COLOR_BUFFER_BIT, 00743 GL_DEPTH_BUFFER_BIT, 00744 GL_STENCIL_BUFFER_BIT 00745 }; 00746 GLint i; 00747 00748 if (!ctx->DrawBuffer->_NumColorDrawBuffers) 00749 return; 00750 00751 if (!clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1, 00752 &dstX0, &dstY0, &dstX1, &dstY1)) { 00753 return; 00754 } 00755 00756 RENDER_START(swrast, ctx); 00757 00758 if (srcX1 - srcX0 == dstX1 - dstX0 && 00759 srcY1 - srcY0 == dstY1 - dstY0 && 00760 srcX0 < srcX1 && 00761 srcY0 < srcY1 && 00762 dstX0 < dstX1 && 00763 dstY0 < dstY1) { 00764 /* no stretching or flipping. 00765 * filter doesn't matter. 00766 */ 00767 for (i = 0; i < 3; i++) { 00768 if (mask & buffers[i]) { 00769 simple_blit(ctx, srcX0, srcY0, srcX1, srcY1, 00770 dstX0, dstY0, dstX1, dstY1, buffers[i]); 00771 } 00772 } 00773 } 00774 else { 00775 if (filter == GL_NEAREST) { 00776 for (i = 0; i < 3; i++) { 00777 if (mask & buffers[i]) { 00778 blit_nearest(ctx, srcX0, srcY0, srcX1, srcY1, 00779 dstX0, dstY0, dstX1, dstY1, buffers[i]); 00780 } 00781 } 00782 } 00783 else { 00784 ASSERT(filter == GL_LINEAR); 00785 if (mask & GL_COLOR_BUFFER_BIT) { /* depth/stencil not allowed */ 00786 blit_linear(ctx, srcX0, srcY0, srcX1, srcY1, 00787 dstX0, dstY0, dstX1, dstY1); 00788 } 00789 } 00790 } 00791 00792 RENDER_FINISH(swrast, ctx); 00793 } Generated on Sat May 26 2012 04:19:31 for ReactOS by
1.7.6.1
|