/* * Render a bitmap. */ void _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLint row, col; GLuint count = 0; struct sw_span span; ASSERT(ctx->RenderMode == GL_RENDER); ASSERT(bitmap); RENDER_START(swrast,ctx); if (SWRAST_CONTEXT(ctx)->NewState) _swrast_validate_derived( ctx ); INIT_SPAN(span, GL_BITMAP, width, 0, SPAN_XY); if (ctx->Visual.rgbMode) { span.interpMask |= SPAN_RGBA; span.red = FloatToFixed(ctx->Current.RasterColor[0] * CHAN_MAXF); span.green = FloatToFixed(ctx->Current.RasterColor[1] * CHAN_MAXF); span.blue = FloatToFixed(ctx->Current.RasterColor[2] * CHAN_MAXF); span.alpha = FloatToFixed(ctx->Current.RasterColor[3] * CHAN_MAXF); span.redStep = span.greenStep = span.blueStep = span.alphaStep = 0; } else { span.interpMask |= SPAN_INDEX; span.index = ChanToFixed(ctx->Current.RasterIndex); span.indexStep = 0; } if (ctx->Depth.Test) _mesa_span_default_z(ctx, &span); if (ctx->Fog.Enabled) _mesa_span_default_fog(ctx, &span); if (ctx->Texture._EnabledUnits) _mesa_span_default_texcoords(ctx, &span); for (row = 0; row < height; row++, span.y++) { const GLubyte *src = (const GLubyte *) _mesa_image_address( unpack, bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 ); if (unpack->LsbFirst) { /* Lsb first */ GLubyte mask = 1U << (unpack->SkipPixels & 0x7); for (col = 0; col < width; col++) { if (*src & mask) { span.array->x[count] = px + col; span.array->y[count] = py + row; count++; } if (mask == 128U) { src++; mask = 1U; } else { mask = mask << 1; } } /* get ready for next row */ if (mask != 1) src++; } else { /* Msb first */ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); for (col = 0; col < width; col++) { if (*src & mask) { span.array->x[count] = px + col; span.array->y[count] = py + row; count++; } if (mask == 1U) { src++; mask = 128U; } else { mask = mask >> 1; } } /* get ready for next row */ if (mask != 128) src++; } if (count + width >= MAX_WIDTH || row + 1 == height) { /* flush the span */ span.end = count; if (ctx->Visual.rgbMode) _mesa_write_rgba_span(ctx, &span); else _mesa_write_index_span(ctx, &span); span.end = 0; count = 0; } } RENDER_FINISH(swrast,ctx); }
/** * Draw large (size >= 1) non-AA point. RGB or CI mode. */ static void large_point(GLcontext *ctx, const SWvertex *vert) { SWcontext *swrast = SWRAST_CONTEXT(ctx); const GLboolean ciMode = !ctx->Visual.rgbMode; SWspan span; GLfloat size; CULL_INVALID(vert); /* z coord */ if (ctx->DrawBuffer->Visual.depthBits <= 16) span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); else span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); span.zStep = 0; size = get_size(ctx, vert, GL_FALSE); /* span init */ INIT_SPAN(span, GL_POINT); span.arrayMask = SPAN_XY; span.facing = swrast->PointLineFacing; if (ciMode) { span.interpMask = SPAN_Z | SPAN_INDEX; span.index = FloatToFixed(vert->attrib[FRAG_ATTRIB_CI][0]); span.indexStep = 0; } else { span.interpMask = SPAN_Z | SPAN_RGBA; span.red = ChanToFixed(vert->color[0]); span.green = ChanToFixed(vert->color[1]); span.blue = ChanToFixed(vert->color[2]); span.alpha = ChanToFixed(vert->color[3]); span.redStep = 0; span.greenStep = 0; span.blueStep = 0; span.alphaStep = 0; } /* need these for fragment programs */ span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; ATTRIB_LOOP_BEGIN COPY_4V(span.attrStart[attr], vert->attrib[attr]); ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0); ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0); ATTRIB_LOOP_END /* compute pos, bounds and render */ { const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0]; const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1]; GLint iSize = (GLint) (size + 0.5F); GLint xmin, xmax, ymin, ymax, ix, iy; GLint iRadius; iSize = MAX2(1, iSize); iRadius = iSize / 2; if (iSize & 1) { /* odd size */ xmin = (GLint) (x - iRadius); xmax = (GLint) (x + iRadius); ymin = (GLint) (y - iRadius); ymax = (GLint) (y + iRadius); } else { /* even size */ /* 0.501 factor allows conformance to pass */ xmin = (GLint) (x + 0.501) - iRadius; xmax = xmin + iSize - 1; ymin = (GLint) (y + 0.501) - iRadius; ymax = ymin + iSize - 1; } /* generate fragments */ span.end = 0; for (iy = ymin; iy <= ymax; iy++) { for (ix = xmin; ix <= xmax; ix++) { span.array->x[span.end] = ix; span.array->y[span.end] = iy; span.end++; } } assert(span.end <= MAX_WIDTH); _swrast_write_rgba_span(ctx, &span); } }
/** * Draw a point sprite */ static void sprite_point(GLcontext *ctx, const SWvertex *vert) { SWcontext *swrast = SWRAST_CONTEXT(ctx); SWspan span; GLfloat size; GLuint tCoords[MAX_TEXTURE_COORD_UNITS + 1]; GLuint numTcoords = 0; GLfloat t0, dtdy; CULL_INVALID(vert); /* z coord */ if (ctx->DrawBuffer->Visual.depthBits <= 16) span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); else span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); span.zStep = 0; size = get_size(ctx, vert, GL_FALSE); /* span init */ INIT_SPAN(span, GL_POINT); span.interpMask = SPAN_Z | SPAN_RGBA; span.facing = swrast->PointLineFacing; span.red = ChanToFixed(vert->color[0]); span.green = ChanToFixed(vert->color[1]); span.blue = ChanToFixed(vert->color[2]); span.alpha = ChanToFixed(vert->color[3]); span.redStep = 0; span.greenStep = 0; span.blueStep = 0; span.alphaStep = 0; /* need these for fragment programs */ span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; { GLfloat s, r, dsdx; /* texcoord / pointcoord interpolants */ s = 0.0; dsdx = 1.0 / size; if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) { dtdy = 1.0 / size; t0 = 0.5 * dtdy; } else { /* GL_UPPER_LEFT */ dtdy = -1.0 / size; t0 = 1.0 + 0.5 * dtdy; } ATTRIB_LOOP_BEGIN if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0) { const GLuint u = attr - FRAG_ATTRIB_TEX0; /* a texcoord */ if (ctx->Point.CoordReplace[u]) { tCoords[numTcoords++] = attr; if (ctx->Point.SpriteRMode == GL_ZERO) r = 0.0F; else if (ctx->Point.SpriteRMode == GL_S) r = vert->attrib[attr][0]; else /* GL_R */ r = vert->attrib[attr][2]; span.attrStart[attr][0] = s; span.attrStart[attr][1] = 0.0; /* overwritten below */ span.attrStart[attr][2] = r; span.attrStart[attr][3] = 1.0; span.attrStepX[attr][0] = dsdx; span.attrStepX[attr][1] = 0.0; span.attrStepX[attr][2] = 0.0; span.attrStepX[attr][3] = 0.0; span.attrStepY[attr][0] = 0.0; span.attrStepY[attr][1] = dtdy; span.attrStepY[attr][2] = 0.0; span.attrStepY[attr][3] = 0.0; continue; } } else if (attr == FRAG_ATTRIB_FOGC) { /* GLSL gl_PointCoord is stored in fog.zw */ span.attrStart[FRAG_ATTRIB_FOGC][2] = 0.0; span.attrStart[FRAG_ATTRIB_FOGC][3] = 0.0; /* t0 set below */ span.attrStepX[FRAG_ATTRIB_FOGC][2] = dsdx; span.attrStepX[FRAG_ATTRIB_FOGC][3] = 0.0; span.attrStepY[FRAG_ATTRIB_FOGC][2] = 0.0; span.attrStepY[FRAG_ATTRIB_FOGC][3] = dtdy; tCoords[numTcoords++] = FRAG_ATTRIB_FOGC; continue; } /* use vertex's texcoord/attrib */ COPY_4V(span.attrStart[attr], vert->attrib[attr]); ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0); ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0); ATTRIB_LOOP_END; } /* compute pos, bounds and render */ { const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0]; const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1]; GLint iSize = (GLint) (size + 0.5F); GLint xmin, xmax, ymin, ymax, iy; GLint iRadius; GLfloat tcoord = t0; iSize = MAX2(1, iSize); iRadius = iSize / 2; if (iSize & 1) { /* odd size */ xmin = (GLint) (x - iRadius); xmax = (GLint) (x + iRadius); ymin = (GLint) (y - iRadius); ymax = (GLint) (y + iRadius); } else { /* even size */ /* 0.501 factor allows conformance to pass */ xmin = (GLint) (x + 0.501) - iRadius; xmax = xmin + iSize - 1; ymin = (GLint) (y + 0.501) - iRadius; ymax = ymin + iSize - 1; } /* render spans */ for (iy = ymin; iy <= ymax; iy++) { GLuint i; /* setup texcoord T for this row */ for (i = 0; i < numTcoords; i++) { if (tCoords[i] == FRAG_ATTRIB_FOGC) span.attrStart[FRAG_ATTRIB_FOGC][3] = tcoord; else span.attrStart[tCoords[i]][1] = tcoord; } /* these might get changed by span clipping */ span.x = xmin; span.y = iy; span.end = xmax - xmin + 1; _swrast_write_rgba_span(ctx, &span); tcoord += dtdy; } } }
/** * Draw smooth/antialiased point. RGB or CI mode. */ static void smooth_point(GLcontext *ctx, const SWvertex *vert) { SWcontext *swrast = SWRAST_CONTEXT(ctx); const GLboolean ciMode = !ctx->Visual.rgbMode; SWspan span; GLfloat size, alphaAtten; CULL_INVALID(vert); /* z coord */ if (ctx->DrawBuffer->Visual.depthBits <= 16) span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); else span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F); span.zStep = 0; size = get_size(ctx, vert, GL_TRUE); /* alpha attenuation / fade factor */ if (ctx->Multisample._Enabled) { if (vert->pointSize >= ctx->Point.Threshold) { alphaAtten = 1.0F; } else { GLfloat dsize = vert->pointSize / ctx->Point.Threshold; alphaAtten = dsize * dsize; } } else { alphaAtten = 1.0; } (void) alphaAtten; /* not used */ /* span init */ INIT_SPAN(span, GL_POINT); span.interpMask = SPAN_Z | SPAN_RGBA; span.arrayMask = SPAN_COVERAGE | SPAN_MASK; span.facing = swrast->PointLineFacing; span.red = ChanToFixed(vert->color[0]); span.green = ChanToFixed(vert->color[1]); span.blue = ChanToFixed(vert->color[2]); span.alpha = ChanToFixed(vert->color[3]); span.redStep = 0; span.greenStep = 0; span.blueStep = 0; span.alphaStep = 0; /* need these for fragment programs */ span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F; span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F; span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F; ATTRIB_LOOP_BEGIN COPY_4V(span.attrStart[attr], vert->attrib[attr]); ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0); ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0); ATTRIB_LOOP_END /* compute pos, bounds and render */ { const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0]; const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1]; const GLfloat radius = 0.5F * size; const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */ const GLfloat rmax = radius + 0.7071F; const GLfloat rmin2 = MAX2(0.0F, rmin * rmin); const GLfloat rmax2 = rmax * rmax; const GLfloat cscale = 1.0F / (rmax2 - rmin2); const GLint xmin = (GLint) (x - radius); const GLint xmax = (GLint) (x + radius); const GLint ymin = (GLint) (y - radius); const GLint ymax = (GLint) (y + radius); GLint ix, iy; for (iy = ymin; iy <= ymax; iy++) { /* these might get changed by span clipping */ span.x = xmin; span.y = iy; span.end = xmax - xmin + 1; /* compute coverage for each pixel in span */ for (ix = xmin; ix <= xmax; ix++) { const GLfloat dx = ix - x + 0.5F; const GLfloat dy = iy - y + 0.5F; const GLfloat dist2 = dx * dx + dy * dy; GLfloat coverage; if (dist2 < rmax2) { if (dist2 >= rmin2) { /* compute partial coverage */ coverage = 1.0F - (dist2 - rmin2) * cscale; if (ciMode) { /* coverage in [0,15] */ coverage *= 15.0; } } else { /* full coverage */ coverage = 1.0F; } span.array->mask[ix - xmin] = 1; } else { /* zero coverage - fragment outside the radius */ coverage = 0.0; span.array->mask[ix - xmin] = 0; } span.array->coverage[ix - xmin] = coverage; } /* render span */ _swrast_write_rgba_span(ctx, &span); } } }