/* * 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); }