ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

s_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.