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_copypix.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  7.1
00004  *
00005  * Copyright (C) 1999-2007  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/context.h"
00028 #include "main/colormac.h"
00029 #include "main/convolve.h"
00030 #include "main/histogram.h"
00031 #include "main/image.h"
00032 #include "main/macros.h"
00033 #include "main/imports.h"
00034 #include "main/pixel.h"
00035 
00036 #include "s_context.h"
00037 #include "s_depth.h"
00038 #include "s_span.h"
00039 #include "s_stencil.h"
00040 #include "s_zoom.h"
00041 
00042 
00043 
00051 static GLboolean
00052 regions_overlap(GLint srcx, GLint srcy,
00053                 GLint dstx, GLint dsty,
00054                 GLint width, GLint height,
00055                 GLfloat zoomX, GLfloat zoomY)
00056 {
00057    if (zoomX == 1.0 && zoomY == 1.0) {
00058       /* no zoom */
00059       if (srcx >= dstx + width || (srcx + width <= dstx)) {
00060          return GL_FALSE;
00061       }
00062       else if (srcy < dsty) { /* this is OK */
00063          return GL_FALSE;
00064       }
00065       else if (srcy > dsty + height) {
00066          return GL_FALSE;
00067       }
00068       else {
00069          return GL_TRUE;
00070       }
00071    }
00072    else {
00073       /* add one pixel of slop when zooming, just to be safe */
00074       if (srcx > (dstx + ((zoomX > 0.0F) ? (width * zoomX + 1.0F) : 0.0F))) {
00075          /* src is completely right of dest */
00076          return GL_FALSE;
00077       }
00078       else if (srcx + width + 1.0F < dstx + ((zoomX > 0.0F) ? 0.0F : (width * zoomX))) {
00079          /* src is completely left of dest */
00080          return GL_FALSE;
00081       }
00082       else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) {
00083          /* src is completely below dest */
00084          return GL_FALSE;
00085       }
00086       else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) {
00087          /* src is completely above dest */
00088          return GL_FALSE;
00089       }
00090       else {
00091          return GL_TRUE;
00092       }
00093    }
00094 }
00095 
00096 
00100 static void
00101 copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
00102                       GLint width, GLint height, GLint destx, GLint desty)
00103 {
00104    GLint row;
00105    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
00106    const GLbitfield transferOps = ctx->_ImageTransferState;
00107    const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink)
00108       || (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink);
00109    GLfloat *dest, *tmpImage, *convImage;
00110    SWspan span;
00111 
00112    INIT_SPAN(span, GL_BITMAP);
00113    _swrast_span_default_attribs(ctx, &span);
00114    span.arrayMask = SPAN_RGBA;
00115    span.arrayAttribs = FRAG_BIT_COL0;
00116 
00117    /* allocate space for GLfloat image */
00118    tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
00119    if (!tmpImage) {
00120       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
00121       return;
00122    }
00123    convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
00124    if (!convImage) {
00125       _mesa_free(tmpImage);
00126       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
00127       return;
00128    }
00129 
00130    /* read source image as float/RGBA */
00131    dest = tmpImage;
00132    for (row = 0; row < height; row++) {
00133       _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer,
00134                              width, srcx, srcy + row, GL_FLOAT, dest);
00135       dest += 4 * width;
00136    }
00137 
00138    /* do the image transfer ops which preceed convolution */
00139    for (row = 0; row < height; row++) {
00140       GLfloat (*rgba)[4] = (GLfloat (*)[4]) (tmpImage + row * width * 4);
00141       _mesa_apply_rgba_transfer_ops(ctx,
00142                                     transferOps & IMAGE_PRE_CONVOLUTION_BITS,
00143                                     width, rgba);
00144    }
00145 
00146    /* do convolution */
00147    if (ctx->Pixel.Convolution2DEnabled) {
00148       _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
00149    }
00150    else {
00151       ASSERT(ctx->Pixel.Separable2DEnabled);
00152       _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
00153    }
00154    _mesa_free(tmpImage);
00155 
00156    /* do remaining post-convolution image transfer ops */
00157    for (row = 0; row < height; row++) {
00158       GLfloat (*rgba)[4] = (GLfloat (*)[4]) (convImage + row * width * 4);
00159       _mesa_apply_rgba_transfer_ops(ctx,
00160                                     transferOps & IMAGE_POST_CONVOLUTION_BITS,
00161                                     width, rgba);
00162    }
00163 
00164    if (!sink) {
00165       /* write the new image */
00166       for (row = 0; row < height; row++) {
00167          const GLfloat *src = convImage + row * width * 4;
00168          GLfloat *rgba = (GLfloat *) span.array->attribs[FRAG_ATTRIB_COL0];
00169 
00170          /* copy convolved colors into span array */
00171          _mesa_memcpy(rgba, src, width * 4 * sizeof(GLfloat));
00172 
00173          /* write span */
00174          span.x = destx;
00175          span.y = desty + row;
00176          span.end = width;
00177          span.array->ChanType = GL_FLOAT;
00178          if (zoom) {
00179             _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
00180          }
00181          else {
00182             _swrast_write_rgba_span(ctx, &span);
00183          }
00184       }
00185       /* restore this */
00186       span.array->ChanType = CHAN_TYPE;
00187    }
00188 
00189    _mesa_free(convImage);
00190 }
00191 
00192 
00196 static void
00197 copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
00198                  GLint width, GLint height, GLint destx, GLint desty)
00199 {
00200    GLfloat *tmpImage, *p;
00201    GLint sy, dy, stepy, row;
00202    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
00203    GLint overlapping;
00204    GLuint transferOps = ctx->_ImageTransferState;
00205    SWspan span;
00206 
00207    if (!ctx->ReadBuffer->_ColorReadBuffer) {
00208       /* no readbuffer - OK */
00209       return;
00210    }
00211 
00212    if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
00213       copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty);
00214       return;
00215    }
00216    else if (ctx->Pixel.Convolution1DEnabled) {
00217       /* make sure we don't apply 1D convolution */
00218       transferOps &= ~(IMAGE_CONVOLUTION_BIT |
00219                        IMAGE_POST_CONVOLUTION_SCALE_BIAS);
00220    }
00221 
00222    if (ctx->DrawBuffer == ctx->ReadBuffer) {
00223       overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
00224                                     ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
00225    }
00226    else {
00227       overlapping = GL_FALSE;
00228    }
00229 
00230    /* Determine if copy should be done bottom-to-top or top-to-bottom */
00231    if (!overlapping && srcy < desty) {
00232       /* top-down  max-to-min */
00233       sy = srcy + height - 1;
00234       dy = desty + height - 1;
00235       stepy = -1;
00236    }
00237    else {
00238       /* bottom-up  min-to-max */
00239       sy = srcy;
00240       dy = desty;
00241       stepy = 1;
00242    }
00243 
00244    INIT_SPAN(span, GL_BITMAP);
00245    _swrast_span_default_attribs(ctx, &span);
00246    span.arrayMask = SPAN_RGBA;
00247    span.arrayAttribs = FRAG_BIT_COL0; /* we'll fill in COL0 attrib values */
00248 
00249    if (overlapping) {
00250       tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat) * 4);
00251       if (!tmpImage) {
00252          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
00253          return;
00254       }
00255       /* read the source image as RGBA/float */
00256       p = tmpImage;
00257       for (row = 0; row < height; row++) {
00258          _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
00259                                  width, srcx, sy + row, GL_FLOAT, p );
00260          p += width * 4;
00261       }
00262       p = tmpImage;
00263    }
00264    else {
00265       tmpImage = NULL;  /* silence compiler warnings */
00266       p = NULL;
00267    }
00268 
00269    ASSERT(width < MAX_WIDTH);
00270 
00271    for (row = 0; row < height; row++, sy += stepy, dy += stepy) {
00272       GLvoid *rgba = span.array->attribs[FRAG_ATTRIB_COL0];
00273 
00274       /* Get row/span of source pixels */
00275       if (overlapping) {
00276          /* get from buffered image */
00277          _mesa_memcpy(rgba, p, width * sizeof(GLfloat) * 4);
00278          p += width * 4;
00279       }
00280       else {
00281          /* get from framebuffer */
00282          _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
00283                                  width, srcx, sy, GL_FLOAT, rgba );
00284       }
00285 
00286       if (transferOps) {
00287          _mesa_apply_rgba_transfer_ops(ctx, transferOps, width,
00288                                        (GLfloat (*)[4]) rgba);
00289       }
00290 
00291       /* Write color span */
00292       span.x = destx;
00293       span.y = dy;
00294       span.end = width;
00295       span.array->ChanType = GL_FLOAT;
00296       if (zoom) {
00297          _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
00298       }
00299       else {
00300          _swrast_write_rgba_span(ctx, &span);
00301       }
00302    }
00303 
00304    span.array->ChanType = CHAN_TYPE; /* restore */
00305 
00306    if (overlapping)
00307       _mesa_free(tmpImage);
00308 }
00309 
00310 
00311 static void
00312 copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
00313                 GLint width, GLint height,
00314                 GLint destx, GLint desty )
00315 {
00316    GLuint *tmpImage,*p;
00317    GLint sy, dy, stepy;
00318    GLint j;
00319    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
00320    GLint overlapping;
00321    SWspan span;
00322 
00323    if (!ctx->ReadBuffer->_ColorReadBuffer) {
00324       /* no readbuffer - OK */
00325       return;
00326    }
00327 
00328    INIT_SPAN(span, GL_BITMAP);
00329    _swrast_span_default_attribs(ctx, &span);
00330    span.arrayMask = SPAN_INDEX;
00331 
00332    if (ctx->DrawBuffer == ctx->ReadBuffer) {
00333       overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
00334                                     ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
00335    }
00336    else {
00337       overlapping = GL_FALSE;
00338    }
00339 
00340    /* Determine if copy should be bottom-to-top or top-to-bottom */
00341    if (!overlapping && srcy < desty) {
00342       /* top-down  max-to-min */
00343       sy = srcy + height - 1;
00344       dy = desty + height - 1;
00345       stepy = -1;
00346    }
00347    else {
00348       /* bottom-up  min-to-max */
00349       sy = srcy;
00350       dy = desty;
00351       stepy = 1;
00352    }
00353 
00354    if (overlapping) {
00355       GLint ssy = sy;
00356       tmpImage = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint));
00357       if (!tmpImage) {
00358          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
00359          return;
00360       }
00361       /* read the image */
00362       p = tmpImage;
00363       for (j = 0; j < height; j++, ssy += stepy) {
00364          _swrast_read_index_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
00365                                   width, srcx, ssy, p );
00366          p += width;
00367       }
00368       p = tmpImage;
00369    }
00370    else {
00371       tmpImage = NULL;  /* silence compiler warning */
00372       p = NULL;
00373    }
00374 
00375    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
00376       /* Get color indexes */
00377       if (overlapping) {
00378          _mesa_memcpy(span.array->index, p, width * sizeof(GLuint));
00379          p += width;
00380       }
00381       else {
00382          _swrast_read_index_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
00383                                   width, srcx, sy, span.array->index );
00384       }
00385 
00386       if (ctx->_ImageTransferState)
00387          _mesa_apply_ci_transfer_ops(ctx, ctx->_ImageTransferState,
00388                                      width, span.array->index);
00389 
00390       /* write color indexes */
00391       span.x = destx;
00392       span.y = dy;
00393       span.end = width;
00394       if (zoom)
00395          _swrast_write_zoomed_index_span(ctx, destx, desty, &span);
00396       else
00397          _swrast_write_index_span(ctx, &span);
00398    }
00399 
00400    if (overlapping)
00401       _mesa_free(tmpImage);
00402 }
00403 
00404 
00409 static void
00410 scale_and_bias_z(GLcontext *ctx, GLuint width,
00411                  const GLfloat depth[], GLuint z[])
00412 {
00413    const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
00414    GLuint i;
00415 
00416    if (depthMax <= 0xffffff &&
00417        ctx->Pixel.DepthScale == 1.0 &&
00418        ctx->Pixel.DepthBias == 0.0) {
00419       /* no scale or bias and no clamping and no worry of overflow */
00420       const GLfloat depthMaxF = ctx->DrawBuffer->_DepthMaxF;
00421       for (i = 0; i < width; i++) {
00422          z[i] = (GLuint) (depth[i] * depthMaxF);
00423       }
00424    }
00425    else {
00426       /* need to be careful with overflow */
00427       const GLdouble depthMaxF = ctx->DrawBuffer->_DepthMaxF;
00428       for (i = 0; i < width; i++) {
00429          GLdouble d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
00430          d = CLAMP(d, 0.0, 1.0) * depthMaxF;
00431          if (d >= depthMaxF)
00432             z[i] = depthMax;
00433          else
00434             z[i] = (GLuint) d;
00435       }
00436    }
00437 }
00438 
00439 
00440 
00441 /*
00442  * TODO: Optimize!!!!
00443  */
00444 static void
00445 copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
00446                    GLint width, GLint height,
00447                    GLint destx, GLint desty )
00448 {
00449    struct gl_framebuffer *fb = ctx->ReadBuffer;
00450    struct gl_renderbuffer *readRb = fb->_DepthBuffer;
00451    GLfloat *p, *tmpImage;
00452    GLint sy, dy, stepy;
00453    GLint j;
00454    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
00455    GLint overlapping;
00456    SWspan span;
00457 
00458    if (!readRb) {
00459       /* no readbuffer - OK */
00460       return;
00461    }
00462 
00463    INIT_SPAN(span, GL_BITMAP);
00464    _swrast_span_default_attribs(ctx, &span);
00465    span.arrayMask = SPAN_Z;
00466 
00467    if (ctx->DrawBuffer == ctx->ReadBuffer) {
00468       overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
00469                                     ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
00470    }
00471    else {
00472       overlapping = GL_FALSE;
00473    }
00474 
00475    /* Determine if copy should be bottom-to-top or top-to-bottom */
00476    if (!overlapping && srcy < desty) {
00477       /* top-down  max-to-min */
00478       sy = srcy + height - 1;
00479       dy = desty + height - 1;
00480       stepy = -1;
00481    }
00482    else {
00483       /* bottom-up  min-to-max */
00484       sy = srcy;
00485       dy = desty;
00486       stepy = 1;
00487    }
00488 
00489    if (overlapping) {
00490       GLint ssy = sy;
00491       tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat));
00492       if (!tmpImage) {
00493          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
00494          return;
00495       }
00496       p = tmpImage;
00497       for (j = 0; j < height; j++, ssy += stepy) {
00498          _swrast_read_depth_span_float(ctx, readRb, width, srcx, ssy, p);
00499          p += width;
00500       }
00501       p = tmpImage;
00502    }
00503    else {
00504       tmpImage = NULL;  /* silence compiler warning */
00505       p = NULL;
00506    }
00507 
00508    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
00509       GLfloat depth[MAX_WIDTH];
00510       /* get depth values */
00511       if (overlapping) {
00512          _mesa_memcpy(depth, p, width * sizeof(GLfloat));
00513          p += width;
00514       }
00515       else {
00516          _swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth);
00517       }
00518 
00519       /* apply scale and bias */
00520       scale_and_bias_z(ctx, width, depth, span.array->z);
00521 
00522       /* write depth values */
00523       span.x = destx;
00524       span.y = dy;
00525       span.end = width;
00526       if (fb->Visual.rgbMode) {
00527          if (zoom)
00528             _swrast_write_zoomed_depth_span(ctx, destx, desty, &span);
00529          else
00530             _swrast_write_rgba_span(ctx, &span);
00531       }
00532       else {
00533          if (zoom)
00534             _swrast_write_zoomed_depth_span(ctx, destx, desty, &span);
00535          else
00536             _swrast_write_index_span(ctx, &span);
00537       }
00538    }
00539 
00540    if (overlapping)
00541       _mesa_free(tmpImage);
00542 }
00543 
00544 
00545 
00546 static void
00547 copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
00548                      GLint width, GLint height,
00549                      GLint destx, GLint desty )
00550 {
00551    struct gl_framebuffer *fb = ctx->ReadBuffer;
00552    struct gl_renderbuffer *rb = fb->_StencilBuffer;
00553    GLint sy, dy, stepy;
00554    GLint j;
00555    GLstencil *p, *tmpImage;
00556    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
00557    GLint overlapping;
00558 
00559    if (!rb) {
00560       /* no readbuffer - OK */
00561       return;
00562    }
00563 
00564    if (ctx->DrawBuffer == ctx->ReadBuffer) {
00565       overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
00566                                     ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
00567    }
00568    else {
00569       overlapping = GL_FALSE;
00570    }
00571 
00572    /* Determine if copy should be bottom-to-top or top-to-bottom */
00573    if (!overlapping && srcy < desty) {
00574       /* top-down  max-to-min */
00575       sy = srcy + height - 1;
00576       dy = desty + height - 1;
00577       stepy = -1;
00578    }
00579    else {
00580       /* bottom-up  min-to-max */
00581       sy = srcy;
00582       dy = desty;
00583       stepy = 1;
00584    }
00585 
00586    if (overlapping) {
00587       GLint ssy = sy;
00588       tmpImage = (GLstencil *) _mesa_malloc(width * height * sizeof(GLstencil));
00589       if (!tmpImage) {
00590          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
00591          return;
00592       }
00593       p = tmpImage;
00594       for (j = 0; j < height; j++, ssy += stepy) {
00595          _swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p );
00596          p += width;
00597       }
00598       p = tmpImage;
00599    }
00600    else {
00601       tmpImage = NULL;  /* silence compiler warning */
00602       p = NULL;
00603    }
00604 
00605    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
00606       GLstencil stencil[MAX_WIDTH];
00607 
00608       /* Get stencil values */
00609       if (overlapping) {
00610          _mesa_memcpy(stencil, p, width * sizeof(GLstencil));
00611          p += width;
00612       }
00613       else {
00614          _swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil );
00615       }
00616 
00617       _mesa_apply_stencil_transfer_ops(ctx, width, stencil);
00618 
00619       /* Write stencil values */
00620       if (zoom) {
00621          _swrast_write_zoomed_stencil_span(ctx, destx, desty, width,
00622                                            destx, dy, stencil);
00623       }
00624       else {
00625          _swrast_write_stencil_span( ctx, width, destx, dy, stencil );
00626       }
00627    }
00628 
00629    if (overlapping)
00630       _mesa_free(tmpImage);
00631 }
00632 
00633 
00639 static void
00640 copy_depth_stencil_pixels(GLcontext *ctx,
00641                           const GLint srcX, const GLint srcY,
00642                           const GLint width, const GLint height,
00643                           const GLint destX, const GLint destY)
00644 {
00645    struct gl_renderbuffer *stencilReadRb, *depthReadRb, *depthDrawRb;
00646    GLint sy, dy, stepy;
00647    GLint j;
00648    GLstencil *tempStencilImage = NULL, *stencilPtr = NULL;
00649    GLfloat *tempDepthImage = NULL, *depthPtr = NULL;
00650    const GLfloat depthScale = ctx->DrawBuffer->_DepthMaxF;
00651    const GLuint stencilMask = ctx->Stencil.WriteMask[0];
00652    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
00653    const GLboolean scaleOrBias
00654       = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
00655    GLint overlapping;
00656 
00657    depthDrawRb = ctx->DrawBuffer->_DepthBuffer;
00658    depthReadRb = ctx->ReadBuffer->_DepthBuffer;
00659    stencilReadRb = ctx->ReadBuffer->_StencilBuffer;
00660 
00661    ASSERT(depthDrawRb);
00662    ASSERT(depthReadRb);
00663    ASSERT(stencilReadRb);
00664 
00665    if (ctx->DrawBuffer == ctx->ReadBuffer) {
00666       overlapping = regions_overlap(srcX, srcY, destX, destY, width, height,
00667                                     ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
00668    }
00669    else {
00670       overlapping = GL_FALSE;
00671    }
00672 
00673    /* Determine if copy should be bottom-to-top or top-to-bottom */
00674    if (!overlapping && srcY < destY) {
00675       /* top-down  max-to-min */
00676       sy = srcY + height - 1;
00677       dy = destY + height - 1;
00678       stepy = -1;
00679    }
00680    else {
00681       /* bottom-up  min-to-max */
00682       sy = srcY;
00683       dy = destY;
00684       stepy = 1;
00685    }
00686 
00687    if (overlapping) {
00688       GLint ssy = sy;
00689 
00690       if (stencilMask != 0x0) {
00691          tempStencilImage
00692             = (GLstencil *) _mesa_malloc(width * height * sizeof(GLstencil));
00693          if (!tempStencilImage) {
00694             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
00695             return;
00696          }
00697 
00698          /* get copy of stencil pixels */
00699          stencilPtr = tempStencilImage;
00700          for (j = 0; j < height; j++, ssy += stepy) {
00701             _swrast_read_stencil_span(ctx, stencilReadRb,
00702                                       width, srcX, ssy, stencilPtr);
00703             stencilPtr += width;
00704          }
00705          stencilPtr = tempStencilImage;
00706       }
00707 
00708       if (ctx->Depth.Mask) {
00709          tempDepthImage
00710             = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat));
00711          if (!tempDepthImage) {
00712             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
00713             _mesa_free(tempStencilImage);
00714             return;
00715          }
00716 
00717          /* get copy of depth pixels */
00718          depthPtr = tempDepthImage;
00719          for (j = 0; j < height; j++, ssy += stepy) {
00720             _swrast_read_depth_span_float(ctx, depthReadRb,
00721                                           width, srcX, ssy, depthPtr);
00722             depthPtr += width;
00723          }
00724          depthPtr = tempDepthImage;
00725       }
00726    }
00727 
00728    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
00729       if (stencilMask != 0x0) {
00730          GLstencil stencil[MAX_WIDTH];
00731 
00732          /* Get stencil values */
00733          if (overlapping) {
00734             _mesa_memcpy(stencil, stencilPtr, width * sizeof(GLstencil));
00735             stencilPtr += width;
00736          }
00737          else {
00738             _swrast_read_stencil_span(ctx, stencilReadRb,
00739                                       width, srcX, sy, stencil);
00740          }
00741 
00742          _mesa_apply_stencil_transfer_ops(ctx, width, stencil);
00743 
00744          /* Write values */
00745          if (zoom) {
00746             _swrast_write_zoomed_stencil_span(ctx, destX, destY, width,
00747                                               destX, dy, stencil);
00748          }
00749          else {
00750             _swrast_write_stencil_span( ctx, width, destX, dy, stencil );
00751          }
00752       }
00753 
00754       if (ctx->Depth.Mask) {
00755          GLfloat depth[MAX_WIDTH];
00756          GLuint zVals32[MAX_WIDTH];
00757          GLushort zVals16[MAX_WIDTH];
00758          GLvoid *zVals;
00759          GLuint zBytes;
00760 
00761          /* get depth values */
00762          if (overlapping) {
00763             _mesa_memcpy(depth, depthPtr, width * sizeof(GLfloat));
00764             depthPtr += width;
00765          }
00766          else {
00767             _swrast_read_depth_span_float(ctx, depthReadRb,
00768                                           width, srcX, sy, depth);
00769          }
00770 
00771          /* scale & bias */
00772          if (scaleOrBias) {
00773             _mesa_scale_and_bias_depth(ctx, width, depth);
00774          }
00775          /* convert to integer Z values */
00776          if (depthDrawRb->DataType == GL_UNSIGNED_SHORT) {
00777             GLint k;
00778             for (k = 0; k < width; k++)
00779                zVals16[k] = (GLushort) (depth[k] * depthScale);
00780             zVals = zVals16;
00781             zBytes = 2;
00782          }
00783          else {
00784             GLint k;
00785             for (k = 0; k < width; k++)
00786                zVals32[k] = (GLuint) (depth[k] * depthScale);
00787             zVals = zVals32;
00788             zBytes = 4;
00789          }
00790 
00791          /* Write values */
00792          if (zoom) {
00793             _swrast_write_zoomed_z_span(ctx, destX, destY, width,
00794                                         destX, dy, zVals);
00795          }
00796          else {
00797             _swrast_put_row(ctx, depthDrawRb, width, destX, dy, zVals, zBytes);
00798          }
00799       }
00800    }
00801 
00802    if (tempStencilImage)
00803       _mesa_free(tempStencilImage);
00804 
00805    if (tempDepthImage)
00806       _mesa_free(tempDepthImage);
00807 }
00808 
00809 
00810 
00814 static GLboolean
00815 fast_copy_pixels(GLcontext *ctx,
00816                  GLint srcX, GLint srcY, GLsizei width, GLsizei height,
00817                  GLint dstX, GLint dstY, GLenum type)
00818 {
00819    struct gl_framebuffer *srcFb = ctx->ReadBuffer;
00820    struct gl_framebuffer *dstFb = ctx->DrawBuffer;
00821    struct gl_renderbuffer *srcRb, *dstRb;
00822    GLint row, yStep;
00823 
00824    if (SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 ||
00825        ctx->Pixel.ZoomX != 1.0F ||
00826        ctx->Pixel.ZoomY != 1.0F ||
00827        ctx->_ImageTransferState) {
00828       /* can't handle these */
00829       return GL_FALSE;
00830    }
00831 
00832    if (type == GL_COLOR) {
00833       if (dstFb->_NumColorDrawBuffers != 1)
00834          return GL_FALSE;
00835       srcRb = srcFb->_ColorReadBuffer;
00836       dstRb = dstFb->_ColorDrawBuffers[0];
00837    }
00838    else if (type == GL_STENCIL) {
00839       srcRb = srcFb->_StencilBuffer;
00840       dstRb = dstFb->_StencilBuffer;
00841    }
00842    else if (type == GL_DEPTH) {
00843       srcRb = srcFb->_DepthBuffer;
00844       dstRb = dstFb->_DepthBuffer;
00845    }
00846    else {
00847       ASSERT(type == GL_DEPTH_STENCIL_EXT);
00848       /* XXX correct? */
00849       srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
00850       dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
00851    }
00852 
00853    /* src and dst renderbuffers must be same format and type */
00854    if (!srcRb || !dstRb ||
00855        srcRb->DataType != dstRb->DataType ||
00856        srcRb->_BaseFormat != dstRb->_BaseFormat) {
00857       return GL_FALSE;
00858    }
00859 
00860    /* clipping not supported */
00861    if (srcX < 0 || srcX + width > (GLint) srcFb->Width ||
00862        srcY < 0 || srcY + height > (GLint) srcFb->Height ||
00863        dstX < dstFb->_Xmin || dstX + width > dstFb->_Xmax ||
00864        dstY < dstFb->_Ymin || dstY + height > dstFb->_Ymax) {
00865       return GL_FALSE;
00866    }
00867 
00868    /* overlapping src/dst doesn't matter, just determine Y direction */
00869    if (srcY < dstY) {
00870       /* top-down  max-to-min */
00871       srcY = srcY + height - 1;
00872       dstY = dstY + height - 1;
00873       yStep = -1;
00874    }
00875    else {
00876       /* bottom-up  min-to-max */
00877       yStep = 1;
00878    }
00879 
00880    for (row = 0; row < height; row++) {
00881       GLuint temp[MAX_WIDTH][4];
00882       srcRb->GetRow(ctx, srcRb, width, srcX, srcY, temp);
00883       dstRb->PutRow(ctx, dstRb, width, dstX, dstY, temp, NULL);
00884       srcY += yStep;
00885       dstY += yStep;
00886    }
00887 
00888    return GL_TRUE;
00889 }
00890 
00891 
00896 void
00897 _swrast_CopyPixels( GLcontext *ctx,
00898             GLint srcx, GLint srcy, GLsizei width, GLsizei height,
00899             GLint destx, GLint desty, GLenum type )
00900 {
00901    SWcontext *swrast = SWRAST_CONTEXT(ctx);
00902    RENDER_START(swrast,ctx);
00903       
00904    if (swrast->NewState)
00905       _swrast_validate_derived( ctx );
00906 
00907    if (!fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) {
00908       switch (type) {
00909       case GL_COLOR:
00910          if (ctx->Visual.rgbMode) {
00911             copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
00912          }
00913          else {
00914             copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty );
00915          }
00916          break;
00917       case GL_DEPTH:
00918          copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
00919          break;
00920       case GL_STENCIL:
00921          copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
00922          break;
00923       case GL_DEPTH_STENCIL_EXT:
00924          copy_depth_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty);
00925          break;
00926       default:
00927          _mesa_problem(ctx, "unexpected type in _swrast_CopyPixels");
00928       }
00929    }
00930 
00931    RENDER_FINISH(swrast,ctx);
00932 }

Generated on Fri May 25 2012 04:18:51 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.