diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/swrast/s_copypix.c | 47 | ||||
-rw-r--r-- | src/mesa/swrast/s_span.c | 184 | ||||
-rw-r--r-- | src/mesa/swrast/s_span.h | 5 | ||||
-rw-r--r-- | src/mesa/swrast/s_texture.c | 8 | ||||
-rw-r--r-- | src/mesa/swrast/s_triangle.c | 4 |
5 files changed, 193 insertions, 55 deletions
diff --git a/src/mesa/swrast/s_copypix.c b/src/mesa/swrast/s_copypix.c index 13fc36cf9ed..91541d2c93c 100644 --- a/src/mesa/swrast/s_copypix.c +++ b/src/mesa/swrast/s_copypix.c @@ -558,6 +558,46 @@ swrast_fast_copy_pixels(struct gl_context *ctx, /** + * Find/map the renderbuffer that we'll be reading from. + * The swrast_render_start() function only maps the drawing buffers, + * not the read buffer. + */ +static struct gl_renderbuffer * +map_readbuffer(struct gl_context *ctx, GLenum type) +{ + struct gl_framebuffer *fb = ctx->ReadBuffer; + struct gl_renderbuffer *rb; + + switch (type) { + case GL_COLOR: + rb = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer; + break; + case GL_DEPTH: + case GL_DEPTH_STENCIL: + rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; + break; + case GL_STENCIL: + rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; + break; + default: + return NULL; + } + + if (!rb || rb->Map) { + /* no buffer, or buffer is mapped already, we're done */ + return NULL; + } + + ctx->Driver.MapRenderbuffer(ctx, rb, + 0, 0, rb->Width, rb->Height, + GL_MAP_READ_BIT, + &rb->Map, &rb->RowStrideBytes); + + return rb; +} + + +/** * Do software-based glCopyPixels. * By time we get here, all parameters will have been error-checked. */ @@ -567,6 +607,7 @@ _swrast_CopyPixels( struct gl_context *ctx, GLint destx, GLint desty, GLenum type ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); + struct gl_renderbuffer *rb; if (!_mesa_check_conditional_render(ctx)) return; /* don't copy */ @@ -585,6 +626,7 @@ _swrast_CopyPixels( struct gl_context *ctx, } swrast_render_start(ctx); + rb = map_readbuffer(ctx, type); switch (type) { case GL_COLOR: @@ -606,4 +648,9 @@ _swrast_CopyPixels( struct gl_context *ctx, } swrast_render_finish(ctx); + + if (rb) { + ctx->Driver.UnmapRenderbuffer(ctx, rb); + rb->Map = NULL; + } } diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c index beadbeb7fcd..157392a619a 100644 --- a/src/mesa/swrast/s_span.c +++ b/src/mesa/swrast/s_span.c @@ -33,6 +33,8 @@ #include "main/glheader.h" #include "main/colormac.h" +#include "main/format_pack.h" +#include "main/format_unpack.h" #include "main/macros.h" #include "main/imports.h" #include "main/image.h" @@ -1043,6 +1045,87 @@ shade_texture_span(struct gl_context *ctx, SWspan *span) } +/** Put colors at x/y locations into a renderbuffer */ +static void +put_values(struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *values, const GLubyte *mask) +{ + GLuint i; + + for (i = 0; i < count; i++) { + if (mask[i]) { + GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]); + + if (rb->DataType == GL_UNSIGNED_BYTE) { + _mesa_pack_ubyte_rgba_row(rb->Format, 1, + (const GLubyte (*)[4]) values + i, dst); + } + else { + assert(rb->DataType == GL_FLOAT); + _mesa_pack_float_rgba_row(rb->Format, count, + (const GLfloat (*)[4]) values + i, dst); + } + } + } +} + + +/** Put row of colors into renderbuffer */ +void +_swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, + const void *values, const GLubyte *mask) +{ + GLubyte *dst = _swrast_pixel_address(rb, x, y); + + if (!mask) { + if (rb->DataType == GL_UNSIGNED_BYTE) { + _mesa_pack_ubyte_rgba_row(rb->Format, count, + (const GLubyte (*)[4]) values, dst); + } + else { + assert(rb->DataType == GL_FLOAT); + _mesa_pack_float_rgba_row(rb->Format, count, + (const GLfloat (*)[4]) values, dst); + } + } + else { + const GLuint bpp = _mesa_get_format_bytes(rb->Format); + GLuint i, runLen, runStart; + /* We can't pass a 'mask' array to the _mesa_pack_rgba_row() functions + * so look for runs where mask=1... + */ + runLen = 0; + for (i = 0; i < count; i++) { + if (mask[i]) { + if (runLen == 0) + runStart = i; + runLen++; + } + + if (!mask[i] || i == count - 1) { + /* might be the end of a run of pixels */ + if (runLen > 0) { + if (rb->DataType == GL_UNSIGNED_BYTE) { + _mesa_pack_ubyte_rgba_row(rb->Format, runLen, + (const GLubyte (*)[4]) values + runStart, + dst + runStart * bpp); + } + else { + assert(rb->DataType == GL_FLOAT); + _mesa_pack_float_rgba_row(rb->Format, runLen, + (const GLfloat (*)[4]) values + runStart, + dst + runStart * bpp); + } + runLen = 0; + } + } + } + } +} + + /** * Apply all the per-fragment operations to a span. @@ -1290,17 +1373,15 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span) if (span->arrayMask & SPAN_XY) { /* array of pixel coords */ - ASSERT(rb->PutValues); - rb->PutValues(ctx, rb, span->end, - span->array->x, span->array->y, - span->array->rgba, span->array->mask); + put_values(ctx, rb, span->end, + span->array->x, span->array->y, + span->array->rgba, span->array->mask); } else { /* horizontal run of pixels */ - ASSERT(rb->PutRow); - rb->PutRow(ctx, rb, span->end, span->x, span->y, - span->array->rgba, - span->writeAll ? NULL: span->array->mask); + _swrast_put_row(ctx, rb, span->end, span->x, span->y, + span->array->rgba, + span->writeAll ? NULL: span->array->mask); } if (!multiFragOutputs && numBuffers > 1) { @@ -1344,6 +1425,8 @@ _swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb, } else { GLint skip, length; + GLubyte *src; + if (x < 0) { /* left edge clipping */ skip = -x; @@ -1372,7 +1455,6 @@ _swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb, } ASSERT(rb); - ASSERT(rb->GetRow); ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RG || @@ -1382,70 +1464,69 @@ _swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb, rb->_BaseFormat == GL_LUMINANCE_ALPHA || rb->_BaseFormat == GL_ALPHA); - if (rb->DataType == dstType) { - rb->GetRow(ctx, rb, length, x + skip, y, - (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType)); + assert(rb->Map); + + src = _swrast_pixel_address(rb, x + skip, y); + + if (dstType == GL_UNSIGNED_BYTE) { + _mesa_unpack_ubyte_rgba_row(rb->Format, length, src, + (GLubyte (*)[4]) rgba + skip); + } + else if (dstType == GL_FLOAT) { + _mesa_unpack_rgba_row(rb->Format, length, src, + (GLfloat (*)[4]) rgba + skip); } else { - GLuint temp[MAX_WIDTH * 4]; - rb->GetRow(ctx, rb, length, x + skip, y, temp); - _mesa_convert_colors(rb->DataType, temp, - dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType), - length, NULL); + _mesa_problem(ctx, "unexpected type in _swrast_read_rgba_span()"); } } } /** - * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid - * reading values outside the buffer bounds. - * We can use this for reading any format/type of renderbuffer. - * \param valueSize is the size in bytes of each value (pixel) put into the - * values array. + * Get colors at x/y positions with clipping. + * \param type type of values to return */ static void get_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], - void *values, GLuint valueSize) + void *values, GLenum type) { - GLuint i, inCount = 0, inStart = 0; + GLuint i; for (i = 0; i < count; i++) { if (x[i] >= 0 && y[i] >= 0 && x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) { /* inside */ - if (inCount == 0) - inStart = i; - inCount++; - } - else { - if (inCount > 0) { - /* read [inStart, inStart + inCount) */ - rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart, - (GLubyte *) values + inStart * valueSize); - inCount = 0; + const GLubyte *src = _swrast_pixel_address(rb, x[i], y[i]); + + if (type == GL_UNSIGNED_BYTE) { + _mesa_unpack_ubyte_rgba_row(rb->Format, 1, src, + (GLubyte (*)[4]) values + i); + } + else if (type == GL_FLOAT) { + _mesa_unpack_rgba_row(rb->Format, 1, src, + (GLfloat (*)[4]) values + i); + } + else { + _mesa_problem(ctx, "unexpected type in get_values()"); } } } - if (inCount > 0) { - /* read last values */ - rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart, - (GLubyte *) values + inStart * valueSize); - } } /** - * Wrapper for gl_renderbuffer::GetRow() which does clipping. - * \param valueSize size of each value (pixel) in bytes + * Get row of colors with clipping. + * \param type type of values to return */ static void get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, GLint x, GLint y, - GLvoid *values, GLuint valueSize) + GLvoid *values, GLenum type) { GLint skip = 0; + GLubyte *src; if (y < 0 || y >= (GLint) rb->Height) return; /* above or below */ @@ -1466,7 +1547,19 @@ get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, count -= skip; } - rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize); + src = _swrast_pixel_address(rb, x, y); + + if (type == GL_UNSIGNED_BYTE) { + _mesa_unpack_ubyte_rgba_row(rb->Format, count, src, + (GLubyte (*)[4]) values + skip); + } + else if (type == GL_FLOAT) { + _mesa_unpack_rgba_row(rb->Format, count, src, + (GLfloat (*)[4]) values + skip); + } + else { + _mesa_problem(ctx, "unexpected type in get_row()"); + } } @@ -1479,7 +1572,6 @@ void * _swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span) { - const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType); void *rbPixels; /* Point rbPixels to a temporary space */ @@ -1488,11 +1580,11 @@ _swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb, /* Get destination values from renderbuffer */ if (span->arrayMask & SPAN_XY) { get_values(ctx, rb, span->end, span->array->x, span->array->y, - rbPixels, pixelSize); + rbPixels, span->array->ChanType); } else { get_row(ctx, rb, span->end, span->x, span->y, - rbPixels, pixelSize); + rbPixels, span->array->ChanType); } return rbPixels; diff --git a/src/mesa/swrast/s_span.h b/src/mesa/swrast/s_span.h index e39ae85382b..4d6eb7ec163 100644 --- a/src/mesa/swrast/s_span.h +++ b/src/mesa/swrast/s_span.h @@ -203,6 +203,11 @@ extern void _swrast_read_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, GLvoid *rgba); +extern void +_swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, + const void *values, const GLubyte *mask); + extern void * _swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span); diff --git a/src/mesa/swrast/s_texture.c b/src/mesa/swrast/s_texture.c index f945a6b0fa8..b98195e7489 100644 --- a/src/mesa/swrast/s_texture.c +++ b/src/mesa/swrast/s_texture.c @@ -342,14 +342,11 @@ map_attachment(struct gl_context *ctx, } else if (rb) { /* Map ordinary renderbuffer */ - /* XXX don't map color buffers yet */ - if (buffer == BUFFER_DEPTH || buffer == BUFFER_STENCIL) { ctx->Driver.MapRenderbuffer(ctx, rb, 0, 0, rb->Width, rb->Height, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, &rb->Map, &rb->RowStrideBytes); assert(rb->Map); - } } } @@ -373,10 +370,7 @@ unmap_attachment(struct gl_context *ctx, } else if (rb) { /* unmap ordinary renderbuffer */ - /* XXX don't map color buffers yet */ - if (buffer == BUFFER_DEPTH || buffer == BUFFER_STENCIL) { - ctx->Driver.UnmapRenderbuffer(ctx, rb); - } + ctx->Driver.UnmapRenderbuffer(ctx, rb); } rb->Map = NULL; diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c index 4d815c5d675..2b54cd13153 100644 --- a/src/mesa/swrast/s_triangle.c +++ b/src/mesa/swrast/s_triangle.c @@ -157,7 +157,7 @@ _swrast_culltriangle( struct gl_context *ctx, span.intTex[0] += span.intTexStep[0]; \ span.intTex[1] += span.intTexStep[1]; \ } \ - rb->PutRow(ctx, rb, span.end, span.x, span.y, rgba, NULL); + _swrast_put_row(ctx, rb, span.end, span.x, span.y, rgba, NULL); #include "s_tritemp.h" @@ -223,7 +223,7 @@ _swrast_culltriangle( struct gl_context *ctx, span.intTex[1] += span.intTexStep[1]; \ span.z += span.zStep; \ } \ - rb->PutRow(ctx, rb, span.end, span.x, span.y, rgba, span.array->mask); + _swrast_put_row(ctx, rb, span.end, span.x, span.y, rgba, span.array->mask); #include "s_tritemp.h" |