diff options
Diffstat (limited to 'mesalib/src/mesa')
40 files changed, 3609 insertions, 6747 deletions
diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index c5c59ebee..e62267394 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -65,6 +65,7 @@ #include "main/teximage.h" #include "main/texparam.h" #include "main/texstate.h" +#include "main/transformfeedback.h" #include "main/uniforms.h" #include "main/varray.h" #include "main/viewport.h" @@ -180,6 +181,8 @@ struct save_state /** Miscellaneous (always disabled) */ GLboolean Lighting; + GLboolean RasterDiscard; + GLboolean TransformFeedbackNeedsResume; }; /** @@ -422,6 +425,15 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) memset(save, 0, sizeof(*save)); save->SavedState = state; + /* Pausing transform feedback needs to be done early, or else we won't be + * able to change other state. + */ + save->TransformFeedbackNeedsResume = + ctx->TransformFeedback.CurrentObject->Active && + !ctx->TransformFeedback.CurrentObject->Paused; + if (save->TransformFeedbackNeedsResume) + _mesa_PauseTransformFeedback(); + if (state & MESA_META_ALPHA_TEST) { save->AlphaEnabled = ctx->Color.AlphaEnabled; save->AlphaFunc = ctx->Color.AlphaFunc; @@ -702,6 +714,9 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) save->Lighting = ctx->Light.Enabled; if (ctx->Light.Enabled) _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE); + save->RasterDiscard = ctx->RasterDiscard; + if (ctx->RasterDiscard) + _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_FALSE); } } @@ -981,6 +996,11 @@ _mesa_meta_end(struct gl_context *ctx) if (save->Lighting) { _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE); } + if (save->RasterDiscard) { + _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_TRUE); + } + if (save->TransformFeedbackNeedsResume) + _mesa_ResumeTransformFeedback(); } diff --git a/mesalib/src/mesa/drivers/dri/common/depthtmp.h b/mesalib/src/mesa/drivers/dri/common/depthtmp.h index c6e2bb75c..d8f259f67 100644 --- a/mesalib/src/mesa/drivers/dri/common/depthtmp.h +++ b/mesalib/src/mesa/drivers/dri/common/depthtmp.h @@ -71,63 +71,6 @@ static void TAG(WriteDepthSpan)( struct gl_context *ctx, } -#if HAVE_HW_DEPTH_SPANS -/* implement MonoWriteDepthSpan() in terms of WriteDepthSpan() */ -static void -TAG(WriteMonoDepthSpan)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *value, const GLubyte mask[] ) -{ - const GLuint depthVal = *((GLuint *) value); - GLuint depths[MAX_WIDTH]; - GLuint i; - for (i = 0; i < n; i++) - depths[i] = depthVal; - TAG(WriteDepthSpan)(ctx, rb, n, x, y, depths, mask); -} -#else -static void TAG(WriteMonoDepthSpan)( struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *value, - const GLubyte mask[] ) -{ - HW_WRITE_LOCK() - { - const GLuint depth = *((GLuint *) value); - GLint x1; - GLint n1; - LOCAL_DEPTH_VARS; - - y = Y_FLIP( y ); - - HW_CLIPLOOP() - { - GLint i = 0; - CLIPSPAN( x, y, n, x1, n1, i ); - - if ( DBG ) fprintf( stderr, "%s %d..%d (x1 %d) = %u\n", - __FUNCTION__, (int)i, (int)n1, (int)x1, (GLuint)depth ); - - if ( mask ) { - for ( ; n1>0 ; i++, x1++, n1-- ) { - if ( mask[i] ) WRITE_DEPTH( x1, y, depth ); - } - } else { - for ( ; n1>0 ; x1++, n1-- ) { - WRITE_DEPTH( x1, y, depth ); - } - } - } - HW_ENDCLIPLOOP(); - } - HW_WRITE_UNLOCK(); - - (void) ctx; -} -#endif - - static void TAG(WriteDepthPixels)( struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint n, @@ -258,10 +201,7 @@ static void TAG(InitDepthPointers)(struct gl_renderbuffer *rb) rb->GetRow = TAG(ReadDepthSpan); rb->GetValues = TAG(ReadDepthPixels); rb->PutRow = TAG(WriteDepthSpan); - rb->PutRowRGB = NULL; - rb->PutMonoRow = TAG(WriteMonoDepthSpan); rb->PutValues = TAG(WriteDepthPixels); - rb->PutMonoValues = NULL; } diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c index 1640c1448..a153d525d 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.c +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c @@ -454,14 +454,18 @@ const __DRIcoreExtension driCoreExtension = { /** DRI2 interface */ const __DRIdri2Extension driDRI2Extension = { - { __DRI_DRI2, __DRI_DRI2_VERSION }, + /* Force the version to 2 because the underlying drivers don't (can't!) + * support the extra requirements of CreateContextAttribs. + */ + { __DRI_DRI2, 2 }, dri2CreateNewScreen, dri2CreateNewDrawable, dri2CreateNewContext, dri2GetAPIMask, dri2CreateNewContextForAPI, dri2AllocateBuffer, - dri2ReleaseBuffer + dri2ReleaseBuffer, + NULL }; const __DRI2configQueryExtension dri2ConfigQueryExtension = { diff --git a/mesalib/src/mesa/drivers/dri/common/drisw_util.c b/mesalib/src/mesa/drivers/dri/common/drisw_util.c index 614339eeb..a19123f70 100644 --- a/mesalib/src/mesa/drivers/dri/common/drisw_util.c +++ b/mesalib/src/mesa/drivers/dri/common/drisw_util.c @@ -288,8 +288,12 @@ const __DRIcoreExtension driCoreExtension = { }; const __DRIswrastExtension driSWRastExtension = { - { __DRI_SWRAST, __DRI_SWRAST_VERSION }, + /* Force the version to 2 because the underlying driver don't (can't!) + * support the extra requirements of CreateContextAttribs. + */ + { __DRI_SWRAST, 2 }, driCreateNewScreen, driCreateNewDrawable, - driCreateNewContextForAPI + driCreateNewContextForAPI, + NULL }; diff --git a/mesalib/src/mesa/drivers/dri/common/spantmp2.h b/mesalib/src/mesa/drivers/dri/common/spantmp2.h index 83cfbb164..744dfcd3b 100644 --- a/mesalib/src/mesa/drivers/dri/common/spantmp2.h +++ b/mesalib/src/mesa/drivers/dri/common/spantmp2.h @@ -63,9 +63,6 @@ #define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v) #endif /* GET_VALUE */ -#define INIT_MONO_PIXEL(p, color) \ - p = PACK_COLOR_565( color[0], color[1], color[2] ) - #define WRITE_RGBA( _x, _y, r, g, b, a ) \ PUT_VALUE(_x, _y, ((((int)r & 0xf8) << 8) | \ (((int)g & 0xfc) << 3) | \ @@ -97,9 +94,6 @@ #define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v) #endif /* GET_VALUE */ -#define INIT_MONO_PIXEL(p, color) \ - p = PACK_COLOR_565_REV( color[0], color[1], color[2] ) - #define WRITE_RGBA( _x, _y, r, g, b, a ) \ PUT_VALUE(_x, _y, PACK_COLOR_565_REV( r, g, b )) @@ -130,9 +124,6 @@ #define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v) #endif /* GET_VALUE */ -#define INIT_MONO_PIXEL(p, color) \ - p = PACK_COLOR_4444_REV(color[3], color[0], color[1], color[2]) - #define WRITE_RGBA( _x, _y, r, g, b, a ) \ PUT_VALUE(_x, _y, PACK_COLOR_4444_REV(a, r, g, b)) \ @@ -163,9 +154,6 @@ #define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v) #endif /* GET_VALUE */ -#define INIT_MONO_PIXEL(p, color) \ - p = PACK_COLOR_4444(color[3], color[0], color[1], color[2]) - #define WRITE_RGBA( _x, _y, r, g, b, a ) \ PUT_VALUE(_x, _y, PACK_COLOR_4444(a, r, g, b)) \ @@ -196,9 +184,6 @@ #define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v) #endif /* GET_VALUE */ -#define INIT_MONO_PIXEL(p, color) \ - p = PACK_COLOR_1555(color[3], color[0], color[1], color[2]) - #define WRITE_RGBA( _x, _y, r, g, b, a ) \ PUT_VALUE(_x, _y, PACK_COLOR_1555(a, r, g, b)) \ @@ -228,9 +213,6 @@ #define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v) #endif /* GET_VALUE */ -#define INIT_MONO_PIXEL(p, color) \ - p = PACK_COLOR_1555_REV(color[3], color[0], color[1], color[2]) - #define WRITE_RGBA( _x, _y, r, g, b, a ) \ PUT_VALUE(_x, _y, PACK_COLOR_1555_REV(a, r, g, b)) \ @@ -261,9 +243,6 @@ #define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v) #endif /* GET_VALUE */ -# define INIT_MONO_PIXEL(p, color) \ - p = PACK_COLOR_8888(color[3], color[0], color[1], color[2]) - # define WRITE_RGBA(_x, _y, r, g, b, a) \ PUT_VALUE(_x, _y, ((r << 16) | \ (g << 8) | \ @@ -316,9 +295,6 @@ #define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v) #endif /* GET_VALUE */ -# define INIT_MONO_PIXEL(p, color) \ - p = PACK_COLOR_8888(color[2], color[1], color[0], color[3]) - # define WRITE_RGBA(_x, _y, r, g, b, a) \ PUT_VALUE(_x, _y, ((r << 8) | \ (g << 16) | \ @@ -374,9 +350,6 @@ #define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v) #endif /* GET_VALUE */ -# define INIT_MONO_PIXEL(p, color) \ - p = PACK_COLOR_8888(0xff, color[0], color[1], color[2]) - # define WRITE_RGBA(_x, _y, r, g, b, a) \ PUT_VALUE(_x, _y, ((r << 16) | \ (g << 8) | \ @@ -428,9 +401,6 @@ #define PUT_VALUE(_x, _y, _v) *(volatile GLubyte *)(GET_PTR(_x, _y)) = (_v) #endif /* GET_VALUE */ -# define INIT_MONO_PIXEL(p, color) \ - p = color[3] - # define WRITE_RGBA(_x, _y, r, g, b, a) \ PUT_VALUE(_x, _y, a | (r & 0 /* quiet warnings */)) @@ -505,46 +475,6 @@ static void TAG(WriteRGBASpan)( struct gl_context *ctx, HW_WRITE_UNLOCK(); } -static void TAG(WriteRGBSpan)( struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *values, const GLubyte mask[] ) -{ - (void) ctx; - - HW_WRITE_LOCK() - { - const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - GLint x1; - GLint n1; - LOCAL_VARS; - - y = Y_FLIP(y); - - HW_WRITE_CLIPLOOP() - { - GLint i = 0; - CLIPSPAN(x,y,n,x1,n1,i); - - if (DBG) fprintf(stderr, "WriteRGBSpan %d..%d (x1 %d)\n", - (int)i, (int)n1, (int)x1); - - if (mask) - { - for (;n1>0;i++,x1++,n1--) - if (mask[i]) - WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 ); - } - else - { - for (;n1>0;i++,x1++,n1--) - WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 ); - } - } - HW_ENDCLIPLOOP(); - } - HW_WRITE_UNLOCK(); -} static void TAG(WriteRGBAPixels)( struct gl_context *ctx, struct gl_renderbuffer *rb, @@ -594,91 +524,6 @@ static void TAG(WriteRGBAPixels)( struct gl_context *ctx, } -static void TAG(WriteMonoRGBASpan)( struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *value, const GLubyte mask[] ) -{ - (void) ctx; - - HW_WRITE_LOCK() - { - const GLubyte *color = (const GLubyte *) value; - GLint x1; - GLint n1; - LOCAL_VARS; - INIT_MONO_PIXEL(p, color); - - y = Y_FLIP( y ); - - if (DBG) fprintf(stderr, "WriteMonoRGBASpan\n"); - - HW_WRITE_CLIPLOOP() - { - GLint i = 0; - CLIPSPAN(x,y,n,x1,n1,i); - if (mask) - { - for (;n1>0;i++,x1++,n1--) - if (mask[i]) - WRITE_PIXEL( x1, y, p ); - } - else - { - for (;n1>0;i++,x1++,n1--) - WRITE_PIXEL( x1, y, p ); - } - } - HW_ENDCLIPLOOP(); - } - HW_WRITE_UNLOCK(); -} - - -static void TAG(WriteMonoRGBAPixels)( struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, - const GLint x[], const GLint y[], - const void *value, - const GLubyte mask[] ) -{ - (void) ctx; - - HW_WRITE_LOCK() - { - const GLubyte *color = (const GLubyte *) value; - GLint i; - LOCAL_VARS; - INIT_MONO_PIXEL(p, color); - - if (DBG) fprintf(stderr, "WriteMonoRGBAPixels\n"); - - HW_WRITE_CLIPLOOP() - { - if (mask) - { - for (i=0;i<n;i++) - if (mask[i]) { - int fy = Y_FLIP(y[i]); - if (CLIPPIXEL( x[i], fy )) - WRITE_PIXEL( x[i], fy, p ); - } - } - else - { - for (i=0;i<n;i++) { - int fy = Y_FLIP(y[i]); - if (CLIPPIXEL( x[i], fy )) - WRITE_PIXEL( x[i], fy, p ); - } - } - } - HW_ENDCLIPLOOP(); - } - HW_WRITE_UNLOCK(); -} - - static void TAG(ReadRGBASpan)( struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint n, GLint x, GLint y, void *values) @@ -878,10 +723,7 @@ static void TAG(ReadRGBAPixels)( struct gl_context *ctx, static void TAG(InitPointers)(struct gl_renderbuffer *rb) { rb->PutRow = TAG(WriteRGBASpan); - rb->PutRowRGB = TAG(WriteRGBSpan); - rb->PutMonoRow = TAG(WriteMonoRGBASpan); rb->PutValues = TAG(WriteRGBAPixels); - rb->PutMonoValues = TAG(WriteMonoRGBAPixels); rb->GetValues = TAG(ReadRGBAPixels); #if defined(GET_PTR) @@ -923,7 +765,6 @@ static void TAG(InitPointers)(struct gl_renderbuffer *rb) } -#undef INIT_MONO_PIXEL #undef WRITE_PIXEL #undef WRITE_RGBA #undef READ_RGBA diff --git a/mesalib/src/mesa/drivers/dri/common/stenciltmp.h b/mesalib/src/mesa/drivers/dri/common/stenciltmp.h index 2ea2e207a..950d3c4df 100644 --- a/mesalib/src/mesa/drivers/dri/common/stenciltmp.h +++ b/mesalib/src/mesa/drivers/dri/common/stenciltmp.h @@ -1,245 +1,186 @@ -
-#include "spantmp_common.h"
-
-#ifndef DBG
-#define DBG 0
-#endif
-
-#ifndef HAVE_HW_STENCIL_SPANS
-#define HAVE_HW_STENCIL_SPANS 0
-#endif
-
-#ifndef HAVE_HW_STENCIL_PIXELS
-#define HAVE_HW_STENCIL_PIXELS 0
-#endif
-
-static void TAG(WriteStencilSpan)( struct gl_context *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *values, const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte *stencil = (const GLubyte *) values;
- GLint x1;
- GLint n1;
- LOCAL_STENCIL_VARS;
-
- y = Y_FLIP(y);
-
-#if HAVE_HW_STENCIL_SPANS
- (void) x1; (void) n1;
-
- if (DBG) fprintf(stderr, "WriteStencilSpan 0..%d (x1 %d)\n",
- (int)n1, (int)x1);
-
- WRITE_STENCIL_SPAN();
-#else /* HAVE_HW_STENCIL_SPANS */
- HW_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
-
- if (DBG) fprintf(stderr, "WriteStencilSpan %d..%d (x1 %d)\n",
- (int)i, (int)n1, (int)x1);
-
- if (mask)
- {
- for (;n1>0;i++,x1++,n1--)
- if (mask[i])
- WRITE_STENCIL( x1, y, stencil[i] );
- }
- else
- {
- for (;n1>0;i++,x1++,n1--)
- WRITE_STENCIL( x1, y, stencil[i] );
- }
- }
- HW_ENDCLIPLOOP();
-#endif /* !HAVE_HW_STENCIL_SPANS */
- }
- HW_WRITE_UNLOCK();
-}
-
-#if HAVE_HW_STENCIL_SPANS
-/* implement MonoWriteDepthSpan() in terms of WriteDepthSpan() */
-static void
-TAG(WriteMonoStencilSpan)( struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *value, const GLubyte mask[] )
-{
- const GLuint stenVal = *((GLuint *) value);
- GLuint stens[MAX_WIDTH];
- GLuint i;
- for (i = 0; i < n; i++)
- stens[i] = stenVal;
- TAG(WriteStencilSpan)(ctx, rb, n, x, y, stens, mask);
-}
-#else /* HAVE_HW_STENCIL_SPANS */
-static void TAG(WriteMonoStencilSpan)( struct gl_context *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *value,
- const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte stencil = *((const GLubyte *) value);
- GLint x1;
- GLint n1;
- LOCAL_STENCIL_VARS;
-
- y = Y_FLIP(y);
-
- HW_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
-
- if (DBG) fprintf(stderr, "WriteStencilSpan %d..%d (x1 %d)\n",
- (int)i, (int)n1, (int)x1);
-
- if (mask)
- {
- for (;n1>0;i++,x1++,n1--)
- if (mask[i])
- WRITE_STENCIL( x1, y, stencil );
- }
- else
- {
- for (;n1>0;i++,x1++,n1--)
- WRITE_STENCIL( x1, y, stencil );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-#endif /* !HAVE_HW_STENCIL_SPANS */
-
-
-static void TAG(WriteStencilPixels)( struct gl_context *ctx,
- struct gl_renderbuffer *rb,
- GLuint n,
- const GLint x[], const GLint y[],
- const void *values, const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte *stencil = (const GLubyte *) values;
- GLuint i;
- LOCAL_STENCIL_VARS;
-
- if (DBG) fprintf(stderr, "WriteStencilPixels\n");
-
-#if HAVE_HW_STENCIL_PIXELS
- (void) i;
-
- WRITE_STENCIL_PIXELS();
-#else /* HAVE_HW_STENCIL_PIXELS */
- HW_CLIPLOOP()
- {
- for (i=0;i<n;i++)
- {
- if (mask[i]) {
- const int fy = Y_FLIP(y[i]);
- if (CLIPPIXEL(x[i],fy))
- WRITE_STENCIL( x[i], fy, stencil[i] );
- }
- }
- }
- HW_ENDCLIPLOOP();
-#endif /* !HAVE_HW_STENCIL_PIXELS */
- }
- HW_WRITE_UNLOCK();
-}
-
-
-/* Read stencil spans and pixels
- */
-static void TAG(ReadStencilSpan)( struct gl_context *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- void *values)
-{
- HW_READ_LOCK()
- {
- GLubyte *stencil = (GLubyte *) values;
- GLint x1,n1;
- LOCAL_STENCIL_VARS;
-
- y = Y_FLIP(y);
-
- if (DBG) fprintf(stderr, "ReadStencilSpan\n");
-
-#if HAVE_HW_STENCIL_SPANS
- (void) x1; (void) n1;
-
- READ_STENCIL_SPAN();
-#else /* HAVE_HW_STENCIL_SPANS */
- HW_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
- for (;n1>0;i++,n1--)
- READ_STENCIL( stencil[i], (x+i), y );
- }
- HW_ENDCLIPLOOP();
-#endif /* !HAVE_HW_STENCIL_SPANS */
- }
- HW_READ_UNLOCK();
-}
-
-static void TAG(ReadStencilPixels)( struct gl_context *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- void *values )
-{
- HW_READ_LOCK()
- {
- GLubyte *stencil = (GLubyte *) values;
- GLuint i;
- LOCAL_STENCIL_VARS;
-
- if (DBG) fprintf(stderr, "ReadStencilPixels\n");
-
-#if HAVE_HW_STENCIL_PIXELS
- (void) i;
-
- READ_STENCIL_PIXELS();
-#else /* HAVE_HW_STENCIL_PIXELS */
- HW_CLIPLOOP()
- {
- for (i=0;i<n;i++) {
- int fy = Y_FLIP( y[i] );
- if (CLIPPIXEL( x[i], fy ))
- READ_STENCIL( stencil[i], x[i], fy );
- }
- }
- HW_ENDCLIPLOOP();
-#endif /* !HAVE_HW_STENCIL_PIXELS */
- }
- HW_READ_UNLOCK();
-}
-
-
-
-/**
- * Initialize the given renderbuffer's span routines to point to
- * the stencil functions we generated above.
- */
-static void TAG(InitStencilPointers)(struct gl_renderbuffer *rb)
-{
- rb->GetRow = TAG(ReadStencilSpan);
- rb->GetValues = TAG(ReadStencilPixels);
- rb->PutRow = TAG(WriteStencilSpan);
- rb->PutRowRGB = NULL;
- rb->PutMonoRow = TAG(WriteMonoStencilSpan);
- rb->PutValues = TAG(WriteStencilPixels);
- rb->PutMonoValues = NULL;
-}
-
-
-#undef WRITE_STENCIL
-#undef READ_STENCIL
-#undef TAG
+ +#include "spantmp_common.h" + +#ifndef DBG +#define DBG 0 +#endif + +#ifndef HAVE_HW_STENCIL_SPANS +#define HAVE_HW_STENCIL_SPANS 0 +#endif + +#ifndef HAVE_HW_STENCIL_PIXELS +#define HAVE_HW_STENCIL_PIXELS 0 +#endif + +static void TAG(WriteStencilSpan)( struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, + const void *values, const GLubyte mask[] ) +{ + HW_WRITE_LOCK() + { + const GLubyte *stencil = (const GLubyte *) values; + GLint x1; + GLint n1; + LOCAL_STENCIL_VARS; + + y = Y_FLIP(y); + +#if HAVE_HW_STENCIL_SPANS + (void) x1; (void) n1; + + if (DBG) fprintf(stderr, "WriteStencilSpan 0..%d (x1 %d)\n", + (int)n1, (int)x1); + + WRITE_STENCIL_SPAN(); +#else /* HAVE_HW_STENCIL_SPANS */ + HW_CLIPLOOP() + { + GLint i = 0; + CLIPSPAN(x,y,n,x1,n1,i); + + if (DBG) fprintf(stderr, "WriteStencilSpan %d..%d (x1 %d)\n", + (int)i, (int)n1, (int)x1); + + if (mask) + { + for (;n1>0;i++,x1++,n1--) + if (mask[i]) + WRITE_STENCIL( x1, y, stencil[i] ); + } + else + { + for (;n1>0;i++,x1++,n1--) + WRITE_STENCIL( x1, y, stencil[i] ); + } + } + HW_ENDCLIPLOOP(); +#endif /* !HAVE_HW_STENCIL_SPANS */ + } + HW_WRITE_UNLOCK(); +} + + +static void TAG(WriteStencilPixels)( struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLuint n, + const GLint x[], const GLint y[], + const void *values, const GLubyte mask[] ) +{ + HW_WRITE_LOCK() + { + const GLubyte *stencil = (const GLubyte *) values; + GLuint i; + LOCAL_STENCIL_VARS; + + if (DBG) fprintf(stderr, "WriteStencilPixels\n"); + +#if HAVE_HW_STENCIL_PIXELS + (void) i; + + WRITE_STENCIL_PIXELS(); +#else /* HAVE_HW_STENCIL_PIXELS */ + HW_CLIPLOOP() + { + for (i=0;i<n;i++) + { + if (mask[i]) { + const int fy = Y_FLIP(y[i]); + if (CLIPPIXEL(x[i],fy)) + WRITE_STENCIL( x[i], fy, stencil[i] ); + } + } + } + HW_ENDCLIPLOOP(); +#endif /* !HAVE_HW_STENCIL_PIXELS */ + } + HW_WRITE_UNLOCK(); +} + + +/* Read stencil spans and pixels + */ +static void TAG(ReadStencilSpan)( struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, + void *values) +{ + HW_READ_LOCK() + { + GLubyte *stencil = (GLubyte *) values; + GLint x1,n1; + LOCAL_STENCIL_VARS; + + y = Y_FLIP(y); + + if (DBG) fprintf(stderr, "ReadStencilSpan\n"); + +#if HAVE_HW_STENCIL_SPANS + (void) x1; (void) n1; + + READ_STENCIL_SPAN(); +#else /* HAVE_HW_STENCIL_SPANS */ + HW_CLIPLOOP() + { + GLint i = 0; + CLIPSPAN(x,y,n,x1,n1,i); + for (;n1>0;i++,n1--) + READ_STENCIL( stencil[i], (x+i), y ); + } + HW_ENDCLIPLOOP(); +#endif /* !HAVE_HW_STENCIL_SPANS */ + } + HW_READ_UNLOCK(); +} + +static void TAG(ReadStencilPixels)( struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLuint n, const GLint x[], const GLint y[], + void *values ) +{ + HW_READ_LOCK() + { + GLubyte *stencil = (GLubyte *) values; + GLuint i; + LOCAL_STENCIL_VARS; + + if (DBG) fprintf(stderr, "ReadStencilPixels\n"); + +#if HAVE_HW_STENCIL_PIXELS + (void) i; + + READ_STENCIL_PIXELS(); +#else /* HAVE_HW_STENCIL_PIXELS */ + HW_CLIPLOOP() + { + for (i=0;i<n;i++) { + int fy = Y_FLIP( y[i] ); + if (CLIPPIXEL( x[i], fy )) + READ_STENCIL( stencil[i], x[i], fy ); + } + } + HW_ENDCLIPLOOP(); +#endif /* !HAVE_HW_STENCIL_PIXELS */ + } + HW_READ_UNLOCK(); +} + + + +/** + * Initialize the given renderbuffer's span routines to point to + * the stencil functions we generated above. + */ +static void TAG(InitStencilPointers)(struct gl_renderbuffer *rb) +{ + rb->GetRow = TAG(ReadStencilSpan); + rb->GetValues = TAG(ReadStencilPixels); + rb->PutRow = TAG(WriteStencilSpan); + rb->PutValues = TAG(WriteStencilPixels); +} + + +#undef WRITE_STENCIL +#undef READ_STENCIL +#undef TAG diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast_span.c b/mesalib/src/mesa/drivers/dri/swrast/swrast_span.c index 772d09f5a..ba6174f9d 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast_span.c +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast_span.c @@ -276,37 +276,25 @@ swrast_set_span_funcs_back(struct swrast_renderbuffer *xrb, xrb->Base.GetRow = get_row_A8R8G8B8; xrb->Base.GetValues = get_values_A8R8G8B8; xrb->Base.PutRow = put_row_A8R8G8B8; - xrb->Base.PutRowRGB = put_row_rgb_A8R8G8B8; - xrb->Base.PutMonoRow = put_mono_row_A8R8G8B8; xrb->Base.PutValues = put_values_A8R8G8B8; - xrb->Base.PutMonoValues = put_mono_values_A8R8G8B8; break; case PF_X8R8G8B8: xrb->Base.GetRow = get_row_X8R8G8B8; xrb->Base.GetValues = get_values_X8R8G8B8; xrb->Base.PutRow = put_row_X8R8G8B8; - xrb->Base.PutRowRGB = put_row_rgb_X8R8G8B8; - xrb->Base.PutMonoRow = put_mono_row_X8R8G8B8; xrb->Base.PutValues = put_values_X8R8G8B8; - xrb->Base.PutMonoValues = put_mono_values_X8R8G8B8; break; case PF_R5G6B5: xrb->Base.GetRow = get_row_R5G6B5; xrb->Base.GetValues = get_values_R5G6B5; xrb->Base.PutRow = put_row_R5G6B5; - xrb->Base.PutRowRGB = put_row_rgb_R5G6B5; - xrb->Base.PutMonoRow = put_mono_row_R5G6B5; xrb->Base.PutValues = put_values_R5G6B5; - xrb->Base.PutMonoValues = put_mono_values_R5G6B5; break; case PF_R3G3B2: xrb->Base.GetRow = get_row_R3G3B2; xrb->Base.GetValues = get_values_R3G3B2; xrb->Base.PutRow = put_row_R3G3B2; - xrb->Base.PutRowRGB = put_row_rgb_R3G3B2; - xrb->Base.PutMonoRow = put_mono_row_R3G3B2; xrb->Base.PutValues = put_values_R3G3B2; - xrb->Base.PutMonoValues = put_mono_values_R3G3B2; break; default: assert(0); @@ -332,37 +320,25 @@ swrast_set_span_funcs_front(struct swrast_renderbuffer *xrb, xrb->Base.GetRow = get_row_A8R8G8B8_front; xrb->Base.GetValues = get_values_A8R8G8B8_front; xrb->Base.PutRow = put_row_A8R8G8B8_front; - xrb->Base.PutRowRGB = put_row_rgb_A8R8G8B8_front; - xrb->Base.PutMonoRow = put_mono_row_A8R8G8B8_front; xrb->Base.PutValues = put_values_A8R8G8B8_front; - xrb->Base.PutMonoValues = put_mono_values_A8R8G8B8_front; break; case PF_X8R8G8B8: xrb->Base.GetRow = get_row_X8R8G8B8_front; xrb->Base.GetValues = get_values_X8R8G8B8_front; xrb->Base.PutRow = put_row_X8R8G8B8_front; - xrb->Base.PutRowRGB = put_row_rgb_X8R8G8B8_front; - xrb->Base.PutMonoRow = put_mono_row_X8R8G8B8_front; xrb->Base.PutValues = put_values_X8R8G8B8_front; - xrb->Base.PutMonoValues = put_mono_values_X8R8G8B8_front; break; case PF_R5G6B5: xrb->Base.GetRow = get_row_R5G6B5_front; xrb->Base.GetValues = get_values_R5G6B5_front; xrb->Base.PutRow = put_row_R5G6B5_front; - xrb->Base.PutRowRGB = put_row_rgb_R5G6B5_front; - xrb->Base.PutMonoRow = put_mono_row_R5G6B5_front; xrb->Base.PutValues = put_values_R5G6B5_front; - xrb->Base.PutMonoValues = put_mono_values_R5G6B5_front; break; case PF_R3G3B2: xrb->Base.GetRow = get_row_R3G3B2_front; xrb->Base.GetValues = get_values_R3G3B2_front; xrb->Base.PutRow = put_row_R3G3B2_front; - xrb->Base.PutRowRGB = put_row_rgb_R3G3B2_front; - xrb->Base.PutMonoRow = put_mono_row_R3G3B2_front; xrb->Base.PutValues = put_values_R3G3B2_front; - xrb->Base.PutMonoValues = put_mono_values_R3G3B2_front; break; default: assert(0); diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h b/mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h index 0d2703ca5..50671193e 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h @@ -1,319 +1,223 @@ -/*
- * Mesa 3-D graphics library
- * Version: 6.5.1
- *
- * Copyright (C) 1999-2006 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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/*
- * Modified version of swrast/s_spantemp.h for front-buffer rendering. The
- * no-mask paths use a scratch row to avoid repeated calls to the loader.
- *
- * For the mask paths we always use an array of 4 elements of RB_TYPE. This is
- * to satisfy the xorg loader requirement of an image pitch of 32 bits and
- * should be ok for other loaders also.
- */
-
-
-#ifndef _SWRAST_SPANTEMP_ONCE
-#define _SWRAST_SPANTEMP_ONCE
-
-static INLINE void
-PUT_PIXEL( struct gl_context *glCtx, GLint x, GLint y, GLvoid *p )
-{
- __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
- __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv;
-
- __DRIscreen *screen = ctx->driScreenPriv;
-
- screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW,
- x, y, 1, 1, (char *)p,
- draw->loaderPrivate);
-}
-
-
-static INLINE void
-GET_PIXEL( struct gl_context *glCtx, GLint x, GLint y, GLubyte *p )
-{
- __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
- __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv;
-
- __DRIscreen *screen = ctx->driScreenPriv;
-
- screen->swrast_loader->getImage(read, x, y, 1, 1, (char *)p,
- read->loaderPrivate);
-}
-
-static INLINE void
-PUT_ROW( struct gl_context *glCtx, GLint x, GLint y, GLuint n, char *row )
-{
- __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
- __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv;
-
- __DRIscreen *screen = ctx->driScreenPriv;
-
- screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW,
- x, y, n, 1, row,
- draw->loaderPrivate);
-}
-
-static INLINE void
-GET_ROW( struct gl_context *glCtx, GLint x, GLint y, GLuint n, char *row )
-{
- __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
- __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv;
-
- __DRIscreen *screen = ctx->driScreenPriv;
-
- screen->swrast_loader->getImage(read, x, y, n, 1, row,
- read->loaderPrivate);
-}
-
-#endif /* _SWRAST_SPANTEMP_ONCE */
-
-
-/*
- * Templates for the span/pixel-array write/read functions called via
- * the gl_renderbuffer's GetRow, GetValues, PutRow, PutMonoRow, PutValues
- * and PutMonoValues functions.
- *
- * Define the following macros before including this file:
- * NAME(BASE) to generate the function name (i.e. add prefix or suffix)
- * RB_TYPE the renderbuffer DataType
- * SPAN_VARS to declare any local variables
- * INIT_PIXEL_PTR(P, X, Y) to initialize a pointer to a pixel
- * INC_PIXEL_PTR(P) to increment a pixel pointer by one pixel
- * STORE_PIXEL(DST, X, Y, VALUE) to store pixel values in buffer
- * FETCH_PIXEL(DST, SRC) to fetch pixel values from buffer
- *
- * Note that in the STORE_PIXEL macros, we also pass in the (X,Y) coordinates
- * for the pixels to be stored. This is useful when dithering and probably
- * ignored otherwise.
- */
-
-#include "main/macros.h"
-
-
-#if !defined(RB_COMPONENTS)
-#define RB_COMPONENTS 4
-#endif
-
-
-static void
-NAME(get_row)( struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, GLint x, GLint y, void *values )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values;
- GLuint i;
- char *row = swrast_drawable(ctx->ReadBuffer)->row;
- INIT_PIXEL_PTR(pixel, x, y);
- GET_ROW( ctx, x, YFLIP(xrb, y), count, row );
- for (i = 0; i < count; i++) {
- FETCH_PIXEL(dest[i], pixel);
- INC_PIXEL_PTR(pixel);
- }
- (void) rb;
-}
-
-
-static void
-NAME(get_values)( struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, const GLint x[], const GLint y[], void *values )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values;
- GLuint i;
- for (i = 0; i < count; i++) {
- RB_TYPE pixel[4];
- GET_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
- FETCH_PIXEL(dest[i], pixel);
- }
- (void) rb;
-}
-
-
-static void
-NAME(put_row)( struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, GLint x, GLint y,
- const void *values, const GLubyte mask[] )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values;
- GLuint i;
- if (mask) {
- for (i = 0; i < count; i++) {
- if (mask[i]) {
- RB_TYPE row[4];
- INIT_PIXEL_PTR(pixel, x, y);
- STORE_PIXEL(pixel, x + i, y, src[i]);
- PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
- }
- }
- }
- else {
- char *row = swrast_drawable(ctx->DrawBuffer)->row;
- INIT_PIXEL_PTR(pixel, x, y);
- for (i = 0; i < count; i++) {
- STORE_PIXEL(pixel, x + i, y, src[i]);
- INC_PIXEL_PTR(pixel);
- }
- PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
- }
- (void) rb;
-}
-
-
-static void
-NAME(put_row_rgb)( struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, GLint x, GLint y,
- const void *values, const GLubyte mask[] )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- const RB_TYPE (*src)[3] = (const RB_TYPE (*)[3]) values;
- GLuint i;
- if (mask) {
- for (i = 0; i < count; i++) {
- if (mask[i]) {
- RB_TYPE row[4];
- INIT_PIXEL_PTR(pixel, x, y);
-#ifdef STORE_PIXEL_RGB
- STORE_PIXEL_RGB(pixel, x + i, y, src[i]);
-#else
- STORE_PIXEL(pixel, x + i, y, src[i]);
-#endif
- PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
- }
- }
- }
- else {
- char *row = swrast_drawable(ctx->DrawBuffer)->row;
- INIT_PIXEL_PTR(pixel, x, y);
- for (i = 0; i < count; i++) {
-#ifdef STORE_PIXEL_RGB
- STORE_PIXEL_RGB(pixel, x + i, y, src[i]);
-#else
- STORE_PIXEL(pixel, x + i, y, src[i]);
-#endif
- INC_PIXEL_PTR(pixel);
- }
- PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
- }
- (void) rb;
-}
-
-
-static void
-NAME(put_mono_row)( struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, GLint x, GLint y,
- const void *value, const GLubyte mask[] )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- const RB_TYPE *src = (const RB_TYPE *) value;
- GLuint i;
- if (mask) {
- for (i = 0; i < count; i++) {
- if (mask[i]) {
- RB_TYPE row[4];
- INIT_PIXEL_PTR(pixel, x, y);
- STORE_PIXEL(pixel, x + i, y, src);
- PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
- }
- }
- }
- else {
- char *row = swrast_drawable(ctx->DrawBuffer)->row;
- INIT_PIXEL_PTR(pixel, x, y);
- for (i = 0; i < count; i++) {
- STORE_PIXEL(pixel, x + i, y, src);
- INC_PIXEL_PTR(pixel);
- }
- PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
- }
- (void) rb;
-}
-
-
-static void
-NAME(put_values)( struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, const GLint x[], const GLint y[],
- const void *values, const GLubyte mask[] )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values;
- GLuint i;
- ASSERT(mask);
- for (i = 0; i < count; i++) {
- if (mask[i]) {
- RB_TYPE row[4];
- INIT_PIXEL_PTR(pixel, x, y);
- STORE_PIXEL(pixel, x[i], y[i], src[i]);
- PUT_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
- }
- }
- (void) rb;
-}
-
-
-static void
-NAME(put_mono_values)( struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, const GLint x[], const GLint y[],
- const void *value, const GLubyte mask[] )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- const RB_TYPE *src = (const RB_TYPE *) value;
- GLuint i;
- ASSERT(mask);
- for (i = 0; i < count; i++) {
- if (mask[i]) {
- RB_TYPE row[4];
- INIT_PIXEL_PTR(pixel, x, y);
- STORE_PIXEL(pixel, x[i], y[i], src);
- PUT_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
- }
- }
- (void) rb;
-}
-
-
-#undef NAME
-#undef RB_TYPE
-#undef RB_COMPONENTS
-#undef SPAN_VARS
-#undef INIT_PIXEL_PTR
-#undef INC_PIXEL_PTR
-#undef STORE_PIXEL
-#undef STORE_PIXEL_RGB
-#undef FETCH_PIXEL
+/* + * Mesa 3-D graphics library + * Version: 6.5.1 + * + * Copyright (C) 1999-2006 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Modified version of swrast/s_spantemp.h for front-buffer rendering. The + * no-mask paths use a scratch row to avoid repeated calls to the loader. + * + * For the mask paths we always use an array of 4 elements of RB_TYPE. This is + * to satisfy the xorg loader requirement of an image pitch of 32 bits and + * should be ok for other loaders also. + */ + + +#ifndef _SWRAST_SPANTEMP_ONCE +#define _SWRAST_SPANTEMP_ONCE + +static INLINE void +PUT_PIXEL( struct gl_context *glCtx, GLint x, GLint y, GLvoid *p ) +{ + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv; + + __DRIscreen *screen = ctx->driScreenPriv; + + screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW, + x, y, 1, 1, (char *)p, + draw->loaderPrivate); +} + + +static INLINE void +GET_PIXEL( struct gl_context *glCtx, GLint x, GLint y, GLubyte *p ) +{ + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv; + + __DRIscreen *screen = ctx->driScreenPriv; + + screen->swrast_loader->getImage(read, x, y, 1, 1, (char *)p, + read->loaderPrivate); +} + +static INLINE void +PUT_ROW( struct gl_context *glCtx, GLint x, GLint y, GLuint n, char *row ) +{ + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv; + + __DRIscreen *screen = ctx->driScreenPriv; + + screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW, + x, y, n, 1, row, + draw->loaderPrivate); +} + +static INLINE void +GET_ROW( struct gl_context *glCtx, GLint x, GLint y, GLuint n, char *row ) +{ + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv; + + __DRIscreen *screen = ctx->driScreenPriv; + + screen->swrast_loader->getImage(read, x, y, n, 1, row, + read->loaderPrivate); +} + +#endif /* _SWRAST_SPANTEMP_ONCE */ + + +/* + * Templates for the span/pixel-array write/read functions called via + * the gl_renderbuffer's GetRow, GetValues, PutRow and PutValues. + * + * Define the following macros before including this file: + * NAME(BASE) to generate the function name (i.e. add prefix or suffix) + * RB_TYPE the renderbuffer DataType + * SPAN_VARS to declare any local variables + * INIT_PIXEL_PTR(P, X, Y) to initialize a pointer to a pixel + * INC_PIXEL_PTR(P) to increment a pixel pointer by one pixel + * STORE_PIXEL(DST, X, Y, VALUE) to store pixel values in buffer + * FETCH_PIXEL(DST, SRC) to fetch pixel values from buffer + * + * Note that in the STORE_PIXEL macros, we also pass in the (X,Y) coordinates + * for the pixels to be stored. This is useful when dithering and probably + * ignored otherwise. + */ + +#include "main/macros.h" + + +#if !defined(RB_COMPONENTS) +#define RB_COMPONENTS 4 +#endif + + +static void +NAME(get_row)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, void *values ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values; + GLuint i; + char *row = swrast_drawable(ctx->ReadBuffer)->row; + INIT_PIXEL_PTR(pixel, x, y); + GET_ROW( ctx, x, YFLIP(xrb, y), count, row ); + for (i = 0; i < count; i++) { + FETCH_PIXEL(dest[i], pixel); + INC_PIXEL_PTR(pixel); + } + (void) rb; +} + + +static void +NAME(get_values)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], void *values ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values; + GLuint i; + for (i = 0; i < count; i++) { + RB_TYPE pixel[4]; + GET_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel); + FETCH_PIXEL(dest[i], pixel); + } + (void) rb; +} + + +static void +NAME(put_row)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, GLint x, GLint y, + const void *values, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values; + GLuint i; + if (mask) { + for (i = 0; i < count; i++) { + if (mask[i]) { + RB_TYPE row[4]; + INIT_PIXEL_PTR(pixel, x, y); + STORE_PIXEL(pixel, x + i, y, src[i]); + PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel); + } + } + } + else { + char *row = swrast_drawable(ctx->DrawBuffer)->row; + INIT_PIXEL_PTR(pixel, x, y); + for (i = 0; i < count; i++) { + STORE_PIXEL(pixel, x + i, y, src[i]); + INC_PIXEL_PTR(pixel); + } + PUT_ROW( ctx, x, YFLIP(xrb, y), count, row ); + } + (void) rb; +} + + +static void +NAME(put_values)( struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *values, const GLubyte mask[] ) +{ +#ifdef SPAN_VARS + SPAN_VARS +#endif + const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values; + GLuint i; + ASSERT(mask); + for (i = 0; i < count; i++) { + if (mask[i]) { + RB_TYPE row[4]; + INIT_PIXEL_PTR(pixel, x, y); + STORE_PIXEL(pixel, x[i], y[i], src[i]); + PUT_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel); + } + } + (void) rb; +} + + + + +#undef NAME +#undef RB_TYPE +#undef RB_COMPONENTS +#undef SPAN_VARS +#undef INIT_PIXEL_PTR +#undef INC_PIXEL_PTR +#undef STORE_PIXEL +#undef STORE_PIXEL_RGB +#undef FETCH_PIXEL diff --git a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c index 675ffdaaa..255d811ca 100644 --- a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c +++ b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c @@ -526,61 +526,6 @@ static void write_rgba_span_front(struct gl_context *ctx, } } -/* Write a horizontal span of RGB color pixels with a boolean mask. */ -static void write_rgb_span_front(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *values, - const GLubyte *mask) -{ - const GLubyte (*rgb)[3] = (const GLubyte (*)[3])values; - WMesaContext pwc = wmesa_context(ctx); - GLuint i; - - (void) ctx; - y=FLIP(y); - if (mask) { - for (i=0; i<n; i++) - if (mask[i]) - SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP], - rgb[i][BCOMP])); - } - else { - for (i=0; i<n; i++) - SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP], - rgb[i][BCOMP])); - } - -} - -/* - * Write a horizontal span of pixels with a boolean mask. The current color - * is used for all pixels. - */ -static void write_mono_rgba_span_front(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *value, - const GLubyte *mask) -{ - const GLchan *color = (const GLchan *)value; - GLuint i; - WMesaContext pwc = wmesa_context(ctx); - COLORREF colorref; - - (void) ctx; - colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]); - y=FLIP(y); - if (mask) { - for (i=0; i<n; i++) - if (mask[i]) - SetPixel(pwc->hDC, x+i, y, colorref); - } - else - for (i=0; i<n; i++) - SetPixel(pwc->hDC, x+i, y, colorref); - -} /* Write an array of RGBA pixels with a boolean mask. */ static void write_rgba_pixels_front(struct gl_context *ctx, @@ -603,28 +548,6 @@ static void write_rgba_pixels_front(struct gl_context *ctx, -/* - * Write an array of pixels with a boolean mask. The current color - * is used for all pixels. - */ -static void write_mono_rgba_pixels_front(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, - const GLint x[], const GLint y[], - const void *value, - const GLubyte *mask) -{ - const GLchan *color = (const GLchan *)value; - GLuint i; - WMesaContext pwc = wmesa_context(ctx); - COLORREF colorref; - (void) ctx; - colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]); - for (i=0; i<n; i++) - if (mask[i]) - SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref); -} - /* Read a horizontal span of color pixels. */ static void read_rgba_span_front(struct gl_context *ctx, struct gl_renderbuffer *rb, @@ -706,64 +629,6 @@ static void write_rgba_span_32(struct gl_context *ctx, } -/* Write a horizontal span of RGB color pixels with a boolean mask. */ -static void write_rgb_span_32(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *values, - const GLubyte *mask) -{ - const GLubyte (*rgb)[3] = (const GLubyte (*)[3])values; - WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); - GLuint i; - LPDWORD lpdw; - - (void) ctx; - - y=FLIP(y); - lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; - if (mask) { - for (i=0; i<n; i++) - if (mask[i]) - lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP], - rgb[i][BCOMP]); - } - else { - for (i=0; i<n; i++) - *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP], - rgb[i][BCOMP]); - } -} - -/* - * Write a horizontal span of pixels with a boolean mask. The current color - * is used for all pixels. - */ -static void write_mono_rgba_span_32(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *value, - const GLubyte *mask) -{ - const GLchan *color = (const GLchan *)value; - LPDWORD lpdw; - DWORD pixel; - GLuint i; - WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); - lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; - y=FLIP(y); - pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]); - if (mask) { - for (i=0; i<n; i++) - if (mask[i]) - lpdw[i] = pixel; - } - else - for (i=0; i<n; i++) - *lpdw++ = pixel; - -} - /* Write an array of RGBA pixels with a boolean mask. */ static void write_rgba_pixels_32(struct gl_context *ctx, struct gl_renderbuffer *rb, @@ -780,25 +645,6 @@ static void write_rgba_pixels_32(struct gl_context *ctx, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); } -/* - * Write an array of pixels with a boolean mask. The current color - * is used for all pixels. - */ -static void write_mono_rgba_pixels_32(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, - const GLint x[], const GLint y[], - const void *value, - const GLubyte *mask) -{ - const GLchan *color = (const GLchan *)value; - GLuint i; - WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); - for (i=0; i<n; i++) - if (mask[i]) - WMSETPIXEL32(pwfb, FLIP(y[i]),x[i],color[RCOMP], - color[GCOMP], color[BCOMP]); -} /* Read a horizontal span of color pixels. */ static void read_rgba_span_32(struct gl_context *ctx, @@ -892,71 +738,6 @@ static void write_rgba_span_24(struct gl_context *ctx, } -/* Write a horizontal span of RGB color pixels with a boolean mask. */ -static void write_rgb_span_24(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *values, - const GLubyte *mask) -{ - const GLubyte (*rgb)[3] = (const GLubyte (*)[3])values; - WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); - GLuint i; - LPBYTE lpb; - - (void) ctx; - - y=FLIP(y); - lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x); - if (mask) { - for (i=0; i<n; i++) - if (mask[i]) { - lpb[3*i] = rgb[i][BCOMP]; - lpb[3*i+1] = rgb[i][GCOMP]; - lpb[3*i+2] = rgb[i][RCOMP]; - } - } - else { - for (i=0; i<n; i++) { - *lpb++ = rgb[i][BCOMP]; - *lpb++ = rgb[i][GCOMP]; - *lpb++ = rgb[i][RCOMP]; - } - } -} - -/* - * Write a horizontal span of pixels with a boolean mask. The current color - * is used for all pixels. - */ -static void write_mono_rgba_span_24(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *value, - const GLubyte *mask) -{ - const GLchan *color = (const GLchan *)value; - LPBYTE lpb; - GLuint i; - WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); - lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x); - y=FLIP(y); - if (mask) { - for (i=0; i<n; i++) - if (mask[i]) { - lpb[3*i] = color[BCOMP]; - lpb[3*i+1] = color[GCOMP]; - lpb[3*i+2] = color[RCOMP]; - } - } - else - for (i=0; i<n; i++) { - *lpb++ = color[BCOMP]; - *lpb++ = color[GCOMP]; - *lpb++ = color[RCOMP]; - } -} - /* Write an array of RGBA pixels with a boolean mask. */ static void write_rgba_pixels_24(struct gl_context *ctx, struct gl_renderbuffer *rb, @@ -973,25 +754,6 @@ static void write_rgba_pixels_24(struct gl_context *ctx, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); } -/* - * Write an array of pixels with a boolean mask. The current color - * is used for all pixels. - */ -static void write_mono_rgba_pixels_24(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, - const GLint x[], const GLint y[], - const void *value, - const GLubyte *mask) -{ - const GLchan *color = (const GLchan *)value; - GLuint i; - WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); - for (i=0; i<n; i++) - if (mask[i]) - WMSETPIXEL24(pwfb, FLIP(y[i]),x[i],color[RCOMP], - color[GCOMP], color[BCOMP]); -} /* Read a horizontal span of color pixels. */ static void read_rgba_span_24(struct gl_context *ctx, @@ -1077,64 +839,6 @@ static void write_rgba_span_16(struct gl_context *ctx, } -/* Write a horizontal span of RGB color pixels with a boolean mask. */ -static void write_rgb_span_16(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *values, - const GLubyte *mask) -{ - const GLubyte (*rgb)[3] = (const GLubyte (*)[3])values; - WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); - GLuint i; - LPWORD lpw; - - (void) ctx; - - y=FLIP(y); - lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; - if (mask) { - for (i=0; i<n; i++) - if (mask[i]) - lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP], - rgb[i][BCOMP]); - } - else { - for (i=0; i<n; i++) - *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP], - rgb[i][BCOMP]); - } -} - -/* - * Write a horizontal span of pixels with a boolean mask. The current color - * is used for all pixels. - */ -static void write_mono_rgba_span_16(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, GLint x, GLint y, - const void *value, - const GLubyte *mask) -{ - const GLchan *color = (const GLchan *)value; - LPWORD lpw; - WORD pixel; - GLuint i; - WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); - (void) ctx; - lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; - y=FLIP(y); - pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]); - if (mask) { - for (i=0; i<n; i++) - if (mask[i]) - lpw[i] = pixel; - } - else - for (i=0; i<n; i++) - *lpw++ = pixel; - -} /* Write an array of RGBA pixels with a boolean mask. */ static void write_rgba_pixels_16(struct gl_context *ctx, @@ -1153,26 +857,6 @@ static void write_rgba_pixels_16(struct gl_context *ctx, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); } -/* - * Write an array of pixels with a boolean mask. The current color - * is used for all pixels. - */ -static void write_mono_rgba_pixels_16(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint n, - const GLint x[], const GLint y[], - const void *value, - const GLubyte *mask) -{ - const GLchan *color = (const GLchan *)value; - GLuint i; - WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); - (void) ctx; - for (i=0; i<n; i++) - if (mask[i]) - WMSETPIXEL16(pwfb, FLIP(y[i]),x[i],color[RCOMP], - color[GCOMP], color[BCOMP]); -} /* Read a horizontal span of color pixels. */ static void read_rgba_span_16(struct gl_context *ctx, @@ -1270,10 +954,7 @@ wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat, switch(pixelformat) { case PF_5R6G5B: rb->PutRow = write_rgba_span_16; - rb->PutRowRGB = write_rgb_span_16; - rb->PutMonoRow = write_mono_rgba_span_16; rb->PutValues = write_rgba_pixels_16; - rb->PutMonoValues = write_mono_rgba_pixels_16; rb->GetRow = read_rgba_span_16; rb->GetValues = read_rgba_pixels_16; break; @@ -1281,22 +962,16 @@ wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat, if (cColorBits == 24) { rb->PutRow = write_rgba_span_24; - rb->PutRowRGB = write_rgb_span_24; - rb->PutMonoRow = write_mono_rgba_span_24; rb->PutValues = write_rgba_pixels_24; - rb->PutMonoValues = write_mono_rgba_pixels_24; rb->GetRow = read_rgba_span_24; rb->GetValues = read_rgba_pixels_24; } else { - rb->PutRow = write_rgba_span_32; - rb->PutRowRGB = write_rgb_span_32; - rb->PutMonoRow = write_mono_rgba_span_32; - rb->PutValues = write_rgba_pixels_32; - rb->PutMonoValues = write_mono_rgba_pixels_32; - rb->GetRow = read_rgba_span_32; - rb->GetValues = read_rgba_pixels_32; + rb->PutRow = write_rgba_span_32; + rb->PutValues = write_rgba_pixels_32; + rb->GetRow = read_rgba_span_32; + rb->GetValues = read_rgba_pixels_32; } break; default: @@ -1306,10 +981,7 @@ wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat, else { /* front buffer (actual Windows window) */ rb->PutRow = write_rgba_span_front; - rb->PutRowRGB = write_rgb_span_front; - rb->PutMonoRow = write_mono_rgba_span_front; rb->PutValues = write_rgba_pixels_front; - rb->PutMonoValues = write_mono_rgba_pixels_front; rb->GetRow = read_rgba_span_front; rb->GetValues = read_rgba_pixels_front; } diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index 01cfff8ab..5816faa78 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -491,6 +491,8 @@ struct dd_function_table { void (*FreeTextureImageBuffer)( struct gl_context *ctx, struct gl_texture_image *tImage ); /** Map a slice of a texture image into user space. + * Note: for GL_TEXTURE_1D_ARRAY, height must be 1, y must be 0 and slice + * indicates the 1D array index. * \param texImage the texture image * \param slice the 3D image slice or array texture slice * \param x, y, w, h region of interest diff --git a/mesalib/src/mesa/main/format_pack.c b/mesalib/src/mesa/main/format_pack.c index 390b494c0..840559bac 100644 --- a/mesalib/src/mesa/main/format_pack.c +++ b/mesalib/src/mesa/main/format_pack.c @@ -2494,3 +2494,78 @@ _mesa_pack_uint_24_8_depth_stencil_row(gl_format format, GLuint n, return; } } + + + +/** + * Convert a boolean color mask to a packed color where each channel of + * the packed value at dst will be 0 or ~0 depending on the colorMask. + */ +void +_mesa_pack_colormask(gl_format format, const GLubyte colorMask[4], void *dst) +{ + GLfloat maskColor[4]; + + switch (_mesa_get_format_datatype(format)) { + case GL_UNSIGNED_NORMALIZED: + /* simple: 1.0 will convert to ~0 in the right bit positions */ + maskColor[0] = colorMask[0] ? 1.0 : 0.0; + maskColor[1] = colorMask[1] ? 1.0 : 0.0; + maskColor[2] = colorMask[2] ? 1.0 : 0.0; + maskColor[3] = colorMask[3] ? 1.0 : 0.0; + _mesa_pack_float_rgba_row(format, 1, + (const GLfloat (*)[4]) maskColor, dst); + break; + case GL_SIGNED_NORMALIZED: + case GL_FLOAT: + /* These formats are harder because it's hard to know the floating + * point values that will convert to ~0 for each color channel's bits. + * This solution just generates a non-zero value for each color channel + * then fixes up the non-zero values to be ~0. + * Note: we'll need to add special case code if we ever have to deal + * with formats with unequal color channel sizes, like R11_G11_B10. + * We issue a warning below for channel sizes other than 8,16,32. + */ + { + GLuint bits = _mesa_get_format_max_bits(format); /* bits per chan */ + GLuint bytes = _mesa_get_format_bytes(format); + GLuint i; + + /* this should put non-zero values into the channels of dst */ + maskColor[0] = colorMask[0] ? -1.0 : 0.0; + maskColor[1] = colorMask[1] ? -1.0 : 0.0; + maskColor[2] = colorMask[2] ? -1.0 : 0.0; + maskColor[3] = colorMask[3] ? -1.0 : 0.0; + _mesa_pack_float_rgba_row(format, 1, + (const GLfloat (*)[4]) maskColor, dst); + + /* fix-up the dst channels by converting non-zero values to ~0 */ + if (bits == 8) { + GLubyte *d = (GLubyte *) dst; + for (i = 0; i < bytes; i++) { + d[i] = d[i] ? 0xffff : 0x0; + } + } + else if (bits == 16) { + GLushort *d = (GLushort *) dst; + for (i = 0; i < bytes / 2; i++) { + d[i] = d[i] ? 0xffff : 0x0; + } + } + else if (bits == 32) { + GLuint *d = (GLuint *) dst; + for (i = 0; i < bytes / 4; i++) { + d[i] = d[i] ? 0xffffffffU : 0x0; + } + } + else { + _mesa_problem(NULL, "unexpected size in _mesa_pack_colormask()"); + return; + } + } + break; + default: + _mesa_problem(NULL, "unexpected format data type in gen_color_mask()"); + return; + } +} diff --git a/mesalib/src/mesa/main/format_pack.h b/mesalib/src/mesa/main/format_pack.h index 7df135632..f1b480510 100644 --- a/mesalib/src/mesa/main/format_pack.h +++ b/mesalib/src/mesa/main/format_pack.h @@ -95,4 +95,7 @@ _mesa_pack_uint_24_8_depth_stencil_row(gl_format format, GLuint n, const GLuint *src, void *dst); +extern void +_mesa_pack_colormask(gl_format format, const GLubyte colorMask[4], void *dst); + #endif diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index 1f83a5368..cca0014b1 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -27,6 +27,7 @@ #include "imports.h" #include "formats.h" #include "mfeatures.h" +#include "macros.h" /** @@ -1613,6 +1614,21 @@ _mesa_get_format_bits(gl_format format, GLenum pname) } +GLuint +_mesa_get_format_max_bits(gl_format format) +{ + const struct gl_format_info *info = _mesa_get_format_info(format); + GLuint max = MAX2(info->RedBits, info->GreenBits); + max = MAX2(max, info->BlueBits); + max = MAX2(max, info->AlphaBits); + max = MAX2(max, info->LuminanceBits); + max = MAX2(max, info->IntensityBits); + max = MAX2(max, info->DepthBits); + max = MAX2(max, info->StencilBits); + return max; +} + + /** * Return the data type (or more specifically, the data representation) * for the given format. diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h index e6b429d5f..960934338 100644 --- a/mesalib/src/mesa/main/formats.h +++ b/mesalib/src/mesa/main/formats.h @@ -290,6 +290,9 @@ _mesa_get_format_bytes(gl_format format); extern GLint _mesa_get_format_bits(gl_format format, GLenum pname); +extern GLuint +_mesa_get_format_max_bits(gl_format format); + extern GLenum _mesa_get_format_datatype(gl_format format); diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 3d3b006d5..02452aa68 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -2538,33 +2538,12 @@ struct gl_renderbuffer void (*PutRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, GLint x, GLint y, const void *values, const GLubyte *mask); - /* Put/Write a row of RGB values. This is a special-case routine that's - * only used for RGBA renderbuffers when the source data is GL_RGB. That's - * a common case for glDrawPixels and some triangle routines. - * The values will be of format GL_RGB and type DataType. - */ - void (*PutRowRGB)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *values, const GLubyte *mask); - - - /* Put/Write a row of identical values. - * The values will be of format _BaseFormat and type DataType. - */ - void (*PutMonoRow)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *value, const GLubyte *mask); - /* Put/Write values at arbitrary locations. * The values will be of format _BaseFormat and type DataType. */ void (*PutValues)(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], const void *values, const GLubyte *mask); - /* Put/Write identical values at arbitrary locations. - * The values will be of format _BaseFormat and type DataType. - */ - void (*PutMonoValues)(struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte *mask); }; diff --git a/mesalib/src/mesa/main/renderbuffer.c b/mesalib/src/mesa/main/renderbuffer.c index d82b19ad5..bb8f46d11 100644 --- a/mesalib/src/mesa/main/renderbuffer.c +++ b/mesalib/src/mesa/main/renderbuffer.c @@ -78,10 +78,7 @@ _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name) rb->GetRow = NULL; rb->GetValues = NULL; rb->PutRow = NULL; - rb->PutRowRGB = NULL; - rb->PutMonoRow = NULL; rb->PutValues = NULL; - rb->PutMonoValues = NULL; } diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index c4d01abc7..b71b44b70 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -1436,7 +1436,7 @@ _mesa_UseProgramObjectARB(GLhandleARB program) ASSERT_OUTSIDE_BEGIN_END(ctx); - if (obj->Active) { + if (obj->Active && !obj->Paused) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram(transform feedback active)"); return; @@ -1638,7 +1638,8 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program) return; } - if (ctx->TransformFeedback.CurrentObject->Active) { + if (ctx->TransformFeedback.CurrentObject->Active && + !ctx->TransformFeedback.CurrentObject->Paused) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseShaderProgramEXT(transform feedback is active)"); return; diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index 3f2418729..738c18112 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -216,183 +216,213 @@ get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions, /** - * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc). - * Compressed textures are handled here as well. + * Get a color texture image with decompression. */ static void -get_tex_rgba(struct gl_context *ctx, GLuint dimensions, - GLenum format, GLenum type, GLvoid *pixels, - struct gl_texture_image *texImage) +get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, + GLenum format, GLenum type, GLvoid *pixels, + struct gl_texture_image *texImage, + GLbitfield transferOps) { /* don't want to apply sRGB -> RGB conversion here so override the format */ - const gl_format texFormat = _mesa_get_srgb_format_linear(texImage->TexFormat); + const gl_format texFormat = + _mesa_get_srgb_format_linear(texImage->TexFormat); + const GLenum baseFormat = _mesa_get_format_base_format(texFormat); const GLuint width = texImage->Width; const GLuint height = texImage->Height; const GLuint depth = texImage->Depth; - const GLenum dataType = _mesa_get_format_datatype(texFormat); - const GLenum baseFormat = _mesa_get_format_base_format(texFormat); - /* Normally, no pixel transfer ops are performed during glGetTexImage. - * The only possible exception is component clamping to [0,1]. - */ - GLbitfield transferOps = 0x0; - - /* In general, clamping does not apply to glGetTexImage, except when - * the returned type of the image can't hold negative values. - */ - if (type_needs_clamping(type)) { - /* the returned image type can't have negative values */ - if (dataType == GL_FLOAT || - dataType == GL_SIGNED_NORMALIZED || - format == GL_LUMINANCE || - format == GL_LUMINANCE_ALPHA) { - transferOps |= IMAGE_CLAMP_BIT; - } + GLfloat *tempImage, *srcRow; + GLuint row; + + /* Decompress into temp float buffer, then pack into user buffer */ + tempImage = (GLfloat *) malloc(width * height * depth + * 4 * sizeof(GLfloat)); + if (!tempImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); + return; } - if (_mesa_is_format_compressed(texFormat)) { - /* Decompress into temp buffer, then pack into user buffer */ - GLfloat *tempImage, *srcRow; - GLuint row; + /* Decompress the texture image - results in 'tempImage' */ + { + GLubyte *srcMap; + GLint srcRowStride; + GLuint bytes, bw, bh; - tempImage = (GLfloat *) malloc(texImage->Width * texImage->Height * - texImage->Depth * 4 * sizeof(GLfloat)); - if (!tempImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); - return; - } + bytes = _mesa_get_format_bytes(texFormat); + _mesa_get_format_block_size(texFormat, &bw, &bh); - /* Decompress the texture image - results in 'tempImage' */ - { - GLubyte *srcMap; - GLint srcRowStride; - GLuint bytes, bw, bh; + ctx->Driver.MapTextureImage(ctx, texImage, 0, + 0, 0, width, height, + GL_MAP_READ_BIT, + &srcMap, &srcRowStride); + if (srcMap) { + /* XXX This line is a bit of a hack to work around the + * mismatch of compressed row strides as returned by + * MapTextureImage() vs. what the texture decompression code + * uses. This will be fixed in the future. + */ + srcRowStride = srcRowStride * bh / bytes; - bytes = _mesa_get_format_bytes(texImage->TexFormat); - _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); + _mesa_decompress_image(texFormat, width, height, + srcMap, srcRowStride, tempImage); - ctx->Driver.MapTextureImage(ctx, texImage, 0, - 0, 0, width, height, - GL_MAP_READ_BIT, - &srcMap, &srcRowStride); + ctx->Driver.UnmapTextureImage(ctx, texImage, 0); + } + else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); + } + } - if (srcMap) { - /* XXX This line is a bit of a hack to work around the - * mismatch of compressed row strides as returned by - * MapTextureImage() vs. what the texture decompression code - * uses. This will be fixed in the future. - */ - srcRowStride = srcRowStride * bh / bytes; + if (baseFormat == GL_LUMINANCE || + baseFormat == GL_LUMINANCE_ALPHA) { + /* Set green and blue to zero since the pack function here will + * compute L=R+G+B. + */ + GLuint i; + for (i = 0; i < width * height; i++) { + tempImage[i * 4 + GCOMP] = tempImage[i * 4 + BCOMP] = 0.0f; + } + } - _mesa_decompress_image(texFormat, width, height, - srcMap, srcRowStride, tempImage); + srcRow = tempImage; + for (row = 0; row < height; row++) { + void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, + width, height, format, type, + 0, row, 0); - ctx->Driver.UnmapTextureImage(ctx, texImage, 0); - } - else { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); - } - } + _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) srcRow, + format, type, dest, &ctx->Pack, transferOps); + srcRow += width * 4; + } - if (baseFormat == GL_LUMINANCE || - baseFormat == GL_LUMINANCE_ALPHA) { - /* Set green and blue to zero since the pack function here will - * compute L=R+G+B. - */ - GLuint i; - for (i = 0; i < width * height; i++) { - tempImage[i * 4 + GCOMP] = tempImage[i * 4 + BCOMP] = 0.0f; - } - } + free(tempImage); +} - srcRow = tempImage; - for (row = 0; row < height; row++) { - void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, - width, height, format, type, - 0, row, 0); - _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) srcRow, - format, type, dest, &ctx->Pack, transferOps); - srcRow += width * 4; - } +/** + * Get an uncompressed color texture image. + */ +static void +get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, + GLenum format, GLenum type, GLvoid *pixels, + struct gl_texture_image *texImage, + GLbitfield transferOps) +{ + /* don't want to apply sRGB -> RGB conversion here so override the format */ + const gl_format texFormat = + _mesa_get_srgb_format_linear(texImage->TexFormat); + const GLuint width = texImage->Width; + const GLuint height = texImage->Height; + const GLuint depth = texImage->Depth; + GLuint img, row; + GLfloat (*rgba)[4]; - free(tempImage); + /* Allocate buffer for one row of texels */ + rgba = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat)); + if (!rgba) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); + return; } - else { - /* No decompression needed */ - GLuint img, row; - GLfloat (*rgba)[4]; - rgba = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat)); - if (!rgba) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); - return; - } + for (img = 0; img < depth; img++) { + GLubyte *srcMap; + GLint rowstride; - for (img = 0; img < depth; img++) { - GLubyte *srcMap; - GLint rowstride; - - /* map src texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, img, - 0, 0, width, height, GL_MAP_READ_BIT, - &srcMap, &rowstride); - - if (srcMap) { - for (row = 0; row < height; row++) { - const GLubyte *src = srcMap + row * rowstride; - void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, - width, height, format, type, - img, row, 0); - - _mesa_unpack_rgba_row(texFormat, width, src, rgba); - - if (texImage->_BaseFormat == GL_ALPHA) { - GLint col; - for (col = 0; col < width; col++) { - rgba[col][RCOMP] = 0.0F; - rgba[col][GCOMP] = 0.0F; - rgba[col][BCOMP] = 0.0F; - } + /* map src texture buffer */ + ctx->Driver.MapTextureImage(ctx, texImage, img, + 0, 0, width, height, GL_MAP_READ_BIT, + &srcMap, &rowstride); + if (srcMap) { + for (row = 0; row < height; row++) { + const GLubyte *src = srcMap + row * rowstride; + void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, + width, height, format, type, + img, row, 0); + + _mesa_unpack_rgba_row(texFormat, width, src, rgba); + + if (texImage->_BaseFormat == GL_ALPHA) { + GLint col; + for (col = 0; col < width; col++) { + rgba[col][RCOMP] = 0.0F; + rgba[col][GCOMP] = 0.0F; + rgba[col][BCOMP] = 0.0F; } - else if (texImage->_BaseFormat == GL_LUMINANCE) { - GLint col; - for (col = 0; col < width; col++) { - rgba[col][GCOMP] = 0.0F; - rgba[col][BCOMP] = 0.0F; - rgba[col][ACOMP] = 1.0F; - } + } + else if (texImage->_BaseFormat == GL_LUMINANCE) { + GLint col; + for (col = 0; col < width; col++) { + rgba[col][GCOMP] = 0.0F; + rgba[col][BCOMP] = 0.0F; + rgba[col][ACOMP] = 1.0F; } - else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) { - GLint col; - for (col = 0; col < width; col++) { - rgba[col][GCOMP] = 0.0F; - rgba[col][BCOMP] = 0.0F; - } + } + else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) { + GLint col; + for (col = 0; col < width; col++) { + rgba[col][GCOMP] = 0.0F; + rgba[col][BCOMP] = 0.0F; } - else if (texImage->_BaseFormat == GL_INTENSITY) { - GLint col; - for (col = 0; col < width; col++) { - rgba[col][GCOMP] = 0.0F; - rgba[col][BCOMP] = 0.0F; - rgba[col][ACOMP] = 1.0F; - } + } + else if (texImage->_BaseFormat == GL_INTENSITY) { + GLint col; + for (col = 0; col < width; col++) { + rgba[col][GCOMP] = 0.0F; + rgba[col][BCOMP] = 0.0F; + rgba[col][ACOMP] = 1.0F; } - - _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, - format, type, dest, - &ctx->Pack, transferOps); } - /* Unmap the src texture buffer */ - ctx->Driver.UnmapTextureImage(ctx, texImage, img); - } - else { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); - break; + _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, + format, type, dest, + &ctx->Pack, transferOps); } + + /* Unmap the src texture buffer */ + ctx->Driver.UnmapTextureImage(ctx, texImage, img); + } + else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); + break; } + } + + free(rgba); +} + - free(rgba); +/** + * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc). + * Compressed textures are handled here as well. + */ +static void +get_tex_rgba(struct gl_context *ctx, GLuint dimensions, + GLenum format, GLenum type, GLvoid *pixels, + struct gl_texture_image *texImage) +{ + const GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat); + GLbitfield transferOps = 0x0; + + /* In general, clamping does not apply to glGetTexImage, except when + * the returned type of the image can't hold negative values. + */ + if (type_needs_clamping(type)) { + /* the returned image type can't have negative values */ + if (dataType == GL_FLOAT || + dataType == GL_SIGNED_NORMALIZED || + format == GL_LUMINANCE || + format == GL_LUMINANCE_ALPHA) { + transferOps |= IMAGE_CLAMP_BIT; + } + } + + if (_mesa_is_format_compressed(texImage->TexFormat)) { + get_tex_rgba_compressed(ctx, dimensions, format, type, + pixels, texImage, transferOps); + } + else { + get_tex_rgba_uncompressed(ctx, dimensions, format, type, + pixels, texImage, transferOps); } } @@ -702,20 +732,20 @@ getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, return GL_TRUE; } - texImage = _mesa_select_tex_image(ctx, texObj, target, level); - if (!texImage) { - /* out of memory */ - return GL_TRUE; - } - if (!_mesa_is_legal_format_and_type(ctx, format, type)) { - /*GL_INVALID_OPERATION is generated by a format/type + /* GL_INVALID_OPERATION is generated by a format/type * mismatch (see the 1.2 spec page 94, sec 3.6.4.) */ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(target)"); return GL_TRUE; } + texImage = _mesa_select_tex_image(ctx, texObj, target, level); + if (!texImage) { + /* non-existant texture image */ + return GL_TRUE; + } + baseFormat = _mesa_get_format_base_format(texImage->TexFormat); /* Make sure the requested image format is compatible with the diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index a57a38e12..86c35d38f 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -4565,9 +4565,137 @@ get_read_write_mode(GLenum userFormat, gl_format texFormat) return GL_MAP_WRITE_BIT; } + +/** + * Helper function for storing 1D, 2D, 3D whole and subimages into texture + * memory. + * The source of the image data may be user memory or a PBO. In the later + * case, we'll map the PBO, copy from it, then unmap it. + */ +static void +store_texsubimage(struct gl_context *ctx, + struct gl_texture_image *texImage, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint width, GLint height, GLint depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + const char *caller) + +{ + const GLbitfield mapMode = get_read_write_mode(format, texImage->TexFormat); + const GLenum target = texImage->TexObject->Target; + GLboolean success = GL_FALSE; + GLuint dims, slice, numSlices = 1, sliceOffset = 0; + GLint srcImageStride = 0; + const GLubyte *src; + + assert(xoffset + width <= texImage->Width); + assert(yoffset + height <= texImage->Height); + assert(zoffset + depth <= texImage->Depth); + + switch (target) { + case GL_TEXTURE_1D: + dims = 1; + break; + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_3D: + dims = 3; + break; + default: + dims = 2; + } + + /* get pointer to src pixels (may be in a pbo which we'll map here) */ + src = (const GLubyte *) + _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, + format, type, pixels, packing, caller); + if (!src) + return; + + /* compute slice info (and do some sanity checks) */ + switch (target) { + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_CUBE_MAP: + /* one image slice, nothing special needs to be done */ + break; + case GL_TEXTURE_1D: + assert(height == 1); + assert(depth == 1); + assert(yoffset == 0); + assert(zoffset == 0); + break; + case GL_TEXTURE_1D_ARRAY: + assert(depth == 1); + assert(zoffset == 0); + numSlices = height; + sliceOffset = yoffset; + height = 1; + yoffset = 0; + srcImageStride = _mesa_image_row_stride(packing, width, format, type); + break; + case GL_TEXTURE_2D_ARRAY: + numSlices = depth; + sliceOffset = zoffset; + depth = 1; + zoffset = 0; + srcImageStride = _mesa_image_image_stride(packing, width, height, + format, type); + break; + case GL_TEXTURE_3D: + /* we'll store 3D images as a series of slices */ + numSlices = depth; + sliceOffset = zoffset; + srcImageStride = _mesa_image_image_stride(packing, width, height, + format, type); + break; + default: + _mesa_warning(ctx, "Unexpected target 0x%x in store_texsubimage()", target); + return; + } + + assert(numSlices == 1 || srcImageStride != 0); + + for (slice = 0; slice < numSlices; slice++) { + GLubyte *dstMap; + GLint dstRowStride; + + ctx->Driver.MapTextureImage(ctx, texImage, + slice + sliceOffset, + xoffset, yoffset, width, height, + mapMode, &dstMap, &dstRowStride); + if (dstMap) { + /* Note: we're only storing a 2D (or 1D) slice at a time but we need + * to pass the right 'dims' value so that GL_UNPACK_SKIP_IMAGES is + * used for 3D images. + */ + success = _mesa_texstore(ctx, dims, texImage->_BaseFormat, + texImage->TexFormat, + 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, + &dstMap, + width, height, 1, /* w, h, d */ + format, type, src, packing); + + ctx->Driver.UnmapTextureImage(ctx, texImage, slice + sliceOffset); + } + + src += srcImageStride; + + if (!success) + break; + } + + if (!success) + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); + + _mesa_unmap_teximage_pbo(ctx, packing); +} + + + /** - * This is the software fallback for Driver.TexImage1D(). - * \sa _mesa_store_teximage2d() + * This is the fallback for Driver.TexImage1D(). */ void _mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level, @@ -4578,13 +4706,6 @@ _mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat); - GLubyte *dstMap; - GLint dstRowStride; - GLboolean success; - - (void) border; - if (width == 0) return; @@ -4595,47 +4716,14 @@ _mesa_store_teximage1d(struct gl_context *ctx, GLenum target, GLint level, return; } - pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, - pixels, packing, "glTexImage1D"); - if (!pixels) { - /* Note: we check for a NULL image pointer here, _after_ we allocated - * memory for the texture. That's what the GL spec calls for. - */ - return; - } - - /* Map dest texture buffer (write to whole region) */ - ctx->Driver.MapTextureImage(ctx, texImage, 0, - 0, 0, width, 1, - rwMode, - &dstMap, &dstRowStride); - if (dstMap) { - success = _mesa_texstore(ctx, 1, texImage->_BaseFormat, - texImage->TexFormat, - 0, 0, 0, /* dstX/Y/Zoffset */ - 0, /* dstRowStride */ - &dstMap, - width, 1, 1, - format, type, pixels, packing); - - ctx->Driver.UnmapTextureImage(ctx, texImage, 0); - } - else { - success = GL_FALSE; - } - - if (!success) - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); - - _mesa_unmap_teximage_pbo(ctx, packing); + store_texsubimage(ctx, texImage, + 0, 0, 0, width, 1, 1, + format, type, pixels, packing, "glTexImage1D"); } /** - * This is the software fallback for Driver.TexImage2D(). - * - * This function is oriented toward storing images in main memory, rather - * than VRAM. Device driver's can easily plug in their own replacement. + * This is the fallback for Driver.TexImage2D(). */ void _mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level, @@ -4646,13 +4734,6 @@ _mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat); - GLubyte *dstMap; - GLint dstRowStride; - GLboolean success; - - (void) border; - if (width == 0 || height == 0) return; @@ -4663,80 +4744,15 @@ _mesa_store_teximage2d(struct gl_context *ctx, GLenum target, GLint level, return; } - pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type, - pixels, packing, "glTexImage2D"); - if (!pixels) { - /* Note: we check for a NULL image pointer here, _after_ we allocated - * memory for the texture. That's what the GL spec calls for. - */ - return; - } - - if (target == GL_TEXTURE_1D_ARRAY) { - const GLint srcStride = - _mesa_image_row_stride(packing, width, format, type); - int y; - - success = GL_TRUE; - - for (y = 0; y < height; y++) { - /* Map dest texture buffer (write to whole region) */ - ctx->Driver.MapTextureImage(ctx, texImage, y, - 0, 0, width, 1, - rwMode, - &dstMap, &dstRowStride); - if (dstMap) { - success = _mesa_texstore(ctx, 2, texImage->_BaseFormat, - texImage->TexFormat, - 0, 0, 0, /* dstX/Y/Zoffset */ - dstRowStride, - &dstMap, - width, 1, 1, - format, type, pixels, packing); - ctx->Driver.UnmapTextureImage(ctx, texImage, y); - } - else { - success = GL_FALSE; - } - - if (!success) - break; - - pixels = (const GLubyte *) pixels + srcStride; - } - } else { - /* Map dest texture buffer (write to whole region) */ - ctx->Driver.MapTextureImage(ctx, texImage, 0, - 0, 0, width, height, - rwMode, - &dstMap, &dstRowStride); - if (dstMap) { - success = _mesa_texstore(ctx, 2, texImage->_BaseFormat, - texImage->TexFormat, - 0, 0, 0, /* dstX/Y/Zoffset */ - dstRowStride, - &dstMap, - width, height, 1, - format, type, pixels, packing); - - ctx->Driver.UnmapTextureImage(ctx, texImage, 0); - } - else { - success = GL_FALSE; - } - } - - if (!success) - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); - - _mesa_unmap_teximage_pbo(ctx, packing); + store_texsubimage(ctx, texImage, + 0, 0, 0, width, height, 1, + format, type, pixels, packing, "glTexImage2D"); } /** - * This is the software fallback for Driver.TexImage3D(). - * \sa _mesa_store_teximage2d() + * This is the fallback for Driver.TexImage3D(). */ void _mesa_store_teximage3d(struct gl_context *ctx, GLenum target, GLint level, @@ -4747,14 +4763,6 @@ _mesa_store_teximage3d(struct gl_context *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat); - GLboolean success = GL_TRUE; - GLint slice; - GLubyte **sliceMaps; - GLint dstRowStride; - - (void) border; - if (width == 0 || height == 0 || depth == 0) return; @@ -4765,66 +4773,16 @@ _mesa_store_teximage3d(struct gl_context *ctx, GLenum target, GLint level, return; } - pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, - format, type, - pixels, packing, "glTexImage3D"); - if (!pixels) { - /* Note: we check for a NULL image pointer here, _after_ we allocated - * memory for the texture. That's what the GL spec calls for. - */ - return; - } - - if (target == GL_TEXTURE_1D_ARRAY) { - depth = height; - height = 1; - } - - sliceMaps = (GLubyte **) calloc(depth, sizeof(GLubyte *)); - - /* Map dest texture buffer slices */ - for (slice = 0; slice < depth; slice++) { - ctx->Driver.MapTextureImage(ctx, texImage, slice, - 0, 0, width, height, - rwMode, - &sliceMaps[slice], &dstRowStride); - if (!sliceMaps[slice]) { - success = GL_FALSE; - break; - } - } - - if (success) { - success = _mesa_texstore(ctx, 3, texImage->_BaseFormat, - texImage->TexFormat, - 0, 0, 0, /* dstX/Y/Zoffset */ - dstRowStride, - sliceMaps, - width, height, depth, - format, type, pixels, packing); - } - - /* Unmap dest texture buffer slices */ - for (slice = 0; slice < depth; slice++) { - if (sliceMaps[slice]) { - ctx->Driver.UnmapTextureImage(ctx, texImage, slice); - } - } - - if (!success) - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); - - _mesa_unmap_teximage_pbo(ctx, packing); - - free(sliceMaps); + store_texsubimage(ctx, texImage, + 0, 0, 0, width, height, depth, + format, type, pixels, packing, "glTexImage3D"); } /* - * This is the software fallback for Driver.TexSubImage1D() - * and Driver.CopyTexSubImage1D(). + * This is the fallback for Driver.TexSubImage1D(). */ void _mesa_store_texsubimage1d(struct gl_context *ctx, GLenum target, GLint level, @@ -4834,49 +4792,15 @@ _mesa_store_texsubimage1d(struct gl_context *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat); - GLubyte *dstMap; - GLint dstRowStride; - GLboolean success; - - /* get pointer to src pixels (may be in a pbo which we'll map here) */ - pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, - pixels, packing, "glTexSubImage1D"); - if (!pixels) - return; - - /* Map dest texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, 0, - xoffset, 0, width, 1, - rwMode, - &dstMap, &dstRowStride); - - if (dstMap) { - success = _mesa_texstore(ctx, 1, texImage->_BaseFormat, - texImage->TexFormat, - 0, 0, 0, /* dstX/Y/Zoffset */ - dstRowStride, - &dstMap, - width, 1, 1, - format, type, pixels, packing); - - ctx->Driver.UnmapTextureImage(ctx, texImage, 0); - } - else { - success = GL_FALSE; - } - - if (!success) - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D"); - - _mesa_unmap_teximage_pbo(ctx, packing); + store_texsubimage(ctx, texImage, + xoffset, 0, 0, width, 1, 1, + format, type, pixels, packing, "glTexSubImage1D"); } /** - * This is the software fallback for Driver.TexSubImage2D() - * and Driver.CopyTexSubImage2D(). + * This is the fallback for Driver.TexSubImage2D(). */ void _mesa_store_texsubimage2d(struct gl_context *ctx, GLenum target, GLint level, @@ -4887,48 +4811,14 @@ _mesa_store_texsubimage2d(struct gl_context *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat); - GLubyte *dstMap; - GLint dstRowStride; - GLboolean success; - - /* get pointer to src pixels (may be in a pbo which we'll map here) */ - pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type, - pixels, packing, "glTexSubImage2D"); - if (!pixels) - return; - - /* Map dest texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, 0, - xoffset, yoffset, width, height, - rwMode, - &dstMap, &dstRowStride); - - if (dstMap) { - success = _mesa_texstore(ctx, 2, texImage->_BaseFormat, - texImage->TexFormat, - 0, 0, 0, /* dstX/Y/Zoffset */ - dstRowStride, - &dstMap, - width, height, 1, - format, type, pixels, packing); - - ctx->Driver.UnmapTextureImage(ctx, texImage, 0); - } - else { - success = GL_FALSE; - } - - if (!success) - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); - - _mesa_unmap_teximage_pbo(ctx, packing); + store_texsubimage(ctx, texImage, + xoffset, yoffset, 0, width, height, 1, + format, type, pixels, packing, "glTexSubImage2D"); } /* - * This is the software fallback for Driver.TexSubImage3D(). - * and Driver.CopyTexSubImage3D(). + * This is the fallback for Driver.TexSubImage3D(). */ void _mesa_store_texsubimage3d(struct gl_context *ctx, GLenum target, GLint level, @@ -4939,56 +4829,9 @@ _mesa_store_texsubimage3d(struct gl_context *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - const GLbitfield rwMode = get_read_write_mode(format, texImage->TexFormat); - GLboolean success = GL_TRUE; - GLint slice; - GLubyte **sliceMaps; - GLint dstRowStride; - - /* get pointer to src pixels (may be in a pbo which we'll map here) */ - pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, - type, pixels, packing, - "glTexSubImage3D"); - if (!pixels) - return; - - sliceMaps = (GLubyte **) calloc(depth, sizeof(GLubyte *)); - - /* Map dest texture buffer slices */ - for (slice = 0; slice < depth; slice++) { - ctx->Driver.MapTextureImage(ctx, texImage, zoffset + slice, - xoffset, yoffset, width, height, - rwMode, - &sliceMaps[slice], &dstRowStride); - if (!sliceMaps[slice]) { - success = GL_FALSE; - break; - } - } - - if (success) { - success = _mesa_texstore(ctx, 3, texImage->_BaseFormat, - texImage->TexFormat, - 0, 0, 0, - dstRowStride, - sliceMaps, - width, height, depth, - format, type, pixels, packing); - } - - /* Unmap dest texture buffer slices */ - for (slice = 0; slice < depth; slice++) { - if (sliceMaps[slice]) { - ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + slice); - } - } - - if (!success) - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D"); - - _mesa_unmap_teximage_pbo(ctx, packing); - - free(sliceMaps); + store_texsubimage(ctx, texImage, + xoffset, yoffset, zoffset, width, height, depth, + format, type, pixels, packing, "glTexSubImage3D"); } diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c index 53c09e265..be0d0ff19 100644 --- a/mesalib/src/mesa/main/transformfeedback.c +++ b/mesalib/src/mesa/main/transformfeedback.c @@ -98,7 +98,8 @@ reference_transform_feedback_object(struct gl_transform_feedback_object **ptr, GLboolean _mesa_validate_primitive_mode(struct gl_context *ctx, GLenum mode) { - if (ctx->TransformFeedback.CurrentObject->Active) { + if (ctx->TransformFeedback.CurrentObject->Active && + !ctx->TransformFeedback.CurrentObject->Paused) { switch (mode) { case GL_POINTS: return ctx->TransformFeedback.Mode == GL_POINTS; @@ -387,6 +388,7 @@ _mesa_EndTransformFeedback(void) FLUSH_VERTICES(ctx, _NEW_TRANSFORM_FEEDBACK); ctx->TransformFeedback.CurrentObject->Active = GL_FALSE; + ctx->TransformFeedback.CurrentObject->Paused = GL_FALSE; ctx->TransformFeedback.CurrentObject->EndedAnytime = GL_TRUE; assert(ctx->Driver.EndTransformFeedback); diff --git a/mesalib/src/mesa/state_tracker/st_cb_xformfb.c b/mesalib/src/mesa/state_tracker/st_cb_xformfb.c index 2fc28dc24..b8534855b 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_xformfb.c +++ b/mesalib/src/mesa/state_tracker/st_cb_xformfb.c @@ -55,8 +55,18 @@ struct st_transform_feedback_object { unsigned num_targets; struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS]; + + /* This encapsulates the count that can be used as a source for draw_vbo. + * It contains a stream output target from the last call of + * EndTransformFeedback. */ + struct pipe_stream_output_target *draw_count; }; +static INLINE struct st_transform_feedback_object * +st_transform_feedback_object(struct gl_transform_feedback_object *obj) +{ + return (struct st_transform_feedback_object *) obj; +} static struct gl_transform_feedback_object * st_new_transform_feedback(struct gl_context *ctx, GLuint name) @@ -78,9 +88,11 @@ st_delete_transform_feedback(struct gl_context *ctx, struct gl_transform_feedback_object *obj) { struct st_transform_feedback_object *sobj = - (struct st_transform_feedback_object*)obj; + st_transform_feedback_object(obj); unsigned i; + pipe_so_target_reference(&sobj->draw_count, NULL); + /* Unreference targets. */ for (i = 0; i < sobj->num_targets; i++) { pipe_so_target_reference(&sobj->targets[i], NULL); @@ -102,7 +114,7 @@ st_begin_transform_feedback(struct gl_context *ctx, GLenum mode, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_transform_feedback_object *sobj = - (struct st_transform_feedback_object*)obj; + st_transform_feedback_object(obj); unsigned i, max_num_targets; max_num_targets = MIN2(Elements(sobj->base.Buffers), @@ -115,6 +127,7 @@ st_begin_transform_feedback(struct gl_context *ctx, GLenum mode, if (bo) { /* Check whether we need to recreate the target. */ if (!sobj->targets[i] || + sobj->targets[i] == sobj->draw_count || sobj->targets[i]->buffer != bo->buffer || sobj->targets[i]->buffer_offset != sobj->base.Offset[i] || sobj->targets[i]->buffer_size != sobj->base.Size[i]) { @@ -141,7 +154,7 @@ st_begin_transform_feedback(struct gl_context *ctx, GLenum mode, static void -st_stop_transform_feedback(struct gl_context *ctx, +st_pause_transform_feedback(struct gl_context *ctx, struct gl_transform_feedback_object *obj) { struct st_context *st = st_context(ctx); @@ -155,31 +168,54 @@ st_resume_transform_feedback(struct gl_context *ctx, { struct st_context *st = st_context(ctx); struct st_transform_feedback_object *sobj = - (struct st_transform_feedback_object*)obj; + st_transform_feedback_object(obj); cso_set_stream_outputs(st->cso_context, sobj->num_targets, sobj->targets, ~0); } -/* Set count_from_stream_output to any stream output target - * from the transform feedback object. */ -void -st_transform_feedback_draw_init(struct gl_transform_feedback_object *obj, - struct pipe_draw_info *out) + +static struct pipe_stream_output_target * +st_transform_feedback_get_draw_target(struct gl_transform_feedback_object *obj) { struct st_transform_feedback_object *sobj = - (struct st_transform_feedback_object*)obj; + st_transform_feedback_object(obj); unsigned i; for (i = 0; i < Elements(sobj->targets); i++) { if (sobj->targets[i]) { - out->count_from_stream_output = sobj->targets[i]; - return; + return sobj->targets[i]; } } assert(0); - out->count_from_stream_output = NULL; + return NULL; +} + + +static void +st_end_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) +{ + struct st_context *st = st_context(ctx); + struct st_transform_feedback_object *sobj = + st_transform_feedback_object(obj); + + cso_set_stream_outputs(st->cso_context, 0, NULL, 0); + + pipe_so_target_reference(&sobj->draw_count, + st_transform_feedback_get_draw_target(obj)); +} + + +void +st_transform_feedback_draw_init(struct gl_transform_feedback_object *obj, + struct pipe_draw_info *out) +{ + struct st_transform_feedback_object *sobj = + st_transform_feedback_object(obj); + + out->count_from_stream_output = sobj->draw_count; } @@ -189,8 +225,8 @@ st_init_xformfb_functions(struct dd_function_table *functions) functions->NewTransformFeedback = st_new_transform_feedback; functions->DeleteTransformFeedback = st_delete_transform_feedback; functions->BeginTransformFeedback = st_begin_transform_feedback; - functions->EndTransformFeedback = st_stop_transform_feedback; - functions->PauseTransformFeedback = st_stop_transform_feedback; + functions->EndTransformFeedback = st_end_transform_feedback; + functions->PauseTransformFeedback = st_pause_transform_feedback; functions->ResumeTransformFeedback = st_resume_transform_feedback; } diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index dc17d76a5..4c8c67fca 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -222,7 +222,7 @@ void st_init_limits(struct st_context *st) c->UniformBooleanTrue = ~0; c->MaxTransformFeedbackSeparateAttribs = - screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_ATTRIBS); + screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS); c->MaxTransformFeedbackSeparateComponents = screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS); c->MaxTransformFeedbackInterleavedComponents = diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index 55699e721..828f0d81f 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -600,6 +600,7 @@ st_context_destroy(struct st_context_iface *stctxi) static struct st_context_iface * st_api_create_context(struct st_api *stapi, struct st_manager *smapi, const struct st_context_attribs *attribs, + enum st_context_error *error, struct st_context_iface *shared_stctxi) { struct st_context *shared_ctx = (struct st_context *) shared_stctxi; @@ -623,17 +624,21 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, break; case ST_PROFILE_OPENGL_CORE: default: + *error = ST_CONTEXT_ERROR_BAD_API; return NULL; break; } pipe = smapi->screen->context_create(smapi->screen, NULL); - if (!pipe) + if (!pipe) { + *error = ST_CONTEXT_ERROR_NO_MEMORY; return NULL; + } st_visual_to_context_mode(&attribs->visual, &mode); st = st_create_context(api, pipe, &mode, shared_ctx); if (!st) { + *error = ST_CONTEXT_ERROR_NO_MEMORY; pipe->destroy(pipe); return NULL; } @@ -645,6 +650,7 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, /* is the actual version less than the requested version? */ if (st->ctx->VersionMajor * 10 + st->ctx->VersionMinor < attribs->major * 10 + attribs->minor) { + *error = ST_CONTEXT_ERROR_BAD_VERSION; st_destroy_context(st); return NULL; } @@ -660,6 +666,7 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, st->iface.share = st_context_share; st->iface.st_context_private = (void *) smapi; + *error = ST_CONTEXT_SUCCESS; return &st->iface; } diff --git a/mesalib/src/mesa/swrast/s_clear.c b/mesalib/src/mesa/swrast/s_clear.c index 851f6d165..d942e6e63 100644 --- a/mesalib/src/mesa/swrast/s_clear.c +++ b/mesalib/src/mesa/swrast/s_clear.c @@ -24,131 +24,146 @@ #include "main/glheader.h" #include "main/accum.h" -#include "main/colormac.h" #include "main/condrender.h" +#include "main/format_pack.h" #include "main/macros.h" #include "main/imports.h" #include "main/mtypes.h" #include "s_context.h" #include "s_depth.h" -#include "s_masking.h" #include "s_stencil.h" + /** - * Clear the color buffer when glColorMask is in effect. + * Clear an rgba color buffer with masking if needed. */ static void -clear_rgba_buffer_with_masking(struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint buf) +clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb, + const GLubyte colorMask[4]) { const GLint x = ctx->DrawBuffer->_Xmin; const GLint y = ctx->DrawBuffer->_Ymin; const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; - SWspan span; - GLint i; - - ASSERT(rb->PutRow); - - /* Initialize color span with clear color */ - /* XXX optimize for clearcolor == black/zero (bzero) */ - INIT_SPAN(span, GL_BITMAP); - span.end = width; - span.arrayMask = SPAN_RGBA; - span.array->ChanType = rb->DataType; - if (span.array->ChanType == GL_UNSIGNED_BYTE) { - GLubyte clearColor[4]; - _mesa_unclamped_float_rgba_to_ubyte(clearColor, ctx->Color.ClearColor.f); - for (i = 0; i < width; i++) { - COPY_4UBV(span.array->rgba[i], clearColor); - } - } - else if (span.array->ChanType == GL_UNSIGNED_SHORT) { - GLushort clearColor[4]; - UNCLAMPED_FLOAT_TO_USHORT(clearColor[RCOMP], ctx->Color.ClearColor.f[0]); - UNCLAMPED_FLOAT_TO_USHORT(clearColor[GCOMP], ctx->Color.ClearColor.f[1]); - UNCLAMPED_FLOAT_TO_USHORT(clearColor[BCOMP], ctx->Color.ClearColor.f[2]); - UNCLAMPED_FLOAT_TO_USHORT(clearColor[ACOMP], ctx->Color.ClearColor.f[3]); - for (i = 0; i < width; i++) { - COPY_4V_CAST(span.array->rgba[i], clearColor, GLchan); - } - } - else { - ASSERT(span.array->ChanType == GL_FLOAT); - for (i = 0; i < width; i++) { - UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][0], ctx->Color.ClearColor.f[0]); - UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][1], ctx->Color.ClearColor.f[1]); - UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][2], ctx->Color.ClearColor.f[2]); - UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][3], ctx->Color.ClearColor.f[3]); - } + const GLuint pixelSize = _mesa_get_format_bytes(rb->Format); + const GLboolean doMasking = (colorMask[0] == 0 || + colorMask[1] == 0 || + colorMask[2] == 0 || + colorMask[3] == 0); + const GLfloat (*clearColor)[4] = + (const GLfloat (*)[4]) ctx->Color.ClearColor.f; + GLbitfield mapMode = GL_MAP_WRITE_BIT; + GLubyte *map; + GLint rowStride; + GLint i, j; + + if (doMasking) { + /* we'll need to read buffer values too */ + mapMode |= GL_MAP_READ_BIT; } - /* Note that masking will change the color values, but only the - * channels for which the write mask is GL_FALSE. The channels - * which which are write-enabled won't get modified. - */ - for (i = 0; i < height; i++) { - span.x = x; - span.y = y + i; - _swrast_mask_rgba_span(ctx, rb, &span, buf); - /* write masked row */ - rb->PutRow(ctx, rb, width, x, y + i, span.array->rgba, NULL); + /* map dest buffer */ + ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, + mapMode, &map, &rowStride); + if (!map) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(color)"); + return; } -} + /* for 1, 2, 4-byte clearing */ +#define SIMPLE_TYPE_CLEAR(TYPE) \ + do { \ + TYPE pixel, pixelMask; \ + _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, &pixel); \ + if (doMasking) { \ + _mesa_pack_colormask(rb->Format, colorMask, &pixelMask); \ + pixel &= pixelMask; \ + pixelMask = ~pixelMask; \ + } \ + for (i = 0; i < height; i++) { \ + TYPE *row = (TYPE *) map; \ + if (doMasking) { \ + for (j = 0; j < width; j++) { \ + row[j] = (row[j] & pixelMask) | pixel; \ + } \ + } \ + else { \ + for (j = 0; j < width; j++) { \ + row[j] = pixel; \ + } \ + } \ + map += rowStride; \ + } \ + } while (0) -/** - * Clear an rgba color buffer without channel masking. - */ -static void -clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint buf) -{ - const GLint x = ctx->DrawBuffer->_Xmin; - const GLint y = ctx->DrawBuffer->_Ymin; - const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; - const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; - GLubyte clear8[4]; - GLushort clear16[4]; - GLvoid *clearVal; - GLfloat clearFloat[4]; - GLint i; - - ASSERT(ctx->Color.ColorMask[buf][0] && - ctx->Color.ColorMask[buf][1] && - ctx->Color.ColorMask[buf][2] && - ctx->Color.ColorMask[buf][3]); - - ASSERT(rb->PutMonoRow); - - switch (rb->DataType) { - case GL_UNSIGNED_BYTE: - _mesa_unclamped_float_rgba_to_ubyte(clear8, ctx->Color.ClearColor.f); - clearVal = clear8; - break; - case GL_UNSIGNED_SHORT: - UNCLAMPED_FLOAT_TO_USHORT(clear16[0], ctx->Color.ClearColor.f[0]); - UNCLAMPED_FLOAT_TO_USHORT(clear16[1], ctx->Color.ClearColor.f[1]); - UNCLAMPED_FLOAT_TO_USHORT(clear16[2], ctx->Color.ClearColor.f[2]); - UNCLAMPED_FLOAT_TO_USHORT(clear16[3], ctx->Color.ClearColor.f[3]); - clearVal = clear16; - break; - case GL_FLOAT: - clearFloat[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F); - clearFloat[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F); - clearFloat[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F); - clearFloat[3] = CLAMP(ctx->Color.ClearColor.f[3], 0.0F, 1.0F); - clearVal = clearFloat; - break; - default: - _mesa_problem(ctx, "Bad rb DataType in clear_color_buffer"); - return; - } - for (i = 0; i < height; i++) { - rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL); + /* for 3, 6, 8, 12, 16-byte clearing */ +#define MULTI_WORD_CLEAR(TYPE, N) \ + do { \ + TYPE pixel[N], pixelMask[N]; \ + GLuint k; \ + _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, pixel); \ + if (doMasking) { \ + _mesa_pack_colormask(rb->Format, colorMask, pixelMask); \ + for (k = 0; k < N; k++) { \ + pixel[k] &= pixelMask[k]; \ + pixelMask[k] = ~pixelMask[k]; \ + } \ + } \ + for (i = 0; i < height; i++) { \ + TYPE *row = (TYPE *) map; \ + if (doMasking) { \ + for (j = 0; j < width; j++) { \ + for (k = 0; k < N; k++) { \ + row[j * N + k] = \ + (row[j * N + k] & pixelMask[k]) | pixel[k]; \ + } \ + } \ + } \ + else { \ + for (j = 0; j < width; j++) { \ + for (k = 0; k < N; k++) { \ + row[j * N + k] = pixel[k]; \ + } \ + } \ + } \ + map += rowStride; \ + } \ + } while(0) + + switch (pixelSize) { + case 1: + SIMPLE_TYPE_CLEAR(GLubyte); + break; + case 2: + SIMPLE_TYPE_CLEAR(GLushort); + break; + case 3: + MULTI_WORD_CLEAR(GLubyte, 3); + break; + case 4: + SIMPLE_TYPE_CLEAR(GLuint); + break; + case 6: + MULTI_WORD_CLEAR(GLushort, 3); + break; + case 8: + MULTI_WORD_CLEAR(GLuint, 2); + break; + case 12: + MULTI_WORD_CLEAR(GLuint, 3); + break; + case 16: + MULTI_WORD_CLEAR(GLuint, 4); + break; + default: + _mesa_problem(ctx, "bad pixel size in clear_rgba_buffer()"); } + + /* unmap buffer */ + ctx->Driver.UnmapRenderbuffer(ctx, rb); } @@ -172,15 +187,7 @@ clear_color_buffers(struct gl_context *ctx) if (rb == NULL) continue; - if (ctx->Color.ColorMask[buf][0] == 0 || - ctx->Color.ColorMask[buf][1] == 0 || - ctx->Color.ColorMask[buf][2] == 0 || - ctx->Color.ColorMask[buf][3] == 0) { - clear_rgba_buffer_with_masking(ctx, rb, buf); - } - else { - clear_rgba_buffer(ctx, rb, buf); - } + clear_rgba_buffer(ctx, rb, ctx->Color.ColorMask[buf]); } } @@ -195,6 +202,8 @@ clear_color_buffers(struct gl_context *ctx) void _swrast_Clear(struct gl_context *ctx, GLbitfield buffers) { + const GLbitfield BUFFER_DS = BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL; + #ifdef DEBUG_FOO { const GLbitfield legalBits = @@ -216,24 +225,33 @@ _swrast_Clear(struct gl_context *ctx, GLbitfield buffers) if (SWRAST_CONTEXT(ctx)->NewState) _swrast_validate_derived(ctx); - swrast_render_start(ctx); + if ((buffers & BUFFER_BITS_COLOR) + && (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) { + clear_color_buffers(ctx); + } - /* do software clearing here */ - if (buffers) { - if ((buffers & BUFFER_BITS_COLOR) - && (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) { - clear_color_buffers(ctx); - } - if (buffers & BUFFER_BIT_DEPTH) { - _swrast_clear_depth_buffer(ctx, ctx->DrawBuffer->_DepthBuffer); - } - if (buffers & BUFFER_BIT_ACCUM) { - _mesa_clear_accum_buffer(ctx); + if (buffers & BUFFER_BIT_ACCUM) { + _mesa_clear_accum_buffer(ctx); + } + + if (buffers & BUFFER_DS) { + struct gl_renderbuffer *depthRb = + ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + struct gl_renderbuffer *stencilRb = + ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; + + if ((buffers & BUFFER_DS) == BUFFER_DS && depthRb == stencilRb) { + /* clear depth and stencil together */ + _swrast_clear_depth_stencil_buffer(ctx); } - if (buffers & BUFFER_BIT_STENCIL) { - _swrast_clear_stencil_buffer(ctx, ctx->DrawBuffer->_StencilBuffer); + else { + /* clear depth, stencil separately */ + if (buffers & BUFFER_BIT_DEPTH) { + _swrast_clear_depth_buffer(ctx); + } + if (buffers & BUFFER_BIT_STENCIL) { + _swrast_clear_stencil_buffer(ctx); + } } } - - swrast_render_finish(ctx); } diff --git a/mesalib/src/mesa/swrast/s_context.h b/mesalib/src/mesa/swrast/s_context.h index 446b990d9..af9e49ecb 100644 --- a/mesalib/src/mesa/swrast/s_context.h +++ b/mesalib/src/mesa/swrast/s_context.h @@ -422,5 +422,17 @@ _swrast_unmap_renderbuffers(struct gl_context *ctx); #define ATTRIB_LOOP_END } } +/** + * Return the address of a pixel value in a mapped renderbuffer. + */ +static inline GLubyte * +_swrast_pixel_address(struct gl_renderbuffer *rb, GLint x, GLint y) +{ + const GLint bpp = _mesa_get_format_bytes(rb->Format); + const GLint rowStride = rb->RowStride * bpp; + return (GLubyte *) rb->Data + y * rowStride + x * bpp; +} + + #endif diff --git a/mesalib/src/mesa/swrast/s_copypix.c b/mesalib/src/mesa/swrast/s_copypix.c index 3bdf48b25..1dc4286a3 100644 --- a/mesalib/src/mesa/swrast/s_copypix.c +++ b/mesalib/src/mesa/swrast/s_copypix.c @@ -245,7 +245,7 @@ copy_depth_pixels( struct gl_context *ctx, GLint srcx, GLint srcy, GLint destx, GLint desty ) { struct gl_framebuffer *fb = ctx->ReadBuffer; - struct gl_renderbuffer *readRb = fb->_DepthBuffer; + struct gl_renderbuffer *readRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; GLfloat *p, *tmpImage; GLint sy, dy, stepy; GLint j; @@ -339,7 +339,7 @@ copy_stencil_pixels( struct gl_context *ctx, GLint srcx, GLint srcy, GLint destx, GLint desty ) { struct gl_framebuffer *fb = ctx->ReadBuffer; - struct gl_renderbuffer *rb = fb->_StencilBuffer; + struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; GLint sy, dy, stepy; GLint j; GLubyte *p, *tmpImage; @@ -422,184 +422,8 @@ copy_stencil_pixels( struct gl_context *ctx, GLint srcx, GLint srcy, /** - * This isn't terribly efficient. If a driver really has combined - * depth/stencil buffers the driver should implement an optimized - * CopyPixels function. - */ -static void -copy_depth_stencil_pixels(struct gl_context *ctx, - const GLint srcX, const GLint srcY, - const GLint width, const GLint height, - const GLint destX, const GLint destY) -{ - struct gl_renderbuffer *stencilReadRb, *depthReadRb, *depthDrawRb; - GLint sy, dy, stepy; - GLint j; - GLubyte *tempStencilImage = NULL, *stencilPtr = NULL; - GLfloat *tempDepthImage = NULL, *depthPtr = NULL; - const GLfloat depthScale = ctx->DrawBuffer->_DepthMaxF; - const GLuint stencilMask = ctx->Stencil.WriteMask[0]; - const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; - const GLboolean scaleOrBias - = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; - GLint overlapping; - - depthDrawRb = ctx->DrawBuffer->_DepthBuffer; - depthReadRb = ctx->ReadBuffer->_DepthBuffer; - stencilReadRb = ctx->ReadBuffer->_StencilBuffer; - - ASSERT(depthDrawRb); - ASSERT(depthReadRb); - ASSERT(stencilReadRb); - - 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; - - if (stencilMask != 0x0) { - tempStencilImage - = (GLubyte *) malloc(width * height * sizeof(GLubyte)); - if (!tempStencilImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); - return; - } - - /* get copy of stencil pixels */ - stencilPtr = tempStencilImage; - for (j = 0; j < height; j++, ssy += stepy) { - _swrast_read_stencil_span(ctx, stencilReadRb, - width, srcX, ssy, stencilPtr); - stencilPtr += width; - } - stencilPtr = tempStencilImage; - } - - if (ctx->Depth.Mask) { - tempDepthImage - = (GLfloat *) malloc(width * height * sizeof(GLfloat)); - if (!tempDepthImage) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); - free(tempStencilImage); - return; - } - - /* get copy of depth pixels */ - depthPtr = tempDepthImage; - for (j = 0; j < height; j++, ssy += stepy) { - _swrast_read_depth_span_float(ctx, depthReadRb, - width, srcX, ssy, depthPtr); - depthPtr += width; - } - depthPtr = tempDepthImage; - } - } - - for (j = 0; j < height; j++, sy += stepy, dy += stepy) { - if (stencilMask != 0x0) { - GLubyte stencil[MAX_WIDTH]; - - /* Get stencil values */ - if (overlapping) { - memcpy(stencil, stencilPtr, width * sizeof(GLubyte)); - stencilPtr += width; - } - else { - _swrast_read_stencil_span(ctx, stencilReadRb, - width, srcX, sy, stencil); - } - - _mesa_apply_stencil_transfer_ops(ctx, width, stencil); - - /* Write values */ - if (zoom) { - _swrast_write_zoomed_stencil_span(ctx, destX, destY, width, - destX, dy, stencil); - } - else { - _swrast_write_stencil_span( ctx, width, destX, dy, stencil ); - } - } - - if (ctx->Depth.Mask) { - GLfloat depth[MAX_WIDTH]; - GLuint zVals32[MAX_WIDTH]; - GLushort zVals16[MAX_WIDTH]; - GLvoid *zVals; - GLuint zBytes; - - /* get depth values */ - if (overlapping) { - memcpy(depth, depthPtr, width * sizeof(GLfloat)); - depthPtr += width; - } - else { - _swrast_read_depth_span_float(ctx, depthReadRb, - width, srcX, sy, depth); - } - - /* scale & bias */ - if (scaleOrBias) { - _mesa_scale_and_bias_depth(ctx, width, depth); - } - /* convert to integer Z values */ - if (depthDrawRb->DataType == GL_UNSIGNED_SHORT) { - GLint k; - for (k = 0; k < width; k++) - zVals16[k] = (GLushort) (depth[k] * depthScale); - zVals = zVals16; - zBytes = 2; - } - else { - GLint k; - for (k = 0; k < width; k++) - zVals32[k] = (GLuint) (depth[k] * depthScale); - zVals = zVals32; - zBytes = 4; - } - - /* Write values */ - if (zoom) { - _swrast_write_zoomed_z_span(ctx, destX, destY, width, - destX, dy, zVals); - } - else { - _swrast_put_row(ctx, depthDrawRb, width, destX, dy, zVals, zBytes); - } - } - } - - if (tempStencilImage) - free(tempStencilImage); - - if (tempDepthImage) - free(tempDepthImage); -} - - - -/** - * Try to do a fast copy pixels. + * Try to do a fast copy pixels with memcpy. + * \return GL_TRUE if successful, GL_FALSE otherwise. */ static GLboolean fast_copy_pixels(struct gl_context *ctx, @@ -609,8 +433,10 @@ fast_copy_pixels(struct gl_context *ctx, struct gl_framebuffer *srcFb = ctx->ReadBuffer; struct gl_framebuffer *dstFb = ctx->DrawBuffer; struct gl_renderbuffer *srcRb, *dstRb; - GLint row, yStep; - void *temp; + GLint row; + GLuint pixelBytes, widthInBytes; + GLubyte *srcMap, *dstMap; + GLint srcRowStride, dstRowStride; if (SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 || ctx->Pixel.ZoomX != 1.0F || @@ -627,12 +453,12 @@ fast_copy_pixels(struct gl_context *ctx, dstRb = dstFb->_ColorDrawBuffers[0]; } else if (type == GL_STENCIL) { - srcRb = srcFb->_StencilBuffer; - dstRb = dstFb->_StencilBuffer; + srcRb = srcFb->Attachment[BUFFER_STENCIL].Renderbuffer; + dstRb = dstFb->Attachment[BUFFER_STENCIL].Renderbuffer; } else if (type == GL_DEPTH) { - srcRb = srcFb->_DepthBuffer; - dstRb = dstFb->_DepthBuffer; + srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer; + dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer; } else { ASSERT(type == GL_DEPTH_STENCIL_EXT); @@ -641,13 +467,24 @@ fast_copy_pixels(struct gl_context *ctx, dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer; } - /* src and dst renderbuffers must be same format and type */ - if (!srcRb || !dstRb || - srcRb->DataType != dstRb->DataType || - srcRb->_BaseFormat != dstRb->_BaseFormat) { + /* src and dst renderbuffers must be same format */ + if (!srcRb || !dstRb || srcRb->Format != dstRb->Format) { return GL_FALSE; } + if (type == GL_STENCIL || type == GL_DEPTH_COMPONENT) { + /* can't handle packed depth+stencil here */ + if (_mesa_is_format_packed_depth_stencil(srcRb->Format) || + _mesa_is_format_packed_depth_stencil(dstRb->Format)) + return GL_FALSE; + } + else if (type == GL_DEPTH_STENCIL) { + /* can't handle separate depth/stencil buffers */ + if (srcRb != srcFb->Attachment[BUFFER_STENCIL].Renderbuffer || + dstRb != dstFb->Attachment[BUFFER_STENCIL].Renderbuffer) + return GL_FALSE; + } + /* clipping not supported */ if (srcX < 0 || srcX + width > (GLint) srcFb->Width || srcY < 0 || srcY + height > (GLint) srcFb->Height || @@ -656,32 +493,73 @@ fast_copy_pixels(struct gl_context *ctx, return GL_FALSE; } - /* overlapping src/dst doesn't matter, just determine Y direction */ - if (srcY < dstY) { - /* top-down max-to-min */ - srcY = srcY + height - 1; - dstY = dstY + height - 1; - yStep = -1; + pixelBytes = _mesa_get_format_bytes(srcRb->Format); + widthInBytes = width * pixelBytes; + + if (srcRb == dstRb) { + /* map whole buffer for read/write */ + /* XXX we could be clever and just map the union region of the + * source and dest rects. + */ + GLubyte *map; + GLint rowStride; + + ctx->Driver.MapRenderbuffer(ctx, srcRb, 0, 0, + srcRb->Width, srcRb->Height, + GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, + &map, &rowStride); + if (!srcMap) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); + return GL_TRUE; /* don't retry with slow path */ + } + + srcMap = map + srcY * rowStride + srcX * pixelBytes; + dstMap = map + dstY * rowStride + dstX * pixelBytes; + + /* this handles overlapping copies */ + if (srcY < dstY) { + /* copy in reverse (top->down) order */ + srcMap += rowStride * (height - 1); + dstMap += rowStride * (height - 1); + srcRowStride = -rowStride; + dstRowStride = -rowStride; + } + else { + /* copy in normal (bottom->up) order */ + srcRowStride = rowStride; + dstRowStride = rowStride; + } } else { - /* bottom-up min-to-max */ - yStep = 1; - } - - temp = malloc(width * MAX_PIXEL_BYTES); - if (!temp) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); - return GL_FALSE; + /* different src/dst buffers */ + ctx->Driver.MapRenderbuffer(ctx, srcRb, srcX, srcY, + width, height, + GL_MAP_READ_BIT, &srcMap, &srcRowStride); + if (!srcMap) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); + return GL_TRUE; /* don't retry with slow path */ + } + ctx->Driver.MapRenderbuffer(ctx, dstRb, dstX, dstY, + width, height, + GL_MAP_WRITE_BIT, &dstMap, &dstRowStride); + if (!dstMap) { + ctx->Driver.UnmapRenderbuffer(ctx, srcRb); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels"); + return GL_TRUE; /* don't retry with slow path */ + } } for (row = 0; row < height; row++) { - srcRb->GetRow(ctx, srcRb, width, srcX, srcY, temp); - dstRb->PutRow(ctx, dstRb, width, dstX, dstY, temp, NULL); - srcY += yStep; - dstY += yStep; + /* memmove() in case of overlap */ + memmove(dstMap, srcMap, widthInBytes); + dstMap += dstRowStride; + srcMap += srcRowStride; } - free(temp); + ctx->Driver.UnmapRenderbuffer(ctx, srcRb); + if (dstRb != srcRb) { + ctx->Driver.UnmapRenderbuffer(ctx, dstRb); + } return GL_TRUE; } @@ -697,7 +575,6 @@ _swrast_CopyPixels( struct gl_context *ctx, GLint destx, GLint desty, GLenum type ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); - swrast_render_start(ctx); if (!_mesa_check_conditional_render(ctx)) return; /* don't copy */ @@ -705,23 +582,30 @@ _swrast_CopyPixels( struct gl_context *ctx, if (swrast->NewState) _swrast_validate_derived( ctx ); - if (!fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) { - switch (type) { - case GL_COLOR: - copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty ); - break; - case GL_DEPTH: - copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty ); - break; - case GL_STENCIL: - copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty ); - break; - case GL_DEPTH_STENCIL_EXT: - copy_depth_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty); - break; - default: - _mesa_problem(ctx, "unexpected type in _swrast_CopyPixels"); - } + if (fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) { + /* all done */ + return; + } + + swrast_render_start(ctx); + + switch (type) { + case GL_COLOR: + copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty ); + break; + case GL_DEPTH: + copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty ); + break; + case GL_STENCIL: + copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty ); + break; + case GL_DEPTH_STENCIL_EXT: + /* Copy buffers separately (if the fast copy path wasn't taken) */ + copy_depth_pixels(ctx, srcx, srcy, width, height, destx, desty); + copy_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty); + break; + default: + _mesa_problem(ctx, "unexpected type in _swrast_CopyPixels"); } swrast_render_finish(ctx); diff --git a/mesalib/src/mesa/swrast/s_depth.c b/mesalib/src/mesa/swrast/s_depth.c index 8d3ad105b..f87adaa84 100644 --- a/mesalib/src/mesa/swrast/s_depth.c +++ b/mesalib/src/mesa/swrast/s_depth.c @@ -26,478 +26,134 @@ #include "main/glheader.h" #include "main/context.h" #include "main/formats.h" +#include "main/format_unpack.h" +#include "main/format_pack.h" #include "main/macros.h" #include "main/imports.h" +#include "s_context.h" #include "s_depth.h" #include "s_span.h" + +#define Z_TEST(COMPARE) \ + do { \ + GLuint i; \ + for (i = 0; i < n; i++) { \ + if (mask[i]) { \ + if (COMPARE) { \ + /* pass */ \ + if (write) { \ + zbuffer[i] = zfrag[i]; \ + } \ + passed++; \ + } \ + else { \ + /* fail */ \ + mask[i] = 0; \ + } \ + } \ + } \ + } while (0) + + /** - * Do depth test for a horizontal span of fragments. - * Input: zbuffer - array of z values in the zbuffer - * z - array of fragment z values - * Return: number of fragments which pass the test. + * Do depth test for an array of 16-bit Z values. + * @param zbuffer array of Z buffer values (16-bit) + * @param zfrag array of fragment Z values (use 16-bit in 32-bit uint) + * @param mask which fragments are alive, killed afterward + * @return number of fragments which pass the test. */ static GLuint depth_test_span16( struct gl_context *ctx, GLuint n, - GLushort zbuffer[], const GLuint z[], GLubyte mask[] ) + GLushort zbuffer[], const GLuint zfrag[], GLubyte mask[] ) { + const GLboolean write = ctx->Depth.Mask; GLuint passed = 0; /* switch cases ordered from most frequent to less frequent */ switch (ctx->Depth.Func) { - case GL_LESS: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - if (z[i] < zbuffer[i]) { - /* pass */ - zbuffer[i] = z[i]; - passed++; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - if (z[i] < zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_LEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] <= zbuffer[i]) { - zbuffer[i] = z[i]; - passed++; - } - else { - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] <= zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_GEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] >= zbuffer[i]) { - zbuffer[i] = z[i]; - passed++; - } - else { - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] >= zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_GREATER: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] > zbuffer[i]) { - zbuffer[i] = z[i]; - passed++; - } - else { - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] > zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_NOTEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] != zbuffer[i]) { - zbuffer[i] = z[i]; - passed++; - } - else { - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] != zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_EQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] == zbuffer[i]) { - zbuffer[i] = z[i]; - passed++; - } - else { - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] == zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_ALWAYS: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - zbuffer[i] = z[i]; - passed++; - } - } - } - else { - /* Don't update Z buffer or mask */ - passed = n; - } - break; - case GL_NEVER: - memset(mask, 0, n * sizeof(GLubyte)); - break; - default: - _mesa_problem(ctx, "Bad depth func in depth_test_span16"); + case GL_LESS: + Z_TEST(zfrag[i] < zbuffer[i]); + break; + case GL_LEQUAL: + Z_TEST(zfrag[i] <= zbuffer[i]); + break; + case GL_GEQUAL: + Z_TEST(zfrag[i] >= zbuffer[i]); + break; + case GL_GREATER: + Z_TEST(zfrag[i] > zbuffer[i]); + break; + case GL_NOTEQUAL: + Z_TEST(zfrag[i] != zbuffer[i]); + break; + case GL_EQUAL: + Z_TEST(zfrag[i] == zbuffer[i]); + break; + case GL_ALWAYS: + Z_TEST(1); + break; + case GL_NEVER: + memset(mask, 0, n * sizeof(GLubyte)); + break; + default: + _mesa_problem(ctx, "Bad depth func in depth_test_span16"); } return passed; } +/** + * Do depth test for an array of 32-bit Z values. + * @param zbuffer array of Z buffer values (32-bit) + * @param zfrag array of fragment Z values (use 32-bits in 32-bit uint) + * @param mask which fragments are alive, killed afterward + * @return number of fragments which pass the test. + */ static GLuint depth_test_span32( struct gl_context *ctx, GLuint n, - GLuint zbuffer[], const GLuint z[], GLubyte mask[] ) + GLuint zbuffer[], const GLuint zfrag[], GLubyte mask[]) { + const GLboolean write = ctx->Depth.Mask; GLuint passed = 0; /* switch cases ordered from most frequent to less frequent */ switch (ctx->Depth.Func) { - case GL_LESS: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - if (z[i] < zbuffer[i]) { - /* pass */ - zbuffer[i] = z[i]; - passed++; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - if (z[i] < zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_LEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] <= zbuffer[i]) { - zbuffer[i] = z[i]; - passed++; - } - else { - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] <= zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_GEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] >= zbuffer[i]) { - zbuffer[i] = z[i]; - passed++; - } - else { - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] >= zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_GREATER: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] > zbuffer[i]) { - zbuffer[i] = z[i]; - passed++; - } - else { - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] > zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_NOTEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] != zbuffer[i]) { - zbuffer[i] = z[i]; - passed++; - } - else { - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] != zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_EQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] == zbuffer[i]) { - zbuffer[i] = z[i]; - passed++; - } - else { - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - if (z[i] == zbuffer[i]) { - /* pass */ - passed++; - } - else { - mask[i] = 0; - } - } - } - } - break; - case GL_ALWAYS: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0;i<n;i++) { - if (mask[i]) { - zbuffer[i] = z[i]; - passed++; - } - } - } - else { - /* Don't update Z buffer or mask */ - passed = n; - } - break; - case GL_NEVER: - memset(mask, 0, n * sizeof(GLubyte)); - break; - default: - _mesa_problem(ctx, "Bad depth func in depth_test_span32"); + case GL_LESS: + Z_TEST(zfrag[i] < zbuffer[i]); + break; + case GL_LEQUAL: + Z_TEST(zfrag[i] <= zbuffer[i]); + break; + case GL_GEQUAL: + Z_TEST(zfrag[i] >= zbuffer[i]); + break; + case GL_GREATER: + Z_TEST(zfrag[i] > zbuffer[i]); + break; + case GL_NOTEQUAL: + Z_TEST(zfrag[i] != zbuffer[i]); + break; + case GL_EQUAL: + Z_TEST(zfrag[i] == zbuffer[i]); + break; + case GL_ALWAYS: + Z_TEST(1); + break; + case GL_NEVER: + memset(mask, 0, n * sizeof(GLubyte)); + break; + default: + _mesa_problem(ctx, "Bad depth func in depth_test_span32"); } return passed; } - /** * Clamp fragment Z values to the depth near/far range (glDepthRange()). * This is used when GL_ARB_depth_clamp/GL_DEPTH_CLAMP is turned on. @@ -547,615 +203,171 @@ _swrast_depth_clamp_span( struct gl_context *ctx, SWspan *span ) } - -/* - * Apply depth test to span of fragments. +/** + * Get array of 32-bit z values from the depth buffer. With clipping. */ -static GLuint -depth_test_span( struct gl_context *ctx, SWspan *span) +static void +get_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + GLuint zbuffer[]) { - struct gl_framebuffer *fb = ctx->DrawBuffer; - struct gl_renderbuffer *rb = fb->_DepthBuffer; - const GLint x = span->x; - const GLint y = span->y; - const GLuint count = span->end; - const GLuint *zValues = span->array->z; - GLubyte *mask = span->array->mask; - GLuint passed; + const GLint w = rb->Width, h = rb->Height; + const GLubyte *map = (const GLubyte *) rb->Data; + GLuint i; - ASSERT((span->arrayMask & SPAN_XY) == 0); - ASSERT(span->arrayMask & SPAN_Z); - - if (rb->GetPointer(ctx, rb, 0, 0)) { - /* Directly access buffer */ - if (rb->DataType == GL_UNSIGNED_SHORT) { - GLushort *zbuffer = (GLushort *) rb->GetPointer(ctx, rb, x, y); - passed = depth_test_span16(ctx, count, zbuffer, zValues, mask); - } - else { - GLuint *zbuffer = (GLuint *) rb->GetPointer(ctx, rb, x, y); - ASSERT(rb->DataType == GL_UNSIGNED_INT); - passed = depth_test_span32(ctx, count, zbuffer, zValues, mask); + if (rb->Format == MESA_FORMAT_Z32) { + const GLint rowStride = rb->RowStride * 4; + for (i = 0; i < count; i++) { + if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { + zbuffer[i] = *((GLuint *) (map + y[i] * rowStride + x[i] * 4)); + } } } else { - /* read depth values from buffer, test, write back */ - if (rb->DataType == GL_UNSIGNED_SHORT) { - GLushort zbuffer[MAX_WIDTH]; - rb->GetRow(ctx, rb, count, x, y, zbuffer); - passed = depth_test_span16(ctx, count, zbuffer, zValues, mask); - rb->PutRow(ctx, rb, count, x, y, zbuffer, mask); - } - else { - GLuint zbuffer[MAX_WIDTH]; - ASSERT(rb->DataType == GL_UNSIGNED_INT); - rb->GetRow(ctx, rb, count, x, y, zbuffer); - passed = depth_test_span32(ctx, count, zbuffer, zValues, mask); - rb->PutRow(ctx, rb, count, x, y, zbuffer, mask); + const GLint bpp = _mesa_get_format_bytes(rb->Format); + const GLint rowStride = rb->RowStride * bpp; + for (i = 0; i < count; i++) { + if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { + const GLubyte *src = map + y[i] * rowStride+ x[i] * bpp; + _mesa_unpack_uint_z_row(rb->Format, 1, src, &zbuffer[i]); + } } } - - if (passed < count) { - span->writeAll = GL_FALSE; - } - return passed; } - - -#define Z_ADDRESS(X, Y) (zStart + (Y) * stride + (X)) - - -/* - * Do depth testing for an array of fragments at assorted locations. - */ static void -direct_depth_test_pixels16(struct gl_context *ctx, GLushort *zStart, GLuint stride, - GLuint n, const GLint x[], const GLint y[], - const GLuint z[], GLubyte mask[] ) +put_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const GLuint zvalues[], const GLubyte mask[]) { - /* switch cases ordered from most frequent to less frequent */ - switch (ctx->Depth.Func) { - case GL_LESS: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] < *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] < *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_LEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] <= *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] <= *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_GEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] >= *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] >= *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_GREATER: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] > *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] > *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_NOTEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] != *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] != *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_EQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] == *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] == *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_ALWAYS: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLushort *zptr = Z_ADDRESS(x[i], y[i]); - *zptr = z[i]; - } - } - } - else { - /* Don't update Z buffer or mask */ - } - break; - case GL_NEVER: - /* depth test never passes */ - memset(mask, 0, n * sizeof(GLubyte)); - break; - default: - _mesa_problem(ctx, "Bad depth func in direct_depth_test_pixels"); - } -} - - + const GLint w = rb->Width, h = rb->Height; + GLubyte *map = (GLubyte *) rb->Data; + GLuint i; -/* - * Do depth testing for an array of fragments with direct access to zbuffer. - */ -static void -direct_depth_test_pixels32(struct gl_context *ctx, GLuint *zStart, GLuint stride, - GLuint n, const GLint x[], const GLint y[], - const GLuint z[], GLubyte mask[] ) -{ - /* switch cases ordered from most frequent to less frequent */ - switch (ctx->Depth.Func) { - case GL_LESS: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] < *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] < *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_LEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] <= *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] <= *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_GEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] >= *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] >= *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_GREATER: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] > *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] > *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_NOTEQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] != *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] != *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_EQUAL: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] == *zptr) { - /* pass */ - *zptr = z[i]; - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - else { - /* Don't update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - if (z[i] == *zptr) { - /* pass */ - } - else { - /* fail */ - mask[i] = 0; - } - } - } - } - break; - case GL_ALWAYS: - if (ctx->Depth.Mask) { - /* Update Z buffer */ - GLuint i; - for (i=0; i<n; i++) { - if (mask[i]) { - GLuint *zptr = Z_ADDRESS(x[i], y[i]); - *zptr = z[i]; - } - } - } - else { - /* Don't update Z buffer or mask */ - } - break; - case GL_NEVER: - /* depth test never passes */ - memset(mask, 0, n * sizeof(GLubyte)); - break; - default: - _mesa_problem(ctx, "Bad depth func in direct_depth_test_pixels"); + if (rb->Format == MESA_FORMAT_Z32) { + const GLuint rowStride = rb->RowStride * 4; + for (i = 0; i < count; i++) { + if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { + GLuint *dst = (GLuint *) (map + y[i] * rowStride + x[i] * 4); + *dst = zvalues[i]; + } + } + } + else { + gl_pack_uint_z_func packZ = _mesa_get_pack_uint_z_func(rb->Format); + const GLint bpp = _mesa_get_format_bytes(rb->Format); + const GLint rowStride = rb->RowStride * bpp; + for (i = 0; i < count; i++) { + if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { + void *dst = map + y[i] * rowStride + x[i] * bpp; + packZ(zvalues + i, dst); + } + } } } - - -static GLuint -depth_test_pixels( struct gl_context *ctx, SWspan *span ) +/** + * Apply depth (Z) buffer testing to the span. + * \return approx number of pixels that passed (only zero is reliable) + */ +GLuint +_swrast_depth_test_span(struct gl_context *ctx, SWspan *span) { struct gl_framebuffer *fb = ctx->DrawBuffer; - struct gl_renderbuffer *rb = fb->_DepthBuffer; + struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; + const GLint bpp = _mesa_get_format_bytes(rb->Format); + void *zStart = _swrast_pixel_address(rb, span->x, span->y); const GLuint count = span->end; - const GLint *x = span->array->x; - const GLint *y = span->array->y; - const GLuint *z = span->array->z; + const GLuint *fragZ = span->array->z; GLubyte *mask = span->array->mask; + void *zBufferVals; + GLuint *zBufferTemp = NULL; + GLuint passed; + GLboolean ztest16 = GL_FALSE; + GLboolean ztest24 = _mesa_get_format_bits(rb->Format, GL_DEPTH_BITS) == 24; - if (rb->GetPointer(ctx, rb, 0, 0)) { - /* Directly access values */ - if (rb->DataType == GL_UNSIGNED_SHORT) { - GLushort *zStart = (GLushort *) rb->Data; - GLuint stride = rb->Width; - direct_depth_test_pixels16(ctx, zStart, stride, count, x, y, z, mask); - } - else { - GLuint *zStart = (GLuint *) rb->Data; - GLuint stride = rb->Width; - ASSERT(rb->DataType == GL_UNSIGNED_INT); - direct_depth_test_pixels32(ctx, zStart, stride, count, x, y, z, mask); - } + if (rb->Format == MESA_FORMAT_Z16 && !(span->arrayMask & SPAN_XY)) { + /* directly read/write row of 16-bit Z values */ + zBufferVals = zStart; + ztest16 = GL_TRUE; + } + else if (rb->Format == MESA_FORMAT_Z32 && !(span->arrayMask & SPAN_XY)) { + /* directly read/write row of 32-bit Z values */ + zBufferVals = zStart; } else { - /* read depth values from buffer, test, write back */ - if (rb->DataType == GL_UNSIGNED_SHORT) { - GLushort zbuffer[MAX_WIDTH]; - _swrast_get_values(ctx, rb, count, x, y, zbuffer, sizeof(GLushort)); - depth_test_span16(ctx, count, zbuffer, z, mask); - rb->PutValues(ctx, rb, count, x, y, zbuffer, mask); + /* copy Z buffer values into temp buffer (32-bit Z values) */ + zBufferTemp = (GLuint *) malloc(count * sizeof(GLuint)); + if (!zBufferTemp) + return 0; + + if (span->arrayMask & SPAN_XY) { + get_z32_values(ctx, rb, count, + span->array->x, span->array->y, zBufferTemp); } else { - GLuint zbuffer[MAX_WIDTH]; - ASSERT(rb->DataType == GL_UNSIGNED_INT); - _swrast_get_values(ctx, rb, count, x, y, zbuffer, sizeof(GLuint)); - depth_test_span32(ctx, count, zbuffer, z, mask); - rb->PutValues(ctx, rb, count, x, y, zbuffer, mask); + _mesa_unpack_uint_z_row(rb->Format, count, zStart, zBufferTemp); } - } - return count; /* not really correct, but OK */ -} + if (ztest24) { + GLuint i; + /* Convert depth buffer values from 32 to 24 bits to match the + * fragment Z values generated by rasterization. + */ + for (i = 0; i < count; i++) { + zBufferTemp[i] >>= 8; + } + } + zBufferVals = zBufferTemp; + } -/** - * Apply depth (Z) buffer testing to the span. - * \return approx number of pixels that passed (only zero is reliable) - */ -GLuint -_swrast_depth_test_span( struct gl_context *ctx, SWspan *span) -{ - if (span->arrayMask & SPAN_XY) - return depth_test_pixels(ctx, span); + /* do the depth test either with 16 or 32-bit values */ + if (ztest16) + passed = depth_test_span16(ctx, count, zBufferVals, fragZ, mask); else - return depth_test_span(ctx, span); + passed = depth_test_span32(ctx, count, zBufferVals, fragZ, mask); + + if (zBufferTemp) { + /* need to write temp Z values back into the buffer */ + + if (ztest24) { + GLuint i; + /* Convert depth buffer values back to 32-bit values. The least + * significant bits don't matter since they'll get dropped when + * they're packed back into the depth buffer. + */ + for (i = 0; i < count; i++) { + zBufferTemp[i] = (zBufferTemp[i] << 8); + } + } + + if (span->arrayMask & SPAN_XY) { + /* random locations */ + put_z32_values(ctx, rb, count, span->array->x, span->array->y, + zBufferTemp, mask); + } + else { + /* horizontal row */ + gl_pack_uint_z_func packZ = _mesa_get_pack_uint_z_func(rb->Format); + GLubyte *dst = zStart; + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + packZ(&zBufferTemp[i], dst); + } + dst += bpp; + } + } + + free(zBufferTemp); + } + + if (passed < count) { + span->writeAll = GL_FALSE; + } + return passed; } @@ -1170,67 +382,42 @@ GLboolean _swrast_depth_bounds_test( struct gl_context *ctx, SWspan *span ) { struct gl_framebuffer *fb = ctx->DrawBuffer; - struct gl_renderbuffer *rb = fb->_DepthBuffer; + struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; + const GLint bpp = _mesa_get_format_bytes(rb->Format); + const GLint rowStride = rb->RowStride * bpp; + GLubyte *zStart = (GLubyte*) rb->Data + span->y * rowStride + span->x * bpp; GLuint zMin = (GLuint) (ctx->Depth.BoundsMin * fb->_DepthMaxF + 0.5F); GLuint zMax = (GLuint) (ctx->Depth.BoundsMax * fb->_DepthMaxF + 0.5F); GLubyte *mask = span->array->mask; const GLuint count = span->end; GLuint i; GLboolean anyPass = GL_FALSE; + GLuint zBufferTemp[MAX_WIDTH]; + const GLuint *zBufferVals; - if (rb->DataType == GL_UNSIGNED_SHORT) { - /* get 16-bit values */ - GLushort zbuffer16[MAX_WIDTH], *zbuffer; - if (span->arrayMask & SPAN_XY) { - _swrast_get_values(ctx, rb, count, span->array->x, span->array->y, - zbuffer16, sizeof(GLushort)); - zbuffer = zbuffer16; - } - else { - zbuffer = (GLushort*) rb->GetPointer(ctx, rb, span->x, span->y); - if (!zbuffer) { - rb->GetRow(ctx, rb, count, span->x, span->y, zbuffer16); - zbuffer = zbuffer16; - } - } - assert(zbuffer); - - /* Now do the tests */ - for (i = 0; i < count; i++) { - if (mask[i]) { - if (zbuffer[i] < zMin || zbuffer[i] > zMax) - mask[i] = GL_FALSE; - else - anyPass = GL_TRUE; - } - } + if (rb->Format == MESA_FORMAT_Z32 && !(span->arrayMask & SPAN_XY)) { + /* directly access 32-bit values in the depth buffer */ + zBufferVals = (const GLuint *) zStart; } else { - /* get 32-bit values */ - GLuint zbuffer32[MAX_WIDTH], *zbuffer; - ASSERT(rb->DataType == GL_UNSIGNED_INT); + /* unpack Z values into a temporary array */ if (span->arrayMask & SPAN_XY) { - _swrast_get_values(ctx, rb, count, span->array->x, span->array->y, - zbuffer32, sizeof(GLuint)); - zbuffer = zbuffer32; + get_z32_values(ctx, rb, count, span->array->x, span->array->y, + zBufferTemp); } else { - zbuffer = (GLuint*) rb->GetPointer(ctx, rb, span->x, span->y); - if (!zbuffer) { - rb->GetRow(ctx, rb, count, span->x, span->y, zbuffer32); - zbuffer = zbuffer32; - } + _mesa_unpack_uint_z_row(rb->Format, count, zStart, zBufferTemp); } - assert(zbuffer); + zBufferVals = zBufferTemp; + } - /* Now do the tests */ - for (i = 0; i < count; i++) { - if (mask[i]) { - if (zbuffer[i] < zMin || zbuffer[i] > zMax) - mask[i] = GL_FALSE; - else - anyPass = GL_TRUE; - } + /* Now do the tests */ + for (i = 0; i < count; i++) { + if (mask[i]) { + if (zBufferVals[i] < zMin || zBufferVals[i] > zMax) + mask[i] = GL_FALSE; + else + anyPass = GL_TRUE; } } @@ -1251,19 +438,16 @@ _swrast_depth_bounds_test( struct gl_context *ctx, SWspan *span ) * bounds. */ void -_swrast_read_depth_span_float( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLint n, GLint x, GLint y, GLfloat depth[] ) +_swrast_read_depth_span_float(struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLint n, GLint x, GLint y, GLfloat depth[]) { - const GLfloat scale = 1.0F / ctx->DrawBuffer->_DepthMaxF; - if (!rb) { /* really only doing this to prevent FP exceptions later */ memset(depth, 0, n * sizeof(GLfloat)); return; } - ASSERT(rb->_BaseFormat == GL_DEPTH_COMPONENT); - if (y < 0 || y >= (GLint) rb->Height || x + n <= 0 || x >= (GLint) rb->Width) { /* span is completely outside framebuffer */ @@ -1291,35 +475,25 @@ _swrast_read_depth_span_float( struct gl_context *ctx, struct gl_renderbuffer *r return; } - if (rb->DataType == GL_UNSIGNED_INT) { - GLuint temp[MAX_WIDTH]; - GLint i; - rb->GetRow(ctx, rb, n, x, y, temp); - for (i = 0; i < n; i++) { - depth[i] = temp[i] * scale; - } - } - else if (rb->DataType == GL_UNSIGNED_SHORT) { - GLushort temp[MAX_WIDTH]; - GLint i; - rb->GetRow(ctx, rb, n, x, y, temp); - for (i = 0; i < n; i++) { - depth[i] = temp[i] * scale; - } - } - else { - _mesa_problem(ctx, "Invalid depth renderbuffer data type"); - } + _mesa_unpack_float_z_row(rb->Format, n, _swrast_pixel_address(rb, x, y), + depth); } + /** - * Clear the given z/depth renderbuffer. + * Clear the given z/depth renderbuffer. If the buffer is a combined + * depth+stencil buffer, only the Z bits will be touched. */ void -_swrast_clear_depth_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb ) +_swrast_clear_depth_buffer(struct gl_context *ctx) { + struct gl_renderbuffer *rb = + ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; GLuint clearValue; GLint x, y, width, height; + GLubyte *map; + GLint rowStride, i, j; + GLbitfield mapMode; if (!rb || !ctx->Depth.Mask) { /* no depth buffer, or writing to it is disabled */ @@ -1334,67 +508,218 @@ _swrast_clear_depth_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb ) clearValue = (GLuint) (ctx->Depth.Clear * ctx->DrawBuffer->_DepthMaxF); } - assert(rb->_BaseFormat == GL_DEPTH_COMPONENT); - /* compute region to clear */ x = ctx->DrawBuffer->_Xmin; y = ctx->DrawBuffer->_Ymin; width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; - if (rb->GetPointer(ctx, rb, 0, 0)) { - /* Direct buffer access is possible. Either this is just malloc'd - * memory, or perhaps the driver mmap'd the zbuffer memory. - */ - if (rb->DataType == GL_UNSIGNED_SHORT) { - if ((clearValue & 0xff) == ((clearValue >> 8) & 0xff) && - ((GLushort *) rb->GetPointer(ctx, rb, 0, 0) + width == - (GLushort *) rb->GetPointer(ctx, rb, 0, 1))) { - /* optimized case */ - GLushort *dst = (GLushort *) rb->GetPointer(ctx, rb, x, y); - GLuint len = width * height * sizeof(GLushort); - memset(dst, (clearValue & 0xff), len); + mapMode = GL_MAP_WRITE_BIT; + if (rb->Format == MESA_FORMAT_S8_Z24 || + rb->Format == MESA_FORMAT_X8_Z24 || + rb->Format == MESA_FORMAT_Z24_S8 || + rb->Format == MESA_FORMAT_Z24_X8) { + mapMode |= GL_MAP_READ_BIT; + } + + ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, + mapMode, &map, &rowStride); + if (!map) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth)"); + return; + } + + switch (rb->Format) { + case MESA_FORMAT_Z16: + { + GLfloat clear = (GLfloat) ctx->Depth.Clear; + GLushort clearVal = 0; + _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); + if (clearVal == 0xffff && width * 2 == rowStride) { + /* common case */ + memset(map, 0xff, width * height * 2); } else { - /* general case */ - GLint i, j; for (i = 0; i < height; i++) { - GLushort *dst = (GLushort *) rb->GetPointer(ctx, rb, x, y + i); + GLushort *row = (GLushort *) map; for (j = 0; j < width; j++) { - dst[j] = clearValue; + row[j] = clearVal; } + map += rowStride; } } } - else { - GLint i, j; - ASSERT(rb->DataType == GL_UNSIGNED_INT); + break; + case MESA_FORMAT_Z32: + case MESA_FORMAT_Z32_FLOAT: + { + GLfloat clear = (GLfloat) ctx->Depth.Clear; + GLuint clearVal = 0; + _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); for (i = 0; i < height; i++) { - GLuint *dst = (GLuint *) rb->GetPointer(ctx, rb, x, y + i); + GLuint *row = (GLuint *) map; for (j = 0; j < width; j++) { - dst[j] = clearValue; + row[j] = clearVal; } + map += rowStride; } } - } - else { - /* Direct access not possible. Use PutRow to write new values. */ - if (rb->DataType == GL_UNSIGNED_SHORT) { - GLushort clearVal16 = (GLushort) (clearValue & 0xffff); - GLint i; + break; + case MESA_FORMAT_S8_Z24: + case MESA_FORMAT_X8_Z24: + case MESA_FORMAT_Z24_S8: + case MESA_FORMAT_Z24_X8: + { + GLfloat clear = (GLfloat) ctx->Depth.Clear; + GLuint clearVal = 0; + GLuint mask; + + if (rb->Format == MESA_FORMAT_S8_Z24 || + rb->Format == MESA_FORMAT_X8_Z24) + mask = 0xff000000; + else + mask = 0xff; + + _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); for (i = 0; i < height; i++) { - rb->PutMonoRow(ctx, rb, width, x, y + i, &clearVal16, NULL); + GLuint *row = (GLuint *) map; + for (j = 0; j < width; j++) { + row[j] = (row[j] & mask) | clearVal; + } + map += rowStride; } + } - else if (rb->DataType == GL_UNSIGNED_INT) { - GLint i; - ASSERT(sizeof(clearValue) == sizeof(GLuint)); + break; + case MESA_FORMAT_Z32_FLOAT_X24S8: + /* XXX untested */ + { + GLfloat clearVal = (GLfloat) ctx->Depth.Clear; for (i = 0; i < height; i++) { - rb->PutMonoRow(ctx, rb, width, x, y + i, &clearValue, NULL); + GLfloat *row = (GLfloat *) map; + for (j = 0; j < width; j++) { + row[j * 2] = clearVal; + } + map += rowStride; } } - else { - _mesa_problem(ctx, "bad depth renderbuffer DataType"); + break; + default: + _mesa_problem(ctx, "Unexpected depth buffer format %s" + " in _swrast_clear_depth_buffer()", + _mesa_get_format_name(rb->Format)); + } + + ctx->Driver.UnmapRenderbuffer(ctx, rb); +} + + + + +/** + * Clear both depth and stencil values in a combined depth+stencil buffer. + */ +void +_swrast_clear_depth_stencil_buffer(struct gl_context *ctx) +{ + const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits; + const GLuint writeMask = ctx->Stencil.WriteMask[0]; + const GLuint stencilMax = (1 << stencilBits) - 1; + struct gl_renderbuffer *rb = + ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + GLint x, y, width, height; + GLbitfield mapMode; + GLubyte *map; + GLint rowStride, i, j; + + /* check that we really have a combined depth+stencil buffer */ + assert(rb == ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer); + + /* compute region to clear */ + x = ctx->DrawBuffer->_Xmin; + y = ctx->DrawBuffer->_Ymin; + width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; + height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; + + mapMode = GL_MAP_WRITE_BIT; + if ((writeMask & stencilMax) != stencilMax) { + /* need to mask stencil values */ + mapMode |= GL_MAP_READ_BIT; + } + + ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, + mapMode, &map, &rowStride); + if (!map) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth+stencil)"); + return; + } + + switch (rb->Format) { + case MESA_FORMAT_S8_Z24: + case MESA_FORMAT_Z24_S8: + { + GLfloat zClear = (GLfloat) ctx->Depth.Clear; + GLuint clear = 0, mask; + + _mesa_pack_float_z_row(rb->Format, 1, &zClear, &clear); + + if (rb->Format == MESA_FORMAT_S8_Z24) { + mask = ((~writeMask) & 0xff) << 24; + clear |= (ctx->Stencil.Clear & writeMask & 0xff) << 24; + } + else { + mask = ((~writeMask) & 0xff); + clear |= (ctx->Stencil.Clear & writeMask & 0xff); + } + + for (i = 0; i < height; i++) { + GLuint *row = (GLuint *) map; + if (mask != 0x0) { + for (j = 0; j < width; j++) { + row[j] = (row[j] & mask) | clear; + } + } + else { + for (j = 0; j < width; j++) { + row[j] = clear; + } + } + map += rowStride; + } } + break; + case MESA_FORMAT_Z32_FLOAT_X24S8: + /* XXX untested */ + { + const GLfloat zClear = (GLfloat) ctx->Depth.Clear; + const GLuint sClear = ctx->Stencil.Clear & writeMask; + const GLuint sMask = (~writeMask) & 0xff; + for (i = 0; i < height; i++) { + GLfloat *zRow = (GLfloat *) map; + GLuint *sRow = (GLuint *) map; + for (j = 0; j < width; j++) { + zRow[j * 2 + 0] = zClear; + } + if (sMask != 0) { + for (j = 0; j < width; j++) { + sRow[j * 2 + 1] = (sRow[j * 2 + 1] & sMask) | sClear; + } + } + else { + for (j = 0; j < width; j++) { + sRow[j * 2 + 1] = sClear; + } + } + map += rowStride; + } + } + break; + default: + _mesa_problem(ctx, "Unexpected depth buffer format %s" + " in _swrast_clear_depth_buffer()", + _mesa_get_format_name(rb->Format)); } + + ctx->Driver.UnmapRenderbuffer(ctx, rb); + } diff --git a/mesalib/src/mesa/swrast/s_depth.h b/mesalib/src/mesa/swrast/s_depth.h index 2caea82e0..25a7a0bbf 100644 --- a/mesalib/src/mesa/swrast/s_depth.h +++ b/mesalib/src/mesa/swrast/s_depth.h @@ -49,7 +49,10 @@ _swrast_read_depth_span_float( struct gl_context *ctx, struct gl_renderbuffer *r GLint n, GLint x, GLint y, GLfloat depth[] ); extern void -_swrast_clear_depth_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb ); +_swrast_clear_depth_buffer(struct gl_context *ctx); + +extern void +_swrast_clear_depth_stencil_buffer(struct gl_context *ctx); #endif diff --git a/mesalib/src/mesa/swrast/s_depthstencil.c b/mesalib/src/mesa/swrast/s_depthstencil.c index dc768e216..e48177ec1 100644 --- a/mesalib/src/mesa/swrast/s_depthstencil.c +++ b/mesalib/src/mesa/swrast/s_depthstencil.c @@ -207,59 +207,6 @@ put_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count, } } -static void -put_mono_row_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count, - GLint x, GLint y, const void *value, const GLubyte *mask) -{ - struct gl_renderbuffer *dsrb = z24rb->Wrapped; - GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); - ASSERT(z24rb->DataType == GL_UNSIGNED_INT); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); - if (dst) { - /* direct access */ - GLuint i; - if (dsrb->Format == MESA_FORMAT_Z24_S8) { - const GLuint shiftedVal = *((GLuint *) value) << 8; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst[i] = shiftedVal | (dst[i] & 0xff); - } - } - } - else { - const GLuint shiftedVal = *((GLuint *) value); - assert(dsrb->Format == MESA_FORMAT_S8_Z24); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst[i] = shiftedVal | (dst[i] & 0xff000000); - } - } - } - } - else { - /* get, modify, put */ - GLuint temp[MAX_WIDTH], i; - dsrb->GetRow(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { - const GLuint shiftedVal = *((GLuint *) value) << 8; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i] = shiftedVal | (temp[i] & 0xff); - } - } - } - else { - const GLuint shiftedVal = *((GLuint *) value); - assert(dsrb->Format == MESA_FORMAT_S8_Z24); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i] = shiftedVal | (temp[i] & 0xff000000); - } - } - } - dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask); - } -} static void put_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint count, @@ -314,35 +261,6 @@ put_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, GLuint cou } } -static void -put_mono_values_z24(struct gl_context *ctx, struct gl_renderbuffer *z24rb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte *mask) -{ - struct gl_renderbuffer *dsrb = z24rb->Wrapped; - GLuint temp[MAX_WIDTH], i; - /* get, modify, put */ - dsrb->GetValues(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { - const GLuint shiftedVal = *((GLuint *) value) << 8; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i] = shiftedVal | (temp[i] & 0xff); - } - } - } - else { - const GLuint shiftedVal = *((GLuint *) value); - assert(dsrb->Format == MESA_FORMAT_S8_Z24); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i] = shiftedVal | (temp[i] & 0xff000000); - } - } - } - dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask); -} - /** * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like @@ -385,10 +303,7 @@ new_z24_renderbuffer_wrapper(struct gl_context *ctx, z24rb->GetRow = get_row_z24; z24rb->GetValues = get_values_z24; z24rb->PutRow = put_row_z24; - z24rb->PutRowRGB = NULL; - z24rb->PutMonoRow = put_mono_row_z24; z24rb->PutValues = put_values_z24; - z24rb->PutMonoValues = put_mono_values_z24; return z24rb; } @@ -467,39 +382,6 @@ put_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint coun } } -static void -put_mono_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, - GLint x, GLint y, const void *value, const GLubyte *mask) -{ - struct gl_renderbuffer *dsrb = z32frb->Wrapped; - GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y); - ASSERT(z32frb->DataType == GL_FLOAT); - ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); - ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); - if (dst) { - /* direct access */ - GLuint i; - const GLfloat val = *(GLfloat*)value; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst[i*2] = val; - } - } - } - else { - /* get, modify, put */ - GLfloat temp[MAX_WIDTH*2]; - GLuint i; - const GLfloat val = *(GLfloat *)value; - dsrb->GetRow(ctx, dsrb, count, x, y, temp); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i*2] = val; - } - } - dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask); - } -} static void put_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, @@ -535,28 +417,6 @@ put_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint c } } -static void -put_mono_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte *mask) -{ - struct gl_renderbuffer *dsrb = z32frb->Wrapped; - GLfloat temp[MAX_WIDTH*2]; - GLuint i; - const GLfloat val = *(GLfloat *)value; - ASSERT(z32frb->DataType == GL_FLOAT); - ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); - ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); - /* get, modify, put */ - dsrb->GetValues(ctx, dsrb, count, x, y, temp); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i*2] = val; - } - } - dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask); -} - /** * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like @@ -596,10 +456,7 @@ new_z32f_renderbuffer_wrapper(struct gl_context *ctx, z32frb->GetRow = get_row_z32f; z32frb->GetValues = get_values_z32f; z32frb->PutRow = put_row_z32f; - z32frb->PutRowRGB = NULL; - z32frb->PutMonoRow = put_mono_row_z32f; z32frb->PutValues = put_values_z32f; - z32frb->PutMonoValues = put_mono_values_z32f; return z32frb; } @@ -739,71 +596,6 @@ put_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count, } } -static void -put_mono_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count, - GLint x, GLint y, const void *value, const GLubyte *mask) -{ - struct gl_renderbuffer *dsrb = s8rb->Wrapped; - const GLubyte val = *((GLubyte *) value); - GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); - ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || - dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); - if (dst) { - /* direct access */ - GLuint i; - if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst[i*2+1] = val; - } - } - } - else if (dsrb->Format == MESA_FORMAT_Z24_S8) { - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst[i] = (dst[i] & 0xffffff00) | val; - } - } - } - else { - assert(dsrb->Format == MESA_FORMAT_S8_Z24); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst[i] = (dst[i] & 0xffffff) | (val << 24); - } - } - } - } - else { - /* get, modify, put */ - GLuint temp[MAX_WIDTH*2], i; - dsrb->GetRow(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i*2+1] = val; - } - } - } - else if (dsrb->Format == MESA_FORMAT_Z24_S8) { - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i] = (temp[i] & 0xffffff00) | val; - } - } - } - else { - assert(dsrb->Format == MESA_FORMAT_S8_Z24); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i] = (temp[i] & 0xffffff) | (val << 24); - } - } - } - dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask); - } -} static void put_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count, @@ -874,41 +666,6 @@ put_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count } } -static void -put_mono_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count, - const GLint x[], const GLint y[], - const void *value, const GLubyte *mask) -{ - struct gl_renderbuffer *dsrb = s8rb->Wrapped; - GLuint temp[MAX_WIDTH*2], i; - const GLubyte val = *((GLubyte *) value); - /* get, modify, put */ - dsrb->GetValues(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i*2+1] = val; - } - } - } - else if (dsrb->Format == MESA_FORMAT_Z24_S8) { - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i] = (temp[i] & 0xffffff00) | val; - } - } - } - else { - assert(dsrb->Format == MESA_FORMAT_S8_Z24); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - temp[i] = (temp[i] & 0xffffff) | (val << 24); - } - } - } - dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask); -} - /** * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like @@ -950,10 +707,7 @@ new_s8_renderbuffer_wrapper(struct gl_context *ctx, struct gl_renderbuffer *dsrb s8rb->GetRow = get_row_s8; s8rb->GetValues = get_values_s8; s8rb->PutRow = put_row_s8; - s8rb->PutRowRGB = NULL; - s8rb->PutMonoRow = put_mono_row_s8; s8rb->PutValues = put_values_s8; - s8rb->PutMonoValues = put_mono_values_s8; return s8rb; } diff --git a/mesalib/src/mesa/swrast/s_drawpix.c b/mesalib/src/mesa/swrast/s_drawpix.c index 7259881c1..4231bb4bd 100644 --- a/mesalib/src/mesa/swrast/s_drawpix.c +++ b/mesalib/src/mesa/swrast/s_drawpix.c @@ -25,8 +25,10 @@ #include "main/glheader.h" #include "main/bufferobj.h" +#include "main/colormac.h" #include "main/condrender.h" #include "main/context.h" +#include "main/format_pack.h" #include "main/image.h" #include "main/imports.h" #include "main/macros.h" @@ -41,6 +43,146 @@ #include "s_zoom.h" +/** + * Handle a common case of drawing GL_RGB/GL_UNSIGNED_BYTE into a + * MESA_FORMAT_XRGB888 or MESA_FORMAT_ARGB888 renderbuffer. + */ +static void +fast_draw_rgb_ubyte_pixels(struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLint x, GLint y, + GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels) +{ + const GLubyte *src = (const GLubyte *) + _mesa_image_address2d(unpack, pixels, width, + height, GL_RGB, GL_UNSIGNED_BYTE, 0, 0); + const GLint srcRowStride = _mesa_image_row_stride(unpack, width, + GL_RGB, GL_UNSIGNED_BYTE); + GLint i, j; + GLubyte *dst; + GLint dstRowStride; + + ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, + GL_MAP_WRITE_BIT, &dst, &dstRowStride); + + if (!dst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); + return; + } + + if (ctx->Pixel.ZoomY == -1.0f) { + dst = dst + (height - 1) * dstRowStride; + dstRowStride = -dstRowStride; + } + + for (i = 0; i < height; i++) { + GLuint *dst4 = (GLuint *) dst; + for (j = 0; j < width; j++) { + dst4[j] = PACK_COLOR_8888(0xff, src[j*3+0], src[j*3+1], src[j*3+2]); + } + dst += dstRowStride; + src += srcRowStride; + } + + ctx->Driver.UnmapRenderbuffer(ctx, rb); +} + + +/** + * Handle a common case of drawing GL_RGBA/GL_UNSIGNED_BYTE into a + * MESA_FORMAT_ARGB888 or MESA_FORMAT_xRGB888 renderbuffer. + */ +static void +fast_draw_rgba_ubyte_pixels(struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLint x, GLint y, + GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels) +{ + const GLubyte *src = (const GLubyte *) + _mesa_image_address2d(unpack, pixels, width, + height, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + const GLint srcRowStride = + _mesa_image_row_stride(unpack, width, GL_RGBA, GL_UNSIGNED_BYTE); + GLint i, j; + GLubyte *dst; + GLint dstRowStride; + + ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, + GL_MAP_WRITE_BIT, &dst, &dstRowStride); + + if (!dst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); + return; + } + + if (ctx->Pixel.ZoomY == -1.0f) { + dst = dst + (height - 1) * dstRowStride; + dstRowStride = -dstRowStride; + } + + for (i = 0; i < height; i++) { + GLuint *dst4 = (GLuint *) dst; + for (j = 0; j < width; j++) { + dst4[j] = PACK_COLOR_8888(src[j*4+3], src[j*4+0], + src[j*4+1], src[j*4+2]); + } + dst += dstRowStride; + src += srcRowStride; + } + + ctx->Driver.UnmapRenderbuffer(ctx, rb); +} + + +/** + * Handle a common case of drawing a format/type combination that + * exactly matches the renderbuffer format. + */ +static void +fast_draw_generic_pixels(struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels) +{ + const GLubyte *src = (const GLubyte *) + _mesa_image_address2d(unpack, pixels, width, + height, format, type, 0, 0); + const GLint srcRowStride = + _mesa_image_row_stride(unpack, width, format, type); + const GLint rowLength = width * _mesa_get_format_bytes(rb->Format); + GLint i; + GLubyte *dst; + GLint dstRowStride; + + ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, + GL_MAP_WRITE_BIT, &dst, &dstRowStride); + + if (!dst) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); + return; + } + + if (ctx->Pixel.ZoomY == -1.0f) { + dst = dst + (height - 1) * dstRowStride; + dstRowStride = -dstRowStride; + } + + for (i = 0; i < height; i++) { + memcpy(dst, src, rowLength); + dst += dstRowStride; + src += srcRowStride; + } + + ctx->Driver.UnmapRenderbuffer(ctx, rb); +} + /** * Try to do a fast and simple RGB(a) glDrawPixels. @@ -53,256 +195,56 @@ fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y, const struct gl_pixelstore_attrib *userUnpack, const GLvoid *pixels) { - const GLint imgX = x, imgY = y; struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; - GLenum rbType; SWcontext *swrast = SWRAST_CONTEXT(ctx); - SWspan span; - GLboolean simpleZoom; - GLint yStep; /* +1 or -1 */ struct gl_pixelstore_attrib unpack; - GLint destX, destY, drawWidth, drawHeight; /* post clipping */ if (!rb) return GL_TRUE; /* no-op */ - rbType = rb->DataType; - - if ((swrast->_RasterMask & ~CLIP_BIT) || + if (ctx->DrawBuffer->_NumColorDrawBuffers > 1 || + (swrast->_RasterMask & ~CLIP_BIT) || ctx->Texture._EnabledCoordUnits || userUnpack->SwapBytes || + ctx->Pixel.ZoomX != 1.0f || + fabsf(ctx->Pixel.ZoomY) != 1.0f || ctx->_ImageTransferState) { /* can't handle any of those conditions */ return GL_FALSE; } - INIT_SPAN(span, GL_BITMAP); - span.arrayMask = SPAN_RGBA; - span.arrayAttribs = FRAG_BIT_COL0; - _swrast_span_default_attribs(ctx, &span); - - /* 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; - yStep = 1; - if (unpack.RowLength == 0) - unpack.RowLength = width; - } - /* - * Ready to draw! - */ - - if (format == GL_RGBA && type == rbType) { - const GLubyte *src - = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width, - height, format, type, 0, 0); - const GLint srcStride = _mesa_image_row_stride(&unpack, width, - format, type); - if (simpleZoom) { - GLint row; - for (row = 0; row < drawHeight; row++) { - rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL); - src += srcStride; - destY += yStep; - } - } - else { - /* with zooming */ - GLint row; - for (row = 0; row < drawHeight; row++) { - span.x = destX; - span.y = destY + row; - span.end = drawWidth; - span.array->ChanType = rbType; - _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, src); - src += srcStride; - } - span.array->ChanType = CHAN_TYPE; - } + /* clipping */ + if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &unpack)) { + /* image was completely clipped: no-op, all done */ return GL_TRUE; } - if (format == GL_RGB && type == rbType) { - const GLubyte *src - = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width, - height, format, type, 0, 0); - const GLint srcStride = _mesa_image_row_stride(&unpack, width, - format, type); - if (simpleZoom) { - GLint row; - for (row = 0; row < drawHeight; row++) { - rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL); - src += srcStride; - destY += yStep; - } - } - else { - /* with zooming */ - GLint row; - for (row = 0; row < drawHeight; row++) { - span.x = destX; - span.y = destY; - span.end = drawWidth; - span.array->ChanType = rbType; - _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, src); - src += srcStride; - destY++; - } - span.array->ChanType = CHAN_TYPE; - } + if (format == GL_RGB && + type == GL_UNSIGNED_BYTE && + (rb->Format == MESA_FORMAT_XRGB8888 || + rb->Format == MESA_FORMAT_ARGB8888)) { + fast_draw_rgb_ubyte_pixels(ctx, rb, x, y, width, height, + &unpack, pixels); return GL_TRUE; } - /* Remaining cases haven't been tested with alignment != 1 */ - if (userUnpack->Alignment != 1) - return GL_FALSE; - - if (format == GL_LUMINANCE && type == CHAN_TYPE && rbType == CHAN_TYPE) { - const GLchan *src = (const GLchan *) pixels - + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels); - if (simpleZoom) { - /* no zooming */ - GLint row; - ASSERT(drawWidth <= MAX_WIDTH); - for (row = 0; row < drawHeight; row++) { - GLchan rgb[MAX_WIDTH][3]; - GLint i; - for (i = 0;i<drawWidth;i++) { - rgb[i][0] = src[i]; - rgb[i][1] = src[i]; - rgb[i][2] = src[i]; - } - rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, rgb, NULL); - src += unpack.RowLength; - destY += yStep; - } - } - else { - /* with zooming */ - GLint row; - ASSERT(drawWidth <= MAX_WIDTH); - for (row = 0; row < drawHeight; row++) { - GLchan rgb[MAX_WIDTH][3]; - GLint i; - for (i = 0;i<drawWidth;i++) { - rgb[i][0] = src[i]; - rgb[i][1] = src[i]; - rgb[i][2] = src[i]; - } - span.x = destX; - span.y = destY; - span.end = drawWidth; - _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, rgb); - src += unpack.RowLength; - destY++; - } - } + if (format == GL_RGBA && + type == GL_UNSIGNED_BYTE && + (rb->Format == MESA_FORMAT_XRGB8888 || + rb->Format == MESA_FORMAT_ARGB8888)) { + fast_draw_rgba_ubyte_pixels(ctx, rb, x, y, width, height, + &unpack, pixels); return GL_TRUE; } - if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE && rbType == CHAN_TYPE) { - const GLchan *src = (const GLchan *) pixels - + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels)*2; - if (simpleZoom) { - GLint row; - ASSERT(drawWidth <= MAX_WIDTH); - for (row = 0; row < drawHeight; row++) { - GLint i; - const GLchan *ptr = src; - for (i = 0;i<drawWidth;i++) { - span.array->rgba[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; - } - } - else { - /* with zooming */ - GLint row; - ASSERT(drawWidth <= MAX_WIDTH); - for (row = 0; row < drawHeight; row++) { - const GLchan *ptr = src; - GLint i; - for (i = 0;i<drawWidth;i++) { - span.array->rgba[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, - span.array->rgba); - src += unpack.RowLength*2; - destY++; - } - } + if (_mesa_format_matches_format_and_type(rb->Format, format, type)) { + fast_draw_generic_pixels(ctx, rb, x, y, width, height, + format, type, &unpack, pixels); 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 (rbType == GL_UNSIGNED_BYTE) { - /* convert ubyte/CI data to ubyte/RGBA */ - if (simpleZoom) { - GLint row; - for (row = 0; row < drawHeight; row++) { - ASSERT(drawWidth <= MAX_WIDTH); - _mesa_map_ci8_to_rgba8(ctx, drawWidth, src, - span.array->rgba8); - rb->PutRow(ctx, rb, drawWidth, destX, destY, - span.array->rgba8, NULL); - src += unpack.RowLength; - destY += yStep; - } - } - else { - /* ubyte/CI to ubyte/RGBA with zooming */ - GLint row; - for (row = 0; row < drawHeight; row++) { - ASSERT(drawWidth <= MAX_WIDTH); - _mesa_map_ci8_to_rgba8(ctx, drawWidth, src, - span.array->rgba8); - span.x = destX; - span.y = destY; - span.end = drawWidth; - _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, - span.array->rgba8); - src += unpack.RowLength; - destY++; - } - } - return GL_TRUE; - } - } - /* can't handle this pixel format and/or data type */ return GL_FALSE; } @@ -480,6 +422,8 @@ draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y, return; } + swrast_render_start(ctx); + INIT_SPAN(span, GL_BITMAP); _swrast_span_default_attribs(ctx, &span); span.arrayMask = SPAN_RGBA; @@ -547,9 +491,46 @@ draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y, if (convImage) { free(convImage); } + + swrast_render_finish(ctx); +} + + +/** + * Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_S8_Z24 + * renderbuffer. No masking, zooming, scaling, etc. + */ +static void +fast_draw_depth_stencil(struct gl_context *ctx, GLint x, GLint y, + GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels) +{ + const GLenum format = GL_DEPTH_STENCIL_EXT; + const GLenum type = GL_UNSIGNED_INT_24_8; + struct gl_renderbuffer *rb = + ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + GLubyte *src, *dst; + GLint srcRowStride, dstRowStride; + GLint i; + + src = _mesa_image_address2d(unpack, pixels, width, height, + format, type, 0, 0); + srcRowStride = _mesa_image_row_stride(unpack, width, format, type); + + dst = _swrast_pixel_address(rb, x, y); + dstRowStride = rb->RowStride * 4; + + for (i = 0; i < height; i++) { + _mesa_pack_uint_24_8_depth_stencil_row(rb->Format, width, + (const GLuint *) src, dst); + dst += dstRowStride; + src += srcRowStride; + } } + /** * This is a bit different from drawing GL_DEPTH_COMPONENT pixels. * The only per-pixel operations that apply are depth scale/bias, @@ -567,7 +548,6 @@ draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, const GLint imgX = x, imgY = y; const GLboolean scaleOrBias = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; - const GLuint depthMax = ctx->DrawBuffer->_DepthMax; const GLuint stencilMask = ctx->Stencil.WriteMask[0]; const GLenum stencilType = GL_UNSIGNED_BYTE; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; @@ -587,27 +567,16 @@ draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, ASSERT(depthRb); ASSERT(stencilRb); - if (depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT && - depthRb->Format == MESA_FORMAT_Z24_S8 && + if (depthRb == stencilRb && + (depthRb->Format == MESA_FORMAT_Z24_S8 || + depthRb->Format == MESA_FORMAT_S8_Z24) && type == GL_UNSIGNED_INT_24_8 && - depthRb == stencilRb && - depthRb->GetRow && /* May be null if depthRb is a wrapper around - * separate depth and stencil buffers. */ !scaleOrBias && !zoom && ctx->Depth.Mask && (stencilMask & 0xff) == 0xff) { - /* This is the ideal case. - * Drawing GL_DEPTH_STENCIL pixels into a combined depth/stencil buffer. - * Plus, no pixel transfer ops, zooming, or masking needed. - */ - GLint i; - for (i = 0; i < height; i++) { - const GLuint *src = (const GLuint *) - _mesa_image_address2d(&clippedUnpack, pixels, width, height, - GL_DEPTH_STENCIL_EXT, type, i, 0); - depthRb->PutRow(ctx, depthRb, width, x, y + i, src, NULL); - } + fast_draw_depth_stencil(ctx, x, y, width, height, + &clippedUnpack, pixels); } else { /* sub-optimal cases: @@ -616,58 +585,27 @@ draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, /* XXX need to handle very wide images (skippixels) */ GLint i; - depthRb = ctx->DrawBuffer->_DepthBuffer; - stencilRb = ctx->DrawBuffer->_StencilBuffer; - for (i = 0; i < height; i++) { const GLuint *depthStencilSrc = (const GLuint *) _mesa_image_address2d(&clippedUnpack, pixels, width, height, GL_DEPTH_STENCIL_EXT, type, i, 0); if (ctx->Depth.Mask) { - if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 24 && - type == GL_UNSIGNED_INT_24_8) { - /* fast path 24-bit zbuffer */ - GLuint zValues[MAX_WIDTH]; - GLint j; - ASSERT(depthRb->DataType == GL_UNSIGNED_INT); - for (j = 0; j < width; j++) { - zValues[j] = depthStencilSrc[j] >> 8; - } - if (zoom) - _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, - x, y + i, zValues); - else - depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL); - } - else if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 16 && - type == GL_UNSIGNED_INT_24_8) { - /* fast path 16-bit zbuffer */ - GLushort zValues[MAX_WIDTH]; - GLint j; - ASSERT(depthRb->DataType == GL_UNSIGNED_SHORT); - for (j = 0; j < width; j++) { - zValues[j] = depthStencilSrc[j] >> 16; - } - if (zoom) - _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, - x, y + i, zValues); - else - depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL); + GLuint zValues[MAX_WIDTH]; /* 32-bit Z values */ + _mesa_unpack_depth_span(ctx, width, + GL_UNSIGNED_INT, /* dest type */ + zValues, /* dest addr */ + 0xffffffff, /* depth max */ + type, /* src type */ + depthStencilSrc, /* src addr */ + &clippedUnpack); + if (zoom) { + _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x, + y + i, zValues); } else { - /* general case */ - GLuint zValues[MAX_WIDTH]; /* 16 or 32-bit Z value storage */ - _mesa_unpack_depth_span(ctx, width, - depthRb->DataType, zValues, depthMax, - type, depthStencilSrc, &clippedUnpack); - if (zoom) { - _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x, - y + i, zValues); - } - else { - depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL); - } + GLubyte *dst = _swrast_pixel_address(depthRb, x, y + i); + _mesa_pack_uint_z_row(depthRb->Format, width, zValues, dst); } } @@ -716,8 +654,6 @@ _swrast_DrawPixels( struct gl_context *ctx, */ _mesa_set_vp_override(ctx, GL_TRUE); - swrast_render_start(ctx); - if (ctx->NewState) _mesa_update_state(ctx); @@ -726,7 +662,6 @@ _swrast_DrawPixels( struct gl_context *ctx, pixels = _mesa_map_pbo_source(ctx, unpack, pixels); if (!pixels) { - swrast_render_finish(ctx); _mesa_set_vp_override(ctx, save_vp_override); return; } @@ -736,20 +671,25 @@ _swrast_DrawPixels( struct gl_context *ctx, */ switch (format) { case GL_STENCIL_INDEX: + swrast_render_start(ctx); draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels ); + swrast_render_finish(ctx); break; case GL_DEPTH_COMPONENT: + swrast_render_start(ctx); draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels ); + swrast_render_finish(ctx); break; case GL_DEPTH_STENCIL_EXT: + swrast_render_start(ctx); draw_depth_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels); + swrast_render_finish(ctx); break; default: /* all other formats should be color formats */ draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels); } - swrast_render_finish(ctx); _mesa_set_vp_override(ctx, save_vp_override); _mesa_unmap_pbo_source(ctx, unpack); diff --git a/mesalib/src/mesa/swrast/s_linetemp.h b/mesalib/src/mesa/swrast/s_linetemp.h index bd94ca40a..1668f7db9 100644 --- a/mesalib/src/mesa/swrast/s_linetemp.h +++ b/mesalib/src/mesa/swrast/s_linetemp.h @@ -1,402 +1,402 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.0
- *
- * Copyright (C) 1999-2007 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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/*
- * Line Rasterizer Template
- *
- * This file is #include'd to generate custom line rasterizers.
- *
- * The following macros may be defined to indicate what auxillary information
- * must be interplated along the line:
- * INTERP_Z - if defined, interpolate Z values
- * INTERP_ATTRIBS - if defined, interpolate attribs (texcoords, varying, etc)
- *
- * When one can directly address pixels in the color buffer the following
- * macros can be defined and used to directly compute pixel addresses during
- * rasterization (see pixelPtr):
- * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
- * BYTES_PER_ROW - number of bytes per row in the color buffer
- * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
- * Y==0 at bottom of screen and increases upward.
- *
- * Similarly, for direct depth buffer access, this type is used for depth
- * buffer addressing:
- * DEPTH_TYPE - either GLushort or GLuint
- *
- * Optionally, one may provide one-time setup code
- * SETUP_CODE - code which is to be executed once per line
- *
- * To actually "plot" each pixel the PLOT macro must be defined...
- * PLOT(X,Y) - code to plot a pixel. Example:
- * if (Z < *zPtr) {
- * *zPtr = Z;
- * color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
- * FixedToInt(b0) );
- * put_pixel( X, Y, color );
- * }
- *
- * This code was designed for the origin to be in the lower-left corner.
- *
- */
-
-
-static void
-NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 )
-{
- const SWcontext *swrast = SWRAST_CONTEXT(ctx);
- SWspan span;
- GLuint interpFlags = 0;
- GLint x0 = (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][0];
- GLint x1 = (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][0];
- GLint y0 = (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][1];
- GLint y1 = (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][1];
- GLint dx, dy;
- GLint numPixels;
- GLint xstep, ystep;
-#if defined(DEPTH_TYPE)
- const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
- const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
- struct gl_renderbuffer *zrb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
-#define FixedToDepth(F) ((F) >> fixedToDepthShift)
- GLint zPtrXstep, zPtrYstep;
- DEPTH_TYPE *zPtr;
-#elif defined(INTERP_Z)
- const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
-#endif
-#ifdef PIXEL_ADDRESS
- PIXEL_TYPE *pixelPtr;
- GLint pixelXstep, pixelYstep;
-#endif
-
-#ifdef SETUP_CODE
- SETUP_CODE
-#endif
-
- (void) swrast;
-
- /* Cull primitives with malformed coordinates.
- */
- {
- GLfloat tmp = vert0->attrib[FRAG_ATTRIB_WPOS][0] + vert0->attrib[FRAG_ATTRIB_WPOS][1]
- + vert1->attrib[FRAG_ATTRIB_WPOS][0] + vert1->attrib[FRAG_ATTRIB_WPOS][1];
- if (IS_INF_OR_NAN(tmp))
- return;
- }
-
- /*
- printf("%s():\n", __FUNCTION__);
- printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
- vert0->attrib[FRAG_ATTRIB_WPOS][0],
- vert0->attrib[FRAG_ATTRIB_WPOS][1],
- vert0->attrib[FRAG_ATTRIB_WPOS][2],
- vert1->attrib[FRAG_ATTRIB_WPOS][0],
- vert1->attrib[FRAG_ATTRIB_WPOS][1],
- vert1->attrib[FRAG_ATTRIB_WPOS][2]);
- printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
- vert0->color[0], vert0->color[1], vert0->color[2],
- vert1->color[0], vert1->color[1], vert1->color[2]);
- printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
- vert0->specular[0], vert0->specular[1], vert0->specular[2],
- vert1->specular[0], vert1->specular[1], vert1->specular[2]);
- */
-
-/*
- * Despite being clipped to the view volume, the line's window coordinates
- * may just lie outside the window bounds. That is, if the legal window
- * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
- * This quick and dirty code nudges the endpoints inside the window if
- * necessary.
- */
-#ifdef CLIP_HACK
- {
- GLint w = ctx->DrawBuffer->Width;
- GLint h = ctx->DrawBuffer->Height;
- if ((x0==w) | (x1==w)) {
- if ((x0==w) & (x1==w))
- return;
- x0 -= x0==w;
- x1 -= x1==w;
- }
- if ((y0==h) | (y1==h)) {
- if ((y0==h) & (y1==h))
- return;
- y0 -= y0==h;
- y1 -= y1==h;
- }
- }
-#endif
-
- dx = x1 - x0;
- dy = y1 - y0;
- if (dx == 0 && dy == 0)
- return;
-
- /*
- printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __FUNCTION__, dx, dy,
- vert0->attrib[FRAG_ATTRIB_COL1][0],
- vert0->attrib[FRAG_ATTRIB_COL1][1],
- vert0->attrib[FRAG_ATTRIB_COL1][2],
- vert0->attrib[FRAG_ATTRIB_COL1][3],
- vert1->attrib[FRAG_ATTRIB_COL1][0],
- vert1->attrib[FRAG_ATTRIB_COL1][1],
- vert1->attrib[FRAG_ATTRIB_COL1][2],
- vert1->attrib[FRAG_ATTRIB_COL1][3]);
- */
-
-#ifdef DEPTH_TYPE
- zPtr = (DEPTH_TYPE *) zrb->GetPointer(ctx, zrb, x0, y0);
-#endif
-#ifdef PIXEL_ADDRESS
- pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
-#endif
-
- if (dx<0) {
- dx = -dx; /* make positive */
- xstep = -1;
-#ifdef DEPTH_TYPE
- zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
-#endif
-#ifdef PIXEL_ADDRESS
- pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
-#endif
- }
- else {
- xstep = 1;
-#ifdef DEPTH_TYPE
- zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
-#endif
-#ifdef PIXEL_ADDRESS
- pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
-#endif
- }
-
- if (dy<0) {
- dy = -dy; /* make positive */
- ystep = -1;
-#ifdef DEPTH_TYPE
- zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)));
-#endif
-#ifdef PIXEL_ADDRESS
- pixelYstep = BYTES_PER_ROW;
-#endif
- }
- else {
- ystep = 1;
-#ifdef DEPTH_TYPE
- zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE));
-#endif
-#ifdef PIXEL_ADDRESS
- pixelYstep = -(BYTES_PER_ROW);
-#endif
- }
-
- ASSERT(dx >= 0);
- ASSERT(dy >= 0);
-
- numPixels = MAX2(dx, dy);
-
- /*
- * Span setup: compute start and step values for all interpolated values.
- */
- interpFlags |= SPAN_RGBA;
- if (ctx->Light.ShadeModel == GL_SMOOTH) {
- span.red = ChanToFixed(vert0->color[0]);
- span.green = ChanToFixed(vert0->color[1]);
- span.blue = ChanToFixed(vert0->color[2]);
- span.alpha = ChanToFixed(vert0->color[3]);
- span.redStep = (ChanToFixed(vert1->color[0]) - span.red ) / numPixels;
- span.greenStep = (ChanToFixed(vert1->color[1]) - span.green) / numPixels;
- span.blueStep = (ChanToFixed(vert1->color[2]) - span.blue ) / numPixels;
- span.alphaStep = (ChanToFixed(vert1->color[3]) - span.alpha) / numPixels;
- }
- else {
- span.red = ChanToFixed(vert1->color[0]);
- span.green = ChanToFixed(vert1->color[1]);
- span.blue = ChanToFixed(vert1->color[2]);
- span.alpha = ChanToFixed(vert1->color[3]);
- span.redStep = 0;
- span.greenStep = 0;
- span.blueStep = 0;
- span.alphaStep = 0;
- }
-#if defined(INTERP_Z) || defined(DEPTH_TYPE)
- interpFlags |= SPAN_Z;
- {
- if (depthBits <= 16) {
- span.z = FloatToFixed(vert0->attrib[FRAG_ATTRIB_WPOS][2]) + FIXED_HALF;
- span.zStep = FloatToFixed( vert1->attrib[FRAG_ATTRIB_WPOS][2]
- - vert0->attrib[FRAG_ATTRIB_WPOS][2]) / numPixels;
- }
- else {
- /* don't use fixed point */
- span.z = (GLuint) vert0->attrib[FRAG_ATTRIB_WPOS][2];
- span.zStep = (GLint) (( vert1->attrib[FRAG_ATTRIB_WPOS][2]
- - vert0->attrib[FRAG_ATTRIB_WPOS][2]) / numPixels);
- }
- }
-#endif
-#if defined(INTERP_ATTRIBS)
- {
- const GLfloat invLen = 1.0F / numPixels;
- const GLfloat invw0 = vert0->attrib[FRAG_ATTRIB_WPOS][3];
- const GLfloat invw1 = vert1->attrib[FRAG_ATTRIB_WPOS][3];
-
- span.attrStart[FRAG_ATTRIB_WPOS][3] = invw0;
- span.attrStepX[FRAG_ATTRIB_WPOS][3] = (invw1 - invw0) * invLen;
- span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;
-
- ATTRIB_LOOP_BEGIN
- if (swrast->_InterpMode[attr] == GL_FLAT) {
- COPY_4V(span.attrStart[attr], vert1->attrib[attr]);
- ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
- }
- else {
- GLuint c;
- for (c = 0; c < 4; c++) {
- float da;
- span.attrStart[attr][c] = invw0 * vert0->attrib[attr][c];
- da = (invw1 * vert1->attrib[attr][c]) - span.attrStart[attr][c];
- span.attrStepX[attr][c] = da * invLen;
- }
- }
- ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
- ATTRIB_LOOP_END
- }
-#endif
-
- INIT_SPAN(span, GL_LINE);
- span.end = numPixels;
- span.interpMask = interpFlags;
- span.arrayMask = SPAN_XY;
-
- span.facing = swrast->PointLineFacing;
-
-
- /*
- * Draw
- */
-
- if (dx > dy) {
- /*** X-major line ***/
- GLint i;
- GLint errorInc = dy+dy;
- GLint error = errorInc-dx;
- GLint errorDec = error-dx;
-
- for (i = 0; i < dx; i++) {
-#ifdef DEPTH_TYPE
- GLuint Z = FixedToDepth(span.z);
-#endif
-#ifdef PLOT
- PLOT( x0, y0 );
-#else
- span.array->x[i] = x0;
- span.array->y[i] = y0;
-#endif
- x0 += xstep;
-#ifdef DEPTH_TYPE
- zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
- span.z += span.zStep;
-#endif
-#ifdef PIXEL_ADDRESS
- pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
-#endif
- if (error < 0) {
- error += errorInc;
- }
- else {
- error += errorDec;
- y0 += ystep;
-#ifdef DEPTH_TYPE
- zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
-#endif
-#ifdef PIXEL_ADDRESS
- pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
-#endif
- }
- }
- }
- else {
- /*** Y-major line ***/
- GLint i;
- GLint errorInc = dx+dx;
- GLint error = errorInc-dy;
- GLint errorDec = error-dy;
-
- for (i=0;i<dy;i++) {
-#ifdef DEPTH_TYPE
- GLuint Z = FixedToDepth(span.z);
-#endif
-#ifdef PLOT
- PLOT( x0, y0 );
-#else
- span.array->x[i] = x0;
- span.array->y[i] = y0;
-#endif
- y0 += ystep;
-#ifdef DEPTH_TYPE
- zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
- span.z += span.zStep;
-#endif
-#ifdef PIXEL_ADDRESS
- pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
-#endif
- if (error<0) {
- error += errorInc;
- }
- else {
- error += errorDec;
- x0 += xstep;
-#ifdef DEPTH_TYPE
- zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
-#endif
-#ifdef PIXEL_ADDRESS
- pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
-#endif
- }
- }
- }
-
-#ifdef RENDER_SPAN
- RENDER_SPAN( span );
-#endif
-
- (void)span;
-
-}
-
-
-#undef NAME
-#undef INTERP_Z
-#undef INTERP_ATTRIBS
-#undef PIXEL_ADDRESS
-#undef PIXEL_TYPE
-#undef DEPTH_TYPE
-#undef BYTES_PER_ROW
-#undef SETUP_CODE
-#undef PLOT
-#undef CLIP_HACK
-#undef FixedToDepth
-#undef RENDER_SPAN
+/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 1999-2007 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Line Rasterizer Template + * + * This file is #include'd to generate custom line rasterizers. + * + * The following macros may be defined to indicate what auxillary information + * must be interplated along the line: + * INTERP_Z - if defined, interpolate Z values + * INTERP_ATTRIBS - if defined, interpolate attribs (texcoords, varying, etc) + * + * When one can directly address pixels in the color buffer the following + * macros can be defined and used to directly compute pixel addresses during + * rasterization (see pixelPtr): + * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint) + * BYTES_PER_ROW - number of bytes per row in the color buffer + * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where + * Y==0 at bottom of screen and increases upward. + * + * Similarly, for direct depth buffer access, this type is used for depth + * buffer addressing: + * DEPTH_TYPE - either GLushort or GLuint + * + * Optionally, one may provide one-time setup code + * SETUP_CODE - code which is to be executed once per line + * + * To actually "plot" each pixel the PLOT macro must be defined... + * PLOT(X,Y) - code to plot a pixel. Example: + * if (Z < *zPtr) { + * *zPtr = Z; + * color = pack_rgb( FixedToInt(r0), FixedToInt(g0), + * FixedToInt(b0) ); + * put_pixel( X, Y, color ); + * } + * + * This code was designed for the origin to be in the lower-left corner. + * + */ + + +static void +NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 ) +{ + const SWcontext *swrast = SWRAST_CONTEXT(ctx); + SWspan span; + GLuint interpFlags = 0; + GLint x0 = (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][0]; + GLint x1 = (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][0]; + GLint y0 = (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][1]; + GLint y1 = (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][1]; + GLint dx, dy; + GLint numPixels; + GLint xstep, ystep; +#if defined(DEPTH_TYPE) + const GLint depthBits = ctx->DrawBuffer->Visual.depthBits; + const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0; + struct gl_renderbuffer *zrb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; +#define FixedToDepth(F) ((F) >> fixedToDepthShift) + GLint zPtrXstep, zPtrYstep; + DEPTH_TYPE *zPtr; +#elif defined(INTERP_Z) + const GLint depthBits = ctx->DrawBuffer->Visual.depthBits; +#endif +#ifdef PIXEL_ADDRESS + PIXEL_TYPE *pixelPtr; + GLint pixelXstep, pixelYstep; +#endif + +#ifdef SETUP_CODE + SETUP_CODE +#endif + + (void) swrast; + + /* Cull primitives with malformed coordinates. + */ + { + GLfloat tmp = vert0->attrib[FRAG_ATTRIB_WPOS][0] + vert0->attrib[FRAG_ATTRIB_WPOS][1] + + vert1->attrib[FRAG_ATTRIB_WPOS][0] + vert1->attrib[FRAG_ATTRIB_WPOS][1]; + if (IS_INF_OR_NAN(tmp)) + return; + } + + /* + printf("%s():\n", __FUNCTION__); + printf(" (%f, %f, %f) -> (%f, %f, %f)\n", + vert0->attrib[FRAG_ATTRIB_WPOS][0], + vert0->attrib[FRAG_ATTRIB_WPOS][1], + vert0->attrib[FRAG_ATTRIB_WPOS][2], + vert1->attrib[FRAG_ATTRIB_WPOS][0], + vert1->attrib[FRAG_ATTRIB_WPOS][1], + vert1->attrib[FRAG_ATTRIB_WPOS][2]); + printf(" (%d, %d, %d) -> (%d, %d, %d)\n", + vert0->color[0], vert0->color[1], vert0->color[2], + vert1->color[0], vert1->color[1], vert1->color[2]); + printf(" (%d, %d, %d) -> (%d, %d, %d)\n", + vert0->specular[0], vert0->specular[1], vert0->specular[2], + vert1->specular[0], vert1->specular[1], vert1->specular[2]); + */ + +/* + * Despite being clipped to the view volume, the line's window coordinates + * may just lie outside the window bounds. That is, if the legal window + * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H. + * This quick and dirty code nudges the endpoints inside the window if + * necessary. + */ +#ifdef CLIP_HACK + { + GLint w = ctx->DrawBuffer->Width; + GLint h = ctx->DrawBuffer->Height; + if ((x0==w) | (x1==w)) { + if ((x0==w) & (x1==w)) + return; + x0 -= x0==w; + x1 -= x1==w; + } + if ((y0==h) | (y1==h)) { + if ((y0==h) & (y1==h)) + return; + y0 -= y0==h; + y1 -= y1==h; + } + } +#endif + + dx = x1 - x0; + dy = y1 - y0; + if (dx == 0 && dy == 0) + return; + + /* + printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __FUNCTION__, dx, dy, + vert0->attrib[FRAG_ATTRIB_COL1][0], + vert0->attrib[FRAG_ATTRIB_COL1][1], + vert0->attrib[FRAG_ATTRIB_COL1][2], + vert0->attrib[FRAG_ATTRIB_COL1][3], + vert1->attrib[FRAG_ATTRIB_COL1][0], + vert1->attrib[FRAG_ATTRIB_COL1][1], + vert1->attrib[FRAG_ATTRIB_COL1][2], + vert1->attrib[FRAG_ATTRIB_COL1][3]); + */ + +#ifdef DEPTH_TYPE + zPtr = (DEPTH_TYPE *) _swrast_pixel_address(zrb, x0, y0); +#endif +#ifdef PIXEL_ADDRESS + pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0); +#endif + + if (dx<0) { + dx = -dx; /* make positive */ + xstep = -1; +#ifdef DEPTH_TYPE + zPtrXstep = -((GLint)sizeof(DEPTH_TYPE)); +#endif +#ifdef PIXEL_ADDRESS + pixelXstep = -((GLint)sizeof(PIXEL_TYPE)); +#endif + } + else { + xstep = 1; +#ifdef DEPTH_TYPE + zPtrXstep = ((GLint)sizeof(DEPTH_TYPE)); +#endif +#ifdef PIXEL_ADDRESS + pixelXstep = ((GLint)sizeof(PIXEL_TYPE)); +#endif + } + + if (dy<0) { + dy = -dy; /* make positive */ + ystep = -1; +#ifdef DEPTH_TYPE + zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE))); +#endif +#ifdef PIXEL_ADDRESS + pixelYstep = BYTES_PER_ROW; +#endif + } + else { + ystep = 1; +#ifdef DEPTH_TYPE + zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)); +#endif +#ifdef PIXEL_ADDRESS + pixelYstep = -(BYTES_PER_ROW); +#endif + } + + ASSERT(dx >= 0); + ASSERT(dy >= 0); + + numPixels = MAX2(dx, dy); + + /* + * Span setup: compute start and step values for all interpolated values. + */ + interpFlags |= SPAN_RGBA; + if (ctx->Light.ShadeModel == GL_SMOOTH) { + span.red = ChanToFixed(vert0->color[0]); + span.green = ChanToFixed(vert0->color[1]); + span.blue = ChanToFixed(vert0->color[2]); + span.alpha = ChanToFixed(vert0->color[3]); + span.redStep = (ChanToFixed(vert1->color[0]) - span.red ) / numPixels; + span.greenStep = (ChanToFixed(vert1->color[1]) - span.green) / numPixels; + span.blueStep = (ChanToFixed(vert1->color[2]) - span.blue ) / numPixels; + span.alphaStep = (ChanToFixed(vert1->color[3]) - span.alpha) / numPixels; + } + else { + span.red = ChanToFixed(vert1->color[0]); + span.green = ChanToFixed(vert1->color[1]); + span.blue = ChanToFixed(vert1->color[2]); + span.alpha = ChanToFixed(vert1->color[3]); + span.redStep = 0; + span.greenStep = 0; + span.blueStep = 0; + span.alphaStep = 0; + } +#if defined(INTERP_Z) || defined(DEPTH_TYPE) + interpFlags |= SPAN_Z; + { + if (depthBits <= 16) { + span.z = FloatToFixed(vert0->attrib[FRAG_ATTRIB_WPOS][2]) + FIXED_HALF; + span.zStep = FloatToFixed( vert1->attrib[FRAG_ATTRIB_WPOS][2] + - vert0->attrib[FRAG_ATTRIB_WPOS][2]) / numPixels; + } + else { + /* don't use fixed point */ + span.z = (GLuint) vert0->attrib[FRAG_ATTRIB_WPOS][2]; + span.zStep = (GLint) (( vert1->attrib[FRAG_ATTRIB_WPOS][2] + - vert0->attrib[FRAG_ATTRIB_WPOS][2]) / numPixels); + } + } +#endif +#if defined(INTERP_ATTRIBS) + { + const GLfloat invLen = 1.0F / numPixels; + const GLfloat invw0 = vert0->attrib[FRAG_ATTRIB_WPOS][3]; + const GLfloat invw1 = vert1->attrib[FRAG_ATTRIB_WPOS][3]; + + span.attrStart[FRAG_ATTRIB_WPOS][3] = invw0; + span.attrStepX[FRAG_ATTRIB_WPOS][3] = (invw1 - invw0) * invLen; + span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0; + + ATTRIB_LOOP_BEGIN + if (swrast->_InterpMode[attr] == GL_FLAT) { + COPY_4V(span.attrStart[attr], vert1->attrib[attr]); + ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0); + } + else { + GLuint c; + for (c = 0; c < 4; c++) { + float da; + span.attrStart[attr][c] = invw0 * vert0->attrib[attr][c]; + da = (invw1 * vert1->attrib[attr][c]) - span.attrStart[attr][c]; + span.attrStepX[attr][c] = da * invLen; + } + } + ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0); + ATTRIB_LOOP_END + } +#endif + + INIT_SPAN(span, GL_LINE); + span.end = numPixels; + span.interpMask = interpFlags; + span.arrayMask = SPAN_XY; + + span.facing = swrast->PointLineFacing; + + + /* + * Draw + */ + + if (dx > dy) { + /*** X-major line ***/ + GLint i; + GLint errorInc = dy+dy; + GLint error = errorInc-dx; + GLint errorDec = error-dx; + + for (i = 0; i < dx; i++) { +#ifdef DEPTH_TYPE + GLuint Z = FixedToDepth(span.z); +#endif +#ifdef PLOT + PLOT( x0, y0 ); +#else + span.array->x[i] = x0; + span.array->y[i] = y0; +#endif + x0 += xstep; +#ifdef DEPTH_TYPE + zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep); + span.z += span.zStep; +#endif +#ifdef PIXEL_ADDRESS + pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep); +#endif + if (error < 0) { + error += errorInc; + } + else { + error += errorDec; + y0 += ystep; +#ifdef DEPTH_TYPE + zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep); +#endif +#ifdef PIXEL_ADDRESS + pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep); +#endif + } + } + } + else { + /*** Y-major line ***/ + GLint i; + GLint errorInc = dx+dx; + GLint error = errorInc-dy; + GLint errorDec = error-dy; + + for (i=0;i<dy;i++) { +#ifdef DEPTH_TYPE + GLuint Z = FixedToDepth(span.z); +#endif +#ifdef PLOT + PLOT( x0, y0 ); +#else + span.array->x[i] = x0; + span.array->y[i] = y0; +#endif + y0 += ystep; +#ifdef DEPTH_TYPE + zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep); + span.z += span.zStep; +#endif +#ifdef PIXEL_ADDRESS + pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep); +#endif + if (error<0) { + error += errorInc; + } + else { + error += errorDec; + x0 += xstep; +#ifdef DEPTH_TYPE + zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep); +#endif +#ifdef PIXEL_ADDRESS + pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep); +#endif + } + } + } + +#ifdef RENDER_SPAN + RENDER_SPAN( span ); +#endif + + (void)span; + +} + + +#undef NAME +#undef INTERP_Z +#undef INTERP_ATTRIBS +#undef PIXEL_ADDRESS +#undef PIXEL_TYPE +#undef DEPTH_TYPE +#undef BYTES_PER_ROW +#undef SETUP_CODE +#undef PLOT +#undef CLIP_HACK +#undef FixedToDepth +#undef RENDER_SPAN diff --git a/mesalib/src/mesa/swrast/s_renderbuffer.c b/mesalib/src/mesa/swrast/s_renderbuffer.c index bb7cdebfe..1a7cb36d9 100644 --- a/mesalib/src/mesa/swrast/s_renderbuffer.c +++ b/mesalib/src/mesa/swrast/s_renderbuffer.c @@ -158,31 +158,6 @@ put_row_generic(struct gl_context *ctx, struct gl_renderbuffer *rb, } } -static void -put_mono_row_generic(struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, GLint x, GLint y, - const void *value, const GLubyte *mask) -{ - void *row = rb->GetPointer(ctx, rb, x, y); - int format_bytes = _mesa_get_format_bytes(rb->Format) / sizeof(GLfloat); - unsigned int i; - - if (mask) { - for (i = 0; i < count; i++) { - char *dst = (char *) row + i * format_bytes; - if (mask[i]) { - memcpy(dst, value, format_bytes); - } - } - } - else { - for (i = 0; i < count; i++) { - char *dst = (char *) row + i * format_bytes; - memcpy(dst, value, format_bytes); - } - } -} - static void put_values_generic(struct gl_context *ctx, struct gl_renderbuffer *rb, @@ -203,22 +178,6 @@ put_values_generic(struct gl_context *ctx, struct gl_renderbuffer *rb, } -static void -put_mono_values_generic(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte *mask) -{ - int format_bytes = _mesa_get_format_bytes(rb->Format) / sizeof(GLfloat); - unsigned int i; - - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - void *dst = rb->GetPointer(ctx, rb, x[i], y[i]); - memcpy(dst, value, format_bytes); - } - } -} /********************************************************************** * Functions for buffers of 1 X GLubyte values. @@ -261,30 +220,6 @@ put_row_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, static void -put_mono_row_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *value, const GLubyte *mask) -{ - const GLubyte val = *((const GLubyte *) value); - GLubyte *dst = (GLubyte *) rb->Data + y * rb->RowStride + x; - ASSERT(rb->DataType == GL_UNSIGNED_BYTE); - if (mask) { - GLuint i; - for (i = 0; i < count; i++) { - if (mask[i]) { - dst[i] = val; - } - } - } - else { - GLuint i; - for (i = 0; i < count; i++) { - dst[i] = val; - } - } -} - - -static void put_values_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], const void *values, const GLubyte *mask) @@ -301,23 +236,6 @@ put_values_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint coun } -static void -put_mono_values_ubyte(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - const GLint x[], const GLint y[], - const void *value, const GLubyte *mask) -{ - const GLubyte val = *((const GLubyte *) value); - GLuint i; - ASSERT(rb->DataType == GL_UNSIGNED_BYTE); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->RowStride + x[i]; - *dst = val; - } - } -} - - /********************************************************************** * Functions for buffers of 1 X GLushort values. * Typically depth/Z. @@ -359,30 +277,6 @@ put_row_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, static void -put_mono_row_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *value, const GLubyte *mask) -{ - const GLushort val = *((const GLushort *) value); - GLushort *dst = (GLushort *) rb->Data + y * rb->RowStride + x; - ASSERT(rb->DataType == GL_UNSIGNED_SHORT); - if (mask) { - GLuint i; - for (i = 0; i < count; i++) { - if (mask[i]) { - dst[i] = val; - } - } - } - else { - GLuint i; - for (i = 0; i < count; i++) { - dst[i] = val; - } - } -} - - -static void put_values_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], const void *values, const GLubyte *mask) @@ -399,32 +293,6 @@ put_values_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint cou } -static void -put_mono_values_ushort(struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte *mask) -{ - const GLushort val = *((const GLushort *) value); - ASSERT(rb->DataType == GL_UNSIGNED_SHORT); - if (mask) { - GLuint i; - for (i = 0; i < count; i++) { - if (mask[i]) { - GLushort *dst = (GLushort *) rb->Data + y[i] * rb->RowStride + x[i]; - *dst = val; - } - } - } - else { - GLuint i; - for (i = 0; i < count; i++) { - GLushort *dst = (GLushort *) rb->Data + y[i] * rb->RowStride + x[i]; - *dst = val; - } - } -} - - /********************************************************************** * Functions for buffers of 1 X GLuint values. * Typically depth/Z or color index. @@ -468,31 +336,6 @@ put_row_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, static void -put_mono_row_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *value, const GLubyte *mask) -{ - const GLuint val = *((const GLuint *) value); - GLuint *dst = (GLuint *) rb->Data + y * rb->RowStride + x; - ASSERT(rb->DataType == GL_UNSIGNED_INT || - rb->DataType == GL_UNSIGNED_INT_24_8_EXT); - if (mask) { - GLuint i; - for (i = 0; i < count; i++) { - if (mask[i]) { - dst[i] = val; - } - } - } - else { - GLuint i; - for (i = 0; i < count; i++) { - dst[i] = val; - } - } -} - - -static void put_values_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], const void *values, const GLubyte *mask) @@ -510,24 +353,6 @@ put_values_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count } -static void -put_mono_values_uint(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - const GLint x[], const GLint y[], const void *value, - const GLubyte *mask) -{ - const GLuint val = *((const GLuint *) value); - GLuint i; - ASSERT(rb->DataType == GL_UNSIGNED_INT || - rb->DataType == GL_UNSIGNED_INT_24_8_EXT); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - GLuint *dst = (GLuint *) rb->Data + y[i] * rb->RowStride + x[i]; - *dst = val; - } - } -} - - /********************************************************************** * Functions for buffers of 3 X GLubyte (or GLbyte) values. * Typically color buffers. @@ -606,54 +431,6 @@ put_row_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, static void -put_row_rgb_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *values, const GLubyte *mask) -{ - /* note: incoming values are RGB+A! */ - const GLubyte *src = (const GLubyte *) values; - GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->RowStride + x); - GLuint i; - ASSERT(rb->Format == MESA_FORMAT_RGB888); - ASSERT(rb->DataType == GL_UNSIGNED_BYTE); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst[i * 3 + 0] = src[i * 3 + 0]; - dst[i * 3 + 1] = src[i * 3 + 1]; - dst[i * 3 + 2] = src[i * 3 + 2]; - } - } -} - - -static void -put_mono_row_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *value, const GLubyte *mask) -{ - /* note: incoming value is RGB+A! */ - const GLubyte val0 = ((const GLubyte *) value)[0]; - const GLubyte val1 = ((const GLubyte *) value)[1]; - const GLubyte val2 = ((const GLubyte *) value)[2]; - GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->RowStride + x); - ASSERT(rb->Format == MESA_FORMAT_RGB888); - ASSERT(rb->DataType == GL_UNSIGNED_BYTE); - if (!mask && val0 == val1 && val1 == val2) { - /* optimized case */ - memset(dst, val0, 3 * count); - } - else { - GLuint i; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst[i * 3 + 0] = val0; - dst[i * 3 + 1] = val1; - dst[i * 3 + 2] = val2; - } - } - } -} - - -static void put_values_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], const void *values, const GLubyte *mask) @@ -674,30 +451,6 @@ put_values_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint cou } -static void -put_mono_values_ubyte3(struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte *mask) -{ - /* note: incoming value is RGB+A! */ - const GLubyte val0 = ((const GLubyte *) value)[0]; - const GLubyte val1 = ((const GLubyte *) value)[1]; - const GLubyte val2 = ((const GLubyte *) value)[2]; - GLuint i; - ASSERT(rb->Format == MESA_FORMAT_RGB888); - ASSERT(rb->DataType == GL_UNSIGNED_BYTE); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - GLubyte *dst = ((GLubyte *) rb->Data) + - 3 * (y[i] * rb->RowStride + x[i]); - dst[0] = val0; - dst[1] = val1; - dst[2] = val2; - } - } -} - - /********************************************************************** * Functions for buffers of 4 X GLubyte (or GLbyte) values. * Typically color buffers. @@ -745,62 +498,6 @@ put_row_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, static void -put_row_rgb_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *values, const GLubyte *mask) -{ - /* Store RGB values in RGBA buffer */ - const GLubyte *src = (const GLubyte *) values; - GLubyte *dst = (GLubyte *) rb->Data + 4 * (y * rb->RowStride + x); - GLuint i; - ASSERT(rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(rb->Format == MESA_FORMAT_RGBA8888 || - rb->Format == MESA_FORMAT_RGBA8888_REV); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst[i * 4 + 0] = src[i * 3 + 0]; - dst[i * 4 + 1] = src[i * 3 + 1]; - dst[i * 4 + 2] = src[i * 3 + 2]; - dst[i * 4 + 3] = 0xff; - } - } -} - - -static void -put_mono_row_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *value, const GLubyte *mask) -{ - /* treat 4*GLubyte as 1*GLuint */ - const GLuint val = *((const GLuint *) value); - GLuint *dst = (GLuint *) rb->Data + (y * rb->RowStride + x); - ASSERT(rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(rb->Format == MESA_FORMAT_RGBA8888 || - rb->Format == MESA_FORMAT_RGBA8888_REV); - if (!mask && val == 0) { - /* common case */ - memset(dst, 0, count * 4 * sizeof(GLubyte)); - } - else { - /* general case */ - if (mask) { - GLuint i; - for (i = 0; i < count; i++) { - if (mask[i]) { - dst[i] = val; - } - } - } - else { - GLuint i; - for (i = 0; i < count; i++) { - dst[i] = val; - } - } - } -} - - -static void put_values_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], const void *values, const GLubyte *mask) @@ -820,26 +517,6 @@ put_values_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint cou } -static void -put_mono_values_ubyte4(struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte *mask) -{ - /* treat 4*GLubyte as 1*GLuint */ - const GLuint val = *((const GLuint *) value); - GLuint i; - ASSERT(rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(rb->Format == MESA_FORMAT_RGBA8888 || - rb->Format == MESA_FORMAT_RGBA8888_REV); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->RowStride + x[i]); - *dst = val; - } - } -} - - /********************************************************************** * Functions for buffers of 4 X GLushort (or GLshort) values. * Typically accum buffer. @@ -885,59 +562,6 @@ put_row_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count static void -put_row_rgb_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *values, const GLubyte *mask) -{ - /* Put RGB values in RGBA buffer */ - const GLushort *src = (const GLushort *) values; - GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->RowStride + x); - ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); - if (mask) { - GLuint i; - for (i = 0; i < count; i++) { - if (mask[i]) { - dst[i * 4 + 0] = src[i * 3 + 0]; - dst[i * 4 + 1] = src[i * 3 + 1]; - dst[i * 4 + 2] = src[i * 3 + 2]; - dst[i * 4 + 3] = 0xffff; - } - } - } - else { - memcpy(dst, src, 4 * count * sizeof(GLushort)); - } -} - - -static void -put_mono_row_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *value, const GLubyte *mask) -{ - const GLushort val0 = ((const GLushort *) value)[0]; - const GLushort val1 = ((const GLushort *) value)[1]; - const GLushort val2 = ((const GLushort *) value)[2]; - const GLushort val3 = ((const GLushort *) value)[3]; - GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->RowStride + x); - ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); - if (!mask && val0 == 0 && val1 == 0 && val2 == 0 && val3 == 0) { - /* common case for clearing accum buffer */ - memset(dst, 0, count * 4 * sizeof(GLushort)); - } - else { - GLuint i; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst[i * 4 + 0] = val0; - dst[i * 4 + 1] = val1; - dst[i * 4 + 2] = val2; - dst[i * 4 + 3] = val3; - } - } - } -} - - -static void put_values_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], const void *values, const GLubyte *mask) @@ -958,29 +582,6 @@ put_values_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint co } -static void -put_mono_values_ushort4(struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte *mask) -{ - const GLushort val0 = ((const GLushort *) value)[0]; - const GLushort val1 = ((const GLushort *) value)[1]; - const GLushort val2 = ((const GLushort *) value)[2]; - const GLushort val3 = ((const GLushort *) value)[3]; - GLuint i; - ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - GLushort *dst = ((GLushort *) rb->Data) + - 4 * (y[i] * rb->RowStride + x[i]); - dst[0] = val0; - dst[1] = val1; - dst[2] = val2; - dst[3] = val3; - } - } -} - /********************************************************************** * Functions for MESA_FORMAT_R8. */ @@ -1241,29 +842,6 @@ put_row_a_float32(struct gl_context *ctx, struct gl_renderbuffer *rb, } static void -put_mono_row_a_float32(struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, GLint x, GLint y, - const void *value, const GLubyte *mask) -{ - float *dst = rb->GetPointer(ctx, rb, x, y); - const float *src = value; - unsigned int i; - - if (mask) { - for (i = 0; i < count; i++) { - if (mask[i]) { - dst[i] = src[ACOMP]; - } - } - } - else { - for (i = 0; i < count; i++) { - dst[i] = src[ACOMP]; - } - } -} - -static void put_values_a_float32(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], const void *values, const GLubyte *mask) @@ -1280,23 +858,6 @@ put_values_a_float32(struct gl_context *ctx, struct gl_renderbuffer *rb, } } -static void -put_mono_values_a_float32(struct gl_context *ctx, - struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte *mask) -{ - const float *src = value; - unsigned int i; - - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - float *dst = rb->GetPointer(ctx, rb, x[i], y[i]); - *dst = src[ACOMP]; - } - } -} - /********************************************************************** * Functions for MESA_FORMAT_R_FLOAT32. */ @@ -1390,10 +951,7 @@ _swrast_set_renderbuffer_accessors(struct gl_renderbuffer *rb) rb->GetRow = get_row_ubyte3; rb->GetValues = get_values_ubyte3; rb->PutRow = put_row_ubyte3; - rb->PutRowRGB = put_row_rgb_ubyte3; - rb->PutMonoRow = put_mono_row_ubyte3; rb->PutValues = put_values_ubyte3; - rb->PutMonoValues = put_mono_values_ubyte3; break; case MESA_FORMAT_RGBA8888: @@ -1401,10 +959,7 @@ _swrast_set_renderbuffer_accessors(struct gl_renderbuffer *rb) rb->DataType = GL_UNSIGNED_BYTE; rb->GetValues = get_values_ubyte4; rb->PutRow = put_row_ubyte4; - rb->PutRowRGB = put_row_rgb_ubyte4; - rb->PutMonoRow = put_mono_row_ubyte4; rb->PutValues = put_values_ubyte4; - rb->PutMonoValues = put_mono_values_ubyte4; break; case MESA_FORMAT_R8: @@ -1412,10 +967,7 @@ _swrast_set_renderbuffer_accessors(struct gl_renderbuffer *rb) rb->GetValues = get_values_r8; rb->GetRow = get_row_r8; rb->PutRow = put_row_generic; - rb->PutRowRGB = put_row_generic; - rb->PutMonoRow = put_mono_row_generic; rb->PutValues = put_values_generic; - rb->PutMonoValues = put_mono_values_generic; break; case MESA_FORMAT_GR88: @@ -1423,10 +975,7 @@ _swrast_set_renderbuffer_accessors(struct gl_renderbuffer *rb) rb->GetValues = get_values_rg88; rb->GetRow = get_row_rg88; rb->PutRow = put_row_generic; - rb->PutRowRGB = put_row_generic; - rb->PutMonoRow = put_mono_row_generic; rb->PutValues = put_values_generic; - rb->PutMonoValues = put_mono_values_generic; break; case MESA_FORMAT_R16: @@ -1434,10 +983,7 @@ _swrast_set_renderbuffer_accessors(struct gl_renderbuffer *rb) rb->GetValues = get_values_r16; rb->GetRow = get_row_r16; rb->PutRow = put_row_generic; - rb->PutRowRGB = put_row_generic; - rb->PutMonoRow = put_mono_row_generic; rb->PutValues = put_values_generic; - rb->PutMonoValues = put_mono_values_generic; break; case MESA_FORMAT_RG1616: @@ -1445,40 +991,28 @@ _swrast_set_renderbuffer_accessors(struct gl_renderbuffer *rb) rb->GetValues = get_values_rg1616; rb->GetRow = get_row_rg1616; rb->PutRow = put_row_generic; - rb->PutRowRGB = put_row_generic; - rb->PutMonoRow = put_mono_row_generic; rb->PutValues = put_values_generic; - rb->PutMonoValues = put_mono_values_generic; break; case MESA_FORMAT_SIGNED_RGBA_16: rb->DataType = GL_SHORT; rb->GetValues = get_values_ushort4; rb->PutRow = put_row_ushort4; - rb->PutRowRGB = put_row_rgb_ushort4; - rb->PutMonoRow = put_mono_row_ushort4; rb->PutValues = put_values_ushort4; - rb->PutMonoValues = put_mono_values_ushort4; break; case MESA_FORMAT_S8: rb->DataType = GL_UNSIGNED_BYTE; rb->GetValues = get_values_ubyte; rb->PutRow = put_row_ubyte; - rb->PutRowRGB = NULL; - rb->PutMonoRow = put_mono_row_ubyte; rb->PutValues = put_values_ubyte; - rb->PutMonoValues = put_mono_values_ubyte; break; case MESA_FORMAT_Z16: rb->DataType = GL_UNSIGNED_SHORT; rb->GetValues = get_values_ushort; rb->PutRow = put_row_ushort; - rb->PutRowRGB = NULL; - rb->PutMonoRow = put_mono_row_ushort; rb->PutValues = put_values_ushort; - rb->PutMonoValues = put_mono_values_ushort; break; case MESA_FORMAT_Z32: @@ -1487,10 +1021,7 @@ _swrast_set_renderbuffer_accessors(struct gl_renderbuffer *rb) rb->DataType = GL_UNSIGNED_INT; rb->GetValues = get_values_uint; rb->PutRow = put_row_uint; - rb->PutRowRGB = NULL; - rb->PutMonoRow = put_mono_row_uint; rb->PutValues = put_values_uint; - rb->PutMonoValues = put_mono_values_uint; break; case MESA_FORMAT_Z24_S8: @@ -1498,70 +1029,49 @@ _swrast_set_renderbuffer_accessors(struct gl_renderbuffer *rb) rb->DataType = GL_UNSIGNED_INT_24_8_EXT; rb->GetValues = get_values_uint; rb->PutRow = put_row_uint; - rb->PutRowRGB = NULL; - rb->PutMonoRow = put_mono_row_uint; rb->PutValues = put_values_uint; - rb->PutMonoValues = put_mono_values_uint; break; case MESA_FORMAT_RGBA_FLOAT32: rb->GetRow = get_row_generic; rb->GetValues = get_values_generic; rb->PutRow = put_row_generic; - rb->PutRowRGB = NULL; - rb->PutMonoRow = put_mono_row_generic; rb->PutValues = put_values_generic; - rb->PutMonoValues = put_mono_values_generic; break; case MESA_FORMAT_INTENSITY_FLOAT32: rb->GetRow = get_row_i_float32; rb->GetValues = get_values_i_float32; rb->PutRow = put_row_generic; - rb->PutRowRGB = NULL; - rb->PutMonoRow = put_mono_row_generic; rb->PutValues = put_values_generic; - rb->PutMonoValues = put_mono_values_generic; break; case MESA_FORMAT_LUMINANCE_FLOAT32: rb->GetRow = get_row_l_float32; rb->GetValues = get_values_l_float32; rb->PutRow = put_row_generic; - rb->PutRowRGB = NULL; - rb->PutMonoRow = put_mono_row_generic; rb->PutValues = put_values_generic; - rb->PutMonoValues = put_mono_values_generic; break; case MESA_FORMAT_ALPHA_FLOAT32: rb->GetRow = get_row_a_float32; rb->GetValues = get_values_a_float32; rb->PutRow = put_row_a_float32; - rb->PutRowRGB = NULL; - rb->PutMonoRow = put_mono_row_a_float32; rb->PutValues = put_values_a_float32; - rb->PutMonoValues = put_mono_values_a_float32; break; case MESA_FORMAT_RG_FLOAT32: rb->GetRow = get_row_rg_float32; rb->GetValues = get_values_rg_float32; rb->PutRow = put_row_generic; - rb->PutRowRGB = NULL; - rb->PutMonoRow = put_mono_row_generic; rb->PutValues = put_values_generic; - rb->PutMonoValues = put_mono_values_generic; break; case MESA_FORMAT_R_FLOAT32: rb->GetRow = get_row_r_float32; rb->GetValues = get_values_r_float32; rb->PutRow = put_row_generic; - rb->PutRowRGB = NULL; - rb->PutMonoRow = put_mono_row_generic; rb->PutValues = put_values_generic; - rb->PutMonoValues = put_mono_values_generic; break; default: @@ -1651,9 +1161,7 @@ soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, ASSERT(rb->GetRow); ASSERT(rb->GetValues); ASSERT(rb->PutRow); - ASSERT(rb->PutMonoRow); ASSERT(rb->PutValues); - ASSERT(rb->PutMonoValues); /* free old buffer storage */ if (rb->Data) { diff --git a/mesalib/src/mesa/swrast/s_spantemp.h b/mesalib/src/mesa/swrast/s_spantemp.h index 517c2eb3f..2d2561b6f 100644 --- a/mesalib/src/mesa/swrast/s_spantemp.h +++ b/mesalib/src/mesa/swrast/s_spantemp.h @@ -25,8 +25,7 @@ /* * Templates for the span/pixel-array write/read functions called via - * the gl_renderbuffer's GetRow, GetValues, PutRow, PutMonoRow, PutValues - * and PutMonoValues functions. + * the gl_renderbuffer's GetRow, GetValues, PutRow, and PutValues. * * Define the following macros before including this file: * NAME(BASE) to generate the function name (i.e. add prefix or suffix) @@ -118,62 +117,6 @@ NAME(put_row)( struct gl_context *ctx, struct gl_renderbuffer *rb, static void -NAME(put_row_rgb)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, GLint x, GLint y, - const void *values, const GLubyte mask[] ) -{ -#ifdef SPAN_VARS - SPAN_VARS -#endif - const RB_TYPE (*src)[3] = (const RB_TYPE (*)[3]) values; - GLuint i; - INIT_PIXEL_PTR(pixel, x, y); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { -#ifdef STORE_PIXEL_RGB - STORE_PIXEL_RGB(pixel, x + i, y, src[i]); -#else - STORE_PIXEL(pixel, x + i, y, src[i]); -#endif - } - INC_PIXEL_PTR(pixel); - } - (void) rb; - (void) ctx; -} - - -static void -NAME(put_mono_row)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, GLint x, GLint y, - const void *value, const GLubyte mask[] ) -{ -#ifdef SPAN_VARS - SPAN_VARS -#endif - const RB_TYPE *src = (const RB_TYPE *) value; - GLuint i; - INIT_PIXEL_PTR(pixel, x, y); - if (mask) { - for (i = 0; i < count; i++) { - if (mask[i]) { - STORE_PIXEL(pixel, x + i, y, src); - } - INC_PIXEL_PTR(pixel); - } - } - else { - for (i = 0; i < count; i++) { - STORE_PIXEL(pixel, x + i, y, src); - INC_PIXEL_PTR(pixel); - } - } - (void) rb; - (void) ctx; -} - - -static void NAME(put_values)( struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], const void *values, const GLubyte mask[] ) @@ -195,28 +138,6 @@ NAME(put_values)( struct gl_context *ctx, struct gl_renderbuffer *rb, } -static void -NAME(put_mono_values)( struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte mask[] ) -{ -#ifdef SPAN_VARS - SPAN_VARS -#endif - const RB_TYPE *src = (const RB_TYPE *) value; - GLuint i; - ASSERT(mask); - for (i = 0; i < count; i++) { - if (mask[i]) { - INIT_PIXEL_PTR(pixel, x[i], y[i]); - STORE_PIXEL(pixel, x[i], y[i], src); - } - } - (void) rb; - (void) ctx; -} - - #undef NAME #undef RB_TYPE #undef RB_COMPONENTS diff --git a/mesalib/src/mesa/swrast/s_stencil.c b/mesalib/src/mesa/swrast/s_stencil.c index 101ee5056..dbcbd2be0 100644 --- a/mesalib/src/mesa/swrast/s_stencil.c +++ b/mesalib/src/mesa/swrast/s_stencil.c @@ -26,6 +26,8 @@ #include "main/glheader.h" #include "main/context.h" #include "main/imports.h" +#include "main/format_pack.h" +#include "main/format_unpack.h" #include "s_context.h" #include "s_depth.h" @@ -50,193 +52,171 @@ ENDIF */ + +/** + * Compute/return the offset of the stencil value in a pixel. + * For example, if the format is Z24+S8, the position of the stencil bits + * within the 4-byte pixel will be either 0 or 3. + */ +static GLint +get_stencil_offset(gl_format format) +{ + const GLubyte one = 1; + GLubyte pixel[MAX_PIXEL_BYTES]; + GLint bpp = _mesa_get_format_bytes(format); + GLint i; + + assert(_mesa_get_format_bits(format, GL_STENCIL_BITS) == 8); + memset(pixel, 0, sizeof(pixel)); + _mesa_pack_ubyte_stencil_row(format, 1, &one, pixel); + + for (i = 0; i < bpp; i++) { + if (pixel[i]) + return i; + } + + _mesa_problem(NULL, "get_stencil_offset() failed\n"); + return 0; +} + + +/** Clamp the stencil value to [0, 255] */ +static inline GLubyte +clamp(GLint val) +{ + if (val < 0) + return 0; + else if (val > 255) + return 255; + else + return val; +} + + +#define STENCIL_OP(NEW_VAL) \ + if (invmask == 0) { \ + for (i = j = 0; i < n; i++, j += stride) { \ + if (mask[i]) { \ + GLubyte s = stencil[j]; \ + (void) s; \ + stencil[j] = (GLubyte) (NEW_VAL); \ + } \ + } \ + } \ + else { \ + for (i = j = 0; i < n; i++, j += stride) { \ + if (mask[i]) { \ + GLubyte s = stencil[j]; \ + stencil[j] = (GLubyte) ((invmask & s) | (wrtmask & (NEW_VAL))); \ + } \ + } \ + } + + /** * Apply the given stencil operator to the array of stencil values. * Don't touch stencil[i] if mask[i] is zero. - * Input: n - size of stencil array - * oper - the stencil buffer operator - * face - 0 or 1 for front or back face operation - * stencil - array of stencil values - * mask - array [n] of flag: 1=apply operator, 0=don't apply operator - * Output: stencil - modified values + * @param n number of stencil values + * @param oper the stencil buffer operator + * @param face 0 or 1 for front or back face operation + * @param stencil array of stencil values (in/out) + * @param mask array [n] of flag: 1=apply operator, 0=don't apply operator + * @param stride stride between stencil values */ static void -apply_stencil_op( const struct gl_context *ctx, GLenum oper, GLuint face, - GLuint n, GLubyte stencil[], const GLubyte mask[] ) +apply_stencil_op(const struct gl_context *ctx, GLenum oper, GLuint face, + GLuint n, GLubyte stencil[], const GLubyte mask[], + GLint stride) { const GLubyte ref = ctx->Stencil.Ref[face]; const GLubyte wrtmask = ctx->Stencil.WriteMask[face]; const GLubyte invmask = (GLubyte) (~wrtmask); - const GLubyte stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; - GLuint i; + GLuint i, j; switch (oper) { - case GL_KEEP: - /* do nothing */ - break; - case GL_ZERO: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - stencil[i] = 0; - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - stencil[i] = (GLubyte) (stencil[i] & invmask); - } - } - } - break; - case GL_REPLACE: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - stencil[i] = ref; - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte s = stencil[i]; - stencil[i] = (GLubyte) ((invmask & s ) | (wrtmask & ref)); - } - } - } - break; - case GL_INCR: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte s = stencil[i]; - if (s < stencilMax) { - stencil[i] = (GLubyte) (s+1); - } - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - /* VERIFY logic of adding 1 to a write-masked value */ - GLubyte s = stencil[i]; - if (s < stencilMax) { - stencil[i] = (GLubyte) ((invmask & s) | (wrtmask & (s+1))); - } - } - } - } - break; - case GL_DECR: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte s = stencil[i]; - if (s>0) { - stencil[i] = (GLubyte) (s-1); - } - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - /* VERIFY logic of subtracting 1 to a write-masked value */ - GLubyte s = stencil[i]; - if (s>0) { - stencil[i] = (GLubyte) ((invmask & s) | (wrtmask & (s-1))); - } - } - } - } - break; - case GL_INCR_WRAP_EXT: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - stencil[i]++; - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte s = stencil[i]; - stencil[i] = (GLubyte) ((invmask & s) | (wrtmask & (s+1))); - } - } - } - break; - case GL_DECR_WRAP_EXT: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - stencil[i]--; - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte s = stencil[i]; - stencil[i] = (GLubyte) ((invmask & s) | (wrtmask & (s-1))); - } - } - } - break; - case GL_INVERT: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte s = stencil[i]; - stencil[i] = (GLubyte) ~s; - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte s = stencil[i]; - stencil[i] = (GLubyte) ((invmask & s) | (wrtmask & ~s)); - } - } - } - break; - default: - _mesa_problem(ctx, "Bad stencil op in apply_stencil_op"); + case GL_KEEP: + /* do nothing */ + break; + case GL_ZERO: + /* replace stencil buf values with zero */ + STENCIL_OP(0); + break; + case GL_REPLACE: + /* replace stencil buf values with ref value */ + STENCIL_OP(ref); + break; + case GL_INCR: + /* increment stencil buf values, with clamping */ + STENCIL_OP(clamp(s + 1)); + break; + case GL_DECR: + /* increment stencil buf values, with clamping */ + STENCIL_OP(clamp(s - 1)); + break; + case GL_INCR_WRAP_EXT: + /* increment stencil buf values, without clamping */ + STENCIL_OP(s + 1); + break; + case GL_DECR_WRAP_EXT: + /* increment stencil buf values, without clamping */ + STENCIL_OP(s - 1); + break; + case GL_INVERT: + /* replace stencil buf values with inverted value */ + STENCIL_OP(~s); + break; + default: + _mesa_problem(ctx, "Bad stencil op in apply_stencil_op"); } } +#define STENCIL_TEST(FUNC) \ + for (i = j = 0; i < n; i++, j += stride) { \ + if (mask[i]) { \ + s = (GLubyte) (stencil[j] & valueMask); \ + if (FUNC) { \ + /* stencil pass */ \ + fail[i] = 0; \ + } \ + else { \ + /* stencil fail */ \ + fail[i] = 1; \ + mask[i] = 0; \ + } \ + } \ + else { \ + fail[i] = 0; \ + } \ + } + + /** * Apply stencil test to an array of stencil values (before depth buffering). - * Input: face - 0 or 1 for front or back-face polygons - * n - number of pixels in the array - * stencil - array of [n] stencil values - * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel - * Output: mask - pixels which fail the stencil test will have their - * mask flag set to 0. - * stencil - updated stencil values (where the test passed) - * Return: GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. + * For the values that fail, we'll apply the GL_STENCIL_FAIL operator to + * the stencil values. + * + * @param face 0 or 1 for front or back-face polygons + * @param n number of pixels in the array + * @param stencil array of [n] stencil values (in/out) + * @param mask array [n] of flag: 0=skip the pixel, 1=stencil the pixel, + * values are set to zero where the stencil test fails. + * @param stride stride between stencil values + * @return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. */ static GLboolean -do_stencil_test( struct gl_context *ctx, GLuint face, GLuint n, GLubyte stencil[], - GLubyte mask[] ) +do_stencil_test(struct gl_context *ctx, GLuint face, GLuint n, + GLubyte stencil[], GLubyte mask[], GLint stride) { GLubyte fail[MAX_WIDTH]; GLboolean allfail = GL_FALSE; - GLuint i; + GLuint i, j; const GLuint valueMask = ctx->Stencil.ValueMask[face]; - const GLubyte r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask); + const GLubyte ref = (GLubyte) (ctx->Stencil.Ref[face] & valueMask); GLubyte s; - ASSERT(n <= MAX_WIDTH); - /* * Perform stencil test. The results of this operation are stored * in the fail[] array: @@ -247,140 +227,39 @@ do_stencil_test( struct gl_context *ctx, GLuint face, GLuint n, GLubyte stencil[ * ENDIF */ switch (ctx->Stencil.Function[face]) { - case GL_NEVER: - /* never pass; always fail */ - for (i=0;i<n;i++) { - if (mask[i]) { - mask[i] = 0; - fail[i] = 1; - } - else { - fail[i] = 0; - } - } - allfail = GL_TRUE; - break; - case GL_LESS: - for (i=0;i<n;i++) { - if (mask[i]) { - s = (GLubyte) (stencil[i] & valueMask); - if (r < s) { - /* passed */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_LEQUAL: - for (i=0;i<n;i++) { - if (mask[i]) { - s = (GLubyte) (stencil[i] & valueMask); - if (r <= s) { - /* pass */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_GREATER: - for (i=0;i<n;i++) { - if (mask[i]) { - s = (GLubyte) (stencil[i] & valueMask); - if (r > s) { - /* passed */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_GEQUAL: - for (i=0;i<n;i++) { - if (mask[i]) { - s = (GLubyte) (stencil[i] & valueMask); - if (r >= s) { - /* passed */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_EQUAL: - for (i=0;i<n;i++) { - if (mask[i]) { - s = (GLubyte) (stencil[i] & valueMask); - if (r == s) { - /* passed */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_NOTEQUAL: - for (i=0;i<n;i++) { - if (mask[i]) { - s = (GLubyte) (stencil[i] & valueMask); - if (r != s) { - /* passed */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_ALWAYS: - /* always pass */ - for (i=0;i<n;i++) { - fail[i] = 0; - } - break; - default: - _mesa_problem(ctx, "Bad stencil func in gl_stencil_span"); - return 0; + case GL_NEVER: + STENCIL_TEST(0); + allfail = GL_TRUE; + break; + case GL_LESS: + STENCIL_TEST(ref < s); + break; + case GL_LEQUAL: + STENCIL_TEST(ref <= s); + break; + case GL_GREATER: + STENCIL_TEST(ref > s); + break; + case GL_GEQUAL: + STENCIL_TEST(ref >= s); + break; + case GL_EQUAL: + STENCIL_TEST(ref == s); + break; + case GL_NOTEQUAL: + STENCIL_TEST(ref != s); + break; + case GL_ALWAYS: + STENCIL_TEST(1); + break; + default: + _mesa_problem(ctx, "Bad stencil func in gl_stencil_span"); + return 0; } if (ctx->Stencil.FailFunc[face] != GL_KEEP) { - apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail ); + apply_stencil_op(ctx, ctx->Stencil.FailFunc[face], face, n, stencil, + fail, stride); } return !allfail; @@ -406,54 +285,100 @@ compute_pass_fail_masks(GLuint n, const GLubyte origMask[], /** - * Apply stencil and depth testing to the span of pixels. - * Both software and hardware stencil buffers are acceptable. - * Input: n - number of pixels in the span - * x, y - location of leftmost pixel in span - * z - array [n] of z values - * mask - array [n] of flags (1=test this pixel, 0=skip the pixel) - * Output: mask - array [n] of flags (1=stencil and depth test passed) - * Return: GL_FALSE - all fragments failed the testing - * GL_TRUE - one or more fragments passed the testing - * + * Get 8-bit stencil values from random locations in the stencil buffer. */ -static GLboolean -stencil_and_ztest_span(struct gl_context *ctx, SWspan *span, GLuint face) +static void +get_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + GLubyte stencil[]) { - struct gl_framebuffer *fb = ctx->DrawBuffer; - struct gl_renderbuffer *rb = fb->_StencilBuffer; - GLubyte stencilRow[MAX_WIDTH]; - GLubyte *stencil; - const GLuint n = span->end; - const GLint x = span->x; - const GLint y = span->y; - GLubyte *mask = span->array->mask; + const GLint w = rb->Width, h = rb->Height; + const GLubyte *map = (const GLubyte *) rb->Data; + GLuint i; - ASSERT((span->arrayMask & SPAN_XY) == 0); - ASSERT(ctx->Stencil.Enabled); - ASSERT(n <= MAX_WIDTH); -#ifdef DEBUG - if (ctx->Depth.Test) { - ASSERT(span->arrayMask & SPAN_Z); + if (rb->Format == MESA_FORMAT_S8) { + const GLuint rowStride = rb->RowStride; + for (i = 0; i < count; i++) { + if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { + stencil[i] = *(map + y[i] * rowStride + x[i]); + } + } + } + else { + const GLuint bpp = _mesa_get_format_bytes(rb->Format); + const GLuint rowStride = rb->RowStride * bpp; + for (i = 0; i < count; i++) { + if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { + const GLubyte *src = map + y[i] * rowStride + x[i] * bpp; + _mesa_unpack_ubyte_stencil_row(rb->Format, 1, src, &stencil[i]); + } + } } -#endif +} + + +/** + * Put 8-bit stencil values at random locations into the stencil buffer. + */ +static void +put_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const GLubyte stencil[]) +{ + const GLint w = rb->Width, h = rb->Height; + GLuint i; - stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y); - if (!stencil) { - rb->GetRow(ctx, rb, n, x, y, stencilRow); - stencil = stencilRow; + for (i = 0; i < count; i++) { + if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { + GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]); + _mesa_pack_ubyte_stencil_row(rb->Format, 1, &stencil[i], dst); + } + } +} + + +/** + * /return GL_TRUE = one or more fragments passed, + * GL_FALSE = all fragments failed. + */ +GLboolean +_swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span) +{ + struct gl_framebuffer *fb = ctx->DrawBuffer; + struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; + const GLint stencilOffset = get_stencil_offset(rb->Format); + const GLint stencilStride = _mesa_get_format_bytes(rb->Format); + const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace; + const GLuint count = span->end; + GLubyte *mask = span->array->mask; + GLubyte stencilTemp[MAX_WIDTH]; + GLubyte *stencilBuf; + + if (span->arrayMask & SPAN_XY) { + /* read stencil values from random locations */ + get_s8_values(ctx, rb, count, span->array->x, span->array->y, + stencilTemp); + stencilBuf = stencilTemp; + } + else { + /* Processing a horizontal run of pixels. Since stencil is always + * 8 bits for all MESA_FORMATs, we just need to use the right offset + * and stride to access them. + */ + stencilBuf = _swrast_pixel_address(rb, span->x, span->y) + stencilOffset; } /* * Apply the stencil test to the fragments. * failMask[i] is 1 if the stencil test failed. */ - if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) { + if (!do_stencil_test(ctx, face, count, stencilBuf, mask, stencilStride)) { /* all fragments failed the stencil test, we're done. */ span->writeAll = GL_FALSE; - if (!rb->GetPointer(ctx, rb, 0, 0)) { - /* put updated stencil values into buffer */ - rb->PutRow(ctx, rb, n, x, y, stencil, NULL); + if (span->arrayMask & SPAN_XY) { + /* need to write the updated stencil values back to the buffer */ + put_s8_values(ctx, rb, count, span->array->x, span->array->y, + stencilTemp); } return GL_FALSE; } @@ -463,11 +388,12 @@ stencil_and_ztest_span(struct gl_context *ctx, SWspan *span, GLuint face) * and apply Zpass and Zfail stencil ops. */ if (ctx->Depth.Test == GL_FALSE || - ctx->DrawBuffer->_DepthBuffer == NULL) { + ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer == NULL) { /* * No depth buffer, just apply zpass stencil function to active pixels. */ - apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask ); + apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, count, + stencilBuf, mask, stencilStride); } else { /* @@ -476,29 +402,28 @@ stencil_and_ztest_span(struct gl_context *ctx, SWspan *span, GLuint face) GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH]; /* save the current mask bits */ - memcpy(origMask, mask, n * sizeof(GLubyte)); + memcpy(origMask, mask, count * sizeof(GLubyte)); /* apply the depth test */ _swrast_depth_test_span(ctx, span); - compute_pass_fail_masks(n, origMask, mask, passMask, failMask); + compute_pass_fail_masks(count, origMask, mask, passMask, failMask); /* apply the pass and fail operations */ if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { - apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face, - n, stencil, failMask ); + apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face, + count, stencilBuf, failMask, stencilStride); } if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { - apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, - n, stencil, passMask ); + apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, + count, stencilBuf, passMask, stencilStride); } } - /* - * Write updated stencil values back into hardware stencil buffer. - */ - if (!rb->GetPointer(ctx, rb, 0, 0)) { - rb->PutRow(ctx, rb, n, x, y, stencil, NULL); + /* Write updated stencil values back into hardware stencil buffer */ + if (span->arrayMask & SPAN_XY) { + put_s8_values(ctx, rb, count, span->array->x, span->array->y, + stencilBuf); } span->writeAll = GL_FALSE; @@ -508,530 +433,6 @@ stencil_and_ztest_span(struct gl_context *ctx, SWspan *span, GLuint face) -/* - * Return the address of a stencil buffer value given the window coords: - */ -#define STENCIL_ADDRESS(X, Y) (stencilStart + (Y) * stride + (X)) - - - -/** - * Apply the given stencil operator for each pixel in the array whose - * mask flag is set. - * \note This is for software stencil buffers only. - * Input: n - number of pixels in the span - * x, y - array of [n] pixels - * operator - the stencil buffer operator - * mask - array [n] of flag: 1=apply operator, 0=don't apply operator - */ -static void -apply_stencil_op_to_pixels( struct gl_context *ctx, - GLuint n, const GLint x[], const GLint y[], - GLenum oper, GLuint face, const GLubyte mask[] ) -{ - struct gl_framebuffer *fb = ctx->DrawBuffer; - struct gl_renderbuffer *rb = fb->_StencilBuffer; - const GLubyte stencilMax = (1 << fb->Visual.stencilBits) - 1; - const GLubyte ref = ctx->Stencil.Ref[face]; - const GLubyte wrtmask = ctx->Stencil.WriteMask[face]; - const GLubyte invmask = (GLubyte) (~wrtmask); - GLuint i; - GLubyte *stencilStart = (GLubyte *) rb->Data; - const GLuint stride = rb->Width; - - ASSERT(rb->GetPointer(ctx, rb, 0, 0)); - - switch (oper) { - case GL_KEEP: - /* do nothing */ - break; - case GL_ZERO: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - *sptr = 0; - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - *sptr = (GLubyte) (invmask & *sptr); - } - } - } - break; - case GL_REPLACE: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - *sptr = ref; - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - *sptr = (GLubyte) ((invmask & *sptr ) | (wrtmask & ref)); - } - } - } - break; - case GL_INCR: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - if (*sptr < stencilMax) { - *sptr = (GLubyte) (*sptr + 1); - } - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - if (*sptr < stencilMax) { - *sptr = (GLubyte) ((invmask & *sptr) | (wrtmask & (*sptr+1))); - } - } - } - } - break; - case GL_DECR: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - if (*sptr>0) { - *sptr = (GLubyte) (*sptr - 1); - } - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - if (*sptr>0) { - *sptr = (GLubyte) ((invmask & *sptr) | (wrtmask & (*sptr-1))); - } - } - } - } - break; - case GL_INCR_WRAP_EXT: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - *sptr = (GLubyte) (*sptr + 1); - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - *sptr = (GLubyte) ((invmask & *sptr) | (wrtmask & (*sptr+1))); - } - } - } - break; - case GL_DECR_WRAP_EXT: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - *sptr = (GLubyte) (*sptr - 1); - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - *sptr = (GLubyte) ((invmask & *sptr) | (wrtmask & (*sptr-1))); - } - } - } - break; - case GL_INVERT: - if (invmask==0) { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - *sptr = (GLubyte) (~*sptr); - } - } - } - else { - for (i=0;i<n;i++) { - if (mask[i]) { - GLubyte *sptr = STENCIL_ADDRESS( x[i], y[i] ); - *sptr = (GLubyte) ((invmask & *sptr) | (wrtmask & ~*sptr)); - } - } - } - break; - default: - _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels"); - } -} - - - -/** - * Apply stencil test to an array of pixels before depth buffering. - * - * \note Used for software stencil buffer only. - * Input: n - number of pixels in the span - * x, y - array of [n] pixels to stencil - * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel - * Output: mask - pixels which fail the stencil test will have their - * mask flag set to 0. - * \return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. - */ -static GLboolean -stencil_test_pixels( struct gl_context *ctx, GLuint face, GLuint n, - const GLint x[], const GLint y[], GLubyte mask[] ) -{ - const struct gl_framebuffer *fb = ctx->DrawBuffer; - struct gl_renderbuffer *rb = fb->_StencilBuffer; - GLubyte fail[MAX_WIDTH]; - GLubyte r, s; - GLuint i; - GLboolean allfail = GL_FALSE; - const GLuint valueMask = ctx->Stencil.ValueMask[face]; - const GLubyte *stencilStart = (GLubyte *) rb->Data; - const GLuint stride = rb->Width; - - ASSERT(rb->GetPointer(ctx, rb, 0, 0)); - - /* - * Perform stencil test. The results of this operation are stored - * in the fail[] array: - * IF fail[i] is non-zero THEN - * the stencil fail operator is to be applied - * ELSE - * the stencil fail operator is not to be applied - * ENDIF - */ - - switch (ctx->Stencil.Function[face]) { - case GL_NEVER: - /* always fail */ - for (i=0;i<n;i++) { - if (mask[i]) { - mask[i] = 0; - fail[i] = 1; - } - else { - fail[i] = 0; - } - } - allfail = GL_TRUE; - break; - case GL_LESS: - r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask); - for (i=0;i<n;i++) { - if (mask[i]) { - const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLubyte) (*sptr & valueMask); - if (r < s) { - /* passed */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_LEQUAL: - r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask); - for (i=0;i<n;i++) { - if (mask[i]) { - const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLubyte) (*sptr & valueMask); - if (r <= s) { - /* pass */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_GREATER: - r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask); - for (i=0;i<n;i++) { - if (mask[i]) { - const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLubyte) (*sptr & valueMask); - if (r > s) { - /* passed */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_GEQUAL: - r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask); - for (i=0;i<n;i++) { - if (mask[i]) { - const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLubyte) (*sptr & valueMask); - if (r >= s) { - /* passed */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_EQUAL: - r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask); - for (i=0;i<n;i++) { - if (mask[i]) { - const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLubyte) (*sptr & valueMask); - if (r == s) { - /* passed */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_NOTEQUAL: - r = (GLubyte) (ctx->Stencil.Ref[face] & valueMask); - for (i=0;i<n;i++) { - if (mask[i]) { - const GLubyte *sptr = STENCIL_ADDRESS(x[i],y[i]); - s = (GLubyte) (*sptr & valueMask); - if (r != s) { - /* passed */ - fail[i] = 0; - } - else { - fail[i] = 1; - mask[i] = 0; - } - } - else { - fail[i] = 0; - } - } - break; - case GL_ALWAYS: - /* always pass */ - for (i=0;i<n;i++) { - fail[i] = 0; - } - break; - default: - _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels"); - return 0; - } - - if (ctx->Stencil.FailFunc[face] != GL_KEEP) { - apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face], - face, fail ); - } - - return !allfail; -} - - - - -/** - * Apply stencil and depth testing to an array of pixels. - * This is used both for software and hardware stencil buffers. - * - * The comments in this function are a bit sparse but the code is - * almost identical to stencil_and_ztest_span(), which is well - * commented. - * - * Input: n - number of pixels in the array - * x, y - array of [n] pixel positions - * z - array [n] of z values - * mask - array [n] of flags (1=test this pixel, 0=skip the pixel) - * Output: mask - array [n] of flags (1=stencil and depth test passed) - * Return: GL_FALSE - all fragments failed the testing - * GL_TRUE - one or more fragments passed the testing - */ -static GLboolean -stencil_and_ztest_pixels( struct gl_context *ctx, SWspan *span, GLuint face ) -{ - GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH]; - struct gl_framebuffer *fb = ctx->DrawBuffer; - struct gl_renderbuffer *rb = fb->_StencilBuffer; - const GLuint n = span->end; - const GLint *x = span->array->x; - const GLint *y = span->array->y; - GLubyte *mask = span->array->mask; - - ASSERT(span->arrayMask & SPAN_XY); - ASSERT(ctx->Stencil.Enabled); - ASSERT(n <= MAX_WIDTH); - - if (!rb->GetPointer(ctx, rb, 0, 0)) { - /* No direct access */ - GLubyte stencil[MAX_WIDTH]; - - ASSERT(rb->DataType == GL_UNSIGNED_BYTE); - _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte)); - - memcpy(origMask, mask, n * sizeof(GLubyte)); - - (void) do_stencil_test(ctx, face, n, stencil, mask); - - if (ctx->Depth.Test == GL_FALSE) { - apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, - n, stencil, mask); - } - else { - GLubyte tmpMask[MAX_WIDTH]; - memcpy(tmpMask, mask, n * sizeof(GLubyte)); - - _swrast_depth_test_span(ctx, span); - - compute_pass_fail_masks(n, tmpMask, mask, passMask, failMask); - - if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { - apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face, - n, stencil, failMask); - } - if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { - apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, - n, stencil, passMask); - } - } - - /* Write updated stencil values into hardware stencil buffer */ - rb->PutValues(ctx, rb, n, x, y, stencil, origMask); - - return GL_TRUE; - } - else { - /* Direct access to stencil buffer */ - - if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) { - /* all fragments failed the stencil test, we're done. */ - return GL_FALSE; - } - - if (ctx->Depth.Test==GL_FALSE) { - apply_stencil_op_to_pixels(ctx, n, x, y, - ctx->Stencil.ZPassFunc[face], face, mask); - } - else { - memcpy(origMask, mask, n * sizeof(GLubyte)); - - _swrast_depth_test_span(ctx, span); - - compute_pass_fail_masks(n, origMask, mask, passMask, failMask); - - if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { - apply_stencil_op_to_pixels(ctx, n, x, y, - ctx->Stencil.ZFailFunc[face], - face, failMask); - } - if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { - apply_stencil_op_to_pixels(ctx, n, x, y, - ctx->Stencil.ZPassFunc[face], - face, passMask); - } - } - - return GL_TRUE; /* one or more fragments passed both tests */ - } -} - - -/** - * /return GL_TRUE = one or more fragments passed, - * GL_FALSE = all fragments failed. - */ -GLboolean -_swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span) -{ - const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace; - - if (span->arrayMask & SPAN_XY) - return stencil_and_ztest_pixels(ctx, span, face); - else - return stencil_and_ztest_span(ctx, span, face); -} - - -#if 0 -GLuint -clip_span(GLuint bufferWidth, GLuint bufferHeight, - GLint x, GLint y, GLuint *count) -{ - GLuint n = *count; - GLuint skipPixels = 0; - - if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) { - /* totally out of bounds */ - n = 0; - } - else { - /* left clip */ - if (x < 0) { - skipPixels = -x; - x = 0; - n -= skipPixels; - } - /* right clip */ - if (x + n > bufferWidth) { - GLint dx = x + n - bufferWidth; - n -= dx; - } - } - - *count = n; - - return skipPixels; -} -#endif - /** * Return a span of stencil values from the stencil buffer. @@ -1044,6 +445,8 @@ void _swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb, GLint n, GLint x, GLint y, GLubyte stencil[]) { + GLubyte *src; + if (y < 0 || y >= (GLint) rb->Height || x + n <= 0 || x >= (GLint) rb->Width) { /* span is completely outside framebuffer */ @@ -1064,7 +467,8 @@ _swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb, return; } - rb->GetRow(ctx, rb, n, x, y, stencil); + src = _swrast_pixel_address(rb, x, y); + _mesa_unpack_ubyte_stencil_row(rb->Format, n, src, stencil); } @@ -1082,9 +486,10 @@ _swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y, const GLubyte stencil[] ) { struct gl_framebuffer *fb = ctx->DrawBuffer; - struct gl_renderbuffer *rb = fb->_StencilBuffer; + struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1; const GLuint stencilMask = ctx->Stencil.WriteMask[0]; + GLubyte *stencilBuf; if (y < 0 || y >= (GLint) rb->Height || x + n <= 0 || x >= (GLint) rb->Width) { @@ -1105,140 +510,129 @@ _swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y, return; } + stencilBuf = _swrast_pixel_address(rb, x, y); + if ((stencilMask & stencilMax) != stencilMax) { /* need to apply writemask */ GLubyte destVals[MAX_WIDTH], newVals[MAX_WIDTH]; GLint i; - rb->GetRow(ctx, rb, n, x, y, destVals); + + _mesa_unpack_ubyte_stencil_row(rb->Format, n, stencilBuf, destVals); for (i = 0; i < n; i++) { newVals[i] = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask); } - rb->PutRow(ctx, rb, n, x, y, newVals, NULL); + _mesa_pack_ubyte_stencil_row(rb->Format, n, newVals, stencilBuf); } else { - rb->PutRow(ctx, rb, n, x, y, stencil, NULL); + _mesa_pack_ubyte_stencil_row(rb->Format, n, stencil, stencilBuf); } } /** - * Clear the stencil buffer. + * Clear the stencil buffer. If the buffer is a combined + * depth+stencil buffer, only the stencil bits will be touched. */ void -_swrast_clear_stencil_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb ) +_swrast_clear_stencil_buffer(struct gl_context *ctx) { + struct gl_renderbuffer *rb = + ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits; - const GLuint mask = ctx->Stencil.WriteMask[0]; - const GLuint invMask = ~mask; - const GLuint clearVal = (ctx->Stencil.Clear & mask); + const GLuint writeMask = ctx->Stencil.WriteMask[0]; const GLuint stencilMax = (1 << stencilBits) - 1; GLint x, y, width, height; + GLubyte *map; + GLint rowStride, i, j; + GLbitfield mapMode; - if (!rb || mask == 0) + if (!rb || writeMask == 0) return; - ASSERT(rb->DataType == GL_UNSIGNED_BYTE || - rb->DataType == GL_UNSIGNED_SHORT); - - ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX); - /* compute region to clear */ x = ctx->DrawBuffer->_Xmin; y = ctx->DrawBuffer->_Ymin; width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; - if (rb->GetPointer(ctx, rb, 0, 0)) { - /* Direct buffer access */ - if ((mask & stencilMax) != stencilMax) { - /* need to mask the clear */ - if (rb->DataType == GL_UNSIGNED_BYTE) { - GLint i, j; - for (i = 0; i < height; i++) { - GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i); - for (j = 0; j < width; j++) { - stencil[j] = (stencil[j] & invMask) | clearVal; - } - } - } - else { - GLint i, j; + mapMode = GL_MAP_WRITE_BIT; + if ((writeMask & stencilMax) != stencilMax) { + /* need to mask stencil values */ + mapMode |= GL_MAP_READ_BIT; + } + else if (_mesa_get_format_bits(rb->Format, GL_DEPTH_BITS) > 0) { + /* combined depth+stencil, need to mask Z values */ + mapMode |= GL_MAP_READ_BIT; + } + + ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, + mapMode, &map, &rowStride); + if (!map) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(stencil)"); + return; + } + + switch (rb->Format) { + case MESA_FORMAT_S8: + { + GLubyte clear = ctx->Stencil.Clear & writeMask & 0xff; + GLubyte mask = (~writeMask) & 0xff; + if (mask != 0) { + /* masked clear */ for (i = 0; i < height; i++) { - GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i); + GLubyte *row = map; for (j = 0; j < width; j++) { - stencil[j] = (stencil[j] & invMask) | clearVal; + row[j] = (row[j] & mask) | clear; } + map += rowStride; } } - } - else { - /* no bit masking */ - if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) { - /* optimized case */ - /* Note: bottom-to-top raster assumed! */ - GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y); - GLuint len = width * height * sizeof(GLubyte); - memset(stencil, clearVal, len); + else if (rowStride == width) { + /* clear whole buffer */ + memset(map, clear, width * height); } else { - /* general case */ - GLint i; + /* clear scissored */ for (i = 0; i < height; i++) { - GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i); - if (rb->DataType == GL_UNSIGNED_BYTE) { - memset(stencil, clearVal, width); - } - else { - _mesa_memset16((short unsigned int*) stencil, clearVal, width); - } + memset(map, clear, width); + map += rowStride; } } } - } - else { - /* no direct access */ - if ((mask & stencilMax) != stencilMax) { - /* need to mask the clear */ - if (rb->DataType == GL_UNSIGNED_BYTE) { - GLint i, j; - for (i = 0; i < height; i++) { - GLubyte stencil[MAX_WIDTH]; - rb->GetRow(ctx, rb, width, x, y + i, stencil); - for (j = 0; j < width; j++) { - stencil[j] = (stencil[j] & invMask) | clearVal; - } - rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL); - } - } - else { - GLint i, j; - for (i = 0; i < height; i++) { - GLushort stencil[MAX_WIDTH]; - rb->GetRow(ctx, rb, width, x, y + i, stencil); - for (j = 0; j < width; j++) { - stencil[j] = (stencil[j] & invMask) | clearVal; - } - rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL); + break; + case MESA_FORMAT_S8_Z24: + { + GLuint clear = (ctx->Stencil.Clear & writeMask & 0xff) << 24; + GLuint mask = (((~writeMask) & 0xff) << 24) | 0xffffff; + for (i = 0; i < height; i++) { + GLuint *row = (GLuint *) map; + for (j = 0; j < width; j++) { + row[j] = (row[j] & mask) | clear; } + map += rowStride; } } - else { - /* no bit masking */ - const GLubyte clear8 = (GLubyte) clearVal; - const GLushort clear16 = (GLushort) clearVal; - const void *clear; - GLint i; - if (rb->DataType == GL_UNSIGNED_BYTE) { - clear = &clear8; - } - else { - clear = &clear16; - } + break; + case MESA_FORMAT_Z24_S8: + { + GLuint clear = ctx->Stencil.Clear & writeMask & 0xff; + GLuint mask = 0xffffff00 | ((~writeMask) & 0xff); for (i = 0; i < height; i++) { - rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL); + GLuint *row = (GLuint *) map; + for (j = 0; j < width; j++) { + row[j] = (row[j] & mask) | clear; + } + map += rowStride; } } + break; + default: + _mesa_problem(ctx, "Unexpected stencil buffer format %s" + " in _swrast_clear_stencil_buffer()", + _mesa_get_format_name(rb->Format)); } + + ctx->Driver.UnmapRenderbuffer(ctx, rb); } diff --git a/mesalib/src/mesa/swrast/s_stencil.h b/mesalib/src/mesa/swrast/s_stencil.h index 37f3c8da1..113649a37 100644 --- a/mesalib/src/mesa/swrast/s_stencil.h +++ b/mesalib/src/mesa/swrast/s_stencil.h @@ -47,7 +47,7 @@ _swrast_write_stencil_span( struct gl_context *ctx, GLint n, GLint x, GLint y, extern void -_swrast_clear_stencil_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb ); +_swrast_clear_stencil_buffer(struct gl_context *ctx); #endif diff --git a/mesalib/src/mesa/swrast/s_texrender.c b/mesalib/src/mesa/swrast/s_texrender.c index 3734ce6d5..523420205 100644 --- a/mesalib/src/mesa/swrast/s_texrender.c +++ b/mesalib/src/mesa/swrast/s_texrender.c @@ -235,125 +235,6 @@ texture_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count } } -/** - * Put row of RGB values into a renderbuffer that wraps a texture image. - */ -static void -texture_put_row_rgb(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *values, const GLubyte *mask) -{ - struct texture_renderbuffer *trb = texture_renderbuffer(rb); - const GLint z = trb->Zoffset; - GLuint i; - - y += trb->Yoffset; - - if (rb->DataType == CHAN_TYPE) { - const GLchan *rgb = (const GLchan *) values; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x + i, y, z, rgb); - } - rgb += 3; - } - } - else if (rb->DataType == GL_UNSIGNED_SHORT) { - const GLushort *zValues = (const GLushort *) values; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x + i, y, z, zValues + i); - } - } - } - else if (rb->DataType == GL_UNSIGNED_INT) { - const GLuint *zValues = (const GLuint *) values; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x + i, y, z, zValues + i); - } - } - } - else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { - const GLuint *zValues = (const GLuint *) values; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff)); - trb->Store(trb->TexImage, x + i, y, z, &flt); - } - } - } - else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) { - const GLuint *zValues = (const GLuint *) values; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff)); - trb->Store(trb->TexImage, x + i, y, z, &flt); - } - } - } - else { - _mesa_problem(ctx, "invalid rb->DataType in texture_put_row"); - } -} - - -static void -texture_put_mono_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, - GLint x, GLint y, const void *value, const GLubyte *mask) -{ - struct texture_renderbuffer *trb = texture_renderbuffer(rb); - const GLint z = trb->Zoffset; - GLuint i; - - y += trb->Yoffset; - - if (rb->DataType == CHAN_TYPE) { - const GLchan *rgba = (const GLchan *) value; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x + i, y, z, rgba); - } - } - } - else if (rb->DataType == GL_UNSIGNED_SHORT) { - const GLushort zValue = *((const GLushort *) value); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x + i, y, z, &zValue); - } - } - } - else if (rb->DataType == GL_UNSIGNED_INT) { - const GLuint zValue = *((const GLuint *) value); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x + i, y, z, &zValue); - } - } - } - else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { - const GLuint zValue = *((const GLuint *) value); - const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff)); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x + i, y, z, &flt); - } - } - } - else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) { - const GLuint zValue = *((const GLuint *) value); - const GLfloat flt = (GLfloat) ((zValue & 0xffffff) * (1.0 / 0xffffff)); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x + i, y, z, &flt); - } - } - } - else { - _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_row"); - } -} - static void texture_put_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, @@ -414,63 +295,6 @@ texture_put_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint co static void -texture_put_mono_values(struct gl_context *ctx, struct gl_renderbuffer *rb, - GLuint count, const GLint x[], const GLint y[], - const void *value, const GLubyte *mask) -{ - struct texture_renderbuffer *trb = texture_renderbuffer(rb); - const GLint z = trb->Zoffset; - GLuint i; - - if (rb->DataType == CHAN_TYPE) { - const GLchan *rgba = (const GLchan *) value; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba); - } - } - } - else if (rb->DataType == GL_UNSIGNED_INT) { - const GLuint zValue = *((const GLuint *) value); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue); - } - } - } - else if (rb->DataType == GL_UNSIGNED_SHORT) { - const GLushort zValue = *((const GLushort *) value); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue); - } - } - } - else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { - const GLuint zValue = *((const GLuint *) value); - const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff)); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt); - } - } - } - else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) { - const GLuint zValue = *((const GLuint *) value); - const GLfloat flt = (GLfloat) ((zValue & 0xffffff) * (1.0 / 0xffffff)); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt); - } - } - } - else { - _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_values"); - } -} - - -static void store_nop(struct swrast_texture_image *texImage, GLint col, GLint row, GLint img, const void *texel) @@ -514,10 +338,7 @@ wrap_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) trb->Base.GetRow = texture_get_row; trb->Base.GetValues = texture_get_values; trb->Base.PutRow = texture_put_row; - trb->Base.PutRowRGB = texture_put_row_rgb; - trb->Base.PutMonoRow = texture_put_mono_row; trb->Base.PutValues = texture_put_values; - trb->Base.PutMonoValues = texture_put_mono_values; /* update attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &(trb->Base)); diff --git a/mesalib/src/mesa/swrast/s_triangle.c b/mesalib/src/mesa/swrast/s_triangle.c index b4f8e7479..43deaf47b 100644 --- a/mesalib/src/mesa/swrast/s_triangle.c +++ b/mesalib/src/mesa/swrast/s_triangle.c @@ -142,7 +142,7 @@ _swrast_culltriangle( struct gl_context *ctx, #define RENDER_SPAN( span ) \ GLuint i; \ - GLubyte rgb[MAX_WIDTH][3]; \ + GLubyte rgba[MAX_WIDTH][4]; \ span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ span.intTex[1] -= FIXED_HALF; \ for (i = 0; i < span.end; i++) { \ @@ -150,13 +150,14 @@ _swrast_culltriangle( struct gl_context *ctx, GLint t = FixedToInt(span.intTex[1]) & tmask; \ GLint pos = (t << twidth_log2) + s; \ pos = pos + pos + pos; /* multiply by 3 */ \ - rgb[i][RCOMP] = texture[pos+2]; \ - rgb[i][GCOMP] = texture[pos+1]; \ - rgb[i][BCOMP] = texture[pos+0]; \ + rgba[i][RCOMP] = texture[pos+2]; \ + rgba[i][GCOMP] = texture[pos+1]; \ + rgba[i][BCOMP] = texture[pos+0]; \ + rgba[i][ACOMP] = 0xff; \ span.intTex[0] += span.intTexStep[0]; \ span.intTex[1] += span.intTexStep[1]; \ } \ - rb->PutRowRGB(ctx, rb, span.end, span.x, span.y, rgb, NULL); + rb->PutRow(ctx, rb, span.end, span.x, span.y, rgba, NULL); #include "s_tritemp.h" @@ -198,7 +199,7 @@ _swrast_culltriangle( struct gl_context *ctx, #define RENDER_SPAN( span ) \ GLuint i; \ - GLubyte rgb[MAX_WIDTH][3]; \ + GLubyte rgba[MAX_WIDTH][4]; \ span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ span.intTex[1] -= FIXED_HALF; \ for (i = 0; i < span.end; i++) { \ @@ -208,9 +209,10 @@ _swrast_culltriangle( struct gl_context *ctx, GLint t = FixedToInt(span.intTex[1]) & tmask; \ GLint pos = (t << twidth_log2) + s; \ pos = pos + pos + pos; /* multiply by 3 */ \ - rgb[i][RCOMP] = texture[pos+2]; \ - rgb[i][GCOMP] = texture[pos+1]; \ - rgb[i][BCOMP] = texture[pos+0]; \ + rgba[i][RCOMP] = texture[pos+2]; \ + rgba[i][GCOMP] = texture[pos+1]; \ + rgba[i][BCOMP] = texture[pos+0]; \ + rgba[i][ACOMP] = 0xff; \ zRow[i] = z; \ span.array->mask[i] = 1; \ } \ @@ -221,7 +223,7 @@ _swrast_culltriangle( struct gl_context *ctx, span.intTex[1] += span.intTexStep[1]; \ span.z += span.zStep; \ } \ - rb->PutRowRGB(ctx, rb, span.end, span.x, span.y, rgb, span.array->mask); + rb->PutRow(ctx, rb, span.end, span.x, span.y, rgba, span.array->mask); #include "s_tritemp.h" @@ -872,22 +874,24 @@ fast_persp_span(struct gl_context *ctx, SWspan *span, /* * Special tri function for occlusion testing */ -#define NAME occlusion_zless_triangle +#define NAME occlusion_zless_16_triangle #define INTERP_Z 1 #define SETUP_CODE \ - struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer; \ + struct gl_renderbuffer *rb = \ + ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; \ struct gl_query_object *q = ctx->Query.CurrentOcclusionObject; \ ASSERT(ctx->Depth.Test); \ ASSERT(!ctx->Depth.Mask); \ ASSERT(ctx->Depth.Func == GL_LESS); \ + assert(rb->Format == MESA_FORMAT_Z16); \ if (!q) { \ return; \ } #define RENDER_SPAN( span ) \ - if (rb->Format == MESA_FORMAT_Z16) { \ + { \ GLuint i; \ const GLushort *zRow = (const GLushort *) \ - rb->GetPointer(ctx, rb, span.x, span.y); \ + _swrast_pixel_address(rb, span.x, span.y); \ for (i = 0; i < span.end; i++) { \ GLuint z = FixedToDepth(span.z); \ if (z < zRow[i]) { \ @@ -895,17 +899,6 @@ fast_persp_span(struct gl_context *ctx, SWspan *span, } \ span.z += span.zStep; \ } \ - } \ - else { \ - GLuint i; \ - const GLuint *zRow = (const GLuint *) \ - rb->GetPointer(ctx, rb, span.x, span.y); \ - for (i = 0; i < span.end; i++) { \ - if ((GLuint)span.z < zRow[i]) { \ - q->Result++; \ - } \ - span.z += span.zStep; \ - } \ } #include "s_tritemp.h" @@ -1012,6 +1005,8 @@ _swrast_choose_triangle( struct gl_context *ctx ) } if (ctx->RenderMode==GL_RENDER) { + struct gl_renderbuffer *depthRb = + ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; if (ctx->Polygon.SmoothFlag) { _swrast_set_aa_triangle_function(ctx); @@ -1024,12 +1019,14 @@ _swrast_choose_triangle( struct gl_context *ctx ) ctx->Depth.Test && ctx->Depth.Mask == GL_FALSE && ctx->Depth.Func == GL_LESS && - !ctx->Stencil._Enabled) { + !ctx->Stencil._Enabled && + depthRb && + depthRb->Format == MESA_FORMAT_Z16) { if (ctx->Color.ColorMask[0][0] == 0 && ctx->Color.ColorMask[0][1] == 0 && ctx->Color.ColorMask[0][2] == 0 && ctx->Color.ColorMask[0][3] == 0) { - USE(occlusion_zless_triangle); + USE(occlusion_zless_16_triangle); return; } } diff --git a/mesalib/src/mesa/swrast/s_tritemp.h b/mesalib/src/mesa/swrast/s_tritemp.h index 340c410ca..061759d26 100644 --- a/mesalib/src/mesa/swrast/s_tritemp.h +++ b/mesalib/src/mesa/swrast/s_tritemp.h @@ -1,929 +1,929 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.0
- *
- * Copyright (C) 1999-2007 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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * Triangle Rasterizer Template
- *
- * This file is #include'd to generate custom triangle rasterizers.
- *
- * The following macros may be defined to indicate what auxillary information
- * must be interpolated across the triangle:
- * INTERP_Z - if defined, interpolate integer Z values
- * INTERP_RGB - if defined, interpolate integer RGB values
- * INTERP_ALPHA - if defined, interpolate integer Alpha values
- * INTERP_INT_TEX - if defined, interpolate integer ST texcoords
- * (fast, simple 2-D texture mapping, without
- * perspective correction)
- * INTERP_ATTRIBS - if defined, interpolate arbitrary attribs (texcoords,
- * varying vars, etc) This also causes W to be
- * computed for perspective correction).
- *
- * When one can directly address pixels in the color buffer the following
- * macros can be defined and used to compute pixel addresses during
- * rasterization (see pRow):
- * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
- * BYTES_PER_ROW - number of bytes per row in the color buffer
- * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
- * Y==0 at bottom of screen and increases upward.
- *
- * Similarly, for direct depth buffer access, this type is used for depth
- * buffer addressing (see zRow):
- * DEPTH_TYPE - either GLushort or GLuint
- *
- * Optionally, one may provide one-time setup code per triangle:
- * SETUP_CODE - code which is to be executed once per triangle
- *
- * The following macro MUST be defined:
- * RENDER_SPAN(span) - code to write a span of pixels.
- *
- * This code was designed for the origin to be in the lower-left corner.
- *
- * Inspired by triangle rasterizer code written by Allen Akin. Thanks Allen!
- *
- *
- * Some notes on rasterization accuracy:
- *
- * This code uses fixed point arithmetic (the GLfixed type) to iterate
- * over the triangle edges and interpolate ancillary data (such as Z,
- * color, secondary color, etc). The number of fractional bits in
- * GLfixed and the value of SUB_PIXEL_BITS has a direct bearing on the
- * accuracy of rasterization.
- *
- * If SUB_PIXEL_BITS=4 then we'll snap the vertices to the nearest
- * 1/16 of a pixel. If we're walking up a long, nearly vertical edge
- * (dx=1/16, dy=1024) we'll need 4 + 10 = 14 fractional bits in
- * GLfixed to walk the edge without error. If the maximum viewport
- * height is 4K pixels, then we'll need 4 + 12 = 16 fractional bits.
- *
- * Historically, Mesa has used 11 fractional bits in GLfixed, snaps
- * vertices to 1/16 pixel and allowed a maximum viewport height of 2K
- * pixels. 11 fractional bits is actually insufficient for accurately
- * rasterizing some triangles. More recently, the maximum viewport
- * height was increased to 4K pixels. Thus, Mesa should be using 16
- * fractional bits in GLfixed. Unfortunately, there may be some issues
- * with setting FIXED_FRAC_BITS=16, such as multiplication overflow.
- * This will have to be examined in some detail...
- *
- * For now, if you find rasterization errors, particularly with tall,
- * sliver triangles, try increasing FIXED_FRAC_BITS and/or decreasing
- * SUB_PIXEL_BITS.
- */
-
-
-/*
- * Some code we unfortunately need to prevent negative interpolated colors.
- */
-#ifndef CLAMP_INTERPOLANT
-#define CLAMP_INTERPOLANT(CHANNEL, CHANNELSTEP, LEN) \
-do { \
- GLfixed endVal = span.CHANNEL + (LEN) * span.CHANNELSTEP; \
- if (endVal < 0) { \
- span.CHANNEL -= endVal; \
- } \
- if (span.CHANNEL < 0) { \
- span.CHANNEL = 0; \
- } \
-} while (0)
-#endif
-
-
-static void NAME(struct gl_context *ctx, const SWvertex *v0,
- const SWvertex *v1,
- const SWvertex *v2 )
-{
- typedef struct {
- const SWvertex *v0, *v1; /* Y(v0) < Y(v1) */
- GLfloat dx; /* X(v1) - X(v0) */
- GLfloat dy; /* Y(v1) - Y(v0) */
- GLfloat dxdy; /* dx/dy */
- GLfixed fdxdy; /* dx/dy in fixed-point */
- GLfloat adjy; /* adjust from v[0]->fy to fsy, scaled */
- GLfixed fsx; /* first sample point x coord */
- GLfixed fsy;
- GLfixed fx0; /* fixed pt X of lower endpoint */
- GLint lines; /* number of lines to be sampled on this edge */
- } EdgeT;
-
- const SWcontext *swrast = SWRAST_CONTEXT(ctx);
-#ifdef INTERP_Z
- const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
- const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
- const GLfloat maxDepth = ctx->DrawBuffer->_DepthMaxF;
-#define FixedToDepth(F) ((F) >> fixedToDepthShift)
-#endif
- EdgeT eMaj, eTop, eBot;
- GLfloat oneOverArea;
- const SWvertex *vMin, *vMid, *vMax; /* Y(vMin)<=Y(vMid)<=Y(vMax) */
- GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign;
- const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */
- GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy;
-
- SWspan span;
-
- (void) swrast;
-
- INIT_SPAN(span, GL_POLYGON);
- span.y = 0; /* silence warnings */
-
-#ifdef INTERP_Z
- (void) fixedToDepthShift;
-#endif
-
- /*
- printf("%s()\n", __FUNCTION__);
- printf(" %g, %g, %g\n",
- v0->attrib[FRAG_ATTRIB_WPOS][0],
- v0->attrib[FRAG_ATTRIB_WPOS][1],
- v0->attrib[FRAG_ATTRIB_WPOS][2]);
- printf(" %g, %g, %g\n",
- v1->attrib[FRAG_ATTRIB_WPOS][0],
- v1->attrib[FRAG_ATTRIB_WPOS][1],
- v1->attrib[FRAG_ATTRIB_WPOS][2]);
- printf(" %g, %g, %g\n",
- v2->attrib[FRAG_ATTRIB_WPOS][0],
- v2->attrib[FRAG_ATTRIB_WPOS][1],
- v2->attrib[FRAG_ATTRIB_WPOS][2]);
- */
-
- /* Compute fixed point x,y coords w/ half-pixel offsets and snapping.
- * And find the order of the 3 vertices along the Y axis.
- */
- {
- const GLfixed fy0 = FloatToFixed(v0->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) & snapMask;
- const GLfixed fy1 = FloatToFixed(v1->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) & snapMask;
- const GLfixed fy2 = FloatToFixed(v2->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) & snapMask;
- if (fy0 <= fy1) {
- if (fy1 <= fy2) {
- /* y0 <= y1 <= y2 */
- vMin = v0; vMid = v1; vMax = v2;
- vMin_fy = fy0; vMid_fy = fy1; vMax_fy = fy2;
- }
- else if (fy2 <= fy0) {
- /* y2 <= y0 <= y1 */
- vMin = v2; vMid = v0; vMax = v1;
- vMin_fy = fy2; vMid_fy = fy0; vMax_fy = fy1;
- }
- else {
- /* y0 <= y2 <= y1 */
- vMin = v0; vMid = v2; vMax = v1;
- vMin_fy = fy0; vMid_fy = fy2; vMax_fy = fy1;
- bf = -bf;
- }
- }
- else {
- if (fy0 <= fy2) {
- /* y1 <= y0 <= y2 */
- vMin = v1; vMid = v0; vMax = v2;
- vMin_fy = fy1; vMid_fy = fy0; vMax_fy = fy2;
- bf = -bf;
- }
- else if (fy2 <= fy1) {
- /* y2 <= y1 <= y0 */
- vMin = v2; vMid = v1; vMax = v0;
- vMin_fy = fy2; vMid_fy = fy1; vMax_fy = fy0;
- bf = -bf;
- }
- else {
- /* y1 <= y2 <= y0 */
- vMin = v1; vMid = v2; vMax = v0;
- vMin_fy = fy1; vMid_fy = fy2; vMax_fy = fy0;
- }
- }
-
- /* fixed point X coords */
- vMin_fx = FloatToFixed(vMin->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) & snapMask;
- vMid_fx = FloatToFixed(vMid->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) & snapMask;
- vMax_fx = FloatToFixed(vMax->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) & snapMask;
- }
-
- /* vertex/edge relationship */
- eMaj.v0 = vMin; eMaj.v1 = vMax; /*TODO: .v1's not needed */
- eTop.v0 = vMid; eTop.v1 = vMax;
- eBot.v0 = vMin; eBot.v1 = vMid;
-
- /* compute deltas for each edge: vertex[upper] - vertex[lower] */
- eMaj.dx = FixedToFloat(vMax_fx - vMin_fx);
- eMaj.dy = FixedToFloat(vMax_fy - vMin_fy);
- eTop.dx = FixedToFloat(vMax_fx - vMid_fx);
- eTop.dy = FixedToFloat(vMax_fy - vMid_fy);
- eBot.dx = FixedToFloat(vMid_fx - vMin_fx);
- eBot.dy = FixedToFloat(vMid_fy - vMin_fy);
-
- /* compute area, oneOverArea and perform backface culling */
- {
- const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
-
- if (IS_INF_OR_NAN(area) || area == 0.0F)
- return;
-
- if (area * bf * swrast->_BackfaceCullSign < 0.0)
- return;
-
- oneOverArea = 1.0F / area;
-
- /* 0 = front, 1 = back */
- span.facing = oneOverArea * bf > 0.0F;
- }
-
- /* Edge setup. For a triangle strip these could be reused... */
- {
- eMaj.fsy = FixedCeil(vMin_fy);
- eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy));
- if (eMaj.lines > 0) {
- eMaj.dxdy = eMaj.dx / eMaj.dy;
- eMaj.fdxdy = SignedFloatToFixed(eMaj.dxdy);
- eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy); /* SCALED! */
- eMaj.fx0 = vMin_fx;
- eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * eMaj.dxdy);
- }
- else {
- return; /*CULLED*/
- }
-
- eTop.fsy = FixedCeil(vMid_fy);
- eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy));
- if (eTop.lines > 0) {
- eTop.dxdy = eTop.dx / eTop.dy;
- eTop.fdxdy = SignedFloatToFixed(eTop.dxdy);
- eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */
- eTop.fx0 = vMid_fx;
- eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * eTop.dxdy);
- }
-
- eBot.fsy = FixedCeil(vMin_fy);
- eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy));
- if (eBot.lines > 0) {
- eBot.dxdy = eBot.dx / eBot.dy;
- eBot.fdxdy = SignedFloatToFixed(eBot.dxdy);
- eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy); /* SCALED! */
- eBot.fx0 = vMin_fx;
- eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * eBot.dxdy);
- }
- }
-
- /*
- * Conceptually, we view a triangle as two subtriangles
- * separated by a perfectly horizontal line. The edge that is
- * intersected by this line is one with maximal absolute dy; we
- * call it a ``major'' edge. The other two edges are the
- * ``top'' edge (for the upper subtriangle) and the ``bottom''
- * edge (for the lower subtriangle). If either of these two
- * edges is horizontal or very close to horizontal, the
- * corresponding subtriangle might cover zero sample points;
- * we take care to handle such cases, for performance as well
- * as correctness.
- *
- * By stepping rasterization parameters along the major edge,
- * we can avoid recomputing them at the discontinuity where
- * the top and bottom edges meet. However, this forces us to
- * be able to scan both left-to-right and right-to-left.
- * Also, we must determine whether the major edge is at the
- * left or right side of the triangle. We do this by
- * computing the magnitude of the cross-product of the major
- * and top edges. Since this magnitude depends on the sine of
- * the angle between the two edges, its sign tells us whether
- * we turn to the left or to the right when travelling along
- * the major edge to the top edge, and from this we infer
- * whether the major edge is on the left or the right.
- *
- * Serendipitously, this cross-product magnitude is also a
- * value we need to compute the iteration parameter
- * derivatives for the triangle, and it can be used to perform
- * backface culling because its sign tells us whether the
- * triangle is clockwise or counterclockwise. In this code we
- * refer to it as ``area'' because it's also proportional to
- * the pixel area of the triangle.
- */
-
- {
- GLint scan_from_left_to_right; /* true if scanning left-to-right */
-
- /*
- * Execute user-supplied setup code
- */
-#ifdef SETUP_CODE
- SETUP_CODE
-#endif
-
- scan_from_left_to_right = (oneOverArea < 0.0F);
-
-
- /* compute d?/dx and d?/dy derivatives */
-#ifdef INTERP_Z
- span.interpMask |= SPAN_Z;
- {
- GLfloat eMaj_dz = vMax->attrib[FRAG_ATTRIB_WPOS][2] - vMin->attrib[FRAG_ATTRIB_WPOS][2];
- GLfloat eBot_dz = vMid->attrib[FRAG_ATTRIB_WPOS][2] - vMin->attrib[FRAG_ATTRIB_WPOS][2];
- span.attrStepX[FRAG_ATTRIB_WPOS][2] = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz);
- if (span.attrStepX[FRAG_ATTRIB_WPOS][2] > maxDepth ||
- span.attrStepX[FRAG_ATTRIB_WPOS][2] < -maxDepth) {
- /* probably a sliver triangle */
- span.attrStepX[FRAG_ATTRIB_WPOS][2] = 0.0;
- span.attrStepY[FRAG_ATTRIB_WPOS][2] = 0.0;
- }
- else {
- span.attrStepY[FRAG_ATTRIB_WPOS][2] = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
- }
- if (depthBits <= 16)
- span.zStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_WPOS][2]);
- else
- span.zStep = (GLint) span.attrStepX[FRAG_ATTRIB_WPOS][2];
- }
-#endif
-#ifdef INTERP_RGB
- span.interpMask |= SPAN_RGBA;
- if (ctx->Light.ShadeModel == GL_SMOOTH) {
- GLfloat eMaj_dr = (GLfloat) (vMax->color[RCOMP] - vMin->color[RCOMP]);
- GLfloat eBot_dr = (GLfloat) (vMid->color[RCOMP] - vMin->color[RCOMP]);
- GLfloat eMaj_dg = (GLfloat) (vMax->color[GCOMP] - vMin->color[GCOMP]);
- GLfloat eBot_dg = (GLfloat) (vMid->color[GCOMP] - vMin->color[GCOMP]);
- GLfloat eMaj_db = (GLfloat) (vMax->color[BCOMP] - vMin->color[BCOMP]);
- GLfloat eBot_db = (GLfloat) (vMid->color[BCOMP] - vMin->color[BCOMP]);
-# ifdef INTERP_ALPHA
- GLfloat eMaj_da = (GLfloat) (vMax->color[ACOMP] - vMin->color[ACOMP]);
- GLfloat eBot_da = (GLfloat) (vMid->color[ACOMP] - vMin->color[ACOMP]);
-# endif
- span.attrStepX[FRAG_ATTRIB_COL0][0] = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
- span.attrStepY[FRAG_ATTRIB_COL0][0] = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
- span.attrStepX[FRAG_ATTRIB_COL0][1] = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
- span.attrStepY[FRAG_ATTRIB_COL0][1] = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
- span.attrStepX[FRAG_ATTRIB_COL0][2] = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
- span.attrStepY[FRAG_ATTRIB_COL0][2] = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
- span.redStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][0]);
- span.greenStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][1]);
- span.blueStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][2]);
-# ifdef INTERP_ALPHA
- span.attrStepX[FRAG_ATTRIB_COL0][3] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
- span.attrStepY[FRAG_ATTRIB_COL0][3] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
- span.alphaStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][3]);
-# endif /* INTERP_ALPHA */
- }
- else {
- ASSERT(ctx->Light.ShadeModel == GL_FLAT);
- span.interpMask |= SPAN_FLAT;
- span.attrStepX[FRAG_ATTRIB_COL0][0] = span.attrStepY[FRAG_ATTRIB_COL0][0] = 0.0F;
- span.attrStepX[FRAG_ATTRIB_COL0][1] = span.attrStepY[FRAG_ATTRIB_COL0][1] = 0.0F;
- span.attrStepX[FRAG_ATTRIB_COL0][2] = span.attrStepY[FRAG_ATTRIB_COL0][2] = 0.0F;
- span.redStep = 0;
- span.greenStep = 0;
- span.blueStep = 0;
-# ifdef INTERP_ALPHA
- span.attrStepX[FRAG_ATTRIB_COL0][3] = span.attrStepY[FRAG_ATTRIB_COL0][3] = 0.0F;
- span.alphaStep = 0;
-# endif
- }
-#endif /* INTERP_RGB */
-#ifdef INTERP_INT_TEX
- {
- GLfloat eMaj_ds = (vMax->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * S_SCALE;
- GLfloat eBot_ds = (vMid->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * S_SCALE;
- GLfloat eMaj_dt = (vMax->attrib[FRAG_ATTRIB_TEX0][1] - vMin->attrib[FRAG_ATTRIB_TEX0][1]) * T_SCALE;
- GLfloat eBot_dt = (vMid->attrib[FRAG_ATTRIB_TEX0][1] - vMin->attrib[FRAG_ATTRIB_TEX0][1]) * T_SCALE;
- span.attrStepX[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
- span.attrStepY[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
- span.attrStepX[FRAG_ATTRIB_TEX0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
- span.attrStepY[FRAG_ATTRIB_TEX0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
- span.intTexStep[0] = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_TEX0][0]);
- span.intTexStep[1] = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_TEX0][1]);
- }
-#endif
-#ifdef INTERP_ATTRIBS
- {
- /* attrib[FRAG_ATTRIB_WPOS][3] is 1/W */
- const GLfloat wMax = vMax->attrib[FRAG_ATTRIB_WPOS][3];
- const GLfloat wMin = vMin->attrib[FRAG_ATTRIB_WPOS][3];
- const GLfloat wMid = vMid->attrib[FRAG_ATTRIB_WPOS][3];
- {
- const GLfloat eMaj_dw = wMax - wMin;
- const GLfloat eBot_dw = wMid - wMin;
- span.attrStepX[FRAG_ATTRIB_WPOS][3] = oneOverArea * (eMaj_dw * eBot.dy - eMaj.dy * eBot_dw);
- span.attrStepY[FRAG_ATTRIB_WPOS][3] = oneOverArea * (eMaj.dx * eBot_dw - eMaj_dw * eBot.dx);
- }
- ATTRIB_LOOP_BEGIN
- if (swrast->_InterpMode[attr] == GL_FLAT) {
- ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
- ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
- }
- else {
- GLuint c;
- for (c = 0; c < 4; c++) {
- GLfloat eMaj_da = vMax->attrib[attr][c] * wMax - vMin->attrib[attr][c] * wMin;
- GLfloat eBot_da = vMid->attrib[attr][c] * wMid - vMin->attrib[attr][c] * wMin;
- span.attrStepX[attr][c] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
- span.attrStepY[attr][c] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
- }
- }
- ATTRIB_LOOP_END
- }
-#endif
-
- /*
- * We always sample at pixel centers. However, we avoid
- * explicit half-pixel offsets in this code by incorporating
- * the proper offset in each of x and y during the
- * transformation to window coordinates.
- *
- * We also apply the usual rasterization rules to prevent
- * cracks and overlaps. A pixel is considered inside a
- * subtriangle if it meets all of four conditions: it is on or
- * to the right of the left edge, strictly to the left of the
- * right edge, on or below the top edge, and strictly above
- * the bottom edge. (Some edges may be degenerate.)
- *
- * The following discussion assumes left-to-right scanning
- * (that is, the major edge is on the left); the right-to-left
- * case is a straightforward variation.
- *
- * We start by finding the half-integral y coordinate that is
- * at or below the top of the triangle. This gives us the
- * first scan line that could possibly contain pixels that are
- * inside the triangle.
- *
- * Next we creep down the major edge until we reach that y,
- * and compute the corresponding x coordinate on the edge.
- * Then we find the half-integral x that lies on or just
- * inside the edge. This is the first pixel that might lie in
- * the interior of the triangle. (We won't know for sure
- * until we check the other edges.)
- *
- * As we rasterize the triangle, we'll step down the major
- * edge. For each step in y, we'll move an integer number
- * of steps in x. There are two possible x step sizes, which
- * we'll call the ``inner'' step (guaranteed to land on the
- * edge or inside it) and the ``outer'' step (guaranteed to
- * land on the edge or outside it). The inner and outer steps
- * differ by one. During rasterization we maintain an error
- * term that indicates our distance from the true edge, and
- * select either the inner step or the outer step, whichever
- * gets us to the first pixel that falls inside the triangle.
- *
- * All parameters (z, red, etc.) as well as the buffer
- * addresses for color and z have inner and outer step values,
- * so that we can increment them appropriately. This method
- * eliminates the need to adjust parameters by creeping a
- * sub-pixel amount into the triangle at each scanline.
- */
-
- {
- GLint subTriangle;
- GLfixed fxLeftEdge = 0, fxRightEdge = 0;
- GLfixed fdxLeftEdge = 0, fdxRightEdge = 0;
- GLfixed fError = 0, fdError = 0;
-#ifdef PIXEL_ADDRESS
- PIXEL_TYPE *pRow = NULL;
- GLint dPRowOuter = 0, dPRowInner; /* offset in bytes */
-#endif
-#ifdef INTERP_Z
-# ifdef DEPTH_TYPE
- struct gl_renderbuffer *zrb
- = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
- DEPTH_TYPE *zRow = NULL;
- GLint dZRowOuter = 0, dZRowInner; /* offset in bytes */
-# endif
- GLuint zLeft = 0;
- GLfixed fdzOuter = 0, fdzInner;
-#endif
-#ifdef INTERP_RGB
- GLint rLeft = 0, fdrOuter = 0, fdrInner;
- GLint gLeft = 0, fdgOuter = 0, fdgInner;
- GLint bLeft = 0, fdbOuter = 0, fdbInner;
-#endif
-#ifdef INTERP_ALPHA
- GLint aLeft = 0, fdaOuter = 0, fdaInner;
-#endif
-#ifdef INTERP_INT_TEX
- GLfixed sLeft=0, dsOuter=0, dsInner;
- GLfixed tLeft=0, dtOuter=0, dtInner;
-#endif
-#ifdef INTERP_ATTRIBS
- GLfloat wLeft = 0, dwOuter = 0, dwInner;
- GLfloat attrLeft[FRAG_ATTRIB_MAX][4];
- GLfloat daOuter[FRAG_ATTRIB_MAX][4], daInner[FRAG_ATTRIB_MAX][4];
-#endif
-
- for (subTriangle=0; subTriangle<=1; subTriangle++) {
- EdgeT *eLeft, *eRight;
- int setupLeft, setupRight;
- int lines;
-
- if (subTriangle==0) {
- /* bottom half */
- if (scan_from_left_to_right) {
- eLeft = &eMaj;
- eRight = &eBot;
- lines = eRight->lines;
- setupLeft = 1;
- setupRight = 1;
- }
- else {
- eLeft = &eBot;
- eRight = &eMaj;
- lines = eLeft->lines;
- setupLeft = 1;
- setupRight = 1;
- }
- }
- else {
- /* top half */
- if (scan_from_left_to_right) {
- eLeft = &eMaj;
- eRight = &eTop;
- lines = eRight->lines;
- setupLeft = 0;
- setupRight = 1;
- }
- else {
- eLeft = &eTop;
- eRight = &eMaj;
- lines = eLeft->lines;
- setupLeft = 1;
- setupRight = 0;
- }
- if (lines == 0)
- return;
- }
-
- if (setupLeft && eLeft->lines > 0) {
- const SWvertex *vLower = eLeft->v0;
- const GLfixed fsy = eLeft->fsy;
- const GLfixed fsx = eLeft->fsx; /* no fractional part */
- const GLfixed fx = FixedCeil(fsx); /* no fractional part */
- const GLfixed adjx = (GLfixed) (fx - eLeft->fx0); /* SCALED! */
- const GLfixed adjy = (GLfixed) eLeft->adjy; /* SCALED! */
- GLint idxOuter;
- GLfloat dxOuter;
- GLfixed fdxOuter;
-
- fError = fx - fsx - FIXED_ONE;
- fxLeftEdge = fsx - FIXED_EPSILON;
- fdxLeftEdge = eLeft->fdxdy;
- fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
- fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
- idxOuter = FixedToInt(fdxOuter);
- dxOuter = (GLfloat) idxOuter;
- span.y = FixedToInt(fsy);
-
- /* silence warnings on some compilers */
- (void) dxOuter;
- (void) adjx;
- (void) adjy;
- (void) vLower;
-
-#ifdef PIXEL_ADDRESS
- {
- pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y);
- dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
- /* negative because Y=0 at bottom and increases upward */
- }
-#endif
- /*
- * Now we need the set of parameter (z, color, etc.) values at
- * the point (fx, fsy). This gives us properly-sampled parameter
- * values that we can step from pixel to pixel. Furthermore,
- * although we might have intermediate results that overflow
- * the normal parameter range when we step temporarily outside
- * the triangle, we shouldn't overflow or underflow for any
- * pixel that's actually inside the triangle.
- */
-
-#ifdef INTERP_Z
- {
- GLfloat z0 = vLower->attrib[FRAG_ATTRIB_WPOS][2];
- if (depthBits <= 16) {
- /* interpolate fixed-pt values */
- GLfloat tmp = (z0 * FIXED_SCALE
- + span.attrStepX[FRAG_ATTRIB_WPOS][2] * adjx
- + span.attrStepY[FRAG_ATTRIB_WPOS][2] * adjy) + FIXED_HALF;
- if (tmp < MAX_GLUINT / 2)
- zLeft = (GLfixed) tmp;
- else
- zLeft = MAX_GLUINT / 2;
- fdzOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_WPOS][2] +
- dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][2]);
- }
- else {
- /* interpolate depth values w/out scaling */
- zLeft = (GLuint) (z0 + span.attrStepX[FRAG_ATTRIB_WPOS][2] * FixedToFloat(adjx)
- + span.attrStepY[FRAG_ATTRIB_WPOS][2] * FixedToFloat(adjy));
- fdzOuter = (GLint) (span.attrStepY[FRAG_ATTRIB_WPOS][2] +
- dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][2]);
- }
-# ifdef DEPTH_TYPE
- zRow = (DEPTH_TYPE *)
- zrb->GetPointer(ctx, zrb, FixedToInt(fxLeftEdge), span.y);
- dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE);
-# endif
- }
-#endif
-#ifdef INTERP_RGB
- if (ctx->Light.ShadeModel == GL_SMOOTH) {
- rLeft = (GLint)(ChanToFixed(vLower->color[RCOMP])
- + span.attrStepX[FRAG_ATTRIB_COL0][0] * adjx
- + span.attrStepY[FRAG_ATTRIB_COL0][0] * adjy) + FIXED_HALF;
- gLeft = (GLint)(ChanToFixed(vLower->color[GCOMP])
- + span.attrStepX[FRAG_ATTRIB_COL0][1] * adjx
- + span.attrStepY[FRAG_ATTRIB_COL0][1] * adjy) + FIXED_HALF;
- bLeft = (GLint)(ChanToFixed(vLower->color[BCOMP])
- + span.attrStepX[FRAG_ATTRIB_COL0][2] * adjx
- + span.attrStepY[FRAG_ATTRIB_COL0][2] * adjy) + FIXED_HALF;
- fdrOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][0]
- + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][0]);
- fdgOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][1]
- + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][1]);
- fdbOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][2]
- + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][2]);
-# ifdef INTERP_ALPHA
- aLeft = (GLint)(ChanToFixed(vLower->color[ACOMP])
- + span.attrStepX[FRAG_ATTRIB_COL0][3] * adjx
- + span.attrStepY[FRAG_ATTRIB_COL0][3] * adjy) + FIXED_HALF;
- fdaOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][3]
- + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][3]);
-# endif
- }
- else {
- ASSERT(ctx->Light.ShadeModel == GL_FLAT);
- rLeft = ChanToFixed(v2->color[RCOMP]);
- gLeft = ChanToFixed(v2->color[GCOMP]);
- bLeft = ChanToFixed(v2->color[BCOMP]);
- fdrOuter = fdgOuter = fdbOuter = 0;
-# ifdef INTERP_ALPHA
- aLeft = ChanToFixed(v2->color[ACOMP]);
- fdaOuter = 0;
-# endif
- }
-#endif /* INTERP_RGB */
-
-
-#ifdef INTERP_INT_TEX
- {
- GLfloat s0, t0;
- s0 = vLower->attrib[FRAG_ATTRIB_TEX0][0] * S_SCALE;
- sLeft = (GLfixed)(s0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][0] * adjx
- + span.attrStepY[FRAG_ATTRIB_TEX0][0] * adjy) + FIXED_HALF;
- dsOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][0]
- + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][0]);
-
- t0 = vLower->attrib[FRAG_ATTRIB_TEX0][1] * T_SCALE;
- tLeft = (GLfixed)(t0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][1] * adjx
- + span.attrStepY[FRAG_ATTRIB_TEX0][1] * adjy) + FIXED_HALF;
- dtOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][1]
- + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][1]);
- }
-#endif
-#ifdef INTERP_ATTRIBS
- {
- const GLuint attr = FRAG_ATTRIB_WPOS;
- wLeft = vLower->attrib[FRAG_ATTRIB_WPOS][3]
- + (span.attrStepX[attr][3] * adjx
- + span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE);
- dwOuter = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3];
- }
- ATTRIB_LOOP_BEGIN
- const GLfloat invW = vLower->attrib[FRAG_ATTRIB_WPOS][3];
- if (swrast->_InterpMode[attr] == GL_FLAT) {
- GLuint c;
- for (c = 0; c < 4; c++) {
- attrLeft[attr][c] = v2->attrib[attr][c] * invW;
- daOuter[attr][c] = 0.0;
- }
- }
- else {
- GLuint c;
- for (c = 0; c < 4; c++) {
- const GLfloat a = vLower->attrib[attr][c] * invW;
- attrLeft[attr][c] = a + ( span.attrStepX[attr][c] * adjx
- + span.attrStepY[attr][c] * adjy) * (1.0F/FIXED_SCALE);
- daOuter[attr][c] = span.attrStepY[attr][c] + dxOuter * span.attrStepX[attr][c];
- }
- }
- ATTRIB_LOOP_END
-#endif
- } /*if setupLeft*/
-
-
- if (setupRight && eRight->lines>0) {
- fxRightEdge = eRight->fsx - FIXED_EPSILON;
- fdxRightEdge = eRight->fdxdy;
- }
-
- if (lines==0) {
- continue;
- }
-
-
- /* Rasterize setup */
-#ifdef PIXEL_ADDRESS
- dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE);
-#endif
-#ifdef INTERP_Z
-# ifdef DEPTH_TYPE
- dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE);
-# endif
- fdzInner = fdzOuter + span.zStep;
-#endif
-#ifdef INTERP_RGB
- fdrInner = fdrOuter + span.redStep;
- fdgInner = fdgOuter + span.greenStep;
- fdbInner = fdbOuter + span.blueStep;
-#endif
-#ifdef INTERP_ALPHA
- fdaInner = fdaOuter + span.alphaStep;
-#endif
-#ifdef INTERP_INT_TEX
- dsInner = dsOuter + span.intTexStep[0];
- dtInner = dtOuter + span.intTexStep[1];
-#endif
-#ifdef INTERP_ATTRIBS
- dwInner = dwOuter + span.attrStepX[FRAG_ATTRIB_WPOS][3];
- ATTRIB_LOOP_BEGIN
- GLuint c;
- for (c = 0; c < 4; c++) {
- daInner[attr][c] = daOuter[attr][c] + span.attrStepX[attr][c];
- }
- ATTRIB_LOOP_END
-#endif
-
- while (lines > 0) {
- /* initialize the span interpolants to the leftmost value */
- /* ff = fixed-pt fragment */
- const GLint right = FixedToInt(fxRightEdge);
- span.x = FixedToInt(fxLeftEdge);
- if (right <= span.x)
- span.end = 0;
- else
- span.end = right - span.x;
-
-#ifdef INTERP_Z
- span.z = zLeft;
-#endif
-#ifdef INTERP_RGB
- span.red = rLeft;
- span.green = gLeft;
- span.blue = bLeft;
-#endif
-#ifdef INTERP_ALPHA
- span.alpha = aLeft;
-#endif
-#ifdef INTERP_INT_TEX
- span.intTex[0] = sLeft;
- span.intTex[1] = tLeft;
-#endif
-
-#ifdef INTERP_ATTRIBS
- span.attrStart[FRAG_ATTRIB_WPOS][3] = wLeft;
- ATTRIB_LOOP_BEGIN
- GLuint c;
- for (c = 0; c < 4; c++) {
- span.attrStart[attr][c] = attrLeft[attr][c];
- }
- ATTRIB_LOOP_END
-#endif
-
- /* This is where we actually generate fragments */
- /* XXX the test for span.y > 0 _shouldn't_ be needed but
- * it fixes a problem on 64-bit Opterons (bug 4842).
- */
- if (span.end > 0 && span.y >= 0) {
- const GLint len = span.end - 1;
- (void) len;
-#ifdef INTERP_RGB
- CLAMP_INTERPOLANT(red, redStep, len);
- CLAMP_INTERPOLANT(green, greenStep, len);
- CLAMP_INTERPOLANT(blue, blueStep, len);
-#endif
-#ifdef INTERP_ALPHA
- CLAMP_INTERPOLANT(alpha, alphaStep, len);
-#endif
- {
- RENDER_SPAN( span );
- }
- }
-
- /*
- * Advance to the next scan line. Compute the
- * new edge coordinates, and adjust the
- * pixel-center x coordinate so that it stays
- * on or inside the major edge.
- */
- span.y++;
- lines--;
-
- fxLeftEdge += fdxLeftEdge;
- fxRightEdge += fdxRightEdge;
-
- fError += fdError;
- if (fError >= 0) {
- fError -= FIXED_ONE;
-
-#ifdef PIXEL_ADDRESS
- pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter);
-#endif
-#ifdef INTERP_Z
-# ifdef DEPTH_TYPE
- zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter);
-# endif
- zLeft += fdzOuter;
-#endif
-#ifdef INTERP_RGB
- rLeft += fdrOuter;
- gLeft += fdgOuter;
- bLeft += fdbOuter;
-#endif
-#ifdef INTERP_ALPHA
- aLeft += fdaOuter;
-#endif
-#ifdef INTERP_INT_TEX
- sLeft += dsOuter;
- tLeft += dtOuter;
-#endif
-#ifdef INTERP_ATTRIBS
- wLeft += dwOuter;
- ATTRIB_LOOP_BEGIN
- GLuint c;
- for (c = 0; c < 4; c++) {
- attrLeft[attr][c] += daOuter[attr][c];
- }
- ATTRIB_LOOP_END
-#endif
- }
- else {
-#ifdef PIXEL_ADDRESS
- pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner);
-#endif
-#ifdef INTERP_Z
-# ifdef DEPTH_TYPE
- zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner);
-# endif
- zLeft += fdzInner;
-#endif
-#ifdef INTERP_RGB
- rLeft += fdrInner;
- gLeft += fdgInner;
- bLeft += fdbInner;
-#endif
-#ifdef INTERP_ALPHA
- aLeft += fdaInner;
-#endif
-#ifdef INTERP_INT_TEX
- sLeft += dsInner;
- tLeft += dtInner;
-#endif
-#ifdef INTERP_ATTRIBS
- wLeft += dwInner;
- ATTRIB_LOOP_BEGIN
- GLuint c;
- for (c = 0; c < 4; c++) {
- attrLeft[attr][c] += daInner[attr][c];
- }
- ATTRIB_LOOP_END
-#endif
- }
- } /*while lines>0*/
-
- } /* for subTriangle */
-
- }
- }
-}
-
-#undef SETUP_CODE
-#undef RENDER_SPAN
-
-#undef PIXEL_TYPE
-#undef BYTES_PER_ROW
-#undef PIXEL_ADDRESS
-#undef DEPTH_TYPE
-
-#undef INTERP_Z
-#undef INTERP_RGB
-#undef INTERP_ALPHA
-#undef INTERP_INT_TEX
-#undef INTERP_ATTRIBS
-
-#undef S_SCALE
-#undef T_SCALE
-
-#undef FixedToDepth
-
-#undef NAME
+/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 1999-2007 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Triangle Rasterizer Template + * + * This file is #include'd to generate custom triangle rasterizers. + * + * The following macros may be defined to indicate what auxillary information + * must be interpolated across the triangle: + * INTERP_Z - if defined, interpolate integer Z values + * INTERP_RGB - if defined, interpolate integer RGB values + * INTERP_ALPHA - if defined, interpolate integer Alpha values + * INTERP_INT_TEX - if defined, interpolate integer ST texcoords + * (fast, simple 2-D texture mapping, without + * perspective correction) + * INTERP_ATTRIBS - if defined, interpolate arbitrary attribs (texcoords, + * varying vars, etc) This also causes W to be + * computed for perspective correction). + * + * When one can directly address pixels in the color buffer the following + * macros can be defined and used to compute pixel addresses during + * rasterization (see pRow): + * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint) + * BYTES_PER_ROW - number of bytes per row in the color buffer + * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where + * Y==0 at bottom of screen and increases upward. + * + * Similarly, for direct depth buffer access, this type is used for depth + * buffer addressing (see zRow): + * DEPTH_TYPE - either GLushort or GLuint + * + * Optionally, one may provide one-time setup code per triangle: + * SETUP_CODE - code which is to be executed once per triangle + * + * The following macro MUST be defined: + * RENDER_SPAN(span) - code to write a span of pixels. + * + * This code was designed for the origin to be in the lower-left corner. + * + * Inspired by triangle rasterizer code written by Allen Akin. Thanks Allen! + * + * + * Some notes on rasterization accuracy: + * + * This code uses fixed point arithmetic (the GLfixed type) to iterate + * over the triangle edges and interpolate ancillary data (such as Z, + * color, secondary color, etc). The number of fractional bits in + * GLfixed and the value of SUB_PIXEL_BITS has a direct bearing on the + * accuracy of rasterization. + * + * If SUB_PIXEL_BITS=4 then we'll snap the vertices to the nearest + * 1/16 of a pixel. If we're walking up a long, nearly vertical edge + * (dx=1/16, dy=1024) we'll need 4 + 10 = 14 fractional bits in + * GLfixed to walk the edge without error. If the maximum viewport + * height is 4K pixels, then we'll need 4 + 12 = 16 fractional bits. + * + * Historically, Mesa has used 11 fractional bits in GLfixed, snaps + * vertices to 1/16 pixel and allowed a maximum viewport height of 2K + * pixels. 11 fractional bits is actually insufficient for accurately + * rasterizing some triangles. More recently, the maximum viewport + * height was increased to 4K pixels. Thus, Mesa should be using 16 + * fractional bits in GLfixed. Unfortunately, there may be some issues + * with setting FIXED_FRAC_BITS=16, such as multiplication overflow. + * This will have to be examined in some detail... + * + * For now, if you find rasterization errors, particularly with tall, + * sliver triangles, try increasing FIXED_FRAC_BITS and/or decreasing + * SUB_PIXEL_BITS. + */ + + +/* + * Some code we unfortunately need to prevent negative interpolated colors. + */ +#ifndef CLAMP_INTERPOLANT +#define CLAMP_INTERPOLANT(CHANNEL, CHANNELSTEP, LEN) \ +do { \ + GLfixed endVal = span.CHANNEL + (LEN) * span.CHANNELSTEP; \ + if (endVal < 0) { \ + span.CHANNEL -= endVal; \ + } \ + if (span.CHANNEL < 0) { \ + span.CHANNEL = 0; \ + } \ +} while (0) +#endif + + +static void NAME(struct gl_context *ctx, const SWvertex *v0, + const SWvertex *v1, + const SWvertex *v2 ) +{ + typedef struct { + const SWvertex *v0, *v1; /* Y(v0) < Y(v1) */ + GLfloat dx; /* X(v1) - X(v0) */ + GLfloat dy; /* Y(v1) - Y(v0) */ + GLfloat dxdy; /* dx/dy */ + GLfixed fdxdy; /* dx/dy in fixed-point */ + GLfloat adjy; /* adjust from v[0]->fy to fsy, scaled */ + GLfixed fsx; /* first sample point x coord */ + GLfixed fsy; + GLfixed fx0; /* fixed pt X of lower endpoint */ + GLint lines; /* number of lines to be sampled on this edge */ + } EdgeT; + + const SWcontext *swrast = SWRAST_CONTEXT(ctx); +#ifdef INTERP_Z + const GLint depthBits = ctx->DrawBuffer->Visual.depthBits; + const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0; + const GLfloat maxDepth = ctx->DrawBuffer->_DepthMaxF; +#define FixedToDepth(F) ((F) >> fixedToDepthShift) +#endif + EdgeT eMaj, eTop, eBot; + GLfloat oneOverArea; + const SWvertex *vMin, *vMid, *vMax; /* Y(vMin)<=Y(vMid)<=Y(vMax) */ + GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign; + const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */ + GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy; + + SWspan span; + + (void) swrast; + + INIT_SPAN(span, GL_POLYGON); + span.y = 0; /* silence warnings */ + +#ifdef INTERP_Z + (void) fixedToDepthShift; +#endif + + /* + printf("%s()\n", __FUNCTION__); + printf(" %g, %g, %g\n", + v0->attrib[FRAG_ATTRIB_WPOS][0], + v0->attrib[FRAG_ATTRIB_WPOS][1], + v0->attrib[FRAG_ATTRIB_WPOS][2]); + printf(" %g, %g, %g\n", + v1->attrib[FRAG_ATTRIB_WPOS][0], + v1->attrib[FRAG_ATTRIB_WPOS][1], + v1->attrib[FRAG_ATTRIB_WPOS][2]); + printf(" %g, %g, %g\n", + v2->attrib[FRAG_ATTRIB_WPOS][0], + v2->attrib[FRAG_ATTRIB_WPOS][1], + v2->attrib[FRAG_ATTRIB_WPOS][2]); + */ + + /* Compute fixed point x,y coords w/ half-pixel offsets and snapping. + * And find the order of the 3 vertices along the Y axis. + */ + { + const GLfixed fy0 = FloatToFixed(v0->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) & snapMask; + const GLfixed fy1 = FloatToFixed(v1->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) & snapMask; + const GLfixed fy2 = FloatToFixed(v2->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) & snapMask; + if (fy0 <= fy1) { + if (fy1 <= fy2) { + /* y0 <= y1 <= y2 */ + vMin = v0; vMid = v1; vMax = v2; + vMin_fy = fy0; vMid_fy = fy1; vMax_fy = fy2; + } + else if (fy2 <= fy0) { + /* y2 <= y0 <= y1 */ + vMin = v2; vMid = v0; vMax = v1; + vMin_fy = fy2; vMid_fy = fy0; vMax_fy = fy1; + } + else { + /* y0 <= y2 <= y1 */ + vMin = v0; vMid = v2; vMax = v1; + vMin_fy = fy0; vMid_fy = fy2; vMax_fy = fy1; + bf = -bf; + } + } + else { + if (fy0 <= fy2) { + /* y1 <= y0 <= y2 */ + vMin = v1; vMid = v0; vMax = v2; + vMin_fy = fy1; vMid_fy = fy0; vMax_fy = fy2; + bf = -bf; + } + else if (fy2 <= fy1) { + /* y2 <= y1 <= y0 */ + vMin = v2; vMid = v1; vMax = v0; + vMin_fy = fy2; vMid_fy = fy1; vMax_fy = fy0; + bf = -bf; + } + else { + /* y1 <= y2 <= y0 */ + vMin = v1; vMid = v2; vMax = v0; + vMin_fy = fy1; vMid_fy = fy2; vMax_fy = fy0; + } + } + + /* fixed point X coords */ + vMin_fx = FloatToFixed(vMin->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) & snapMask; + vMid_fx = FloatToFixed(vMid->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) & snapMask; + vMax_fx = FloatToFixed(vMax->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) & snapMask; + } + + /* vertex/edge relationship */ + eMaj.v0 = vMin; eMaj.v1 = vMax; /*TODO: .v1's not needed */ + eTop.v0 = vMid; eTop.v1 = vMax; + eBot.v0 = vMin; eBot.v1 = vMid; + + /* compute deltas for each edge: vertex[upper] - vertex[lower] */ + eMaj.dx = FixedToFloat(vMax_fx - vMin_fx); + eMaj.dy = FixedToFloat(vMax_fy - vMin_fy); + eTop.dx = FixedToFloat(vMax_fx - vMid_fx); + eTop.dy = FixedToFloat(vMax_fy - vMid_fy); + eBot.dx = FixedToFloat(vMid_fx - vMin_fx); + eBot.dy = FixedToFloat(vMid_fy - vMin_fy); + + /* compute area, oneOverArea and perform backface culling */ + { + const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy; + + if (IS_INF_OR_NAN(area) || area == 0.0F) + return; + + if (area * bf * swrast->_BackfaceCullSign < 0.0) + return; + + oneOverArea = 1.0F / area; + + /* 0 = front, 1 = back */ + span.facing = oneOverArea * bf > 0.0F; + } + + /* Edge setup. For a triangle strip these could be reused... */ + { + eMaj.fsy = FixedCeil(vMin_fy); + eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy)); + if (eMaj.lines > 0) { + eMaj.dxdy = eMaj.dx / eMaj.dy; + eMaj.fdxdy = SignedFloatToFixed(eMaj.dxdy); + eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy); /* SCALED! */ + eMaj.fx0 = vMin_fx; + eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * eMaj.dxdy); + } + else { + return; /*CULLED*/ + } + + eTop.fsy = FixedCeil(vMid_fy); + eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy)); + if (eTop.lines > 0) { + eTop.dxdy = eTop.dx / eTop.dy; + eTop.fdxdy = SignedFloatToFixed(eTop.dxdy); + eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */ + eTop.fx0 = vMid_fx; + eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * eTop.dxdy); + } + + eBot.fsy = FixedCeil(vMin_fy); + eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy)); + if (eBot.lines > 0) { + eBot.dxdy = eBot.dx / eBot.dy; + eBot.fdxdy = SignedFloatToFixed(eBot.dxdy); + eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy); /* SCALED! */ + eBot.fx0 = vMin_fx; + eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * eBot.dxdy); + } + } + + /* + * Conceptually, we view a triangle as two subtriangles + * separated by a perfectly horizontal line. The edge that is + * intersected by this line is one with maximal absolute dy; we + * call it a ``major'' edge. The other two edges are the + * ``top'' edge (for the upper subtriangle) and the ``bottom'' + * edge (for the lower subtriangle). If either of these two + * edges is horizontal or very close to horizontal, the + * corresponding subtriangle might cover zero sample points; + * we take care to handle such cases, for performance as well + * as correctness. + * + * By stepping rasterization parameters along the major edge, + * we can avoid recomputing them at the discontinuity where + * the top and bottom edges meet. However, this forces us to + * be able to scan both left-to-right and right-to-left. + * Also, we must determine whether the major edge is at the + * left or right side of the triangle. We do this by + * computing the magnitude of the cross-product of the major + * and top edges. Since this magnitude depends on the sine of + * the angle between the two edges, its sign tells us whether + * we turn to the left or to the right when travelling along + * the major edge to the top edge, and from this we infer + * whether the major edge is on the left or the right. + * + * Serendipitously, this cross-product magnitude is also a + * value we need to compute the iteration parameter + * derivatives for the triangle, and it can be used to perform + * backface culling because its sign tells us whether the + * triangle is clockwise or counterclockwise. In this code we + * refer to it as ``area'' because it's also proportional to + * the pixel area of the triangle. + */ + + { + GLint scan_from_left_to_right; /* true if scanning left-to-right */ + + /* + * Execute user-supplied setup code + */ +#ifdef SETUP_CODE + SETUP_CODE +#endif + + scan_from_left_to_right = (oneOverArea < 0.0F); + + + /* compute d?/dx and d?/dy derivatives */ +#ifdef INTERP_Z + span.interpMask |= SPAN_Z; + { + GLfloat eMaj_dz = vMax->attrib[FRAG_ATTRIB_WPOS][2] - vMin->attrib[FRAG_ATTRIB_WPOS][2]; + GLfloat eBot_dz = vMid->attrib[FRAG_ATTRIB_WPOS][2] - vMin->attrib[FRAG_ATTRIB_WPOS][2]; + span.attrStepX[FRAG_ATTRIB_WPOS][2] = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz); + if (span.attrStepX[FRAG_ATTRIB_WPOS][2] > maxDepth || + span.attrStepX[FRAG_ATTRIB_WPOS][2] < -maxDepth) { + /* probably a sliver triangle */ + span.attrStepX[FRAG_ATTRIB_WPOS][2] = 0.0; + span.attrStepY[FRAG_ATTRIB_WPOS][2] = 0.0; + } + else { + span.attrStepY[FRAG_ATTRIB_WPOS][2] = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx); + } + if (depthBits <= 16) + span.zStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_WPOS][2]); + else + span.zStep = (GLint) span.attrStepX[FRAG_ATTRIB_WPOS][2]; + } +#endif +#ifdef INTERP_RGB + span.interpMask |= SPAN_RGBA; + if (ctx->Light.ShadeModel == GL_SMOOTH) { + GLfloat eMaj_dr = (GLfloat) (vMax->color[RCOMP] - vMin->color[RCOMP]); + GLfloat eBot_dr = (GLfloat) (vMid->color[RCOMP] - vMin->color[RCOMP]); + GLfloat eMaj_dg = (GLfloat) (vMax->color[GCOMP] - vMin->color[GCOMP]); + GLfloat eBot_dg = (GLfloat) (vMid->color[GCOMP] - vMin->color[GCOMP]); + GLfloat eMaj_db = (GLfloat) (vMax->color[BCOMP] - vMin->color[BCOMP]); + GLfloat eBot_db = (GLfloat) (vMid->color[BCOMP] - vMin->color[BCOMP]); +# ifdef INTERP_ALPHA + GLfloat eMaj_da = (GLfloat) (vMax->color[ACOMP] - vMin->color[ACOMP]); + GLfloat eBot_da = (GLfloat) (vMid->color[ACOMP] - vMin->color[ACOMP]); +# endif + span.attrStepX[FRAG_ATTRIB_COL0][0] = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr); + span.attrStepY[FRAG_ATTRIB_COL0][0] = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx); + span.attrStepX[FRAG_ATTRIB_COL0][1] = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg); + span.attrStepY[FRAG_ATTRIB_COL0][1] = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx); + span.attrStepX[FRAG_ATTRIB_COL0][2] = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db); + span.attrStepY[FRAG_ATTRIB_COL0][2] = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx); + span.redStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][0]); + span.greenStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][1]); + span.blueStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][2]); +# ifdef INTERP_ALPHA + span.attrStepX[FRAG_ATTRIB_COL0][3] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da); + span.attrStepY[FRAG_ATTRIB_COL0][3] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx); + span.alphaStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][3]); +# endif /* INTERP_ALPHA */ + } + else { + ASSERT(ctx->Light.ShadeModel == GL_FLAT); + span.interpMask |= SPAN_FLAT; + span.attrStepX[FRAG_ATTRIB_COL0][0] = span.attrStepY[FRAG_ATTRIB_COL0][0] = 0.0F; + span.attrStepX[FRAG_ATTRIB_COL0][1] = span.attrStepY[FRAG_ATTRIB_COL0][1] = 0.0F; + span.attrStepX[FRAG_ATTRIB_COL0][2] = span.attrStepY[FRAG_ATTRIB_COL0][2] = 0.0F; + span.redStep = 0; + span.greenStep = 0; + span.blueStep = 0; +# ifdef INTERP_ALPHA + span.attrStepX[FRAG_ATTRIB_COL0][3] = span.attrStepY[FRAG_ATTRIB_COL0][3] = 0.0F; + span.alphaStep = 0; +# endif + } +#endif /* INTERP_RGB */ +#ifdef INTERP_INT_TEX + { + GLfloat eMaj_ds = (vMax->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * S_SCALE; + GLfloat eBot_ds = (vMid->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * S_SCALE; + GLfloat eMaj_dt = (vMax->attrib[FRAG_ATTRIB_TEX0][1] - vMin->attrib[FRAG_ATTRIB_TEX0][1]) * T_SCALE; + GLfloat eBot_dt = (vMid->attrib[FRAG_ATTRIB_TEX0][1] - vMin->attrib[FRAG_ATTRIB_TEX0][1]) * T_SCALE; + span.attrStepX[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds); + span.attrStepY[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx); + span.attrStepX[FRAG_ATTRIB_TEX0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt); + span.attrStepY[FRAG_ATTRIB_TEX0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx); + span.intTexStep[0] = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_TEX0][0]); + span.intTexStep[1] = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_TEX0][1]); + } +#endif +#ifdef INTERP_ATTRIBS + { + /* attrib[FRAG_ATTRIB_WPOS][3] is 1/W */ + const GLfloat wMax = vMax->attrib[FRAG_ATTRIB_WPOS][3]; + const GLfloat wMin = vMin->attrib[FRAG_ATTRIB_WPOS][3]; + const GLfloat wMid = vMid->attrib[FRAG_ATTRIB_WPOS][3]; + { + const GLfloat eMaj_dw = wMax - wMin; + const GLfloat eBot_dw = wMid - wMin; + span.attrStepX[FRAG_ATTRIB_WPOS][3] = oneOverArea * (eMaj_dw * eBot.dy - eMaj.dy * eBot_dw); + span.attrStepY[FRAG_ATTRIB_WPOS][3] = oneOverArea * (eMaj.dx * eBot_dw - eMaj_dw * eBot.dx); + } + ATTRIB_LOOP_BEGIN + if (swrast->_InterpMode[attr] == GL_FLAT) { + ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0); + ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0); + } + else { + GLuint c; + for (c = 0; c < 4; c++) { + GLfloat eMaj_da = vMax->attrib[attr][c] * wMax - vMin->attrib[attr][c] * wMin; + GLfloat eBot_da = vMid->attrib[attr][c] * wMid - vMin->attrib[attr][c] * wMin; + span.attrStepX[attr][c] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da); + span.attrStepY[attr][c] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx); + } + } + ATTRIB_LOOP_END + } +#endif + + /* + * We always sample at pixel centers. However, we avoid + * explicit half-pixel offsets in this code by incorporating + * the proper offset in each of x and y during the + * transformation to window coordinates. + * + * We also apply the usual rasterization rules to prevent + * cracks and overlaps. A pixel is considered inside a + * subtriangle if it meets all of four conditions: it is on or + * to the right of the left edge, strictly to the left of the + * right edge, on or below the top edge, and strictly above + * the bottom edge. (Some edges may be degenerate.) + * + * The following discussion assumes left-to-right scanning + * (that is, the major edge is on the left); the right-to-left + * case is a straightforward variation. + * + * We start by finding the half-integral y coordinate that is + * at or below the top of the triangle. This gives us the + * first scan line that could possibly contain pixels that are + * inside the triangle. + * + * Next we creep down the major edge until we reach that y, + * and compute the corresponding x coordinate on the edge. + * Then we find the half-integral x that lies on or just + * inside the edge. This is the first pixel that might lie in + * the interior of the triangle. (We won't know for sure + * until we check the other edges.) + * + * As we rasterize the triangle, we'll step down the major + * edge. For each step in y, we'll move an integer number + * of steps in x. There are two possible x step sizes, which + * we'll call the ``inner'' step (guaranteed to land on the + * edge or inside it) and the ``outer'' step (guaranteed to + * land on the edge or outside it). The inner and outer steps + * differ by one. During rasterization we maintain an error + * term that indicates our distance from the true edge, and + * select either the inner step or the outer step, whichever + * gets us to the first pixel that falls inside the triangle. + * + * All parameters (z, red, etc.) as well as the buffer + * addresses for color and z have inner and outer step values, + * so that we can increment them appropriately. This method + * eliminates the need to adjust parameters by creeping a + * sub-pixel amount into the triangle at each scanline. + */ + + { + GLint subTriangle; + GLfixed fxLeftEdge = 0, fxRightEdge = 0; + GLfixed fdxLeftEdge = 0, fdxRightEdge = 0; + GLfixed fError = 0, fdError = 0; +#ifdef PIXEL_ADDRESS + PIXEL_TYPE *pRow = NULL; + GLint dPRowOuter = 0, dPRowInner; /* offset in bytes */ +#endif +#ifdef INTERP_Z +# ifdef DEPTH_TYPE + struct gl_renderbuffer *zrb + = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + DEPTH_TYPE *zRow = NULL; + GLint dZRowOuter = 0, dZRowInner; /* offset in bytes */ +# endif + GLuint zLeft = 0; + GLfixed fdzOuter = 0, fdzInner; +#endif +#ifdef INTERP_RGB + GLint rLeft = 0, fdrOuter = 0, fdrInner; + GLint gLeft = 0, fdgOuter = 0, fdgInner; + GLint bLeft = 0, fdbOuter = 0, fdbInner; +#endif +#ifdef INTERP_ALPHA + GLint aLeft = 0, fdaOuter = 0, fdaInner; +#endif +#ifdef INTERP_INT_TEX + GLfixed sLeft=0, dsOuter=0, dsInner; + GLfixed tLeft=0, dtOuter=0, dtInner; +#endif +#ifdef INTERP_ATTRIBS + GLfloat wLeft = 0, dwOuter = 0, dwInner; + GLfloat attrLeft[FRAG_ATTRIB_MAX][4]; + GLfloat daOuter[FRAG_ATTRIB_MAX][4], daInner[FRAG_ATTRIB_MAX][4]; +#endif + + for (subTriangle=0; subTriangle<=1; subTriangle++) { + EdgeT *eLeft, *eRight; + int setupLeft, setupRight; + int lines; + + if (subTriangle==0) { + /* bottom half */ + if (scan_from_left_to_right) { + eLeft = &eMaj; + eRight = &eBot; + lines = eRight->lines; + setupLeft = 1; + setupRight = 1; + } + else { + eLeft = &eBot; + eRight = &eMaj; + lines = eLeft->lines; + setupLeft = 1; + setupRight = 1; + } + } + else { + /* top half */ + if (scan_from_left_to_right) { + eLeft = &eMaj; + eRight = &eTop; + lines = eRight->lines; + setupLeft = 0; + setupRight = 1; + } + else { + eLeft = &eTop; + eRight = &eMaj; + lines = eLeft->lines; + setupLeft = 1; + setupRight = 0; + } + if (lines == 0) + return; + } + + if (setupLeft && eLeft->lines > 0) { + const SWvertex *vLower = eLeft->v0; + const GLfixed fsy = eLeft->fsy; + const GLfixed fsx = eLeft->fsx; /* no fractional part */ + const GLfixed fx = FixedCeil(fsx); /* no fractional part */ + const GLfixed adjx = (GLfixed) (fx - eLeft->fx0); /* SCALED! */ + const GLfixed adjy = (GLfixed) eLeft->adjy; /* SCALED! */ + GLint idxOuter; + GLfloat dxOuter; + GLfixed fdxOuter; + + fError = fx - fsx - FIXED_ONE; + fxLeftEdge = fsx - FIXED_EPSILON; + fdxLeftEdge = eLeft->fdxdy; + fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON); + fdError = fdxOuter - fdxLeftEdge + FIXED_ONE; + idxOuter = FixedToInt(fdxOuter); + dxOuter = (GLfloat) idxOuter; + span.y = FixedToInt(fsy); + + /* silence warnings on some compilers */ + (void) dxOuter; + (void) adjx; + (void) adjy; + (void) vLower; + +#ifdef PIXEL_ADDRESS + { + pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y); + dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE); + /* negative because Y=0 at bottom and increases upward */ + } +#endif + /* + * Now we need the set of parameter (z, color, etc.) values at + * the point (fx, fsy). This gives us properly-sampled parameter + * values that we can step from pixel to pixel. Furthermore, + * although we might have intermediate results that overflow + * the normal parameter range when we step temporarily outside + * the triangle, we shouldn't overflow or underflow for any + * pixel that's actually inside the triangle. + */ + +#ifdef INTERP_Z + { + GLfloat z0 = vLower->attrib[FRAG_ATTRIB_WPOS][2]; + if (depthBits <= 16) { + /* interpolate fixed-pt values */ + GLfloat tmp = (z0 * FIXED_SCALE + + span.attrStepX[FRAG_ATTRIB_WPOS][2] * adjx + + span.attrStepY[FRAG_ATTRIB_WPOS][2] * adjy) + FIXED_HALF; + if (tmp < MAX_GLUINT / 2) + zLeft = (GLfixed) tmp; + else + zLeft = MAX_GLUINT / 2; + fdzOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_WPOS][2] + + dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][2]); + } + else { + /* interpolate depth values w/out scaling */ + zLeft = (GLuint) (z0 + span.attrStepX[FRAG_ATTRIB_WPOS][2] * FixedToFloat(adjx) + + span.attrStepY[FRAG_ATTRIB_WPOS][2] * FixedToFloat(adjy)); + fdzOuter = (GLint) (span.attrStepY[FRAG_ATTRIB_WPOS][2] + + dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][2]); + } +# ifdef DEPTH_TYPE + zRow = (DEPTH_TYPE *) + _swrast_pixel_address(zrb, FixedToInt(fxLeftEdge), span.y); + dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE); +# endif + } +#endif +#ifdef INTERP_RGB + if (ctx->Light.ShadeModel == GL_SMOOTH) { + rLeft = (GLint)(ChanToFixed(vLower->color[RCOMP]) + + span.attrStepX[FRAG_ATTRIB_COL0][0] * adjx + + span.attrStepY[FRAG_ATTRIB_COL0][0] * adjy) + FIXED_HALF; + gLeft = (GLint)(ChanToFixed(vLower->color[GCOMP]) + + span.attrStepX[FRAG_ATTRIB_COL0][1] * adjx + + span.attrStepY[FRAG_ATTRIB_COL0][1] * adjy) + FIXED_HALF; + bLeft = (GLint)(ChanToFixed(vLower->color[BCOMP]) + + span.attrStepX[FRAG_ATTRIB_COL0][2] * adjx + + span.attrStepY[FRAG_ATTRIB_COL0][2] * adjy) + FIXED_HALF; + fdrOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][0] + + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][0]); + fdgOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][1] + + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][1]); + fdbOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][2] + + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][2]); +# ifdef INTERP_ALPHA + aLeft = (GLint)(ChanToFixed(vLower->color[ACOMP]) + + span.attrStepX[FRAG_ATTRIB_COL0][3] * adjx + + span.attrStepY[FRAG_ATTRIB_COL0][3] * adjy) + FIXED_HALF; + fdaOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][3] + + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][3]); +# endif + } + else { + ASSERT(ctx->Light.ShadeModel == GL_FLAT); + rLeft = ChanToFixed(v2->color[RCOMP]); + gLeft = ChanToFixed(v2->color[GCOMP]); + bLeft = ChanToFixed(v2->color[BCOMP]); + fdrOuter = fdgOuter = fdbOuter = 0; +# ifdef INTERP_ALPHA + aLeft = ChanToFixed(v2->color[ACOMP]); + fdaOuter = 0; +# endif + } +#endif /* INTERP_RGB */ + + +#ifdef INTERP_INT_TEX + { + GLfloat s0, t0; + s0 = vLower->attrib[FRAG_ATTRIB_TEX0][0] * S_SCALE; + sLeft = (GLfixed)(s0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][0] * adjx + + span.attrStepY[FRAG_ATTRIB_TEX0][0] * adjy) + FIXED_HALF; + dsOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][0] + + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][0]); + + t0 = vLower->attrib[FRAG_ATTRIB_TEX0][1] * T_SCALE; + tLeft = (GLfixed)(t0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][1] * adjx + + span.attrStepY[FRAG_ATTRIB_TEX0][1] * adjy) + FIXED_HALF; + dtOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][1] + + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][1]); + } +#endif +#ifdef INTERP_ATTRIBS + { + const GLuint attr = FRAG_ATTRIB_WPOS; + wLeft = vLower->attrib[FRAG_ATTRIB_WPOS][3] + + (span.attrStepX[attr][3] * adjx + + span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE); + dwOuter = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3]; + } + ATTRIB_LOOP_BEGIN + const GLfloat invW = vLower->attrib[FRAG_ATTRIB_WPOS][3]; + if (swrast->_InterpMode[attr] == GL_FLAT) { + GLuint c; + for (c = 0; c < 4; c++) { + attrLeft[attr][c] = v2->attrib[attr][c] * invW; + daOuter[attr][c] = 0.0; + } + } + else { + GLuint c; + for (c = 0; c < 4; c++) { + const GLfloat a = vLower->attrib[attr][c] * invW; + attrLeft[attr][c] = a + ( span.attrStepX[attr][c] * adjx + + span.attrStepY[attr][c] * adjy) * (1.0F/FIXED_SCALE); + daOuter[attr][c] = span.attrStepY[attr][c] + dxOuter * span.attrStepX[attr][c]; + } + } + ATTRIB_LOOP_END +#endif + } /*if setupLeft*/ + + + if (setupRight && eRight->lines>0) { + fxRightEdge = eRight->fsx - FIXED_EPSILON; + fdxRightEdge = eRight->fdxdy; + } + + if (lines==0) { + continue; + } + + + /* Rasterize setup */ +#ifdef PIXEL_ADDRESS + dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE); +#endif +#ifdef INTERP_Z +# ifdef DEPTH_TYPE + dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE); +# endif + fdzInner = fdzOuter + span.zStep; +#endif +#ifdef INTERP_RGB + fdrInner = fdrOuter + span.redStep; + fdgInner = fdgOuter + span.greenStep; + fdbInner = fdbOuter + span.blueStep; +#endif +#ifdef INTERP_ALPHA + fdaInner = fdaOuter + span.alphaStep; +#endif +#ifdef INTERP_INT_TEX + dsInner = dsOuter + span.intTexStep[0]; + dtInner = dtOuter + span.intTexStep[1]; +#endif +#ifdef INTERP_ATTRIBS + dwInner = dwOuter + span.attrStepX[FRAG_ATTRIB_WPOS][3]; + ATTRIB_LOOP_BEGIN + GLuint c; + for (c = 0; c < 4; c++) { + daInner[attr][c] = daOuter[attr][c] + span.attrStepX[attr][c]; + } + ATTRIB_LOOP_END +#endif + + while (lines > 0) { + /* initialize the span interpolants to the leftmost value */ + /* ff = fixed-pt fragment */ + const GLint right = FixedToInt(fxRightEdge); + span.x = FixedToInt(fxLeftEdge); + if (right <= span.x) + span.end = 0; + else + span.end = right - span.x; + +#ifdef INTERP_Z + span.z = zLeft; +#endif +#ifdef INTERP_RGB + span.red = rLeft; + span.green = gLeft; + span.blue = bLeft; +#endif +#ifdef INTERP_ALPHA + span.alpha = aLeft; +#endif +#ifdef INTERP_INT_TEX + span.intTex[0] = sLeft; + span.intTex[1] = tLeft; +#endif + +#ifdef INTERP_ATTRIBS + span.attrStart[FRAG_ATTRIB_WPOS][3] = wLeft; + ATTRIB_LOOP_BEGIN + GLuint c; + for (c = 0; c < 4; c++) { + span.attrStart[attr][c] = attrLeft[attr][c]; + } + ATTRIB_LOOP_END +#endif + + /* This is where we actually generate fragments */ + /* XXX the test for span.y > 0 _shouldn't_ be needed but + * it fixes a problem on 64-bit Opterons (bug 4842). + */ + if (span.end > 0 && span.y >= 0) { + const GLint len = span.end - 1; + (void) len; +#ifdef INTERP_RGB + CLAMP_INTERPOLANT(red, redStep, len); + CLAMP_INTERPOLANT(green, greenStep, len); + CLAMP_INTERPOLANT(blue, blueStep, len); +#endif +#ifdef INTERP_ALPHA + CLAMP_INTERPOLANT(alpha, alphaStep, len); +#endif + { + RENDER_SPAN( span ); + } + } + + /* + * Advance to the next scan line. Compute the + * new edge coordinates, and adjust the + * pixel-center x coordinate so that it stays + * on or inside the major edge. + */ + span.y++; + lines--; + + fxLeftEdge += fdxLeftEdge; + fxRightEdge += fdxRightEdge; + + fError += fdError; + if (fError >= 0) { + fError -= FIXED_ONE; + +#ifdef PIXEL_ADDRESS + pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter); +#endif +#ifdef INTERP_Z +# ifdef DEPTH_TYPE + zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter); +# endif + zLeft += fdzOuter; +#endif +#ifdef INTERP_RGB + rLeft += fdrOuter; + gLeft += fdgOuter; + bLeft += fdbOuter; +#endif +#ifdef INTERP_ALPHA + aLeft += fdaOuter; +#endif +#ifdef INTERP_INT_TEX + sLeft += dsOuter; + tLeft += dtOuter; +#endif +#ifdef INTERP_ATTRIBS + wLeft += dwOuter; + ATTRIB_LOOP_BEGIN + GLuint c; + for (c = 0; c < 4; c++) { + attrLeft[attr][c] += daOuter[attr][c]; + } + ATTRIB_LOOP_END +#endif + } + else { +#ifdef PIXEL_ADDRESS + pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner); +#endif +#ifdef INTERP_Z +# ifdef DEPTH_TYPE + zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner); +# endif + zLeft += fdzInner; +#endif +#ifdef INTERP_RGB + rLeft += fdrInner; + gLeft += fdgInner; + bLeft += fdbInner; +#endif +#ifdef INTERP_ALPHA + aLeft += fdaInner; +#endif +#ifdef INTERP_INT_TEX + sLeft += dsInner; + tLeft += dtInner; +#endif +#ifdef INTERP_ATTRIBS + wLeft += dwInner; + ATTRIB_LOOP_BEGIN + GLuint c; + for (c = 0; c < 4; c++) { + attrLeft[attr][c] += daInner[attr][c]; + } + ATTRIB_LOOP_END +#endif + } + } /*while lines>0*/ + + } /* for subTriangle */ + + } + } +} + +#undef SETUP_CODE +#undef RENDER_SPAN + +#undef PIXEL_TYPE +#undef BYTES_PER_ROW +#undef PIXEL_ADDRESS +#undef DEPTH_TYPE + +#undef INTERP_Z +#undef INTERP_RGB +#undef INTERP_ALPHA +#undef INTERP_INT_TEX +#undef INTERP_ATTRIBS + +#undef S_SCALE +#undef T_SCALE + +#undef FixedToDepth + +#undef NAME diff --git a/mesalib/src/mesa/swrast/s_zoom.c b/mesalib/src/mesa/swrast/s_zoom.c index f407fdcf4..73bff482b 100644 --- a/mesalib/src/mesa/swrast/s_zoom.c +++ b/mesalib/src/mesa/swrast/s_zoom.c @@ -25,6 +25,7 @@ #include "main/glheader.h" #include "main/macros.h" #include "main/imports.h" +#include "main/format_pack.h" #include "main/colormac.h" #include "s_context.h" @@ -390,17 +391,17 @@ _swrast_write_zoomed_stencil_span(struct gl_context *ctx, GLint imgX, GLint imgY /** - * Zoom/write z values (16 or 32-bit). + * Zoom/write 32-bit Z values. * No per-fragment operations are applied. */ void _swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY, GLint width, GLint spanX, GLint spanY, - const GLvoid *z) + const GLuint *zVals) { - struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer; - GLushort zoomedVals16[MAX_WIDTH]; - GLuint zoomedVals32[MAX_WIDTH]; + struct gl_renderbuffer *rb = + ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + GLuint zoomedVals[MAX_WIDTH]; GLint x0, x1, y0, y1, y; GLint i, zoomedWidth; @@ -414,28 +415,16 @@ _swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY, ASSERT(zoomedWidth <= MAX_WIDTH); /* zoom the span horizontally */ - 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 { - 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; + 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] = zVals[j]; } /* write the zoomed spans */ for (y = y0; y < y1; y++) { - rb->PutRow(ctx, rb, zoomedWidth, x0, y, z, NULL); + GLubyte *dst = _swrast_pixel_address(rb, x0, y); + _mesa_pack_uint_z_row(rb->Format, zoomedWidth, zoomedVals, dst); } } diff --git a/mesalib/src/mesa/swrast/s_zoom.h b/mesalib/src/mesa/swrast/s_zoom.h index 0b82bb824..1955e7e88 100644 --- a/mesalib/src/mesa/swrast/s_zoom.h +++ b/mesalib/src/mesa/swrast/s_zoom.h @@ -50,7 +50,7 @@ _swrast_write_zoomed_stencil_span(struct gl_context *ctx, GLint imgX, GLint imgY extern void _swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY, GLint width, GLint spanX, GLint spanY, - const GLvoid *z); + const GLuint *zVals); #endif |