aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/swrast
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/swrast')
-rw-r--r--mesalib/src/mesa/swrast/s_clear.c268
-rw-r--r--mesalib/src/mesa/swrast/s_context.h12
-rw-r--r--mesalib/src/mesa/swrast/s_copypix.c338
-rw-r--r--mesalib/src/mesa/swrast/s_depth.c1575
-rw-r--r--mesalib/src/mesa/swrast/s_depth.h5
-rw-r--r--mesalib/src/mesa/swrast/s_depthstencil.c246
-rw-r--r--mesalib/src/mesa/swrast/s_drawpix.c514
-rw-r--r--mesalib/src/mesa/swrast/s_linetemp.h804
-rw-r--r--mesalib/src/mesa/swrast/s_renderbuffer.c492
-rw-r--r--mesalib/src/mesa/swrast/s_spantemp.h81
-rw-r--r--mesalib/src/mesa/swrast/s_stencil.c1298
-rw-r--r--mesalib/src/mesa/swrast/s_stencil.h2
-rw-r--r--mesalib/src/mesa/swrast/s_texrender.c179
-rw-r--r--mesalib/src/mesa/swrast/s_triangle.c51
-rw-r--r--mesalib/src/mesa/swrast/s_tritemp.h1858
-rw-r--r--mesalib/src/mesa/swrast/s_zoom.c37
-rw-r--r--mesalib/src/mesa/swrast/s_zoom.h2
17 files changed, 2664 insertions, 5098 deletions
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