-/* $Id: s_zoom.c,v 1.9 2002/01/27 18:32:03 brianp Exp $ */
-
/*
* Mesa 3-D graphics library
- * Version: 4.1
+ * Version: 7.1
*
- * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2008 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"),
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "glheader.h"
-#include "macros.h"
-#include "mem.h"
-#include "colormac.h"
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/colormac.h"
#include "s_context.h"
#include "s_span.h"
#include "s_zoom.h"
-#ifdef DEBUG
-
-#define SAVE_SPAN(span) struct sw_span tmp_span = (span);
-
-#define RESTORE_SPAN(span) \
-{ \
- GLint i; \
- for (i=tmp_span.start; i<tmp_span.end; i++) { \
- if (tmp_span.color.rgba[i][RCOMP] != \
- (span).color.rgba[i][RCOMP] || \
- tmp_span.color.rgba[i][GCOMP] != \
- (span).color.rgba[i][GCOMP] || \
- tmp_span.color.rgba[i][BCOMP] != \
- (span).color.rgba[i][BCOMP]) { \
- fprintf(stderr, "glZoom: Color-span changed in subfunction."); \
- } \
- if (tmp_span.zArray[i] != (span).zArray[i]) { \
- fprintf(stderr, "glZoom: Depth-span changed in subfunction."); \
- } \
- } \
- (span) = tmp_span; \
-}
-
-#else /* DEBUG not defined */
-
-#define SAVE_SPAN(span) GLint start = (span).start, end = (span).end;
-#define RESTORE_SPAN(span) (span).start = start, (span).end = end; \
- (span).writeAll = GL_TRUE;
-
-#endif /* DEBUG */
-
-/*
- * Write a span of pixels to the frame buffer while applying a pixel zoom.
- * This is only used by glDrawPixels and glCopyPixels.
- * Input: n - number of pixels in input row
- * x, y - destination of the span
- * z - depth values for the span
- * red, green, blue, alpha - array of colors
- * y0 - location of first row in the image we're drawing.
+/**
+ * Compute the bounds of the region resulting from zooming a pixel span.
+ * The resulting region will be entirely inside the window/scissor bounds
+ * so no additional clipping is needed.
+ * \param imageX, imageY position of the mage being drawn (gl WindowPos)
+ * \param spanX, spanY position of span being drawing
+ * \param width number of pixels in span
+ * \param x0, x1 returned X bounds of zoomed region [x0, x1)
+ * \param y0, y1 returned Y bounds of zoomed region [y0, y1)
+ * \return GL_TRUE if any zoomed pixels visible, GL_FALSE if totally clipped
*/
-void
-_mesa_write_zoomed_rgba_span( GLcontext *ctx,
- GLuint n, GLint x, GLint y, const GLdepth z[],
- const GLfloat *fog,
- CONST GLchan rgba[][4], GLint y0 )
+static GLboolean
+compute_zoomed_bounds(GLcontext *ctx, GLint imageX, GLint imageY,
+ GLint spanX, GLint spanY, GLint width,
+ GLint *x0, GLint *x1, GLint *y0, GLint *y1)
{
- GLint r0, r1, row;
- GLint i, j;
- struct sw_span zoomed;
- const GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
-
- SW_SPAN_RESET (zoomed);
- INIT_SPAN(zoomed);
-
- /* compute width of output row */
- zoomed.end = (GLint) ABSF( n * ctx->Pixel.ZoomX );
- if (zoomed.end == 0) {
- return;
+ const struct gl_framebuffer *fb = ctx->DrawBuffer;
+ GLint c0, c1, r0, r1;
+
+ ASSERT(spanX >= imageX);
+ ASSERT(spanY >= imageY);
+
+ /*
+ * Compute destination columns: [c0, c1)
+ */
+ c0 = imageX + (GLint) ((spanX - imageX) * ctx->Pixel.ZoomX);
+ c1 = imageX + (GLint) ((spanX + width - imageX) * ctx->Pixel.ZoomX);
+ if (c1 < c0) {
+ /* swap */
+ GLint tmp = c1;
+ c1 = c0;
+ c0 = tmp;
+ }
+ c0 = CLAMP(c0, fb->_Xmin, fb->_Xmax);
+ c1 = CLAMP(c1, fb->_Xmin, fb->_Xmax);
+ if (c0 == c1) {
+ return GL_FALSE; /* no width */
+ }
+
+ /*
+ * Compute destination rows: [r0, r1)
+ */
+ r0 = imageY + (GLint) ((spanY - imageY) * ctx->Pixel.ZoomY);
+ r1 = imageY + (GLint) ((spanY + 1 - imageY) * ctx->Pixel.ZoomY);
+ if (r1 < r0) {
+ /* swap */
+ GLint tmp = r1;
+ r1 = r0;
+ r0 = tmp;
}
- /*here ok or better latter? like it was before */
- else if (zoomed.end > maxwidth) {
- zoomed.end = maxwidth;
+ r0 = CLAMP(r0, fb->_Ymin, fb->_Ymax);
+ r1 = CLAMP(r1, fb->_Ymin, fb->_Ymax);
+ if (r0 == r1) {
+ return GL_FALSE; /* no height */
}
- if (ctx->Pixel.ZoomX<0.0) {
- /* adjust x coordinate for left/right mirroring */
- zoomed.x = x - zoomed.end;
- }
- else
- zoomed.x = x;
+ *x0 = c0;
+ *x1 = c1;
+ *y0 = r0;
+ *y1 = r1;
+ return GL_TRUE;
+}
- /* compute which rows to draw */
- row = y-y0;
- r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
- r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
- if (r0==r1) {
- return;
- }
- else if (r1<r0) {
- GLint rtmp = r1;
- r1 = r0;
- r0 = rtmp;
- }
- /* return early if r0...r1 is above or below window */
- if (r0<0 && r1<0) {
- /* below window */
- return;
- }
- if (r0>=ctx->DrawBuffer->Height && r1>=ctx->DrawBuffer->Height) {
- /* above window */
- return;
- }
+/**
+ * Convert a zoomed x image coordinate back to an unzoomed x coord.
+ * 'zx' is screen position of a pixel in the zoomed image, who's left edge
+ * is at 'imageX'.
+ * return corresponding x coord in the original, unzoomed image.
+ * This can use this for unzooming X or Y values.
+ */
+static INLINE GLint
+unzoom_x(GLfloat zoomX, GLint imageX, GLint zx)
+{
+ /*
+ zx = imageX + (x - imageX) * zoomX;
+ zx - imageX = (x - imageX) * zoomX;
+ (zx - imageX) / zoomX = x - imageX;
+ */
+ GLint x;
+ if (zoomX < 0.0)
+ zx++;
+ x = imageX + (GLint) ((zx - imageX) / zoomX);
+ return x;
+}
- /* check if left edge is outside window */
- if (zoomed.x < 0) {
- zoomed.start = -x;
- }
- /* make sure span isn't too long or short */
- /* if (m>maxwidth) {
- m = maxwidth;
- }*/
- if (zoomed.end <= zoomed.start) {
+/**
+ * Helper function called from _swrast_write_zoomed_rgba/rgb/
+ * index/depth_span().
+ */
+static void
+zoom_span( GLcontext *ctx, GLint imgX, GLint imgY, const SWspan *span,
+ const GLvoid *src, GLenum format )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ SWspan zoomed;
+ GLint x0, x1, y0, y1;
+ GLint zoomedWidth;
+
+ if (!compute_zoomed_bounds(ctx, imgX, imgY, span->x, span->y, span->end,
+ &x0, &x1, &y0, &y1)) {
+ return; /* totally clipped */
+ }
+
+ if (!swrast->ZoomedArrays) {
+ /* allocate on demand */
+ swrast->ZoomedArrays = (SWspanarrays *) CALLOC(sizeof(SWspanarrays));
+ if (!swrast->ZoomedArrays)
+ return;
+ }
+
+ zoomedWidth = x1 - x0;
+ ASSERT(zoomedWidth > 0);
+ ASSERT(zoomedWidth <= MAX_WIDTH);
+
+ /* no pixel arrays! must be horizontal spans. */
+ ASSERT((span->arrayMask & SPAN_XY) == 0);
+ ASSERT(span->primitive == GL_BITMAP);
+
+ INIT_SPAN(zoomed, GL_BITMAP);
+ zoomed.x = x0;
+ zoomed.end = zoomedWidth;
+ zoomed.array = swrast->ZoomedArrays;
+ zoomed.array->ChanType = span->array->ChanType;
+ if (zoomed.array->ChanType == GL_UNSIGNED_BYTE)
+ zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba8;
+ else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT)
+ zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba16;
+ else
+ zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->attribs[FRAG_ATTRIB_COL0];
+
+ COPY_4V(zoomed.attrStart[FRAG_ATTRIB_WPOS], span->attrStart[FRAG_ATTRIB_WPOS]);
+ COPY_4V(zoomed.attrStepX[FRAG_ATTRIB_WPOS], span->attrStepX[FRAG_ATTRIB_WPOS]);
+ COPY_4V(zoomed.attrStepY[FRAG_ATTRIB_WPOS], span->attrStepY[FRAG_ATTRIB_WPOS]);
+
+ zoomed.attrStart[FRAG_ATTRIB_FOGC][0] = span->attrStart[FRAG_ATTRIB_FOGC][0];
+ zoomed.attrStepX[FRAG_ATTRIB_FOGC][0] = span->attrStepX[FRAG_ATTRIB_FOGC][0];
+ zoomed.attrStepY[FRAG_ATTRIB_FOGC][0] = span->attrStepY[FRAG_ATTRIB_FOGC][0];
+
+ if (format == GL_RGBA || format == GL_RGB) {
+ /* copy Z info */
+ zoomed.z = span->z;
+ zoomed.zStep = span->zStep;
+ /* we'll generate an array of colorss */
+ zoomed.interpMask = span->interpMask & ~SPAN_RGBA;
+ zoomed.arrayMask |= SPAN_RGBA;
+ zoomed.arrayAttribs |= FRAG_BIT_COL0; /* we'll produce these values */
+ ASSERT(span->arrayMask & SPAN_RGBA);
+ }
+ else if (format == GL_DEPTH_COMPONENT) {
+ /* Copy color info */
+ zoomed.red = span->red;
+ zoomed.green = span->green;
+ zoomed.blue = span->blue;
+ zoomed.alpha = span->alpha;
+ zoomed.redStep = span->redStep;
+ zoomed.greenStep = span->greenStep;
+ zoomed.blueStep = span->blueStep;
+ zoomed.alphaStep = span->alphaStep;
+ /* we'll generate an array of depth values */
+ zoomed.interpMask = span->interpMask & ~SPAN_Z;
+ zoomed.arrayMask |= SPAN_Z;
+ ASSERT(span->arrayMask & SPAN_Z);
+ }
+ else {
+ _mesa_problem(ctx, "Bad format in zoom_span");
return;
}
- ASSERT( zoomed.end <= MAX_WIDTH );
-
/* zoom the span horizontally */
- if (ctx->Pixel.ZoomX==-1.0F) {
- SW_SPAN_SET_FLAG(zoomed.filledColor);
- SW_SPAN_SET_FLAG(zoomed.filledAlpha);
- SW_SPAN_SET_FLAG(zoomed.filledDepth);
- /* n==m */
- for (j=zoomed.start; j<zoomed.end; j++) {
- i = n - j - 1;
- COPY_CHAN4(zoomed.color.rgba[j], rgba[i]);
- zoomed.zArray[j] = z[i];
+ if (format == GL_RGBA) {
+ if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
+ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < (GLint) span->end);
+ COPY_4UBV(zoomed.array->rgba8[i], rgba[j]);
+ }
+ }
+ else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
+ const GLushort (*rgba)[4] = (const GLushort (*)[4]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < (GLint) span->end);
+ COPY_4V(zoomed.array->rgba16[i], rgba[j]);
+ }
}
- if (fog && ctx->Fog.Enabled) {
- for (j=zoomed.start; j<zoomed.end; j++) {
- i = n - j - 1;
- zoomed.fogArray[j] = fog[i];
- }
+ else {
+ const GLfloat (*rgba)[4] = (const GLfloat (*)[4]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < span->end);
+ COPY_4V(zoomed.array->attribs[FRAG_ATTRIB_COL0][i], rgba[j]);
+ }
}
}
- else {
- const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
- SW_SPAN_SET_FLAG(zoomed.filledColor);
- SW_SPAN_SET_FLAG(zoomed.filledAlpha);
- SW_SPAN_SET_FLAG(zoomed.filledDepth);
- for (j=zoomed.start; j<zoomed.end; j++) {
- i = (GLint) (j * xscale);
- if (i<0) i = n + i - 1;
- COPY_CHAN4(zoomed.color.rgba[j], rgba[i]);
- zoomed.zArray[j] = z[i];
+ else if (format == GL_RGB) {
+ if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
+ const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < (GLint) span->end);
+ zoomed.array->rgba8[i][0] = rgb[j][0];
+ zoomed.array->rgba8[i][1] = rgb[j][1];
+ zoomed.array->rgba8[i][2] = rgb[j][2];
+ zoomed.array->rgba8[i][3] = 0xff;
+ }
+ }
+ else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
+ const GLushort (*rgb)[3] = (const GLushort (*)[3]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < (GLint) span->end);
+ zoomed.array->rgba16[i][0] = rgb[j][0];
+ zoomed.array->rgba16[i][1] = rgb[j][1];
+ zoomed.array->rgba16[i][2] = rgb[j][2];
+ zoomed.array->rgba16[i][3] = 0xffff;
+ }
}
- if (fog && ctx->Fog.Enabled) {
- for (j=zoomed.start; j<zoomed.end; j++) {
- i = (GLint) (j * xscale);
- if (i<0) i = n + i - 1;
- zoomed.fogArray[j] = fog[i];
- }
+ else {
+ const GLfloat (*rgb)[3] = (const GLfloat (*)[3]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < span->end);
+ zoomed.array->attribs[FRAG_ATTRIB_COL0][i][0] = rgb[j][0];
+ zoomed.array->attribs[FRAG_ATTRIB_COL0][i][1] = rgb[j][1];
+ zoomed.array->attribs[FRAG_ATTRIB_COL0][i][2] = rgb[j][2];
+ zoomed.array->attribs[FRAG_ATTRIB_COL0][i][3] = 1.0F;
+ }
}
}
-
- zoomed.arrayMask |= SPAN_Z;
- if (fog)
- zoomed.arrayMask |= SPAN_FOG;
-
- /* write the span */
- for (zoomed.y = r0; zoomed.y < r1; zoomed.y++) {
- SAVE_SPAN(zoomed);
- ASSERT((zoomed.interpMask & SPAN_RGBA) == 0);
- _mesa_write_rgba_span(ctx, &zoomed, GL_BITMAP);
- RESTORE_SPAN(zoomed);
- /* problem here: "zoomed" can change inside
- "_mesa_write_rgba_span". Best solution: make copy "tmpspan"
- and give to function, but too slow */
+ else if (format == GL_DEPTH_COMPONENT) {
+ const GLuint *zValues = (const GLuint *) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < (GLint) span->end);
+ zoomed.array->z[i] = zValues[j];
+ }
+ /* Now, fall into the RGB path below */
+ format = GL_RGBA;
+ }
+
+ /* write the span in rows [r0, r1) */
+ if (format == GL_RGBA || format == GL_RGB) {
+ /* Writing the span may modify the colors, so make a backup now if we're
+ * going to call _swrast_write_zoomed_span() more than once.
+ * Also, clipping may change the span end value, so store it as well.
+ */
+ const GLint end = zoomed.end; /* save */
+ GLuint rgbaSave[MAX_WIDTH][4];
+ const GLint pixelSize =
+ (zoomed.array->ChanType == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) :
+ ((zoomed.array->ChanType == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort)
+ : 4 * sizeof(GLfloat));
+ if (y1 - y0 > 1) {
+ memcpy(rgbaSave, zoomed.array->rgba, zoomed.end * pixelSize);
+ }
+ for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) {
+ _swrast_write_rgba_span(ctx, &zoomed);
+ zoomed.end = end; /* restore */
+ if (y1 - y0 > 1) {
+ /* restore the colors */
+ memcpy(zoomed.array->rgba, rgbaSave, zoomed.end * pixelSize);
+ }
+ }
}
}
-
void
-_mesa_write_zoomed_rgb_span( GLcontext *ctx,
- GLuint n, GLint x, GLint y, const GLdepth z[],
- const GLfloat *fog,
- CONST GLchan rgb[][3], GLint y0 )
+_swrast_write_zoomed_rgba_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ const SWspan *span, const GLvoid *rgba)
{
- GLint m;
- GLint r0, r1, row, r;
- GLint i, j, skipcol;
- GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
- struct sw_span zoomed;
-
- INIT_SPAN(zoomed);
- zoomed.arrayMask |= SPAN_RGBA;
-
- if (fog && ctx->Fog.Enabled)
- zoomed.arrayMask |= SPAN_FOG;
-
-
- /* compute width of output row */
- m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
- if (m==0) {
- return;
- }
- if (ctx->Pixel.ZoomX<0.0) {
- /* adjust x coordinate for left/right mirroring */
- x = x - m;
- }
-
- /* compute which rows to draw */
- row = y-y0;
- r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
- r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
- if (r0==r1) {
- return;
- }
- else if (r1<r0) {
- GLint rtmp = r1;
- r1 = r0;
- r0 = rtmp;
- }
+ zoom_span(ctx, imgX, imgY, span, rgba, GL_RGBA);
+}
- /* return early if r0...r1 is above or below window */
- if (r0<0 && r1<0) {
- /* below window */
- return;
- }
- if (r0>=ctx->DrawBuffer->Height && r1>=ctx->DrawBuffer->Height) {
- /* above window */
- return;
- }
- /* check if left edge is outside window */
- skipcol = 0;
- if (x<0) {
- skipcol = -x;
- m += x;
- }
- /* make sure span isn't too long or short */
- if (m>maxwidth) {
- m = maxwidth;
- }
- else if (m<=0) {
- return;
- }
+void
+_swrast_write_zoomed_rgb_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ const SWspan *span, const GLvoid *rgb)
+{
+ zoom_span(ctx, imgX, imgY, span, rgb, GL_RGB);
+}
- ASSERT( m <= MAX_WIDTH );
- /* zoom the span horizontally */
- if (ctx->Pixel.ZoomX==-1.0F) {
- /* n==m */
- for (j=0;j<m;j++) {
- i = n - (j+skipcol) - 1;
- zoomed.color.rgba[j][0] = rgb[i][0];
- zoomed.color.rgba[j][1] = rgb[i][1];
- zoomed.color.rgba[j][2] = rgb[i][2];
- zoomed.color.rgba[j][3] = CHAN_MAX;
- zoomed.zArray[j] = z[i];
- }
- if (zoomed.arrayMask & SPAN_FOG) {
- for (j=0;j<m;j++) {
- i = n - (j+skipcol) - 1;
- zoomed.fogArray[j] = fog[i];
- }
- }
- }
- else {
- GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
- for (j=0;j<m;j++) {
- i = (GLint) ((j+skipcol) * xscale);
- if (i<0) i = n + i - 1;
- zoomed.color.rgba[j][0] = rgb[i][0];
- zoomed.color.rgba[j][1] = rgb[i][1];
- zoomed.color.rgba[j][2] = rgb[i][2];
- zoomed.color.rgba[j][3] = CHAN_MAX;
- zoomed.zArray[j] = z[i];
- }
- if (zoomed.arrayMask & SPAN_FOG) {
- for (j=0;j<m;j++) {
- i = (GLint) ((j+skipcol) * xscale);
- if (i<0) i = n + i - 1;
- zoomed.fogArray[j] = fog[i];
- }
- }
- }
-
- /* write the span */
- for (r=r0; r<r1; r++) {
- zoomed.x = x + skipcol;
- zoomed.y = r;
- zoomed.end = m;
- ASSERT((zoomed.interpMask & SPAN_RGBA) == 0);
- _mesa_write_rgba_span( ctx, &zoomed, GL_BITMAP );
- }
+void
+_swrast_write_zoomed_depth_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ const SWspan *span)
+{
+ zoom_span(ctx, imgX, imgY, span,
+ (const GLvoid *) span->array->z, GL_DEPTH_COMPONENT);
}
-
-/*
- * As above, but write CI pixels.
+/**
+ * Zoom/write stencil values.
+ * No per-fragment operations are applied.
*/
void
-_mesa_write_zoomed_index_span( GLcontext *ctx,
- GLuint n, GLint x, GLint y, const GLdepth z[],
- const GLfloat *fog,
- const GLuint indexes[], GLint y0 )
+_swrast_write_zoomed_stencil_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ GLint width, GLint spanX, GLint spanY,
+ const GLstencil stencil[])
{
- GLint m;
- GLint r0, r1, row, r;
- GLint i, j, skipcol;
- GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
- struct sw_span zoomed;
-
- SW_SPAN_RESET(zoomed);
- INIT_SPAN(zoomed);
- zoomed.arrayMask |= SPAN_INDEX;
-
- /* compute width of output row */
- m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
- if (m==0) {
- return;
- }
- if (ctx->Pixel.ZoomX<0.0) {
- /* adjust x coordinate for left/right mirroring */
- x = x - m;
- }
+ GLstencil zoomedVals[MAX_WIDTH];
+ GLint x0, x1, y0, y1, y;
+ GLint i, zoomedWidth;
- /* compute which rows to draw */
- row = y-y0;
- r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
- r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
- if (r0==r1) {
- return;
- }
- else if (r1<r0) {
- GLint rtmp = r1;
- r1 = r0;
- r0 = rtmp;
+ if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
+ &x0, &x1, &y0, &y1)) {
+ return; /* totally clipped */
}
- /* return early if r0...r1 is above or below window */
- if (r0<0 && r1<0) {
- /* below window */
- return;
- }
- if (r0>=ctx->DrawBuffer->Height && r1>=ctx->DrawBuffer->Height) {
- /* above window */
- return;
- }
-
- /* check if left edge is outside window */
- skipcol = 0;
- if (x<0) {
- skipcol = -x;
- m += x;
- }
- /* make sure span isn't too long or short */
- if (m>maxwidth) {
- m = maxwidth;
- }
- else if (m<=0) {
- return;
- }
-
- ASSERT( m <= MAX_WIDTH );
+ zoomedWidth = x1 - x0;
+ ASSERT(zoomedWidth > 0);
+ ASSERT(zoomedWidth <= MAX_WIDTH);
/* zoom the span horizontally */
- if (ctx->Pixel.ZoomX==-1.0F) {
- /* n==m */
- for (j=0;j<m;j++) {
- i = n - (j+skipcol) - 1;
- zoomed.color.index[j] = indexes[i];
- zoomed.zArray[j] = z[i];
- }
- if (fog && ctx->Fog.Enabled) {
- for (j=0;j<m;j++) {
- i = n - (j+skipcol) - 1;
- zoomed.fogArray[j] = fog[i];
- }
- zoomed.arrayMask |= SPAN_FOG;
- }
- }
- else {
- GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
- for (j=0;j<m;j++) {
- i = (GLint) ((j+skipcol) * xscale);
- if (i<0) i = n + i - 1;
- zoomed.color.index[j] = indexes[i];
- zoomed.zArray[j] = z[i];
- }
- if (fog && ctx->Fog.Enabled) {
- for (j=0;j<m;j++) {
- i = (GLint) ((j+skipcol) * xscale);
- if (i<0) i = n + i - 1;
- zoomed.fogArray[j] = fog[i];
- }
- zoomed.arrayMask |= SPAN_FOG;
- }
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
+ ASSERT(j >= 0);
+ ASSERT(j < width);
+ zoomedVals[i] = stencil[j];
}
- zoomed.arrayMask |= SPAN_Z;
-
- /* write the span */
- for (r=r0; r<r1; r++) {
- SAVE_SPAN(zoomed);
- ASSERT((zoomed.interpMask & SPAN_INDEX) == 0);
- zoomed.x = x + skipcol;
- zoomed.y = r;
- zoomed.end = m;
- _mesa_write_index_span(ctx, &zoomed, GL_BITMAP);
- RESTORE_SPAN(zoomed);
+ /* write the zoomed spans */
+ for (y = y0; y < y1; y++) {
+ _swrast_write_stencil_span(ctx, zoomedWidth, x0, y, zoomedVals);
}
}
-
-/*
- * As above, but write stencil values.
+/**
+ * Zoom/write z values (16 or 32-bit).
+ * No per-fragment operations are applied.
*/
void
-_mesa_write_zoomed_stencil_span( GLcontext *ctx,
- GLuint n, GLint x, GLint y,
- const GLstencil stencil[], GLint y0 )
+_swrast_write_zoomed_z_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ GLint width, GLint spanX, GLint spanY,
+ const GLvoid *z)
{
- GLint m;
- GLint r0, r1, row, r;
- GLint i, j, skipcol;
- GLstencil zstencil[MAX_WIDTH]; /* zoomed stencil values */
- GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH );
-
- /* compute width of output row */
- m = (GLint) ABSF( n * ctx->Pixel.ZoomX );
- if (m==0) {
- return;
- }
- if (ctx->Pixel.ZoomX<0.0) {
- /* adjust x coordinate for left/right mirroring */
- x = x - m;
- }
-
- /* compute which rows to draw */
- row = y-y0;
- r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY);
- r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY);
- if (r0==r1) {
- return;
- }
- else if (r1<r0) {
- GLint rtmp = r1;
- r1 = r0;
- r0 = rtmp;
- }
-
- /* return early if r0...r1 is above or below window */
- if (r0<0 && r1<0) {
- /* below window */
- return;
- }
- if (r0>=ctx->DrawBuffer->Height && r1>=ctx->DrawBuffer->Height) {
- /* above window */
- return;
- }
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer;
+ GLushort zoomedVals16[MAX_WIDTH];
+ GLuint zoomedVals32[MAX_WIDTH];
+ GLint x0, x1, y0, y1, y;
+ GLint i, zoomedWidth;
- /* check if left edge is outside window */
- skipcol = 0;
- if (x<0) {
- skipcol = -x;
- m += x;
- }
- /* make sure span isn't too long or short */
- if (m>maxwidth) {
- m = maxwidth;
- }
- else if (m<=0) {
- return;
+ if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
+ &x0, &x1, &y0, &y1)) {
+ return; /* totally clipped */
}
- ASSERT( m <= MAX_WIDTH );
+ zoomedWidth = x1 - x0;
+ ASSERT(zoomedWidth > 0);
+ ASSERT(zoomedWidth <= MAX_WIDTH);
/* zoom the span horizontally */
- if (ctx->Pixel.ZoomX==-1.0F) {
- /* n==m */
- for (j=0;j<m;j++) {
- i = n - (j+skipcol) - 1;
- zstencil[j] = stencil[i];
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
+ ASSERT(j >= 0);
+ ASSERT(j < width);
+ zoomedVals16[i] = ((GLushort *) z)[j];
}
+ z = zoomedVals16;
}
else {
- GLfloat xscale = 1.0F / ctx->Pixel.ZoomX;
- for (j=0;j<m;j++) {
- i = (GLint) ((j+skipcol) * xscale);
- if (i<0) i = n + i - 1;
- zstencil[j] = stencil[i];
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
+ ASSERT(j >= 0);
+ ASSERT(j < width);
+ zoomedVals32[i] = ((GLuint *) z)[j];
}
+ z = zoomedVals32;
}
- /* write the span */
- for (r=r0; r<r1; r++) {
- _mesa_write_stencil_span( ctx, m, x+skipcol, r, zstencil );
+ /* write the zoomed spans */
+ for (y = y0; y < y1; y++) {
+ rb->PutRow(ctx, rb, zoomedWidth, x0, y, z, NULL);
}
}