From 55fa6a2fdbc9108f2d435b70cefb58e77bba903a Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 11 Oct 2006 22:07:01 +0000 Subject: rewrite/simplify the fast_draw_pixels() function --- src/mesa/swrast/s_drawpix.c | 570 +++++++++++++++++--------------------------- 1 file changed, 221 insertions(+), 349 deletions(-) diff --git a/src/mesa/swrast/s_drawpix.c b/src/mesa/swrast/s_drawpix.c index ac09401bba..02db69a2a4 100644 --- a/src/mesa/swrast/s_drawpix.c +++ b/src/mesa/swrast/s_drawpix.c @@ -40,7 +40,7 @@ #include "s_zoom.h" -/* +/** * Try to do a fast and simple RGB(a) glDrawPixels. * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead */ @@ -48,24 +48,29 @@ static GLboolean fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - const struct gl_pixelstore_attrib *unpack, + const struct gl_pixelstore_attrib *userUnpack, const GLvoid *pixels) { const GLint imgX = x, imgY = y; struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0]; + const GLenum rbType = rb->DataType; SWcontext *swrast = SWRAST_CONTEXT(ctx); SWspan span; - - INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); - - if (swrast->_RasterMask & MULTI_DRAW_BIT) - return GL_FALSE; - - if (ctx->_ImageTransferState) { - /* don't handle any pixel transfer options here */ + GLboolean simpleZoom; + GLint yStep; /* +1 or -1 */ + struct gl_pixelstore_attrib unpack; + GLint destX, destY, drawWidth, drawHeight; /* post clipping */ + + if ((swrast->_RasterMask & ~CLIP_BIT) || + ctx->Texture._EnabledCoordUnits || + userUnpack->Alignment != 1 || + userUnpack->SwapBytes || + ctx->_ImageTransferState) { + /* can't handle any of those conditions */ return GL_FALSE; } + INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); if (ctx->Depth.Test) _swrast_span_default_z(ctx, &span); if (swrast->_FogEnabled) @@ -73,373 +78,235 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, if (ctx->Texture._EnabledCoordUnits) _swrast_span_default_texcoords(ctx, &span); - if ((swrast->_RasterMask & ~CLIP_BIT) == 0 - && ctx->Texture._EnabledCoordUnits == 0 - && unpack->Alignment == 1 /* XXX may not really need this */ - && !unpack->SwapBytes - && !unpack->LsbFirst) { - - /* XXX there's a lot of clipping code here that should be replaced - * by a call to _mesa_clip_drawpixels(). - */ - GLint destX = x; - GLint destY = y; - GLint drawWidth = width; /* actual width drawn */ - GLint drawHeight = height; /* actual height drawn */ - GLint skipPixels = unpack->SkipPixels; - GLint skipRows = unpack->SkipRows; - GLint rowLength; - - if (unpack->RowLength > 0) - rowLength = unpack->RowLength; - else - rowLength = width; + /* copy input params since clipping may change them */ + unpack = *userUnpack; + destX = x; + destY = y; + drawWidth = width; + drawHeight = height; + + /* check for simple zooming and clipping */ + if (ctx->Pixel.ZoomX == 1.0F && + (ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F)) { + if (!_mesa_clip_drawpixels(ctx, &destX, &destY, + &drawWidth, &drawHeight, &unpack)) { + /* image was completely clipped: no-op, all done */ + return GL_TRUE; + } + simpleZoom = GL_TRUE; + yStep = (GLint) ctx->Pixel.ZoomY; + ASSERT(yStep == 1 || yStep == -1); + } + else { + /* non-simple zooming */ + simpleZoom = GL_FALSE; + if (unpack.RowLength == 0) + unpack.RowLength = width; + } - /* If we're not using pixel zoom then do all clipping calculations - * now. Otherwise, we'll let the _swrast_write_zoomed_*_span() functions - * handle the clipping. - */ - if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { - /* horizontal clipping */ - if (destX < ctx->DrawBuffer->_Xmin) { - skipPixels += (ctx->DrawBuffer->_Xmin - destX); - drawWidth -= (ctx->DrawBuffer->_Xmin - destX); - destX = ctx->DrawBuffer->_Xmin; - } - if (destX + drawWidth > ctx->DrawBuffer->_Xmax) - drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax); - if (drawWidth <= 0) - return GL_TRUE; + /* + * Ready to draw! + * The window region at (destX, destY) of size (drawWidth, drawHeight) + * will be written to. + * We'll take pixel data from buffer pointed to by "pixels" but we'll + * skip "unpack.SkipRows" rows and skip "unpack.SkipPixels" pixels/row. + */ - /* vertical clipping */ - if (destY < ctx->DrawBuffer->_Ymin) { - skipRows += (ctx->DrawBuffer->_Ymin - destY); - drawHeight -= (ctx->DrawBuffer->_Ymin - destY); - destY = ctx->DrawBuffer->_Ymin; + if (format == GL_RGBA && type == CHAN_TYPE && rbType == CHAN_TYPE) { + const GLchan *src = (const GLchan *) pixels + + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels) * 4; + if (simpleZoom) { + GLint row; + for (row = 0; row < drawHeight; row++) { + rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL); + src += unpack.RowLength * 4; + destY += yStep; } - if (destY + drawHeight > ctx->DrawBuffer->_Ymax) - drawHeight -= (destY + drawHeight - ctx->DrawBuffer->_Ymax); - if (drawHeight <= 0) - return GL_TRUE; } - else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { - /* upside-down image */ - /* horizontal clipping */ - if (destX < ctx->DrawBuffer->_Xmin) { - skipPixels += (ctx->DrawBuffer->_Xmin - destX); - drawWidth -= (ctx->DrawBuffer->_Xmin - destX); - destX = ctx->DrawBuffer->_Xmin; + else { + /* with zooming */ + GLint row; + for (row = 0; row < drawHeight; row++) { + span.x = destX; + span.y = destY + row; + span.end = drawWidth; + _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, + (CONST GLchan (*)[4]) src); + src += unpack.RowLength * 4; } - if (destX + drawWidth > ctx->DrawBuffer->_Xmax) - drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax); - if (drawWidth <= 0) - return GL_TRUE; + } + return GL_TRUE; + } - /* vertical clipping */ - if (destY > ctx->DrawBuffer->_Ymax) { - skipRows += (destY - ctx->DrawBuffer->_Ymax); - drawHeight -= (destY - ctx->DrawBuffer->_Ymax); - destY = ctx->DrawBuffer->_Ymax; + if (format == GL_RGB && type == CHAN_TYPE && rbType == CHAN_TYPE) { + const GLchan *src = (const GLchan *) pixels + + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels) * 3; + if (simpleZoom) { + GLint row; + for (row = 0; row < drawHeight; row++) { + rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL); + src += unpack.RowLength * 3; + destY += yStep; } - if (destY - drawHeight < ctx->DrawBuffer->_Ymin) - drawHeight -= (ctx->DrawBuffer->_Ymin - (destY - drawHeight)); - if (drawHeight <= 0) - return GL_TRUE; } else { - if (drawWidth > MAX_WIDTH) - return GL_FALSE; /* fall back to general case path */ + /* with zooming */ + GLint row; + for (row = 0; row < drawHeight; row++) { + span.x = destX; + span.y = destY; + span.end = drawWidth; + _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, + (CONST GLchan (*)[3]) src); + src += unpack.RowLength * 3; + destY++; + } } + return GL_TRUE; + } - - /* - * Ready to draw! - * The window region at (destX, destY) of size (drawWidth, drawHeight) - * will be written to. - * We'll take pixel data from buffer pointed to by "pixels" but we'll - * skip "skipRows" rows and skip "skipPixels" pixels/row. - */ - - if (format == GL_RGBA && type == CHAN_TYPE) { - if (ctx->Visual.rgbMode) { - const GLchan *src = (const GLchan *) pixels - + (skipRows * rowLength + skipPixels) * 4; - if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { - /* no zooming */ - GLint row; - for (row=0; rowPutRow(ctx, rb, drawWidth, destX, destY, src, NULL); - src += rowLength * 4; - destY++; - } - } - else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { - /* upside-down */ - GLint row; - for (row=0; rowPutRow(ctx, rb, drawWidth, destX, destY, src, NULL); - src += rowLength * 4; - } - } - else { - /* with zooming */ - GLint row; - for (row=0; rowPutRowRGB(ctx, rb, drawWidth, destX, destY, rgb, NULL); + src += unpack.RowLength; + destY += yStep; } - return GL_TRUE; } - else if (format == GL_RGB && type == CHAN_TYPE) { - if (ctx->Visual.rgbMode) { - const GLchan *src = (const GLchan *) pixels - + (skipRows * rowLength + skipPixels) * 3; - if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { - GLint row; - for (row=0; rowPutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL); - src += rowLength * 3; - destY++; - } - } - else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { - /* upside-down */ - GLint row; - for (row=0; rowPutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL); - src += rowLength * 3; - } - } - else { - /* with zooming */ - GLint row; - for (row=0; rowVisual.rgbMode) { - const GLchan *src = (const GLchan *) pixels - + (skipRows * rowLength + skipPixels); - if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { - /* no zooming */ - GLint row; - ASSERT(drawWidth <= MAX_WIDTH); - for (row=0; rowPutRowRGB(ctx, rb, drawWidth, destX, destY, rgb, NULL); - src += rowLength; - destY++; - } - } - else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { - /* upside-down */ - GLint row; - ASSERT(drawWidth <= MAX_WIDTH); - for (row=0; rowPutRow(ctx, rb, drawWidth, destX, destY, rgb, NULL); - src += rowLength; - } - } - else { - /* with zooming */ - GLint row; - ASSERT(drawWidth <= MAX_WIDTH); - for (row=0; rowrgba[i][0] = *ptr; + span.array->rgba[i][1] = *ptr; + span.array->rgba[i][2] = *ptr++; + span.array->rgba[i][3] = *ptr++; } + rb->PutRow(ctx, rb, drawWidth, destX, destY, + span.array->rgba, NULL); + src += unpack.RowLength*2; + destY += yStep; } - return GL_TRUE; } - else if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE) { - if (ctx->Visual.rgbMode) { - const GLchan *src = (const GLchan *) pixels - + (skipRows * rowLength + skipPixels)*2; - if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { - /* no zooming */ - GLint row; - ASSERT(drawWidth <= MAX_WIDTH); - for (row=0; rowrgba[i][0] = *ptr; - span.array->rgba[i][1] = *ptr; - span.array->rgba[i][2] = *ptr++; - span.array->rgba[i][3] = *ptr++; - } - rb->PutRow(ctx, rb, drawWidth, destX, destY, - span.array->rgba, NULL); - src += rowLength*2; - destY++; - } - } - else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { - /* upside-down */ - GLint row; - ASSERT(drawWidth <= MAX_WIDTH); - for (row=0; rowrgba[i][0] = *ptr; - span.array->rgba[i][1] = *ptr; - span.array->rgba[i][2] = *ptr++; - span.array->rgba[i][3] = *ptr++; - } - destY--; - rb->PutRow(ctx, rb, drawWidth, destX, destY, - span.array->rgba, NULL); - src += rowLength*2; - } - } - else { - /* with zooming */ - GLint row; - ASSERT(drawWidth <= MAX_WIDTH); - for (row=0; rowrgba[i][0] = *ptr; - span.array->rgba[i][1] = *ptr; - span.array->rgba[i][2] = *ptr++; - span.array->rgba[i][3] = *ptr++; - } - span.x = destX; - span.y = destY; - span.end = drawWidth; - _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, - (CONST GLchan (*)[4]) span.array->rgba); - src += rowLength*2; - destY++; - } + else { + /* with zooming */ + GLint row; + ASSERT(drawWidth <= MAX_WIDTH); + for (row = 0; row < drawHeight; row++) { + const GLchan *ptr = src; + GLint i; + for (i = 0;irgba[i][0] = *ptr; + span.array->rgba[i][1] = *ptr; + span.array->rgba[i][2] = *ptr++; + span.array->rgba[i][3] = *ptr++; } + span.x = destX; + span.y = destY; + span.end = drawWidth; + _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, + (CONST GLchan (*)[4]) span.array->rgba); + src += unpack.RowLength*2; + destY++; } - return GL_TRUE; } - else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) { - const GLubyte *src = - (const GLubyte *) pixels + skipRows * rowLength + skipPixels; - if (ctx->Visual.rgbMode) { - /* convert CI data to RGBA */ - if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { - /* no zooming */ - GLint row; - for (row=0; rowrgba); - rb->PutRow(ctx, rb, drawWidth, destX, destY, - span.array->rgba, NULL); - src += rowLength; - destY++; - } - return GL_TRUE; - } - else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { - /* upside-down */ - GLint row; - for (row=0; rowrgba); - destY--; - rb->PutRow(ctx, rb, drawWidth, destX, destY, - span.array->rgba, NULL); - src += rowLength; - } - return GL_TRUE; - } - else { - /* with zooming */ - GLint row; - for (row=0; rowrgba); - span.x = destX; - span.y = destY; - span.end = drawWidth; - _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, - (CONST GLchan (*)[4]) span.array->rgba); - src += rowLength; - destY++; - } - return GL_TRUE; + return GL_TRUE; + } + + if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) { + const GLubyte *src = (const GLubyte *) pixels + + unpack.SkipRows * unpack.RowLength + unpack.SkipPixels; + if (ctx->Visual.rgbMode && rbType == CHAN_TYPE) { + /* convert CI data to RGBA */ + if (simpleZoom) { + GLint row; + for (row = 0; row < drawHeight; row++) { + ASSERT(drawWidth <= MAX_WIDTH); + _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba); + rb->PutRow(ctx, rb, drawWidth, destX, destY, + span.array->rgba, NULL); + src += unpack.RowLength; + destY += yStep; } } else { - /* write CI data to CI frame buffer */ + /* with zooming */ GLint row; - if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { - /* no zooming */ - for (row=0; rowPutRow(ctx, rb, drawWidth, destX, destY, index32, NULL); - src += rowLength; - destY++; - } - return GL_TRUE; - } - else { - /* with zooming */ - return GL_FALSE; + for (row = 0; row < drawHeight; row++) { + ASSERT(drawWidth <= MAX_WIDTH); + _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba); + span.x = destX; + span.y = destY; + span.end = drawWidth; + _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, + (CONST GLchan (*)[4]) span.array->rgba); + src += unpack.RowLength; + destY++; } } + return GL_TRUE; } - else { - /* can't handle this pixel format and/or data type here */ - return GL_FALSE; + else if (!ctx->Visual.rgbMode && rbType == GL_UNSIGNED_INT) { + /* write CI data to CI frame buffer */ + GLint row; + if (simpleZoom) { + for (row = 0; row < drawHeight; row++) { + GLuint index32[MAX_WIDTH]; + GLint col; + for (col = 0; col < drawWidth; col++) + index32[col] = src[col]; + rb->PutRow(ctx, rb, drawWidth, destX, destY, index32, NULL); + src += unpack.RowLength; + destY += yStep; + } + return GL_TRUE; + } } } - /* can't do a simple draw, have to use slow path */ + /* can't handle this pixel format and/or data type */ return GL_FALSE; } @@ -685,12 +552,12 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, GLuint transferOps = ctx->_ImageTransferState; SWspan span; - INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); - /* Try an optimized glDrawPixels first */ if (fast_draw_pixels(ctx, x, y, width, height, format, type, unpack, pixels)) return; + INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); + if (ctx->Depth.Test) _swrast_span_default_z(ctx, &span); if (swrast->_FogEnabled) @@ -702,8 +569,11 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, && x + width <= (GLint) ctx->DrawBuffer->Width && y + height <= (GLint) ctx->DrawBuffer->Height && ctx->DrawBuffer->_NumColorDrawBuffers[0] == 1) { - quickDraw = GL_TRUE; rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0]; + if (rb->DataType == format) + quickDraw = GL_TRUE; + else + quickDraw = GL_FALSE; } else { quickDraw = GL_FALSE; @@ -765,6 +635,8 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, * General solution */ { + const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) + || (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink); const GLbitfield interpMask = span.interpMask; const GLbitfield arrayMask = span.arrayMask; GLint skipPixels = 0; @@ -783,6 +655,7 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, /* Set these for each row since the _swrast_write_* function may * change them while clipping. */ + span.array->ChanType = CHAN_TYPE; span.x = x + skipPixels; span.y = y + row; span.end = spanWidth; @@ -794,8 +667,7 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, format, type, source, unpack, transferOps); - if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) || - (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink)) + if (sink) continue; /* draw the span */ -- cgit v1.2.3