X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fswrast%2Fs_copypix.c;h=0692adfbff96916d199f323a36c7619e1803a3b1;hb=a60c89e8c8348a348dcdd770a033f4976ea93206;hp=401955d00ae0ea2b5c59d3268d10a2db701af7f1;hpb=b6bcae5698df88f7730d40004ce7ce0462e97a20;p=mesa.git diff --git a/src/mesa/swrast/s_copypix.c b/src/mesa/swrast/s_copypix.c index 401955d00ae..0692adfbff9 100644 --- a/src/mesa/swrast/s_copypix.c +++ b/src/mesa/swrast/s_copypix.c @@ -1,21 +1,19 @@ -/* $Id: s_copypix.c,v 1.10 2001/01/23 23:39:37 brianp Exp $ */ - /* * Mesa 3-D graphics library - * Version: 3.5 - * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. - * + * Version: 5.1 + * + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -26,18 +24,15 @@ #include "glheader.h" -#include "colormac.h" #include "context.h" #include "convolve.h" -#include "feedback.h" +#include "histogram.h" #include "macros.h" -#include "mem.h" -#include "mmath.h" +#include "imports.h" #include "pixel.h" #include "s_context.h" #include "s_depth.h" -#include "s_histogram.h" #include "s_pixeltex.h" #include "s_span.h" #include "s_stencil.h" @@ -47,23 +42,46 @@ /* - * Determine if there's overlap in an image copy + * Determine if there's overlap in an image copy. + * This test also compensates for the fact that copies are done from + * bottom to top and overlaps can sometimes be handled correctly + * without making a temporary image copy. */ static GLboolean -regions_overlap(int srcx, int srcy, int dstx, int dsty, int width, int height, - float zoomX, float zoomY) +regions_overlap(GLint srcx, GLint srcy, + GLint dstx, GLint dsty, + GLint width, GLint height, + GLfloat zoomX, GLfloat zoomY) { - if ((srcx > dstx + (width * zoomX) + 1) || (srcx + width + 1 < dstx)) { - return GL_FALSE; - } - else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) { - return GL_FALSE; - } - else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) { - return GL_FALSE; + if (zoomX == 1.0 && zoomY == 1.0) { + /* no zoom */ + if (srcx >= dstx + width || (srcx + width <= dstx)) { + return GL_FALSE; + } + else if (srcy < dsty) { /* this is OK */ + return GL_FALSE; + } + else if (srcy > dsty + height) { + return GL_FALSE; + } + else { + return GL_TRUE; + } } else { - return GL_TRUE; + /* add one pixel of slop when zooming, just to be safe */ + if ((srcx > dstx + (width * zoomX) + 1) || (srcx + width + 1 < dstx)) { + return GL_FALSE; + } + else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) { + return GL_FALSE; + } + else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) { + return GL_FALSE; + } + else { + return GL_TRUE; + } } } @@ -76,29 +94,27 @@ static void copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty) { - GLdepth zspan[MAX_WIDTH]; + SWcontext *swrast = SWRAST_CONTEXT(ctx); GLboolean quick_draw; GLint row; GLboolean changeBuffer; - GLchan *saveReadAlpha; 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 (ctx->Fog.Enabled) + _swrast_span_default_fog(ctx, &span); - if (ctx->Depth.Test || ctx->Fog.Enabled) { - /* fill in array of z values */ - GLdepth z = (GLdepth) - (ctx->Current.RasterPos[2] * ctx->DepthMax); - GLint i; - for (i = 0; i < width; i++) { - zspan[i] = z; - } - } if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom && destx >= 0 - && destx + width <= ctx->DrawBuffer->Width) { + && destx + width <= (GLint) ctx->DrawBuffer->Width) { quick_draw = GL_TRUE; } else { @@ -106,7 +122,6 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } /* If read and draw buffer are different we must do buffer switching */ - saveReadAlpha = ctx->ReadBuffer->Alpha; changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer || ctx->DrawBuffer != ctx->ReadBuffer; @@ -114,29 +129,21 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, /* allocate space for GLfloat image */ tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); if (!tmpImage) { - gl_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); return; } convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); if (!convImage) { FREE(tmpImage); - gl_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); return; } dest = tmpImage; if (changeBuffer) { - (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - if (ctx->Pixel.DriverReadBuffer == GL_FRONT_LEFT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontLeftAlpha; - else if (ctx->Pixel.DriverReadBuffer == GL_BACK_LEFT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackLeftAlpha; - else if (ctx->Pixel.DriverReadBuffer == GL_FRONT_RIGHT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontRightAlpha; - else - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackRightAlpha; + /* choose the read buffer */ + _swrast_use_read_buffer(ctx); } /* read source image */ @@ -144,7 +151,7 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, for (row = 0; row < height; row++) { GLchan rgba[MAX_WIDTH][4]; GLint i; - gl_read_rgba_span(ctx, ctx->ReadBuffer, width, srcx, srcy + row, rgba); + _swrast_read_rgba_span(ctx, ctx->ReadBuffer, width, srcx, srcy + row, rgba); /* convert GLchan to GLfloat */ for (i = 0; i < width; i++) { *dest++ = (GLfloat) rgba[i][RCOMP] * (1.0F / CHAN_MAXF); @@ -154,16 +161,14 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } } - /* read from the draw buffer again (in case of blending) */ if (changeBuffer) { - (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); - ctx->ReadBuffer->Alpha = saveReadAlpha; + /* restore default src/dst buffer */ + _swrast_use_draw_buffer(ctx); } /* do image transfer ops up until convolution */ for (row = 0; row < height; row++) { - GLfloat (*rgba)[4] = (GLfloat (*)[4]) tmpImage + row * width * 4; + GLfloat (*rgba)[4] = (GLfloat (*)[4]) (tmpImage + row * width * 4); /* scale & bias */ if (transferOps & IMAGE_SCALE_BIAS_BIT) { @@ -195,7 +200,7 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, /* do remaining image transfer ops */ for (row = 0; row < height; row++) { - GLfloat (*rgba)[4] = (GLfloat (*)[4]) convImage + row * width * 4; + GLfloat (*rgba)[4] = (GLfloat (*)[4]) (convImage + row * width * 4); /* GL_POST_CONVOLUTION_COLOR_TABLE lookup */ if (transferOps & IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT) { @@ -221,7 +226,6 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, for (row = 0; row < height; row++) { const GLfloat *src = convImage + row * width * 4; - GLchan rgba[MAX_WIDTH][4]; GLint i, dy; /* clamp to [0,1] and convert float back to chan */ @@ -230,41 +234,37 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint g = (GLint) (src[i * 4 + GCOMP] * CHAN_MAXF); GLint b = (GLint) (src[i * 4 + BCOMP] * CHAN_MAXF); GLint a = (GLint) (src[i * 4 + ACOMP] * CHAN_MAXF); - rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX); - rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX); - rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX); - rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); + span.array->rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX); + span.array->rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX); + span.array->rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX); + span.array->rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); } - if (ctx->Texture._ReallyEnabled && ctx->Pixel.PixelTextureEnabled) { - GLfloat s[MAX_WIDTH], t[MAX_WIDTH], r[MAX_WIDTH], q[MAX_WIDTH]; - GLchan primary_rgba[MAX_WIDTH][4]; - GLuint unit; - /* XXX not sure how multitexture is supposed to work here */ - - MEMCPY(primary_rgba, rgba, 4 * width * sizeof(GLchan)); - - for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { - _mesa_pixeltexgen(ctx, width, (const GLchan (*)[4]) rgba, - s, t, r, q); - _swrast_texture_fragments(ctx, unit, width, s, t, r, NULL, - primary_rgba, rgba); - } + if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) { + span.end = width; + _swrast_pixel_texture(ctx, &span); } /* write row to framebuffer */ dy = desty + row; - if (quick_draw && dy >= 0 && dy < ctx->DrawBuffer->Height) { - (*ctx->Driver.WriteRGBASpan)( ctx, width, destx, dy, - (const GLchan (*)[4])rgba, NULL ); + if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) { + (*swrast->Driver.WriteRGBASpan)( ctx, width, destx, dy, + (const GLchan (*)[4])span.array->rgba, NULL ); } else if (zoom) { - gl_write_zoomed_rgba_span( ctx, width, destx, dy, zspan, 0, - (const GLchan (*)[4])rgba, desty); + span.x = destx; + span.y = dy; + span.end = width; + _swrast_write_zoomed_rgba_span(ctx, &span, + (CONST GLchan (*)[4])span.array->rgba, + desty, 0); } else { - gl_write_rgba_span( ctx, width, destx, dy, zspan, 0, rgba, GL_BITMAP ); + span.x = destx; + span.y = dy; + span.end = width; + _swrast_write_rgba_span(ctx, &span); } } @@ -279,17 +279,17 @@ static void copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty) { - GLdepth zspan[MAX_WIDTH]; - GLchan rgba[MAX_WIDTH][4]; + SWcontext *swrast = SWRAST_CONTEXT(ctx); GLchan *tmpImage,*p; GLboolean quick_draw; - GLint sy, dy, stepy; - GLint i, j; + GLint sy, dy, stepy, j; GLboolean changeBuffer; - GLchan *saveReadAlpha; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; GLint overlapping; const GLuint transferOps = ctx->_ImageTransferState; + struct sw_span span; + + 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); @@ -310,21 +310,23 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, stepy = 1; } - overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, - ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); - - if (ctx->Depth.Test || ctx->Fog.Enabled) { - /* fill in array of z values */ - GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMax); - for (i=0;iDrawBuffer == 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 (ctx->Fog.Enabled) + _swrast_span_default_fog(ctx, &span); + if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom && destx >= 0 - && destx + width <= ctx->DrawBuffer->Width) { + && destx + width <= (GLint) ctx->DrawBuffer->Width) { quick_draw = GL_TRUE; } else { @@ -332,39 +334,32 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } /* If read and draw buffer are different we must do buffer switching */ - saveReadAlpha = ctx->ReadBuffer->Alpha; changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer || ctx->DrawBuffer != ctx->ReadBuffer; - (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - if (overlapping) { GLint ssy = sy; tmpImage = (GLchan *) MALLOC(width * height * sizeof(GLchan) * 4); if (!tmpImage) { - gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } + /* setup source */ + if (changeBuffer) + _swrast_use_read_buffer(ctx); + /* read the source image */ p = tmpImage; - if (changeBuffer) { - (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - if (ctx->Pixel.DriverReadBuffer == GL_FRONT_LEFT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontLeftAlpha; - else if (ctx->Pixel.DriverReadBuffer == GL_BACK_LEFT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackLeftAlpha; - else if (ctx->Pixel.DriverReadBuffer == GL_FRONT_RIGHT) - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontRightAlpha; - else - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackRightAlpha; - } for (j = 0; j < height; j++, ssy += stepy) { - gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, ssy, + _swrast_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, ssy, (GLchan (*)[4]) p ); - p += (width * sizeof(GLchan) * 4); + p += width * 4; } p = tmpImage; + /* restore dest */ + if (changeBuffer) { + _swrast_use_draw_buffer(ctx); + changeBuffer = GL_FALSE; + } } else { tmpImage = NULL; /* silence compiler warnings */ @@ -375,47 +370,33 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, /* Get source pixels */ if (overlapping) { /* get from buffered image */ - MEMCPY(rgba, p, width * sizeof(GLchan) * 4); - p += (width * sizeof(GLchan) * 4); + ASSERT(width < MAX_WIDTH); + MEMCPY(span.array->rgba, p, width * sizeof(GLchan) * 4); + p += width * 4; } else { /* get from framebuffer */ - if (changeBuffer) { - (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - if (ctx->Pixel.DriverReadBuffer == GL_FRONT_LEFT) { - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontLeftAlpha; - } - else if (ctx->Pixel.DriverReadBuffer == GL_BACK_LEFT) { - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackLeftAlpha; - } - else if (ctx->Pixel.DriverReadBuffer == GL_FRONT_RIGHT) { - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->FrontRightAlpha; - } - else { - ctx->ReadBuffer->Alpha = ctx->ReadBuffer->BackRightAlpha; - } - } - gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, sy, rgba ); - } - - if (changeBuffer) { - /* read from the draw buffer again (in case of blending) */ - (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); - ctx->ReadBuffer->Alpha = saveReadAlpha; + if (changeBuffer) + _swrast_use_read_buffer(ctx); + ASSERT(width < MAX_WIDTH); + _swrast_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, sy, + span.array->rgba ); + if (changeBuffer) + _swrast_use_draw_buffer(ctx); } if (transferOps) { const GLfloat scale = (1.0F / CHAN_MAXF); - GLfloat rgbaFloat[MAX_WIDTH][4]; - GLuint k; + GLint k; + DEFMARRAY(GLfloat, rgbaFloat, MAX_WIDTH, 4); /* mac 32k limitation */ + CHECKARRAY(rgbaFloat, return); + /* convert chan to float */ for (k = 0; k < width; k++) { - rgbaFloat[k][RCOMP] = (GLfloat) rgba[k][RCOMP] * scale; - rgbaFloat[k][GCOMP] = (GLfloat) rgba[k][GCOMP] * scale; - rgbaFloat[k][BCOMP] = (GLfloat) rgba[k][BCOMP] * scale; - rgbaFloat[k][ACOMP] = (GLfloat) rgba[k][ACOMP] * scale; + rgbaFloat[k][RCOMP] = (GLfloat) span.array->rgba[k][RCOMP] * scale; + rgbaFloat[k][GCOMP] = (GLfloat) span.array->rgba[k][GCOMP] * scale; + rgbaFloat[k][BCOMP] = (GLfloat) span.array->rgba[k][BCOMP] * scale; + rgbaFloat[k][ACOMP] = (GLfloat) span.array->rgba[k][ACOMP] * scale; } /* scale & bias */ if (transferOps & IMAGE_SCALE_BIAS_BIT) { @@ -435,7 +416,8 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } /* convolution */ if (transferOps & IMAGE_CONVOLUTION_BIT) { - /* XXX to do */ + _mesa_problem(ctx, "Convolution should not be enabled in copy_rgba_pixels()"); + return; } /* GL_POST_CONVOLUTION_RED/GREEN/BLUE/ALPHA_SCALE/BIAS */ if (transferOps & IMAGE_POST_CONVOLUTION_SCALE_BIAS) { @@ -475,63 +457,60 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint g = (GLint) (rgbaFloat[k][GCOMP] * CHAN_MAXF); GLint b = (GLint) (rgbaFloat[k][BCOMP] * CHAN_MAXF); GLint a = (GLint) (rgbaFloat[k][ACOMP] * CHAN_MAXF); - rgba[k][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX); - rgba[k][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX); - rgba[k][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX); - rgba[k][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); + span.array->rgba[k][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX); + span.array->rgba[k][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX); + span.array->rgba[k][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX); + span.array->rgba[k][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); } + UNDEFARRAY(rgbaFloat); /* mac 32k limitation */ } - if (ctx->Texture._ReallyEnabled && ctx->Pixel.PixelTextureEnabled) { - GLfloat s[MAX_WIDTH], t[MAX_WIDTH], r[MAX_WIDTH], q[MAX_WIDTH]; - GLchan primary_rgba[MAX_WIDTH][4]; - GLuint unit; - /* XXX not sure how multitexture is supposed to work here */ - - MEMCPY(primary_rgba, rgba, 4 * width * sizeof(GLchan)); - - for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { - _mesa_pixeltexgen(ctx, width, (const GLchan (*)[4]) rgba, - s, t, r, q); - _swrast_texture_fragments(ctx, unit, width, s, t, r, NULL, - primary_rgba, rgba); - } + if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) { + span.end = width; + _swrast_pixel_texture(ctx, &span); } - if (quick_draw && dy >= 0 && dy < ctx->DrawBuffer->Height) { - (*ctx->Driver.WriteRGBASpan)( ctx, width, destx, dy, - (const GLchan (*)[4])rgba, NULL ); + /* Write color span */ + if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) { + (*swrast->Driver.WriteRGBASpan)( ctx, width, destx, dy, + (const GLchan (*)[4])span.array->rgba, NULL ); } else if (zoom) { - gl_write_zoomed_rgba_span( ctx, width, destx, dy, zspan, 0, - (const GLchan (*)[4])rgba, desty); + span.x = destx; + span.y = dy; + span.end = width; + _swrast_write_zoomed_rgba_span(ctx, &span, + (CONST GLchan (*)[4]) span.array->rgba, + desty, 0); } else { - gl_write_rgba_span( ctx, width, destx, dy, zspan, 0, rgba, GL_BITMAP ); + span.x = destx; + span.y = dy; + span.end = width; + _swrast_write_rgba_span(ctx, &span); } } - /* Restore pixel source to be the draw buffer (for blending, etc) */ - (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); - if (overlapping) FREE(tmpImage); } -static void copy_ci_pixels( GLcontext *ctx, - GLint srcx, GLint srcy, GLint width, GLint height, - GLint destx, GLint desty ) +static void +copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy, + GLint width, GLint height, + GLint destx, GLint desty ) { - GLdepth zspan[MAX_WIDTH]; GLuint *tmpImage,*p; GLint sy, dy, stepy; - GLint i, j; + GLint j; GLboolean changeBuffer; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset; GLint overlapping; + struct sw_span span; + + INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_INDEX); /* Determine if copy should be bottom-to-top or top-to-bottom */ if (srcyPixel.ZoomX, ctx->Pixel.ZoomY); - - if (ctx->Depth.Test || ctx->Fog.Enabled) { - /* fill in array of z values */ - GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMax); - for (i=0;iDrawBuffer == 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 (ctx->Fog.Enabled) + _swrast_span_default_fog(ctx, &span); /* If read and draw buffer are different we must do buffer switching */ changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer || ctx->DrawBuffer != ctx->ReadBuffer; - (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - if (overlapping) { GLint ssy = sy; tmpImage = (GLuint *) MALLOC(width * height * sizeof(GLuint)); if (!tmpImage) { - gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } + /* setup source */ + if (changeBuffer) + _swrast_use_read_buffer(ctx); + /* read the image */ p = tmpImage; - if (changeBuffer) { - (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - } for (j = 0; j < height; j++, ssy += stepy) { - gl_read_index_span( ctx, ctx->ReadBuffer, width, srcx, ssy, p ); + _swrast_read_index_span( ctx, ctx->ReadBuffer, width, srcx, ssy, p ); p += width; } p = tmpImage; + /* restore to draw buffer */ + if (changeBuffer) { + _swrast_use_draw_buffer(ctx); + changeBuffer = GL_FALSE; + } } else { tmpImage = NULL; /* silence compiler warning */ @@ -589,44 +572,38 @@ static void copy_ci_pixels( GLcontext *ctx, } for (j = 0; j < height; j++, sy += stepy, dy += stepy) { - GLuint indexes[MAX_WIDTH]; + /* Get color indexes */ if (overlapping) { - MEMCPY(indexes, p, width * sizeof(GLuint)); + MEMCPY(span.array->index, p, width * sizeof(GLuint)); p += width; } else { - if (changeBuffer) { - (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, - ctx->Pixel.DriverReadBuffer ); - } - gl_read_index_span( ctx, ctx->ReadBuffer, width, srcx, sy, indexes ); - } - - if (changeBuffer) { - /* set read buffer back to draw buffer (in case of logicops) */ - (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); + if (changeBuffer) + _swrast_use_read_buffer(ctx); + _swrast_read_index_span( ctx, ctx->ReadBuffer, width, srcx, sy, + span.array->index ); + if (changeBuffer) + _swrast_use_draw_buffer(ctx); } + /* Apply shift, offset, look-up table */ if (shift_or_offset) { - _mesa_shift_and_offset_ci( ctx, width, indexes ); + _mesa_shift_and_offset_ci( ctx, width, span.array->index ); } if (ctx->Pixel.MapColorFlag) { - _mesa_map_ci( ctx, width, indexes ); + _mesa_map_ci( ctx, width, span.array->index ); } - if (zoom) { - gl_write_zoomed_index_span( ctx, width, destx, dy, zspan, 0, indexes, desty ); - } - else { - gl_write_index_span(ctx, width, destx, dy, zspan, 0, indexes, GL_BITMAP); - } + /* write color indexes */ + span.x = destx; + span.y = dy; + span.end = width; + if (zoom) + _swrast_write_zoomed_index_span(ctx, &span, desty, 0); + else + _swrast_write_index_span(ctx, &span); } - /* Restore pixel source to be the draw buffer (for blending, etc) */ - (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, - ctx->Color.DriverDrawBuffer ); - if (overlapping) FREE(tmpImage); } @@ -636,22 +613,22 @@ static void copy_ci_pixels( GLcontext *ctx, /* * TODO: Optimize!!!! */ -static void copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy, - GLint width, GLint height, - GLint destx, GLint desty ) +static void +copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy, + GLint width, GLint height, + GLint destx, GLint desty ) { - GLfloat depth[MAX_WIDTH]; - GLdepth zspan[MAX_WIDTH]; GLfloat *p, *tmpImage; - GLuint indexes[MAX_WIDTH]; - GLchan rgba[MAX_WIDTH][4]; GLint sy, dy, stepy; GLint i, j; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; GLint overlapping; + struct sw_span span; + + INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_Z); if (!ctx->Visual.depthBits) { - gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" ); + _mesa_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" ); return; } @@ -669,33 +646,28 @@ static void copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy, stepy = 1; } - overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, - ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); - - /* setup colors or indexes */ - if (ctx->Visual.rgbMode) { - GLuint *rgba32 = (GLuint *) rgba; - GLuint color = *(GLuint*)( ctx->Current.Color ); - for (i = 0; i < width; i++) { - rgba32[i] = color; - } + if (ctx->DrawBuffer == ctx->ReadBuffer) { + overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, + ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); } else { - for (i = 0; i < width; i++) { - indexes[i] = ctx->Current.Index; - } + overlapping = GL_FALSE; } + _swrast_span_default_color(ctx, &span); + if (ctx->Fog.Enabled) + _swrast_span_default_fog(ctx, &span); + if (overlapping) { GLint ssy = sy; tmpImage = (GLfloat *) MALLOC(width * height * sizeof(GLfloat)); if (!tmpImage) { - gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } p = tmpImage; for (j = 0; j < height; j++, ssy += stepy) { - _mesa_read_depth_span_float(ctx, width, srcx, ssy, p); + _swrast_read_depth_span_float(ctx, width, srcx, ssy, p); p += width; } p = tmpImage; @@ -706,50 +678,52 @@ static void copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy, } for (j = 0; j < height; j++, sy += stepy, dy += stepy) { + GLfloat depth[MAX_WIDTH]; + + /* get depth values */ if (overlapping) { MEMCPY(depth, p, width * sizeof(GLfloat)); p += width; } else { - _mesa_read_depth_span_float(ctx, width, srcx, sy, depth); + _swrast_read_depth_span_float(ctx, width, srcx, sy, depth); } + /* apply scale and bias */ for (i = 0; i < width; i++) { GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; - zspan[i] = (GLdepth) (CLAMP(d, 0.0F, 1.0F) * ctx->DepthMax); + span.array->z[i] = (GLdepth) (CLAMP(d, 0.0F, 1.0F) * ctx->DepthMax); } + /* write depth values */ + span.x = destx; + span.y = dy; + span.end = width; if (ctx->Visual.rgbMode) { - if (zoom) { - gl_write_zoomed_rgba_span( ctx, width, destx, dy, zspan, 0, - (const GLchan (*)[4])rgba, desty ); - } - else { - gl_write_rgba_span( ctx, width, destx, dy, zspan, 0, - rgba, GL_BITMAP); - } + if (zoom) + _swrast_write_zoomed_rgba_span( ctx, &span, + (const GLchan (*)[4])span.array->rgba, desty, 0 ); + else + _swrast_write_rgba_span(ctx, &span); } else { - if (zoom) { - gl_write_zoomed_index_span( ctx, width, destx, dy, - zspan, 0, indexes, desty ); - } - else { - gl_write_index_span( ctx, width, destx, dy, - zspan, 0, indexes, GL_BITMAP ); - } + if (zoom) + _swrast_write_zoomed_index_span( ctx, &span, desty, 0 ); + else + _swrast_write_index_span(ctx, &span); } } - if (overlapping) - FREE(tmpImage); + if (overlapping) + FREE(tmpImage); } -static void copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy, - GLint width, GLint height, - GLint destx, GLint desty ) +static void +copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy, + GLint width, GLint height, + GLint destx, GLint desty ) { GLint sy, dy, stepy; GLint j; @@ -759,7 +733,7 @@ static void copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy, GLint overlapping; if (!ctx->Visual.stencilBits) { - gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" ); + _mesa_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" ); return; } @@ -777,19 +751,24 @@ static void copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy, stepy = 1; } - overlapping = regions_overlap(srcx, srcy, destx, desty, width, height, - ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); + 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 (overlapping) { GLint ssy = sy; tmpImage = (GLstencil *) MALLOC(width * height * sizeof(GLstencil)); if (!tmpImage) { - gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); + _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } p = tmpImage; for (j = 0; j < height; j++, ssy += stepy) { - _mesa_read_stencil_span( ctx, width, srcx, ssy, p ); + _swrast_read_stencil_span( ctx, width, srcx, ssy, p ); p += width; } p = tmpImage; @@ -802,14 +781,16 @@ static void copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy, for (j = 0; j < height; j++, sy += stepy, dy += stepy) { GLstencil stencil[MAX_WIDTH]; + /* Get stencil values */ if (overlapping) { MEMCPY(stencil, p, width * sizeof(GLstencil)); p += width; } else { - _mesa_read_stencil_span( ctx, width, srcx, sy, stencil ); + _swrast_read_stencil_span( ctx, width, srcx, sy, stencil ); } + /* Apply shift, offset, look-up table */ if (shift_or_offset) { _mesa_shift_and_offset_stencil( ctx, width, stencil ); } @@ -817,11 +798,13 @@ static void copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy, _mesa_map_stencil( ctx, width, stencil ); } + /* Write stencil values */ if (zoom) { - gl_write_zoomed_stencil_span( ctx, width, destx, dy, stencil, desty ); + _swrast_write_zoomed_stencil_span( ctx, width, destx, dy, + stencil, desty, 0 ); } else { - _mesa_write_stencil_span( ctx, width, destx, dy, stencil ); + _swrast_write_stencil_span( ctx, width, destx, dy, stencil ); } } @@ -831,14 +814,16 @@ static void copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy, - void _swrast_CopyPixels( GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint destx, GLint desty, GLenum type ) { - if (SWRAST_CONTEXT(ctx)->NewState) + SWcontext *swrast = SWRAST_CONTEXT(ctx); + RENDER_START(swrast,ctx); + + if (swrast->NewState) _swrast_validate_derived( ctx ); if (type == GL_COLOR && ctx->Visual.rgbMode) { @@ -854,6 +839,8 @@ _swrast_CopyPixels( GLcontext *ctx, copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty ); } else { - gl_error( ctx, GL_INVALID_ENUM, "glCopyPixels" ); + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyPixels" ); } + + RENDER_FINISH(swrast,ctx); }