summaryrefslogtreecommitdiff
path: root/src/mesa/swrast/s_span.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/swrast/s_span.c')
-rw-r--r--src/mesa/swrast/s_span.c184
1 files changed, 138 insertions, 46 deletions
diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c
index fe199cbc783..2b67d55767d 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"
@@ -1024,6 +1026,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.
@@ -1271,17 +1354,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) {
@@ -1325,6 +1406,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;
@@ -1353,7 +1436,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 ||
@@ -1363,70 +1445,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 */
@@ -1447,7 +1528,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()");
+ }
}
@@ -1460,7 +1553,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 */
@@ -1469,11 +1561,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;