/* * To draw a wide line we can simply redraw the span N times, side by side. */ static void draw_wide_line( GLcontext *ctx, SWspan *span, GLboolean xMajor ) { const GLint width = (GLint) CLAMP(ctx->Line.Width, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth); GLint start; ASSERT(span->end < MAX_WIDTH); if (width & 1) start = width / 2; else start = width / 2 - 1; if (xMajor) { GLint *y = span->array->y; GLuint i; GLint w; for (w = 0; w < width; w++) { if (w == 0) { for (i = 0; i < span->end; i++) y[i] -= start; } else { for (i = 0; i < span->end; i++) y[i]++; } if (ctx->Visual.rgbMode) _swrast_write_rgba_span(ctx, span); else _swrast_write_index_span(ctx, span); } } else { GLint *x = span->array->x; GLuint i; GLint w; for (w = 0; w < width; w++) { if (w == 0) { for (i = 0; i < span->end; i++) x[i] -= start; } else { for (i = 0; i < span->end; i++) x[i]++; } if (ctx->Visual.rgbMode) _swrast_write_rgba_span(ctx, span); else _swrast_write_index_span(ctx, span); } } }
/* * Draw color index image. */ static void draw_index_pixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels ) { const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; GLint row, skipPixels; struct sw_span span; INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_INDEX); if (ctx->Depth.Test) _swrast_span_default_z(ctx, &span); if (ctx->Fog.Enabled) _swrast_span_default_fog(ctx, &span); /* * General solution */ skipPixels = 0; while (skipPixels < width) { const GLint spanX = x + (zoom ? 0 : skipPixels); GLint spanY = y; const GLint spanEnd = (width - skipPixels > MAX_WIDTH) ? MAX_WIDTH : (width - skipPixels); ASSERT(spanEnd <= MAX_WIDTH); for (row = 0; row < height; row++, spanY++) { const GLvoid *source = _mesa_image_address2d(unpack, pixels, width, height, GL_COLOR_INDEX, type, row, skipPixels); _mesa_unpack_index_span(ctx, spanEnd, GL_UNSIGNED_INT, span.array->index, type, source, unpack, ctx->_ImageTransferState); /* These may get changed during writing/clipping */ span.x = spanX; span.y = spanY; span.end = spanEnd; if (zoom) _swrast_write_zoomed_index_span(ctx, &span, y, skipPixels); else _swrast_write_index_span(ctx, &span); } skipPixels += spanEnd; } }
void _swrast_flush( GLcontext *ctx ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); /* flush any pending fragments from rendering points */ if (swrast->PointSpan.end > 0) { if (ctx->Visual.rgbMode) { _swrast_write_rgba_span(ctx, &(swrast->PointSpan)); } else { _swrast_write_index_span(ctx, &(swrast->PointSpan)); } swrast->PointSpan.end = 0; } }
/* * Draw color index image. */ static void draw_index_pixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels ) { const GLint imgX = x, imgY = y; const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; GLint row, skipPixels; SWspan span; INIT_SPAN(span, GL_BITMAP); span.arrayMask = SPAN_INDEX; _swrast_span_default_attribs(ctx, &span); /* * General solution */ skipPixels = 0; while (skipPixels < width) { const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); ASSERT(spanWidth <= MAX_WIDTH); for (row = 0; row < height; row++) { const GLvoid *source = _mesa_image_address2d(unpack, pixels, width, height, GL_COLOR_INDEX, type, row, skipPixels); _mesa_unpack_index_span(ctx, spanWidth, GL_UNSIGNED_INT, span.array->index, type, source, unpack, ctx->_ImageTransferState); /* These may get changed during writing/clipping */ span.x = x + skipPixels; span.y = y + row; span.end = spanWidth; if (zoom) _swrast_write_zoomed_index_span(ctx, imgX, imgY, &span); else _swrast_write_index_span(ctx, &span); } skipPixels += spanWidth; } }
/** * Render a bitmap. * Called via ctx->Driver.Bitmap() * All parameter error checking will have been done before this is called. */ void _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLint row, col; GLuint count = 0; SWspan span; ASSERT(ctx->RenderMode == GL_RENDER); bitmap = _mesa_map_bitmap_pbo(ctx, unpack, bitmap); if (!bitmap) return; RENDER_START(swrast,ctx); if (SWRAST_CONTEXT(ctx)->NewState) _swrast_validate_derived( ctx ); INIT_SPAN(span, GL_BITMAP); span.end = width; span.arrayMask = SPAN_XY; _swrast_span_default_attribs(ctx, &span); for (row = 0; row < height; row++) { const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack, bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0); if (unpack->LsbFirst) { /* Lsb first */ GLubyte mask = 1U << (unpack->SkipPixels & 0x7); for (col = 0; col < width; col++) { if (*src & mask) { span.array->x[count] = px + col; span.array->y[count] = py + row; count++; } if (mask == 128U) { src++; mask = 1U; } else { mask = mask << 1; } } /* get ready for next row */ if (mask != 1) src++; } else { /* Msb first */ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); for (col = 0; col < width; col++) { if (*src & mask) { span.array->x[count] = px + col; span.array->y[count] = py + row; count++; } if (mask == 1U) { src++; mask = 128U; } else { mask = mask >> 1; } } /* get ready for next row */ if (mask != 128) src++; } if (count + width >= MAX_WIDTH || row + 1 == height) { /* flush the span */ span.end = count; if (ctx->Visual.rgbMode) _swrast_write_rgba_span(ctx, &span); else _swrast_write_index_span(ctx, &span); span.end = 0; count = 0; } } RENDER_FINISH(swrast,ctx); _mesa_unmap_bitmap_pbo(ctx, unpack); }
/* * XXX this is another way to implement Bitmap. Use horizontal runs of * fragments, initializing the mask array to indicate which fragments to * draw or skip. */ void _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLint row, col; SWspan span; ASSERT(ctx->RenderMode == GL_RENDER); ASSERT(bitmap); RENDER_START(swrast,ctx); if (SWRAST_CONTEXT(ctx)->NewState) _swrast_validate_derived( ctx ); INIT_SPAN(span, GL_BITMAP); span.end = width; span.arrayMask = SPAN_MASK; _swrast_span_default_attribs(ctx, &span); /*span.arrayMask |= SPAN_MASK;*/ /* we'll init span.mask[] */ span.x = px; span.y = py; /*span.end = width;*/ for (row=0; row<height; row++, span.y++) { const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack, bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0); if (unpack->LsbFirst) { /* Lsb first */ GLubyte mask = 1U << (unpack->SkipPixels & 0x7); for (col=0; col<width; col++) { span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE; if (mask == 128U) { src++; mask = 1U; } else { mask = mask << 1; } } if (ctx->Visual.rgbMode) _swrast_write_rgba_span(ctx, &span); else _swrast_write_index_span(ctx, &span); /* get ready for next row */ if (mask != 1) src++; } else { /* Msb first */ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); for (col=0; col<width; col++) { span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE; if (mask == 1U) { src++; mask = 128U; } else { mask = mask >> 1; } } if (ctx->Visual.rgbMode) _swrast_write_rgba_span(ctx, &span); else _swrast_write_index_span(ctx, &span); /* get ready for next row */ if (mask != 128) src++; } } RENDER_FINISH(swrast,ctx); }
/** * Draw size=1, single-pixel point */ static void pixel_point(GLcontext *ctx, const SWvertex *vert) { SWcontext *swrast = SWRAST_CONTEXT(ctx); const GLboolean ciMode = !ctx->Visual.rgbMode; /* * Note that unlike the other functions, we put single-pixel points * into a special span array in order to render as many points as * possible with a single _swrast_write_rgba_span() call. */ SWspan *span = &(swrast->PointSpan); GLuint count; CULL_INVALID(vert); /* Span init */ span->interpMask = 0; span->arrayMask = SPAN_XY | SPAN_Z; if (ciMode) span->arrayMask |= SPAN_INDEX; else span->arrayMask |= SPAN_RGBA; /*span->arrayMask |= SPAN_LAMBDA;*/ span->arrayAttribs = swrast->_ActiveAttribMask; /* we'll produce these vals */ /* need these for fragment programs */ span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; /* check if we need to flush */ if (span->end >= MAX_WIDTH || (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT)) || span->facing != swrast->PointLineFacing) { if (span->end > 0) { if (ciMode) _swrast_write_index_span(ctx, span); else _swrast_write_rgba_span(ctx, span); span->end = 0; } } count = span->end; span->facing = swrast->PointLineFacing; /* fragment attributes */ if (ciMode) { span->array->index[count] = (GLuint) vert->attrib[FRAG_ATTRIB_CI][0]; } else { span->array->rgba[count][RCOMP] = vert->color[0]; span->array->rgba[count][GCOMP] = vert->color[1]; span->array->rgba[count][BCOMP] = vert->color[2]; span->array->rgba[count][ACOMP] = vert->color[3]; } ATTRIB_LOOP_BEGIN COPY_4V(span->array->attribs[attr][count], vert->attrib[attr]); ATTRIB_LOOP_END /* fragment position */ span->array->x[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][0]; span->array->y[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][1]; span->array->z[count] = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); span->end = count + 1; ASSERT(span->end <= MAX_WIDTH); }
/* * TODO: Optimize!!!! */ static void copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); struct gl_framebuffer *fb = ctx->ReadBuffer; struct gl_renderbuffer *readRb = fb->_DepthBuffer; const GLfloat depthMax = fb->_DepthMaxF; GLfloat *p, *tmpImage; 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; if (!readRb) { /* no readbuffer - OK */ return; } INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_Z); /* Determine if copy should be 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; } _swrast_span_default_color(ctx, &span); if (swrast->_FogEnabled) _swrast_span_default_fog(ctx, &span); if (overlapping) { GLint ssy = sy; tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat)); if (!tmpImage) { _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } p = tmpImage; for (j = 0; j < height; j++, ssy += stepy) { _swrast_read_depth_span_float(ctx, readRb, width, srcx, ssy, p); p += width; } p = tmpImage; } else { tmpImage = NULL; /* silence compiler warning */ p = NULL; } for (j = 0; j < height; j++, sy += stepy, dy += stepy) { GLfloat depth[MAX_WIDTH]; /* get depth values */ if (overlapping) { _mesa_memcpy(depth, p, width * sizeof(GLfloat)); p += width; } else { _swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth); } /* apply scale and bias */ for (i = 0; i < width; i++) { GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; span.array->z[i] = (GLuint) (CLAMP(d, 0.0F, 1.0F) * depthMax); } /* write depth values */ span.x = destx; span.y = dy; span.end = width; if (fb->Visual.rgbMode) { if (zoom) _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, (const GLchan (*)[4]) span.array->rgba); else _swrast_write_rgba_span(ctx, &span); } else { if (zoom) _swrast_write_zoomed_index_span(ctx, destx, desty, &span); else _swrast_write_index_span(ctx, &span); } } if (overlapping) _mesa_free(tmpImage); }
static void copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLuint *tmpImage,*p; GLint sy, dy, stepy; GLint j; 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; if (!ctx->ReadBuffer->_ColorReadBuffer) { /* no readbuffer - OK */ return; } INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_INDEX); /* Determine if copy should be 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 (overlapping) { GLint ssy = sy; tmpImage = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint)); if (!tmpImage) { _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } /* read the image */ p = tmpImage; for (j = 0; j < height; j++, ssy += stepy) { _swrast_read_index_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, width, srcx, ssy, p ); p += width; } p = tmpImage; } else { tmpImage = NULL; /* silence compiler warning */ p = NULL; } for (j = 0; j < height; j++, sy += stepy, dy += stepy) { /* Get color indexes */ if (overlapping) { _mesa_memcpy(span.array->index, p, width * sizeof(GLuint)); p += width; } else { _swrast_read_index_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, width, srcx, sy, span.array->index ); } /* Apply shift, offset, look-up table */ if (shift_or_offset) { _mesa_shift_and_offset_ci( ctx, width, span.array->index ); } if (ctx->Pixel.MapColorFlag) { _mesa_map_ci( ctx, width, span.array->index ); } /* write color indexes */ span.x = destx; span.y = dy; span.end = width; if (zoom) _swrast_write_zoomed_index_span(ctx, destx, desty, &span); else _swrast_write_index_span(ctx, &span); } if (overlapping) _mesa_free(tmpImage); }
/* * Helper function called from _swrast_write_zoomed_rgba/rgb/index_span(). */ static void zoom_span( GLcontext *ctx, const struct sw_span *span, const GLvoid *src, GLint y0, GLenum format, GLint skipPixels ) { GLint r0, r1, row; GLint c0, c1, skipCol; GLint i, j; const GLuint maxWidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH ); struct sw_span zoomed; struct span_arrays zoomed_arrays; /* this is big! */ /* no pixel arrays! must be horizontal spans. */ ASSERT((span->arrayMask & SPAN_XY) == 0); ASSERT(span->primitive == GL_BITMAP); INIT_SPAN(zoomed, GL_BITMAP, 0, 0, 0); zoomed.array = &zoomed_arrays; /* copy fog interp info */ zoomed.fog = span->fog; zoomed.fogStep = span->fogStep; /* XXX copy texcoord info? */ 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; } else if (format == GL_COLOR_INDEX) { /* copy Z info */ zoomed.z = span->z; zoomed.zStep = span->zStep; /* we'll generate an array of color indexes */ zoomed.interpMask = span->interpMask & ~SPAN_INDEX; zoomed.arrayMask |= SPAN_INDEX; } else { assert(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; } /* * Compute which columns to draw: [c0, c1) */ c0 = (GLint) (span->x + skipPixels * ctx->Pixel.ZoomX); c1 = (GLint) (span->x + (skipPixels + span->end) * ctx->Pixel.ZoomX); if (c0 == c1) { return; } else if (c1 < c0) { /* swap */ GLint ctmp = c1; c1 = c0; c0 = ctmp; } if (c0 < 0) { zoomed.x = 0; zoomed.start = 0; zoomed.end = c1; skipCol = -c0; } else { zoomed.x = c0; zoomed.start = 0; zoomed.end = c1 - c0; skipCol = 0; } if (zoomed.end > maxWidth) zoomed.end = maxWidth; /* * Compute which rows to draw: [r0, r1) */ row = span->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) { /* swap */ GLint rtmp = r1; r1 = r0; r0 = rtmp; } ASSERT(r0 < r1); ASSERT(c0 < c1); /* * Trivial clip rejection testing. */ if (r1 < 0) /* below window */ return; if (r0 >= (GLint) ctx->DrawBuffer->Height) /* above window */ return; if (c1 < 0) /* left of window */ return; if (c0 >= (GLint) ctx->DrawBuffer->Width) /* right of window */ return; /* zoom the span horizontally */ if (format == GL_RGBA) { const GLchan (*rgba)[4] = (const GLchan (*)[4]) src; if (ctx->Pixel.ZoomX == -1.0F) { /* common case */ for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = span->end - (j + skipCol) - 1; COPY_CHAN4(zoomed.array->rgba[j], rgba[i]); } } else { /* general solution */ const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = (GLint) ((j + skipCol) * xscale); if (ctx->Pixel.ZoomX < 0.0) { ASSERT(i <= 0); i = span->end + i - 1; } ASSERT(i >= 0); ASSERT(i < (GLint) span->end); COPY_CHAN4(zoomed.array->rgba[j], rgba[i]); } } } else if (format == GL_RGB) { const GLchan (*rgb)[3] = (const GLchan (*)[3]) src; if (ctx->Pixel.ZoomX == -1.0F) { /* common case */ for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = span->end - (j + skipCol) - 1; zoomed.array->rgba[j][0] = rgb[i][0]; zoomed.array->rgba[j][1] = rgb[i][1]; zoomed.array->rgba[j][2] = rgb[i][2]; zoomed.array->rgba[j][3] = CHAN_MAX; } } else { /* general solution */ const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = (GLint) ((j + skipCol) * xscale); if (ctx->Pixel.ZoomX < 0.0) { ASSERT(i <= 0); i = span->end + i - 1; } ASSERT(i >= 0); ASSERT(i < (GLint) span->end); zoomed.array->rgba[j][0] = rgb[i][0]; zoomed.array->rgba[j][1] = rgb[i][1]; zoomed.array->rgba[j][2] = rgb[i][2]; zoomed.array->rgba[j][3] = CHAN_MAX; } } } else if (format == GL_COLOR_INDEX) { const GLuint *indexes = (const GLuint *) src; if (ctx->Pixel.ZoomX == -1.0F) { /* common case */ for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = span->end - (j + skipCol) - 1; zoomed.array->index[j] = indexes[i]; } } else { /* general solution */ const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = (GLint) ((j + skipCol) * xscale); if (ctx->Pixel.ZoomX < 0.0) { ASSERT(i <= 0); i = span->end + i - 1; } ASSERT(i >= 0); ASSERT(i < (GLint) span->end); zoomed.array->index[j] = indexes[i]; } } } else { const GLdepth *zValues = (const GLuint *) src; assert(format == GL_DEPTH_COMPONENT); if (ctx->Pixel.ZoomX == -1.0F) { /* common case */ for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = span->end - (j + skipCol) - 1; zoomed.array->z[j] = zValues[i]; } } else { /* general solution */ const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = (GLint) ((j + skipCol) * xscale); if (ctx->Pixel.ZoomX < 0.0) { ASSERT(i <= 0); i = span->end + i - 1; } ASSERT(i >= 0); ASSERT(i < (GLint) span->end); zoomed.array->z[j] = zValues[i]; } } /* Now, fall into either the RGB or COLOR_INDEX path below */ if (ctx->Visual.rgbMode) format = GL_RGBA; else format = GL_COLOR_INDEX; } /* 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. */ GLchan rgbaSave[MAX_WIDTH][4]; const GLint end = zoomed.end; /* save */ if (r1 - r0 > 1) { MEMCPY(rgbaSave, zoomed.array->rgba, zoomed.end * 4 * sizeof(GLchan)); } for (zoomed.y = r0; zoomed.y < r1; zoomed.y++) { _swrast_write_rgba_span(ctx, &zoomed); zoomed.end = end; /* restore */ if (r1 - r0 > 1) { /* restore the colors */ MEMCPY(zoomed.array->rgba, rgbaSave, zoomed.end*4 * sizeof(GLchan)); } } } else if (format == GL_COLOR_INDEX) { GLuint indexSave[MAX_WIDTH]; const GLint end = zoomed.end; /* save */ if (r1 - r0 > 1) { MEMCPY(indexSave, zoomed.array->index, zoomed.end * sizeof(GLuint)); } for (zoomed.y = r0; zoomed.y < r1; zoomed.y++) { _swrast_write_index_span(ctx, &zoomed); zoomed.end = end; /* restore */ if (r1 - r0 > 1) { /* restore the colors */ MEMCPY(zoomed.array->index, indexSave, zoomed.end * sizeof(GLuint)); } } } }
/* * TODO: Optimize!!!! */ static void copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty ) { struct gl_framebuffer *fb = ctx->ReadBuffer; struct gl_renderbuffer *readRb = fb->_DepthBuffer; GLfloat *p, *tmpImage; GLint sy, dy, stepy; GLint j; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; GLint overlapping; SWspan span; if (!readRb) { /* no readbuffer - OK */ return; } INIT_SPAN(span, GL_BITMAP); _swrast_span_default_attribs(ctx, &span); span.arrayMask = SPAN_Z; 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 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; } if (overlapping) { GLint ssy = sy; tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat)); if (!tmpImage) { _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } p = tmpImage; for (j = 0; j < height; j++, ssy += stepy) { _swrast_read_depth_span_float(ctx, readRb, width, srcx, ssy, p); p += width; } p = tmpImage; } else { tmpImage = NULL; /* silence compiler warning */ p = NULL; } for (j = 0; j < height; j++, sy += stepy, dy += stepy) { GLfloat depth[MAX_WIDTH]; /* get depth values */ if (overlapping) { _mesa_memcpy(depth, p, width * sizeof(GLfloat)); p += width; } else { _swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth); } /* apply scale and bias */ scale_and_bias_z(ctx, width, depth, span.array->z); /* write depth values */ span.x = destx; span.y = dy; span.end = width; if (fb->Visual.rgbMode) { if (zoom) _swrast_write_zoomed_depth_span(ctx, destx, desty, &span); else _swrast_write_rgba_span(ctx, &span); } else { if (zoom) _swrast_write_zoomed_depth_span(ctx, destx, desty, &span); else _swrast_write_index_span(ctx, &span); } } if (overlapping) _mesa_free(tmpImage); }
static void copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy, GLint width, GLint height, GLint destx, GLint desty ) { GLuint *tmpImage,*p; GLint sy, dy, stepy; GLint j; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; GLint overlapping; SWspan span; if (!ctx->ReadBuffer->_ColorReadBuffer) { /* no readbuffer - OK */ return; } INIT_SPAN(span, GL_BITMAP); _swrast_span_default_attribs(ctx, &span); span.arrayMask = SPAN_INDEX; 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 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; } if (overlapping) { GLint ssy = sy; tmpImage = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint)); if (!tmpImage) { _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" ); return; } /* read the image */ p = tmpImage; for (j = 0; j < height; j++, ssy += stepy) { _swrast_read_index_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, width, srcx, ssy, p ); p += width; } p = tmpImage; } else { tmpImage = NULL; /* silence compiler warning */ p = NULL; } for (j = 0; j < height; j++, sy += stepy, dy += stepy) { /* Get color indexes */ if (overlapping) { _mesa_memcpy(span.array->index, p, width * sizeof(GLuint)); p += width; } else { _swrast_read_index_span( ctx, ctx->ReadBuffer->_ColorReadBuffer, width, srcx, sy, span.array->index ); } if (ctx->_ImageTransferState) _mesa_apply_ci_transfer_ops(ctx, ctx->_ImageTransferState, width, span.array->index); /* write color indexes */ span.x = destx; span.y = dy; span.end = width; if (zoom) _swrast_write_zoomed_index_span(ctx, destx, desty, &span); else _swrast_write_index_span(ctx, &span); } if (overlapping) _mesa_free(tmpImage); }