Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  6.5
  4.  *
  5.  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  6.  *
  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:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  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.
  23.  */
  24.  
  25.  
  26. #include "main/glheader.h"
  27. #include "main/condrender.h"
  28. #include "main/image.h"
  29. #include "main/macros.h"
  30. #include "s_context.h"
  31.  
  32.  
  33. #define ABS(X)   ((X) < 0 ? -(X) : (X))
  34.  
  35.  
  36. /**
  37.  * Generate a row resampler function for GL_NEAREST mode.
  38.  */
  39. #define RESAMPLE(NAME, PIXELTYPE, SIZE)                 \
  40. static void                                             \
  41. NAME(GLint srcWidth, GLint dstWidth,                    \
  42.      const GLvoid *srcBuffer, GLvoid *dstBuffer,        \
  43.      GLboolean flip)                                    \
  44. {                                                       \
  45.    const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
  46.    PIXELTYPE *dst = (PIXELTYPE *) dstBuffer;            \
  47.    GLint dstCol;                                        \
  48.                                                         \
  49.    if (flip) {                                          \
  50.       for (dstCol = 0; dstCol < dstWidth; dstCol++) {   \
  51.          GLint srcCol = (dstCol * srcWidth) / dstWidth; \
  52.          ASSERT(srcCol >= 0);                           \
  53.          ASSERT(srcCol < srcWidth);                     \
  54.          srcCol = srcWidth - 1 - srcCol; /* flip */     \
  55.          if (SIZE == 1) {                               \
  56.             dst[dstCol] = src[srcCol];                  \
  57.          }                                              \
  58.          else if (SIZE == 2) {                          \
  59.             dst[dstCol*2+0] = src[srcCol*2+0];          \
  60.             dst[dstCol*2+1] = src[srcCol*2+1];          \
  61.          }                                              \
  62.          else if (SIZE == 4) {                          \
  63.             dst[dstCol*4+0] = src[srcCol*4+0];          \
  64.             dst[dstCol*4+1] = src[srcCol*4+1];          \
  65.             dst[dstCol*4+2] = src[srcCol*4+2];          \
  66.             dst[dstCol*4+3] = src[srcCol*4+3];          \
  67.          }                                              \
  68.       }                                                 \
  69.    }                                                    \
  70.    else {                                               \
  71.       for (dstCol = 0; dstCol < dstWidth; dstCol++) {   \
  72.          GLint srcCol = (dstCol * srcWidth) / dstWidth; \
  73.          ASSERT(srcCol >= 0);                           \
  74.          ASSERT(srcCol < srcWidth);                     \
  75.          if (SIZE == 1) {                               \
  76.             dst[dstCol] = src[srcCol];                  \
  77.          }                                              \
  78.          else if (SIZE == 2) {                          \
  79.             dst[dstCol*2+0] = src[srcCol*2+0];          \
  80.             dst[dstCol*2+1] = src[srcCol*2+1];          \
  81.          }                                              \
  82.          else if (SIZE == 4) {                          \
  83.             dst[dstCol*4+0] = src[srcCol*4+0];          \
  84.             dst[dstCol*4+1] = src[srcCol*4+1];          \
  85.             dst[dstCol*4+2] = src[srcCol*4+2];          \
  86.             dst[dstCol*4+3] = src[srcCol*4+3];          \
  87.          }                                              \
  88.       }                                                 \
  89.    }                                                    \
  90. }
  91.  
  92. /**
  93.  * Resamplers for 1, 2, 4, 8 and 16-byte pixels.
  94.  */
  95. RESAMPLE(resample_row_1, GLubyte, 1)
  96. RESAMPLE(resample_row_2, GLushort, 1)
  97. RESAMPLE(resample_row_4, GLuint, 1)
  98. RESAMPLE(resample_row_8, GLuint, 2)
  99. RESAMPLE(resample_row_16, GLuint, 4)
  100.  
  101.  
  102. /**
  103.  * Blit color, depth or stencil with GL_NEAREST filtering.
  104.  */
  105. static void
  106. blit_nearest(struct gl_context *ctx,
  107.              GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
  108.              GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
  109.              GLbitfield buffer)
  110. {
  111.    struct gl_renderbuffer *readRb, *drawRb;
  112.  
  113.    const GLint srcWidth = ABS(srcX1 - srcX0);
  114.    const GLint dstWidth = ABS(dstX1 - dstX0);
  115.    const GLint srcHeight = ABS(srcY1 - srcY0);
  116.    const GLint dstHeight = ABS(dstY1 - dstY0);
  117.  
  118.    const GLint srcXpos = MIN2(srcX0, srcX1);
  119.    const GLint srcYpos = MIN2(srcY0, srcY1);
  120.    const GLint dstXpos = MIN2(dstX0, dstX1);
  121.    const GLint dstYpos = MIN2(dstY0, dstY1);
  122.  
  123.    const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
  124.    const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
  125.  
  126.    GLint dstRow;
  127.  
  128.    GLint comps, pixelSize;
  129.    GLvoid *srcBuffer, *dstBuffer;
  130.    GLint prevY = -1;
  131.  
  132.    typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
  133.                                  const GLvoid *srcBuffer, GLvoid *dstBuffer,
  134.                                  GLboolean flip);
  135.    resample_func resampleRow;
  136.  
  137.    switch (buffer) {
  138.    case GL_COLOR_BUFFER_BIT:
  139.       readRb = ctx->ReadBuffer->_ColorReadBuffer;
  140.       drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
  141.       comps = 4;
  142.       break;
  143.    case GL_DEPTH_BUFFER_BIT:
  144.       readRb = ctx->ReadBuffer->_DepthBuffer;
  145.       drawRb = ctx->DrawBuffer->_DepthBuffer;
  146.       comps = 1;
  147.       break;
  148.    case GL_STENCIL_BUFFER_BIT:
  149.       readRb = ctx->ReadBuffer->_StencilBuffer;
  150.       drawRb = ctx->DrawBuffer->_StencilBuffer;
  151.       comps = 1;
  152.       break;
  153.    default:
  154.       _mesa_problem(ctx, "unexpected buffer in blit_nearest()");
  155.       return;
  156.    }
  157.  
  158.    switch (readRb->DataType) {
  159.    case GL_UNSIGNED_BYTE:
  160.       pixelSize = comps * sizeof(GLubyte);
  161.       break;
  162.    case GL_UNSIGNED_SHORT:
  163.       pixelSize = comps * sizeof(GLushort);
  164.       break;
  165.    case GL_UNSIGNED_INT:
  166.       pixelSize = comps * sizeof(GLuint);
  167.       break;
  168.    case GL_FLOAT:
  169.       pixelSize = comps * sizeof(GLfloat);
  170.       break;
  171.    default:
  172.       _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
  173.                     readRb->DataType);
  174.       return;
  175.    }
  176.  
  177.    /* choose row resampler */
  178.    switch (pixelSize) {
  179.    case 1:
  180.       resampleRow = resample_row_1;
  181.       break;
  182.    case 2:
  183.       resampleRow = resample_row_2;
  184.       break;
  185.    case 4:
  186.       resampleRow = resample_row_4;
  187.       break;
  188.    case 8:
  189.       resampleRow = resample_row_8;
  190.       break;
  191.    case 16:
  192.       resampleRow = resample_row_16;
  193.       break;
  194.    default:
  195.       _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
  196.                     pixelSize);
  197.       return;
  198.    }
  199.  
  200.    /* allocate the src/dst row buffers */
  201.    srcBuffer = malloc(pixelSize * srcWidth);
  202.    if (!srcBuffer) {
  203.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
  204.       return;
  205.    }
  206.    dstBuffer = malloc(pixelSize * dstWidth);
  207.    if (!dstBuffer) {
  208.       free(srcBuffer);
  209.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
  210.       return;
  211.    }
  212.  
  213.    for (dstRow = 0; dstRow < dstHeight; dstRow++) {
  214.       const GLint dstY = dstYpos + dstRow;
  215.       GLint srcRow = (dstRow * srcHeight) / dstHeight;
  216.       GLint srcY;
  217.  
  218.       ASSERT(srcRow >= 0);
  219.       ASSERT(srcRow < srcHeight);
  220.  
  221.       if (invertY) {
  222.          srcRow = srcHeight - 1 - srcRow;
  223.       }
  224.  
  225.       srcY = srcYpos + srcRow;
  226.  
  227.       /* get pixel row from source and resample to match dest width */
  228.       if (prevY != srcY) {
  229.          readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY, srcBuffer);
  230.          (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
  231.          prevY = srcY;
  232.       }
  233.  
  234.       /* store pixel row in destination */
  235.       drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
  236.    }
  237.  
  238.    free(srcBuffer);
  239.    free(dstBuffer);
  240. }
  241.  
  242.  
  243.  
  244. #define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )
  245.  
  246. static INLINE GLfloat
  247. lerp_2d(GLfloat a, GLfloat b,
  248.         GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
  249. {
  250.    const GLfloat temp0 = LERP(a, v00, v10);
  251.    const GLfloat temp1 = LERP(a, v01, v11);
  252.    return LERP(b, temp0, temp1);
  253. }
  254.  
  255.  
  256. /**
  257.  * Bilinear interpolation of two source rows.
  258.  * GLubyte pixels.
  259.  */
  260. static void
  261. resample_linear_row_ub(GLint srcWidth, GLint dstWidth,
  262.                        const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
  263.                        GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
  264. {
  265.    const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
  266.    const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
  267.    GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
  268.    const GLfloat dstWidthF = (GLfloat) dstWidth;
  269.    GLint dstCol;
  270.  
  271.    for (dstCol = 0; dstCol < dstWidth; dstCol++) {
  272.       const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;
  273.       GLint srcCol0 = IFLOOR(srcCol);
  274.       GLint srcCol1 = srcCol0 + 1;
  275.       GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
  276.       GLfloat red, green, blue, alpha;
  277.  
  278.       ASSERT(srcCol0 >= 0);
  279.       ASSERT(srcCol0 < srcWidth);
  280.       ASSERT(srcCol1 <= srcWidth);
  281.  
  282.       if (srcCol1 == srcWidth) {
  283.          /* last column fudge */
  284.          srcCol1--;
  285.          colWeight = 0.0;
  286.       }
  287.  
  288.       if (flip) {
  289.          srcCol0 = srcWidth - 1 - srcCol0;
  290.          srcCol1 = srcWidth - 1 - srcCol1;
  291.       }
  292.  
  293.       red = lerp_2d(colWeight, rowWeight,
  294.                     srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
  295.                     srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
  296.       green = lerp_2d(colWeight, rowWeight,
  297.                     srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
  298.                     srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
  299.       blue = lerp_2d(colWeight, rowWeight,
  300.                     srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
  301.                     srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
  302.       alpha = lerp_2d(colWeight, rowWeight,
  303.                     srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
  304.                     srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
  305.      
  306.       dstColor[dstCol][RCOMP] = IFLOOR(red);
  307.       dstColor[dstCol][GCOMP] = IFLOOR(green);
  308.       dstColor[dstCol][BCOMP] = IFLOOR(blue);
  309.       dstColor[dstCol][ACOMP] = IFLOOR(alpha);
  310.    }
  311. }
  312.  
  313.  
  314.  
  315. /**
  316.  * Bilinear filtered blit (color only).
  317.  */
  318. static void
  319. blit_linear(struct gl_context *ctx,
  320.             GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
  321.             GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
  322. {
  323.    struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;
  324.    struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
  325.  
  326.    const GLint srcWidth = ABS(srcX1 - srcX0);
  327.    const GLint dstWidth = ABS(dstX1 - dstX0);
  328.    const GLint srcHeight = ABS(srcY1 - srcY0);
  329.    const GLint dstHeight = ABS(dstY1 - dstY0);
  330.    const GLfloat dstHeightF = (GLfloat) dstHeight;
  331.  
  332.    const GLint srcXpos = MIN2(srcX0, srcX1);
  333.    const GLint srcYpos = MIN2(srcY0, srcY1);
  334.    const GLint dstXpos = MIN2(dstX0, dstX1);
  335.    const GLint dstYpos = MIN2(dstY0, dstY1);
  336.  
  337.    const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
  338.    const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
  339.  
  340.    GLint dstRow;
  341.  
  342.    GLint pixelSize;
  343.    GLvoid *srcBuffer0, *srcBuffer1;
  344.    GLint srcBufferY0 = -1, srcBufferY1 = -1;
  345.    GLvoid *dstBuffer;
  346.  
  347.    switch (readRb->DataType) {
  348.    case GL_UNSIGNED_BYTE:
  349.       pixelSize = 4 * sizeof(GLubyte);
  350.       break;
  351.    case GL_UNSIGNED_SHORT:
  352.       pixelSize = 4 * sizeof(GLushort);
  353.       break;
  354.    case GL_UNSIGNED_INT:
  355.       pixelSize = 4 * sizeof(GLuint);
  356.       break;
  357.    case GL_FLOAT:
  358.       pixelSize = 4 * sizeof(GLfloat);
  359.       break;
  360.    default:
  361.       _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
  362.                     readRb->DataType);
  363.       return;
  364.    }
  365.  
  366.    /* Allocate the src/dst row buffers.
  367.     * Keep two adjacent src rows around for bilinear sampling.
  368.     */
  369.    srcBuffer0 = malloc(pixelSize * srcWidth);
  370.    if (!srcBuffer0) {
  371.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
  372.       return;
  373.    }
  374.    srcBuffer1 = malloc(pixelSize * srcWidth);
  375.    if (!srcBuffer1) {
  376.       free(srcBuffer0);
  377.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
  378.       return;
  379.    }
  380.    dstBuffer = malloc(pixelSize * dstWidth);
  381.    if (!dstBuffer) {
  382.       free(srcBuffer0);
  383.       free(srcBuffer1);
  384.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
  385.       return;
  386.    }
  387.  
  388.    for (dstRow = 0; dstRow < dstHeight; dstRow++) {
  389.       const GLint dstY = dstYpos + dstRow;
  390.       const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
  391.       GLint srcRow0 = IFLOOR(srcRow);
  392.       GLint srcRow1 = srcRow0 + 1;
  393.       GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
  394.  
  395.       ASSERT(srcRow >= 0);
  396.       ASSERT(srcRow < srcHeight);
  397.  
  398.       if (srcRow1 == srcHeight) {
  399.          /* last row fudge */
  400.          srcRow1 = srcRow0;
  401.          rowWeight = 0.0;
  402.       }
  403.  
  404.       if (invertY) {
  405.          srcRow0 = srcHeight - 1 - srcRow0;
  406.          srcRow1 = srcHeight - 1 - srcRow1;
  407.       }
  408.  
  409.       srcY0 = srcYpos + srcRow0;
  410.       srcY1 = srcYpos + srcRow1;
  411.  
  412.       /* get the two source rows */
  413.       if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
  414.          /* use same source row buffers again */
  415.       }
  416.       else if (srcY0 == srcBufferY1) {
  417.          /* move buffer1 into buffer0 by swapping pointers */
  418.          GLvoid *tmp = srcBuffer0;
  419.          srcBuffer0 = srcBuffer1;
  420.          srcBuffer1 = tmp;
  421.          /* get y1 row */
  422.          readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
  423.          srcBufferY0 = srcY0;
  424.          srcBufferY1 = srcY1;
  425.       }
  426.       else {
  427.          /* get both new rows */
  428.          readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0, srcBuffer0);
  429.          readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
  430.          srcBufferY0 = srcY0;
  431.          srcBufferY1 = srcY1;
  432.       }
  433.  
  434.       if (readRb->DataType == GL_UNSIGNED_BYTE) {
  435.          resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
  436.                                 dstBuffer, invertX, rowWeight);
  437.       }
  438.       else {
  439.          _mesa_problem(ctx, "Unsupported color channel type in sw blit");
  440.          break;
  441.       }
  442.  
  443.       /* store pixel row in destination */
  444.       drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
  445.    }
  446.  
  447.    free(srcBuffer0);
  448.    free(srcBuffer1);
  449.    free(dstBuffer);
  450. }
  451.  
  452.  
  453. /**
  454.  * Simple case:  Blit color, depth or stencil with no scaling or flipping.
  455.  * XXX we could easily support vertical flipping here.
  456.  */
  457. static void
  458. simple_blit(struct gl_context *ctx,
  459.             GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
  460.             GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
  461.             GLbitfield buffer)
  462. {
  463.    struct gl_renderbuffer *readRb, *drawRb;
  464.    const GLint width = srcX1 - srcX0;
  465.    const GLint height = srcY1 - srcY0;
  466.    GLint row, srcY, dstY, yStep;
  467.    GLint comps, bytesPerRow;
  468.    void *rowBuffer;
  469.  
  470.    /* only one buffer */
  471.    ASSERT(_mesa_bitcount(buffer) == 1);
  472.    /* no flipping checks */
  473.    ASSERT(srcX0 < srcX1);
  474.    ASSERT(srcY0 < srcY1);
  475.    ASSERT(dstX0 < dstX1);
  476.    ASSERT(dstY0 < dstY1);
  477.    /* size checks */
  478.    ASSERT(srcX1 - srcX0 == dstX1 - dstX0);
  479.    ASSERT(srcY1 - srcY0 == dstY1 - dstY0);
  480.  
  481.    /* determine if copy should be bottom-to-top or top-to-bottom */
  482.    if (srcY0 > dstY0) {
  483.       /* src above dst: copy bottom-to-top */
  484.       yStep = 1;
  485.       srcY = srcY0;
  486.       dstY = dstY0;
  487.    }
  488.    else {
  489.       /* src below dst: copy top-to-bottom */
  490.       yStep = -1;
  491.       srcY = srcY1 - 1;
  492.       dstY = dstY1 - 1;
  493.    }
  494.  
  495.    switch (buffer) {
  496.    case GL_COLOR_BUFFER_BIT:
  497.       readRb = ctx->ReadBuffer->_ColorReadBuffer;
  498.       drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
  499.       comps = 4;
  500.       break;
  501.    case GL_DEPTH_BUFFER_BIT:
  502.       readRb = ctx->ReadBuffer->_DepthBuffer;
  503.       drawRb = ctx->DrawBuffer->_DepthBuffer;
  504.       comps = 1;
  505.       break;
  506.    case GL_STENCIL_BUFFER_BIT:
  507.       readRb = ctx->ReadBuffer->_StencilBuffer;
  508.       drawRb = ctx->DrawBuffer->_StencilBuffer;
  509.       comps = 1;
  510.       break;
  511.    default:
  512.       _mesa_problem(ctx, "unexpected buffer in simple_blit()");
  513.       return;
  514.    }
  515.  
  516.    ASSERT(readRb->DataType == drawRb->DataType);
  517.  
  518.    /* compute bytes per row */
  519.    switch (readRb->DataType) {
  520.    case GL_UNSIGNED_BYTE:
  521.       bytesPerRow = comps * width * sizeof(GLubyte);
  522.       break;
  523.    case GL_UNSIGNED_SHORT:
  524.       bytesPerRow = comps * width * sizeof(GLushort);
  525.       break;
  526.    case GL_UNSIGNED_INT:
  527.       bytesPerRow = comps * width * sizeof(GLuint);
  528.       break;
  529.    case GL_FLOAT:
  530.       bytesPerRow = comps * width * sizeof(GLfloat);
  531.       break;
  532.    default:
  533.       _mesa_problem(ctx, "unexpected buffer type in simple_blit");
  534.       return;
  535.    }
  536.  
  537.    /* allocate the row buffer */
  538.    rowBuffer = malloc(bytesPerRow);
  539.    if (!rowBuffer) {
  540.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
  541.       return;
  542.    }
  543.  
  544.    for (row = 0; row < height; row++) {
  545.       readRb->GetRow(ctx, readRb, width, srcX0, srcY, rowBuffer);
  546.       drawRb->PutRow(ctx, drawRb, width, dstX0, dstY, rowBuffer, NULL);
  547.       srcY += yStep;
  548.       dstY += yStep;
  549.    }
  550.  
  551.    free(rowBuffer);
  552. }
  553.  
  554.  
  555. /**
  556.  * Software fallback for glBlitFramebufferEXT().
  557.  */
  558. void
  559. _swrast_BlitFramebuffer(struct gl_context *ctx,
  560.                         GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
  561.                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
  562.                         GLbitfield mask, GLenum filter)
  563. {
  564.    static const GLbitfield buffers[3] = {
  565.       GL_COLOR_BUFFER_BIT,
  566.       GL_DEPTH_BUFFER_BIT,
  567.       GL_STENCIL_BUFFER_BIT
  568.    };
  569.    GLint i;
  570.  
  571.    if (!_mesa_check_conditional_render(ctx))
  572.       return; /* don't clear */
  573.  
  574.    if (!ctx->DrawBuffer->_NumColorDrawBuffers)
  575.       return;
  576.  
  577.    if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
  578.                         &dstX0, &dstY0, &dstX1, &dstY1)) {
  579.       return;
  580.    }
  581.  
  582.    swrast_render_start(ctx);
  583.  
  584.    if (srcX1 - srcX0 == dstX1 - dstX0 &&
  585.        srcY1 - srcY0 == dstY1 - dstY0 &&
  586.        srcX0 < srcX1 &&
  587.        srcY0 < srcY1 &&
  588.        dstX0 < dstX1 &&
  589.        dstY0 < dstY1) {
  590.       /* no stretching or flipping.
  591.        * filter doesn't matter.
  592.        */
  593.       for (i = 0; i < 3; i++) {
  594.          if (mask & buffers[i]) {
  595.             simple_blit(ctx, srcX0, srcY0, srcX1, srcY1,
  596.                         dstX0, dstY0, dstX1, dstY1, buffers[i]);
  597.          }
  598.       }
  599.    }
  600.    else {
  601.       if (filter == GL_NEAREST) {
  602.          for (i = 0; i < 3; i++) {
  603.             if (mask & buffers[i]) {
  604.                blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
  605.                             dstX0, dstY0, dstX1, dstY1, buffers[i]);
  606.             }
  607.          }
  608.       }
  609.       else {
  610.          ASSERT(filter == GL_LINEAR);
  611.          if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
  612.             blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
  613.                         dstX0, dstY0, dstX1, dstY1);
  614.          }
  615.       }
  616.    }
  617.  
  618.    swrast_render_finish(ctx);
  619. }
  620.