Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygens_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
1.7.6.1
|