void _swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLchan data[MAX_WIDTH][4]; struct gl_buffer_object *bufferSave; if (!ctx->ReadBuffer->_ColorReadBuffer) { /* no readbuffer - OK */ return; } if (width > MAX_WIDTH) width = MAX_WIDTH; RENDER_START( swrast, ctx ); /* read the data from framebuffer */ _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, width, x, y, CHAN_TYPE, data ); RENDER_FINISH(swrast,ctx); /* save PBO binding */ bufferSave = ctx->Unpack.BufferObj; ctx->Unpack.BufferObj = ctx->Array.NullBufferObj; _mesa_ColorSubTable(target, start, width, GL_RGBA, CHAN_TYPE, data); /* restore PBO binding */ ctx->Unpack.BufferObj = bufferSave; }
void _swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLchan rgba[MAX_CONVOLUTION_WIDTH][4]; struct gl_buffer_object *bufferSave; if (!ctx->ReadBuffer->_ColorReadBuffer) { /* no readbuffer - OK */ return; } RENDER_START( swrast, ctx ); /* read the data from framebuffer */ _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, width, x, y, CHAN_TYPE, rgba ); RENDER_FINISH( swrast, ctx ); /* save PBO binding */ bufferSave = ctx->Unpack.BufferObj; ctx->Unpack.BufferObj = ctx->Array.NullBufferObj; /* store as convolution filter */ _mesa_ConvolutionFilter1D(target, internalFormat, width, GL_RGBA, CHAN_TYPE, rgba); /* restore PBO binding */ ctx->Unpack.BufferObj = bufferSave; }
/** * Apply the current logic operator to a span of RGBA pixels. * We can handle horizontal runs of pixels (spans) or arrays of x/y * pixel coordinates. */ void _swrast_logicop_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb, const struct sw_span *span, GLchan rgba[][4]) { GLchan dest[MAX_WIDTH][4]; ASSERT(span->end < MAX_WIDTH); ASSERT(span->arrayMask & SPAN_RGBA); ASSERT(rb->DataType == GL_UNSIGNED_BYTE); if (span->arrayMask & SPAN_XY) { _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y, dest, 4 * sizeof(GLchan)); } else { _swrast_read_rgba_span(ctx, rb, span->end, span->x, span->y, dest); } /* XXX make this a runtime test */ #if CHAN_TYPE == GL_UNSIGNED_BYTE /* treat 4*GLubyte as GLuint */ logicop_uint(ctx, span->end, (GLuint *) rgba, (const GLuint *) dest, span->array->mask); #elif CHAN_TYPE == GL_UNSIGNED_SHORT logicop_ushort(ctx, 4 * span->end, (GLushort *) rgba, (const GLushort *) dest, span->array->mask); #elif CHAN_TYPE == GL_FLOAT logicop_uint(ctx, 4 * span->end, (GLuint *) rgba, (const GLuint *) dest, span->array->mask); #endif (void) logicop_ubyte; (void) logicop_ushort; (void) logicop_uint; }
/* * Apply the current logic operator to a span of RGBA pixels. * We can handle horizontal runs of pixels (spans) or arrays of x/y * pixel coordinates. */ void _swrast_logicop_rgba_span( GLcontext *ctx, const struct sw_span *span, GLchan rgba[][4] ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLchan dest[MAX_WIDTH][4]; ASSERT(span->end < MAX_WIDTH); ASSERT(span->arrayMask & SPAN_RGBA); if (span->arrayMask & SPAN_XY) { (*swrast->Driver.ReadRGBAPixels)(ctx, span->end, span->array->x, span->array->y, dest, span->array->mask); if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { _swrast_read_alpha_pixels(ctx, span->end, span->array->x, span->array->y, dest, span->array->mask); } } else { _swrast_read_rgba_span(ctx, ctx->DrawBuffer, span->end, span->x, span->y, dest); } if (sizeof(GLchan) * 4 == sizeof(GLuint)) { rgba_logicop_ui(ctx, span->end, span->array->mask, (GLuint *) rgba, (const GLuint *) dest); } else { rgba_logicop_chan(ctx, 4 * span->end, span->array->mask, (GLchan *) rgba, (const GLchan *) dest); } }
void _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height) { SWcontext *swrast = SWRAST_CONTEXT(ctx); struct gl_pixelstore_attrib packSave; GLchan rgba[MAX_CONVOLUTION_HEIGHT][MAX_CONVOLUTION_WIDTH][4]; GLint i; struct gl_buffer_object *bufferSave; if (!ctx->ReadBuffer->_ColorReadBuffer) { /* no readbuffer - OK */ return; } RENDER_START(swrast,ctx); /* read pixels from framebuffer */ for (i = 0; i < height; i++) { _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, width, x, y + i, CHAN_TYPE, rgba[i] ); } RENDER_FINISH(swrast,ctx); /* * HACK: save & restore context state so we can store this as a * convolution filter via the GL api. Doesn't call any callbacks * hanging off ctx->Unpack statechanges. */ packSave = ctx->Unpack; /* save pixel packing params */ ctx->Unpack.Alignment = 1; ctx->Unpack.RowLength = MAX_CONVOLUTION_WIDTH; ctx->Unpack.SkipPixels = 0; ctx->Unpack.SkipRows = 0; ctx->Unpack.ImageHeight = 0; ctx->Unpack.SkipImages = 0; ctx->Unpack.SwapBytes = GL_FALSE; ctx->Unpack.LsbFirst = GL_FALSE; ctx->Unpack.BufferObj = ctx->Array.NullBufferObj; ctx->NewState |= _NEW_PACKUNPACK; /* save PBO binding */ bufferSave = ctx->Unpack.BufferObj; ctx->Unpack.BufferObj = ctx->Array.NullBufferObj; _mesa_ConvolutionFilter2D(target, internalFormat, width, height, GL_RGBA, CHAN_TYPE, rgba); /* restore PBO binding */ ctx->Unpack.BufferObj = bufferSave; ctx->Unpack = packSave; /* restore pixel packing params */ ctx->NewState |= _NEW_PACKUNPACK; }
static void accum_load(GLcontext *ctx, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); struct gl_renderbuffer *rb = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer; const GLboolean directAccess = (rb->GetPointer(ctx, rb, 0, 0) != NULL); assert(rb); if (!ctx->ReadBuffer->_ColorReadBuffer) { /* no read buffer - OK */ return; } /* This is a change to go into optimized accum buffer mode */ if (value > 0.0 && value <= 1.0) { #if USE_OPTIMIZED_ACCUM swrast->_IntegerAccumMode = GL_TRUE; #else swrast->_IntegerAccumMode = GL_FALSE; #endif swrast->_IntegerAccumScaler = value; } else { swrast->_IntegerAccumMode = GL_FALSE; swrast->_IntegerAccumScaler = 0.0; } if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) { const GLfloat scale = value * ACCUM_SCALE16 / CHAN_MAXF; GLshort accumRow[4 * MAX_WIDTH]; GLchan rgba[MAX_WIDTH][4]; GLint i; for (i = 0; i < height; i++) { GLshort *acc; if (directAccess) { acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i); } else { rb->GetRow(ctx, rb, width, xpos, ypos + i, accumRow); acc = accumRow; } /* read colors from color buffer */ _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width, xpos, ypos + i, CHAN_TYPE, rgba); /* do load */ if (swrast->_IntegerAccumMode) { /* just copy values in */ GLint j; assert(swrast->_IntegerAccumScaler > 0.0); assert(swrast->_IntegerAccumScaler <= 1.0); for (j = 0; j < width; j++) { acc[j * 4 + 0] = rgba[j][RCOMP]; acc[j * 4 + 1] = rgba[j][GCOMP]; acc[j * 4 + 2] = rgba[j][BCOMP]; acc[j * 4 + 3] = rgba[j][ACOMP]; } } else { /* scaled integer (or float) accum buffer */ GLint j; for (j = 0; j < width; j++) { acc[j * 4 + 0] = (GLshort) ((GLfloat) rgba[j][RCOMP] * scale); acc[j * 4 + 1] = (GLshort) ((GLfloat) rgba[j][GCOMP] * scale); acc[j * 4 + 2] = (GLshort) ((GLfloat) rgba[j][BCOMP] * scale); acc[j * 4 + 3] = (GLshort) ((GLfloat) rgba[j][ACOMP] * scale); } } if (!directAccess) { rb->PutRow(ctx, rb, width, xpos, ypos + i, accumRow, NULL); } } } }
static void accum_accum(GLcontext *ctx, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); struct gl_renderbuffer *rb = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer; const GLboolean directAccess = (rb->GetPointer(ctx, rb, 0, 0) != NULL); assert(rb); if (!ctx->ReadBuffer->_ColorReadBuffer) { /* no read buffer - OK */ return; } /* May have to leave optimized accum buffer mode */ if (swrast->_IntegerAccumScaler == 0.0 && value > 0.0 && value <= 1.0) swrast->_IntegerAccumScaler = value; if (swrast->_IntegerAccumMode && value != swrast->_IntegerAccumScaler) rescale_accum(ctx); if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) { const GLfloat scale = value * ACCUM_SCALE16 / CHAN_MAXF; GLshort accumRow[4 * MAX_WIDTH]; GLchan rgba[MAX_WIDTH][4]; GLint i; for (i = 0; i < height; i++) { GLshort *acc; if (directAccess) { acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i); } else { rb->GetRow(ctx, rb, width, xpos, ypos + i, accumRow); acc = accumRow; } /* read colors from color buffer */ _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width, xpos, ypos + i, CHAN_TYPE, rgba); /* do accumulation */ if (swrast->_IntegerAccumMode) { /* simply add integer color values into accum buffer */ GLint j; for (j = 0; j < width; j++) { acc[j * 4 + 0] += rgba[j][RCOMP]; acc[j * 4 + 1] += rgba[j][GCOMP]; acc[j * 4 + 2] += rgba[j][BCOMP]; acc[j * 4 + 3] += rgba[j][ACOMP]; } } else { /* scaled integer (or float) accum buffer */ GLint j; for (j = 0; j < width; j++) { acc[j * 4 + 0] += (GLshort) ((GLfloat) rgba[j][RCOMP] * scale); acc[j * 4 + 1] += (GLshort) ((GLfloat) rgba[j][GCOMP] * scale); acc[j * 4 + 2] += (GLshort) ((GLfloat) rgba[j][BCOMP] * scale); acc[j * 4 + 3] += (GLshort) ((GLfloat) rgba[j][ACOMP] * scale); } } if (!directAccess) { rb->PutRow(ctx, rb, width, xpos, ypos + i, accumRow, NULL); } } } else { /* other types someday */ } }
/* * 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 with convolution. */ static void copy_conv_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 = NULL; GLboolean quick_draw; GLint row; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; const GLuint transferOps = ctx->_ImageTransferState; GLfloat *dest, *tmpImage, *convImage; struct sw_span span; 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); 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; } /* allocate space for GLfloat image */ tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!tmpImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); return; } convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!convImage) { _mesa_free(tmpImage); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); return; } /* read source image */ dest = tmpImage; for (row = 0; row < height; row++) { GLchan rgba[MAX_WIDTH][4]; /* Read GLchan and convert to GLfloat */ _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width, srcx, srcy + row, rgba); chan_span_to_float(width, (CONST GLchan (*)[4]) rgba, (GLfloat (*)[4]) dest); dest += 4 * width; } /* do the image transfer ops which preceed convolution */ for (row = 0; row < height; row++) { GLfloat (*rgba)[4] = (GLfloat (*)[4]) (tmpImage + row * width * 4); _mesa_apply_rgba_transfer_ops(ctx, transferOps & IMAGE_PRE_CONVOLUTION_BITS, width, rgba); } /* do convolution */ if (ctx->Pixel.Convolution2DEnabled) { _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage); } else { ASSERT(ctx->Pixel.Separable2DEnabled); _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage); } _mesa_free(tmpImage); /* do remaining post-convolution image transfer ops */ for (row = 0; row < height; row++) { GLfloat (*rgba)[4] = (GLfloat (*)[4]) (convImage + row * width * 4); _mesa_apply_rgba_transfer_ops(ctx, transferOps & IMAGE_POST_CONVOLUTION_BITS, width, rgba); } /* write the new image */ for (row = 0; row < height; row++) { const GLfloat *src = convImage + row * width * 4; GLint dy; /* convert floats back to chan */ float_span_to_chan(width, (const GLfloat (*)[4]) src, span.array->rgba); /* write row to framebuffer */ dy = desty + row; 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); } } } _mesa_free(convImage); }
/** * RGBA copypixels with convolution. */ static void copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLint row; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; const GLbitfield transferOps = ctx->_ImageTransferState; const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) || (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink); GLfloat *dest, *tmpImage, *convImage; SWspan span; 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); /* allocate space for GLfloat image */ tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!tmpImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); return; } convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!convImage) { _mesa_free(tmpImage); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); return; } /* read source image as float/RGBA */ dest = tmpImage; for (row = 0; row < height; row++) { _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width, srcx, srcy + row, GL_FLOAT, dest); dest += 4 * width; } /* do the image transfer ops which preceed convolution */ for (row = 0; row < height; row++) { GLfloat (*rgba)[4] = (GLfloat (*)[4]) (tmpImage + row * width * 4); _mesa_apply_rgba_transfer_ops(ctx, transferOps & IMAGE_PRE_CONVOLUTION_BITS, width, rgba); } /* do convolution */ if (ctx->Pixel.Convolution2DEnabled) { _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage); } else { ASSERT(ctx->Pixel.Separable2DEnabled); _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage); } _mesa_free(tmpImage); /* do remaining post-convolution image transfer ops */ for (row = 0; row < height; row++) { GLfloat (*rgba)[4] = (GLfloat (*)[4]) (convImage + row * width * 4); _mesa_apply_rgba_transfer_ops(ctx, transferOps & IMAGE_POST_CONVOLUTION_BITS, width, rgba); } if (!sink) { /* write the new image */ for (row = 0; row < height; row++) { const GLfloat *src = convImage + row * width * 4; GLvoid *rgba = (GLvoid *) span.array->attribs[FRAG_ATTRIB_COL0]; /* copy convolved colors into span array */ _mesa_memcpy(rgba, src, width * 4 * sizeof(GLfloat)); /* write span */ span.x = destx; span.y = desty + row; 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); } } /* restore this */ span.array->ChanType = CHAN_TYPE; } _mesa_free(convImage); }
/** * 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); }
/** * RGBA copypixels */ static void copy_rgba_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty) { 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->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); _swrast_span_default_attribs(ctx, &span); span.arrayMask = SPAN_RGBA; span.arrayAttribs = VARYING_BIT_COL0; /* we'll fill in COL0 attrib values */ if (overlapping) { tmpImage = 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, p ); p += width * 4; } p = tmpImage; } else { tmpImage = NULL; /* silence compiler warnings */ p = NULL; } ASSERT(width < SWRAST_MAX_WIDTH); for (row = 0; row < height; row++, sy += stepy, dy += stepy) { GLvoid *rgba = span.array->attribs[VARYING_SLOT_COL0]; /* Get row/span of source pixels */ if (overlapping) { /* get from buffered image */ 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, 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) free(tmpImage); }