/* * RGBA copypixels */ static void copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty) { SWcontext *swrast = SWRAST_CONTEXT(ctx); struct gl_renderbuffer *drawRb; GLchan *tmpImage,*p; GLboolean quick_draw; GLint sy, dy, stepy, j; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; GLint overlapping; const GLuint transferOps = ctx->_ImageTransferState; struct sw_span span; if (!ctx->ReadBuffer->_ColorReadBuffer) { /* no readbuffer - OK */ return; } INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) { copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty); return; } /* Determine if copy should be done bottom-to-top or top-to-bottom */ if (srcy < desty) { /* top-down max-to-min */ sy = srcy + height - 1; dy = desty + height - 1; stepy = -1; } else { /* bottom-up min-to-max */ sy = srcy; dy = desty; stepy = 1; } if (ctx->DrawBuffer == ctx->ReadBuffer) { overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); } else { overlapping = GL_FALSE; } if (ctx->Depth.Test) _swrast_span_default_z(ctx, &span); if (swrast->_FogEnabled) _swrast_span_default_fog(ctx, &span); if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom && destx >= 0 && destx + width <= (GLint) ctx->DrawBuffer->Width) { quick_draw = GL_TRUE; drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0][0]; } else { quick_draw = GL_FALSE; drawRb = NULL; } if (overlapping) { GLint ssy = sy; tmpImage = (GLchan *) _mesa_malloc(width * height * sizeof(GLchan) * 4); if (!tmpImage) { _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } /* read the source image */ p = tmpImage; for (j = 0; j < height; j++, ssy += stepy) { _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, width, srcx, ssy, (GLchan (*)[4]) p ); p += width * 4; } p = tmpImage; } else { tmpImage = NULL; /* silence compiler warnings */ p = NULL; } for (j = 0; j < height; j++, sy += stepy, dy += stepy) { /* Get source pixels */ if (overlapping) { /* get from buffered image */ ASSERT(width < MAX_WIDTH); _mesa_memcpy(span.array->rgba, p, width * sizeof(GLchan) * 4); p += width * 4; } else { /* get from framebuffer */ ASSERT(width < MAX_WIDTH); _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, width, srcx, sy, span.array->rgba ); } if (transferOps) { GLfloat rgbaFloat[MAX_WIDTH][4]; /* convert to float, transfer, convert back to chan */ chan_span_to_float(width, (CONST GLchan (*)[4]) span.array->rgba, rgbaFloat); _mesa_apply_rgba_transfer_ops(ctx, transferOps, width, rgbaFloat); float_span_to_chan(width, (CONST GLfloat (*)[4]) rgbaFloat, span.array->rgba); } /* Write color span */ if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) { drawRb->PutRow(ctx, drawRb, width, destx, dy, span.array->rgba, NULL); } else { span.x = destx; span.y = dy; span.end = width; if (zoom) { _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, (CONST GLchan (*)[4]) span.array->rgba); } else { _swrast_write_rgba_span(ctx, &span); } } } if (overlapping) _mesa_free(tmpImage); }
/** * RGBA copypixels */ static void copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLfloat *tmpImage, *p; GLint sy, dy, stepy, row; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; GLint overlapping; GLuint transferOps = ctx->_ImageTransferState; SWspan span; if (!ctx->ReadBuffer->_ColorReadBuffer) { /* no readbuffer - OK */ return; } if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) { copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty); return; } else if (ctx->Pixel.Convolution1DEnabled) { /* make sure we don't apply 1D convolution */ transferOps &= ~(IMAGE_CONVOLUTION_BIT | IMAGE_POST_CONVOLUTION_SCALE_BIAS); } if (ctx->DrawBuffer == ctx->ReadBuffer) { overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); } else { overlapping = GL_FALSE; } /* Determine if copy should be done bottom-to-top or top-to-bottom */ if (!overlapping && srcy < desty) { /* top-down max-to-min */ sy = srcy + height - 1; dy = desty + height - 1; stepy = -1; } else { /* bottom-up min-to-max */ sy = srcy; dy = desty; stepy = 1; } INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); if (ctx->Depth.Test) _swrast_span_default_z(ctx, &span); if (swrast->_FogEnabled) _swrast_span_default_fog(ctx, &span); _swrast_span_default_secondary_color(ctx, &span); if (overlapping) { tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat) * 4); if (!tmpImage) { _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } /* read the source image as RGBA/float */ p = tmpImage; for (row = 0; row < height; row++) { _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, width, srcx, sy + row, GL_FLOAT, p ); p += width * 4; } p = tmpImage; } else { tmpImage = NULL; /* silence compiler warnings */ p = NULL; } ASSERT(width < MAX_WIDTH); for (row = 0; row < height; row++, sy += stepy, dy += stepy) { GLvoid *rgba = span.array->attribs[FRAG_ATTRIB_COL0]; /* Get row/span of source pixels */ if (overlapping) { /* get from buffered image */ _mesa_memcpy(rgba, p, width * sizeof(GLfloat) * 4); p += width * 4; } else { /* get from framebuffer */ _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, width, srcx, sy, GL_FLOAT, rgba ); } if (transferOps) { _mesa_apply_rgba_transfer_ops(ctx, transferOps, width, (GLfloat (*)[4]) rgba); } /* Write color span */ span.x = destx; span.y = dy; span.end = width; span.array->ChanType = GL_FLOAT; if (zoom) { _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba); } else { _swrast_write_rgba_span(ctx, &span); } } span.array->ChanType = CHAN_TYPE; /* restore */ if (overlapping) _mesa_free(tmpImage); }