/*
* Mesa 3-D graphics library
- * Version: 7.5
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
* 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.
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
#include "main/glheader.h"
#include "main/colormac.h"
+#include "main/format_pack.h"
+#include "main/format_unpack.h"
#include "main/macros.h"
#include "main/imports.h"
#include "main/image.h"
+#include "main/samplerobj.h"
#include "s_atifragshader.h"
#include "s_alpha.h"
#include "s_stencil.h"
#include "s_texcombine.h"
+#include <stdbool.h>
/**
* Set default fragment attributes for the span using the
}
/* W (for perspective correction) */
- span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0;
- span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0;
- span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;
+ span->attrStart[VARYING_SLOT_POS][3] = 1.0;
+ span->attrStepX[VARYING_SLOT_POS][3] = 0.0;
+ span->attrStepY[VARYING_SLOT_POS][3] = 0.0;
/* primary color, or color index */
UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
span->alphaStep = 0;
span->interpMask |= SPAN_RGBA;
- COPY_4V(span->attrStart[FRAG_ATTRIB_COL0], ctx->Current.RasterColor);
- ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
- ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
+ COPY_4V(span->attrStart[VARYING_SLOT_COL0], ctx->Current.RasterColor);
+ ASSIGN_4V(span->attrStepX[VARYING_SLOT_COL0], 0.0, 0.0, 0.0, 0.0);
+ ASSIGN_4V(span->attrStepY[VARYING_SLOT_COL0], 0.0, 0.0, 0.0, 0.0);
/* Secondary color */
if (ctx->Light.Enabled || ctx->Fog.ColorSumEnabled)
{
- COPY_4V(span->attrStart[FRAG_ATTRIB_COL1], ctx->Current.RasterSecondaryColor);
- ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
- ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
+ COPY_4V(span->attrStart[VARYING_SLOT_COL1], ctx->Current.RasterSecondaryColor);
+ ASSIGN_4V(span->attrStepX[VARYING_SLOT_COL1], 0.0, 0.0, 0.0, 0.0);
+ ASSIGN_4V(span->attrStepY[VARYING_SLOT_COL1], 0.0, 0.0, 0.0, 0.0);
}
/* fog */
/* fog blend factor should be computed from fogcoord now */
fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
}
- span->attrStart[FRAG_ATTRIB_FOGC][0] = fogVal;
- span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
- span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
+ span->attrStart[VARYING_SLOT_FOGC][0] = fogVal;
+ span->attrStepX[VARYING_SLOT_FOGC][0] = 0.0;
+ span->attrStepY[VARYING_SLOT_FOGC][0] = 0.0;
}
/* texcoords */
{
GLuint i;
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
- const GLuint attr = FRAG_ATTRIB_TEX0 + i;
+ const GLuint attr = VARYING_SLOT_TEX0 + i;
const GLfloat *tc = ctx->Current.RasterTexCoords[i];
- if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) {
+ if (_swrast_use_fragment_program(ctx) ||
+ ctx->ATIFragmentShader._Enabled) {
COPY_4V(span->attrStart[attr], tc);
}
else if (tc[3] > 0.0F) {
* Interpolate the active attributes (and'd with attrMask) to
* fill in span->array->attribs[].
* Perspective correction will be done. The point/line/triangle function
- * should have computed attrStart/Step values for FRAG_ATTRIB_WPOS[3]!
+ * should have computed attrStart/Step values for VARYING_SLOT_POS[3]!
*/
-static INLINE void
-interpolate_active_attribs(struct gl_context *ctx, SWspan *span, GLbitfield attrMask)
+static inline void
+interpolate_active_attribs(struct gl_context *ctx, SWspan *span,
+ GLbitfield64 attrMask)
{
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
attrMask &= ~span->arrayAttribs;
ATTRIB_LOOP_BEGIN
- if (attrMask & (1 << attr)) {
- const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
- GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
+ if (attrMask & BITFIELD64_BIT(attr)) {
+ const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3];
+ GLfloat w = span->attrStart[VARYING_SLOT_POS][3];
const GLfloat dv0dx = span->attrStepX[attr][0];
const GLfloat dv1dx = span->attrStepX[attr][1];
const GLfloat dv2dx = span->attrStepX[attr][2];
v3 += dv3dx;
w += dwdx;
}
- ASSERT((span->arrayAttribs & (1 << attr)) == 0);
- span->arrayAttribs |= (1 << attr);
+ ASSERT((span->arrayAttribs & BITFIELD64_BIT(attr)) == 0);
+ span->arrayAttribs |= BITFIELD64_BIT(attr);
}
ATTRIB_LOOP_END
}
* Interpolate primary colors to fill in the span->array->rgba8 (or rgb16)
* color array.
*/
-static INLINE void
+static inline void
interpolate_int_colors(struct gl_context *ctx, SWspan *span)
{
+#if CHAN_BITS != 32
const GLuint n = span->end;
GLuint i;
-#if CHAN_BITS != 32
ASSERT(!(span->arrayMask & SPAN_RGBA));
#endif
break;
#endif
case GL_FLOAT:
- interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
+ interpolate_active_attribs(ctx, span, VARYING_BIT_COL0);
break;
default:
_mesa_problem(ctx, "bad datatype 0x%x in interpolate_int_colors",
/**
- * Populate the FRAG_ATTRIB_COL0 array.
+ * Populate the VARYING_SLOT_COL0 array.
*/
-static INLINE void
+static inline void
interpolate_float_colors(SWspan *span)
{
- GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ GLfloat (*col0)[4] = span->array->attribs[VARYING_SLOT_COL0];
const GLuint n = span->end;
GLuint i;
- assert(!(span->arrayAttribs & FRAG_BIT_COL0));
+ assert(!(span->arrayAttribs & VARYING_BIT_COL0));
if (span->arrayMask & SPAN_RGBA) {
/* convert array of int colors */
}
}
- span->arrayAttribs |= FRAG_BIT_COL0;
+ span->arrayAttribs |= VARYING_BIT_COL0;
span->array->ChanType = GL_FLOAT;
}
GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
- GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
- GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
+ GLfloat x = sqrtf(dudx * dudx + dvdx * dvdx);
+ GLfloat y = sqrtf(dudy * dudy + dvdy * dvdy);
GLfloat rho = MAX2(x, y);
GLfloat lambda = LOG2(rho);
return lambda;
/**
- * Fill in the span.array->attrib[FRAG_ATTRIB_TEXn] arrays from the
+ * Fill in the span.array->attrib[VARYING_SLOT_TEXn] arrays from the
* using the attrStart/Step values.
*
* This function only used during fixed-function fragment processing.
/* XXX CoordUnits vs. ImageUnits */
for (u = 0; u < maxUnit; u++) {
if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
- const GLuint attr = FRAG_ATTRIB_TEX0 + u;
+ const GLuint attr = VARYING_SLOT_TEX0 + u;
const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
GLfloat texW, texH;
GLboolean needLambda;
if (obj) {
const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
- needLambda = (obj->Sampler.MinFilter != obj->Sampler.MagFilter)
- || ctx->FragmentProgram._Current;
- texW = img->WidthScale;
- texH = img->HeightScale;
+ const struct swrast_texture_image *swImg =
+ swrast_texture_image_const(img);
+ const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, u);
+
+ needLambda = (samp->MinFilter != samp->MagFilter)
+ || _swrast_use_fragment_program(ctx);
+ /* LOD is calculated directly in the ansiotropic filter, we can
+ * skip the normal lambda function as the result is ignored.
+ */
+ if (samp->MaxAnisotropy > 1.0 &&
+ samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
+ needLambda = GL_FALSE;
+ }
+ texW = swImg->WidthScale;
+ texH = swImg->HeightScale;
}
else {
/* using a fragment program */
if (needLambda) {
GLuint i;
- if (ctx->FragmentProgram._Current
+ if (_swrast_use_fragment_program(ctx)
|| ctx->ATIFragmentShader._Enabled) {
/* do perspective correction but don't divide s, t, r by q */
- const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
- GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
+ const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3];
+ GLfloat w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dwdx;
for (i = 0; i < span->end; i++) {
const GLfloat invW = 1.0F / w;
texcoord[i][0] = s * invW;
}
else {
GLuint i;
- if (ctx->FragmentProgram._Current ||
+ if (_swrast_use_fragment_program(ctx) ||
ctx->ATIFragmentShader._Enabled) {
/* do perspective correction but don't divide s, t, r by q */
- const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
- GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
+ const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3];
+ GLfloat w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dwdx;
for (i = 0; i < span->end; i++) {
const GLfloat invW = 1.0F / w;
texcoord[i][0] = s * invW;
/**
- * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array.
+ * Fill in the arrays->attribs[VARYING_SLOT_POS] array.
*/
-static INLINE void
+static inline void
interpolate_wpos(struct gl_context *ctx, SWspan *span)
{
- GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS];
+ GLfloat (*wpos)[4] = span->array->attribs[VARYING_SLOT_POS];
GLuint i;
const GLfloat zScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
GLfloat w, dw;
}
}
- dw = span->attrStepX[FRAG_ATTRIB_WPOS][3];
- w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dw;
+ dw = span->attrStepX[VARYING_SLOT_POS][3];
+ w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dw;
for (i = 0; i < span->end; i++) {
wpos[i][2] = (GLfloat) span->array->z[i] * zScale;
wpos[i][3] = w;
/**
* Apply the current polygon stipple pattern to a span of pixels.
*/
-static INLINE void
+static inline void
stipple_polygon_span(struct gl_context *ctx, SWspan *span)
{
GLubyte *mask = span->array->mask;
* Return: GL_TRUE some pixels still visible
* GL_FALSE nothing visible
*/
-static INLINE GLuint
+static inline GLuint
clip_span( struct gl_context *ctx, SWspan *span )
{
const GLint xmin = ctx->DrawBuffer->_Xmin;
const GLint n = span->end;
GLubyte *mask = span->array->mask;
GLint i;
+ GLuint passed = 0;
if (span->arrayMask & SPAN_MASK) {
/* note: using & intead of && to reduce branches */
for (i = 0; i < n; i++) {
mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
& (y[i] >= ymin) & (y[i] < ymax);
+ passed += mask[i];
}
}
else {
for (i = 0; i < n; i++) {
mask[i] = (x[i] >= xmin) & (x[i] < xmax)
& (y[i] >= ymin) & (y[i] < ymax);
+ passed += mask[i];
}
}
- return GL_TRUE; /* some pixels visible */
+ return passed > 0;
}
else {
/* horizontal span of pixels */
* fragment attributes.
* For arrays of values, shift them left.
*/
- for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
+ for (i = 0; i < VARYING_SLOT_MAX; i++) {
if (span->interpMask & (1 << i)) {
GLuint j;
for (j = 0; j < 4; j++) {
span->intTex[1] += leftClip * span->intTexStep[1];
#define SHIFT_ARRAY(ARRAY, SHIFT, LEN) \
- memcpy(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0]))
+ memmove(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0]))
- for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
+ for (i = 0; i < VARYING_SLOT_MAX; i++) {
if (span->arrayAttribs & (1 << i)) {
/* shift array elements left by 'leftClip' */
SHIFT_ARRAY(span->array->attribs[i], leftClip, n - leftClip);
/**
* Add specular colors to primary colors.
* Only called during fixed-function operation.
- * Result is float color array (FRAG_ATTRIB_COL0).
+ * Result is float color array (VARYING_SLOT_COL0).
*/
-static INLINE void
+static inline void
add_specular(struct gl_context *ctx, SWspan *span)
{
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLubyte *mask = span->array->mask;
- GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
- GLfloat (*col1)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
+ GLfloat (*col0)[4] = span->array->attribs[VARYING_SLOT_COL0];
+ GLfloat (*col1)[4] = span->array->attribs[VARYING_SLOT_COL1];
GLuint i;
- ASSERT(!ctx->FragmentProgram._Current);
+ ASSERT(!_swrast_use_fragment_program(ctx));
ASSERT(span->arrayMask & SPAN_RGBA);
- ASSERT(swrast->_ActiveAttribMask & FRAG_BIT_COL1);
+ ASSERT(swrast->_ActiveAttribMask & VARYING_BIT_COL1);
(void) swrast; /* silence warning */
if (span->array->ChanType == GL_FLOAT) {
- if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
- interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
+ if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
+ interpolate_active_attribs(ctx, span, VARYING_BIT_COL0);
}
}
else {
/* need float colors */
- if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
+ if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
interpolate_float_colors(span);
}
}
- if ((span->arrayAttribs & FRAG_BIT_COL1) == 0) {
+ if ((span->arrayAttribs & VARYING_BIT_COL1) == 0) {
/* XXX could avoid this and interpolate COL1 in the loop below */
- interpolate_active_attribs(ctx, span, FRAG_BIT_COL1);
+ interpolate_active_attribs(ctx, span, VARYING_BIT_COL1);
}
- ASSERT(span->arrayAttribs & FRAG_BIT_COL0);
- ASSERT(span->arrayAttribs & FRAG_BIT_COL1);
+ ASSERT(span->arrayAttribs & VARYING_BIT_COL0);
+ ASSERT(span->arrayAttribs & VARYING_BIT_COL1);
for (i = 0; i < span->end; i++) {
if (mask[i]) {
/**
* Apply antialiasing coverage value to alpha values.
*/
-static INLINE void
+static inline void
apply_aa_coverage(SWspan *span)
{
const GLfloat *coverage = span->array->coverage;
}
}
else {
- GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
for (i = 0; i < span->end; i++) {
rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
/* clamp later */
/**
* Clamp span's float colors to [0,1]
*/
-static INLINE void
+static inline void
clamp_colors(SWspan *span)
{
- GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
GLuint i;
ASSERT(span->array->ChanType == GL_FLOAT);
for (i = 0; i < span->end; i++) {
* program that writes to gl_FragData[1] or higher.
* \param output which fragment program color output is being processed
*/
-static INLINE void
+static inline void
convert_color_type(SWspan *span, GLenum newType, GLuint output)
{
GLvoid *src, *dst;
if (output > 0 || span->array->ChanType == GL_FLOAT) {
- src = span->array->attribs[FRAG_ATTRIB_COL0 + output];
+ src = span->array->attribs[VARYING_SLOT_COL0 + output];
span->array->ChanType = GL_FLOAT;
}
else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
dst = span->array->rgba16;
}
else {
- dst = span->array->attribs[FRAG_ATTRIB_COL0];
+ dst = span->array->attribs[VARYING_SLOT_COL0];
}
_mesa_convert_colors(span->array->ChanType, src,
/**
* Apply fragment shader, fragment program or normal texturing to span.
*/
-static INLINE void
+static inline void
shade_texture_span(struct gl_context *ctx, SWspan *span)
{
- GLbitfield inputsRead;
-
- /* Determine which fragment attributes are actually needed */
- if (ctx->FragmentProgram._Current) {
- inputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
- }
- else {
- /* XXX we could be a bit smarter about this */
- inputsRead = ~0;
- }
-
- if (ctx->FragmentProgram._Current ||
+ if (_swrast_use_fragment_program(ctx) ||
ctx->ATIFragmentShader._Enabled) {
/* programmable shading */
if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) {
convert_color_type(span, GL_FLOAT, 0);
}
else {
- span->array->rgba = (void *) span->array->attribs[FRAG_ATTRIB_COL0];
+ span->array->rgba = (void *) span->array->attribs[VARYING_SLOT_COL0];
}
if (span->primitive != GL_POINT ||
_swrast_span_interpolate_z (ctx, span);
#if 0
- if (inputsRead & FRAG_BIT_WPOS)
+ if (inputsRead & VARYING_BIT_POS)
#else
/* XXX always interpolate wpos so that DDX/DDY work */
#endif
interpolate_wpos(ctx, span);
/* Run fragment program/shader now */
- if (ctx->FragmentProgram._Current) {
+ if (_swrast_use_fragment_program(ctx)) {
_swrast_exec_fragment_program(ctx, span);
}
else {
/* conventional texturing */
#if CHAN_BITS == 32
- if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
+ if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
interpolate_int_colors(ctx, span);
}
#else
if (!(span->arrayMask & SPAN_RGBA))
interpolate_int_colors(ctx, span);
#endif
- if ((span->arrayAttribs & FRAG_BITS_TEX_ANY) == 0x0)
+ if ((span->arrayAttribs & VARYING_BITS_TEX_ANY) == 0x0)
interpolate_texcoords(ctx, span);
_swrast_texture_span(ctx, span);
}
+/** Put colors at x/y locations into a renderbuffer */
+static void
+put_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLenum datatype,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *values, const GLubyte *mask)
+{
+ gl_pack_ubyte_rgba_func pack_ubyte = NULL;
+ gl_pack_float_rgba_func pack_float = NULL;
+ GLuint i;
+
+ if (datatype == GL_UNSIGNED_BYTE)
+ pack_ubyte = _mesa_get_pack_ubyte_rgba_function(rb->Format);
+ else
+ pack_float = _mesa_get_pack_float_rgba_function(rb->Format);
+
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]);
+
+ if (datatype == GL_UNSIGNED_BYTE) {
+ pack_ubyte((const GLubyte *) values + 4 * i, dst);
+ }
+ else {
+ assert(datatype == GL_FLOAT);
+ pack_float((const GLfloat *) values + 4 * i, dst);
+ }
+ }
+ }
+}
+
+
+/** Put row of colors into renderbuffer */
+void
+_swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLenum datatype,
+ GLuint count, GLint x, GLint y,
+ const void *values, const GLubyte *mask)
+{
+ GLubyte *dst = _swrast_pixel_address(rb, x, y);
+
+ if (!mask) {
+ if (datatype == GL_UNSIGNED_BYTE) {
+ _mesa_pack_ubyte_rgba_row(rb->Format, count,
+ (const GLubyte (*)[4]) values, dst);
+ }
+ else {
+ assert(datatype == GL_FLOAT);
+ _mesa_pack_float_rgba_row(rb->Format, count,
+ (const GLfloat (*)[4]) values, dst);
+ }
+ }
+ else {
+ const GLuint bpp = _mesa_get_format_bytes(rb->Format);
+ GLuint i, runLen, runStart;
+ /* We can't pass a 'mask' array to the _mesa_pack_rgba_row() functions
+ * so look for runs where mask=1...
+ */
+ runLen = runStart = 0;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ if (runLen == 0)
+ runStart = i;
+ runLen++;
+ }
+
+ if (!mask[i] || i == count - 1) {
+ /* might be the end of a run of pixels */
+ if (runLen > 0) {
+ if (datatype == GL_UNSIGNED_BYTE) {
+ _mesa_pack_ubyte_rgba_row(rb->Format, runLen,
+ (const GLubyte (*)[4]) values + runStart,
+ dst + runStart * bpp);
+ }
+ else {
+ assert(datatype == GL_FLOAT);
+ _mesa_pack_float_rgba_row(rb->Format, runLen,
+ (const GLfloat (*)[4]) values + runStart,
+ dst + runStart * bpp);
+ }
+ runLen = 0;
+ }
+ }
+ }
+ }
+}
+
+
/**
* Apply all the per-fragment operations to a span.
const GLuint *colorMask = (GLuint *) ctx->Color.ColorMask;
const GLbitfield origInterpMask = span->interpMask;
const GLbitfield origArrayMask = span->arrayMask;
- const GLbitfield origArrayAttribs = span->arrayAttribs;
+ const GLbitfield64 origArrayAttribs = span->arrayAttribs;
const GLenum origChanType = span->array->ChanType;
void * const origRgba = span->array->rgba;
- const GLboolean shader = (ctx->FragmentProgram._Current
+ const GLboolean shader = (_swrast_use_fragment_program(ctx)
|| ctx->ATIFragmentShader._Enabled);
const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledCoordUnits;
struct gl_framebuffer *fb = ctx->DrawBuffer;
return;
}
- ASSERT(span->end <= MAX_WIDTH);
+ ASSERT(span->end <= SWRAST_MAX_WIDTH);
/* Depth bounds test */
if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
}
#if CHAN_BITS == 32
- if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
- interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
+ if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
+ interpolate_active_attribs(ctx, span, VARYING_BIT_COL0);
}
#else
if ((span->arrayMask & SPAN_RGBA) == 0) {
const GLuint numBuffers = fb->_NumColorDrawBuffers;
const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
const GLboolean multiFragOutputs =
- (fp && fp->Base.OutputsWritten >= (1 << FRAG_RESULT_DATA0));
+ _swrast_use_fragment_program(ctx)
+ && fp->Base.OutputsWritten >= (1 << FRAG_RESULT_DATA0);
GLuint buf;
for (buf = 0; buf < numBuffers; buf++) {
/* color[fragOutput] will be written to buffer[buf] */
if (rb) {
- GLchan rgbaSave[MAX_WIDTH][4];
- const GLuint fragOutput = multiFragOutputs ? buf : 0;
+ /* re-use one of the attribute array buffers for rgbaSave */
+ GLchan (*rgbaSave)[4] = (GLchan (*)[4]) span->array->attribs[0];
+ struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
+ GLenum colorType = srb->ColorType;
+
+ assert(colorType == GL_UNSIGNED_BYTE ||
+ colorType == GL_FLOAT);
- /* set span->array->rgba to colors for render buffer's datatype */
- if (rb->DataType != span->array->ChanType || fragOutput > 0) {
- convert_color_type(span, rb->DataType, fragOutput);
+ /* set span->array->rgba to colors for renderbuffer's datatype */
+ if (span->array->ChanType != colorType) {
+ convert_color_type(span, colorType, 0);
}
else {
- if (rb->DataType == GL_UNSIGNED_BYTE) {
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
span->array->rgba = span->array->rgba8;
}
- else if (rb->DataType == GL_UNSIGNED_SHORT) {
- span->array->rgba = (void *) span->array->rgba16;
- }
else {
span->array->rgba = (void *)
- span->array->attribs[FRAG_ATTRIB_COL0];
+ span->array->attribs[VARYING_SLOT_COL0];
}
}
4 * span->end * sizeof(GLchan));
}
- ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB ||
+ ASSERT(rb->_BaseFormat == GL_RGBA ||
+ rb->_BaseFormat == GL_RGB ||
+ rb->_BaseFormat == GL_RED ||
+ rb->_BaseFormat == GL_RG ||
rb->_BaseFormat == GL_ALPHA);
- if (ctx->Color._LogicOpEnabled) {
+ if (ctx->Color.ColorLogicOpEnabled) {
_swrast_logicop_rgba_span(ctx, rb, span);
}
else if ((ctx->Color.BlendEnabled >> buf) & 1) {
if (span->arrayMask & SPAN_XY) {
/* array of pixel coords */
- ASSERT(rb->PutValues);
- rb->PutValues(ctx, rb, span->end,
- span->array->x, span->array->y,
- span->array->rgba, span->array->mask);
+ put_values(ctx, rb,
+ span->array->ChanType, span->end,
+ span->array->x, span->array->y,
+ span->array->rgba, span->array->mask);
}
else {
/* horizontal run of pixels */
- ASSERT(rb->PutRow);
- rb->PutRow(ctx, rb, span->end, span->x, span->y,
- span->array->rgba,
- span->writeAll ? NULL: span->array->mask);
+ _swrast_put_row(ctx, rb,
+ span->array->ChanType,
+ span->end, span->x, span->y,
+ span->array->rgba,
+ span->writeAll ? NULL: span->array->mask);
}
if (!multiFragOutputs && numBuffers > 1) {
/**
- * Read RGBA pixels from a renderbuffer. Clipping will be done to prevent
- * reading ouside the buffer's boundaries.
- * \param dstType datatype for returned colors
+ * Read float RGBA pixels from a renderbuffer. Clipping will be done to
+ * prevent reading ouside the buffer's boundaries.
* \param rgba the returned colors
*/
void
_swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y, GLenum dstType,
+ GLuint n, GLint x, GLint y,
GLvoid *rgba)
{
+ struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
+ GLenum dstType = GL_FLOAT;
const GLint bufWidth = (GLint) rb->Width;
const GLint bufHeight = (GLint) rb->Height;
}
else {
GLint skip, length;
+ GLubyte *src;
+
if (x < 0) {
/* left edge clipping */
skip = -x;
}
ASSERT(rb);
- ASSERT(rb->GetRow);
ASSERT(rb->_BaseFormat == GL_RGBA ||
rb->_BaseFormat == GL_RGB ||
rb->_BaseFormat == GL_RG ||
rb->_BaseFormat == GL_LUMINANCE_ALPHA ||
rb->_BaseFormat == GL_ALPHA);
- if (rb->DataType == dstType) {
- rb->GetRow(ctx, rb, length, x + skip, y,
- (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
+ assert(srb->Map);
+
+ src = _swrast_pixel_address(rb, x + skip, y);
+
+ if (dstType == GL_UNSIGNED_BYTE) {
+ _mesa_unpack_ubyte_rgba_row(rb->Format, length, src,
+ (GLubyte (*)[4]) rgba + skip);
+ }
+ else if (dstType == GL_FLOAT) {
+ _mesa_unpack_rgba_row(rb->Format, length, src,
+ (GLfloat (*)[4]) rgba + skip);
}
else {
- GLuint temp[MAX_WIDTH * 4];
- rb->GetRow(ctx, rb, length, x + skip, y, temp);
- _mesa_convert_colors(rb->DataType, temp,
- dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
- length, NULL);
+ _mesa_problem(ctx, "unexpected type in _swrast_read_rgba_span()");
}
}
}
/**
- * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
- * reading values outside the buffer bounds.
- * We can use this for reading any format/type of renderbuffer.
- * \param valueSize is the size in bytes of each value (pixel) put into the
- * values array.
+ * Get colors at x/y positions with clipping.
+ * \param type type of values to return
*/
-void
-_swrast_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, const GLint x[], const GLint y[],
- void *values, GLuint valueSize)
+static void
+get_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ void *values, GLenum type)
{
- GLuint i, inCount = 0, inStart = 0;
+ GLuint i;
for (i = 0; i < count; i++) {
if (x[i] >= 0 && y[i] >= 0 &&
x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
/* inside */
- if (inCount == 0)
- inStart = i;
- inCount++;
- }
- else {
- if (inCount > 0) {
- /* read [inStart, inStart + inCount) */
- rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
- (GLubyte *) values + inStart * valueSize);
- inCount = 0;
+ const GLubyte *src = _swrast_pixel_address(rb, x[i], y[i]);
+
+ if (type == GL_UNSIGNED_BYTE) {
+ _mesa_unpack_ubyte_rgba_row(rb->Format, 1, src,
+ (GLubyte (*)[4]) values + i);
+ }
+ else if (type == GL_FLOAT) {
+ _mesa_unpack_rgba_row(rb->Format, 1, src,
+ (GLfloat (*)[4]) values + i);
+ }
+ else {
+ _mesa_problem(ctx, "unexpected type in get_values()");
}
}
}
- if (inCount > 0) {
- /* read last values */
- rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
- (GLubyte *) values + inStart * valueSize);
- }
}
/**
- * Wrapper for gl_renderbuffer::PutRow() which does clipping.
- * \param valueSize size of each value (pixel) in bytes
+ * Get row of colors with clipping.
+ * \param type type of values to return
*/
-void
-_swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, GLint x, GLint y,
- const GLvoid *values, GLuint valueSize)
+static void
+get_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ GLvoid *values, GLenum type)
{
GLint skip = 0;
+ GLubyte *src;
if (y < 0 || y >= (GLint) rb->Height)
return; /* above or below */
if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
return; /* entirely left or right */
- if ((GLint) (x + count) > (GLint) rb->Width) {
+ if (x + count > rb->Width) {
/* right clip */
GLint clip = x + count - rb->Width;
count -= clip;
count -= skip;
}
- rb->PutRow(ctx, rb, count, x, y,
- (const GLubyte *) values + skip * valueSize, NULL);
-}
-
-
-/**
- * Wrapper for gl_renderbuffer::GetRow() which does clipping.
- * \param valueSize size of each value (pixel) in bytes
- */
-void
-_swrast_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
- GLuint count, GLint x, GLint y,
- GLvoid *values, GLuint valueSize)
-{
- GLint skip = 0;
-
- if (y < 0 || y >= (GLint) rb->Height)
- return; /* above or below */
-
- if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
- return; /* entirely left or right */
+ src = _swrast_pixel_address(rb, x, y);
- if (x + count > rb->Width) {
- /* right clip */
- GLint clip = x + count - rb->Width;
- count -= clip;
+ if (type == GL_UNSIGNED_BYTE) {
+ _mesa_unpack_ubyte_rgba_row(rb->Format, count, src,
+ (GLubyte (*)[4]) values + skip);
}
-
- if (x < 0) {
- /* left clip */
- skip = -x;
- x = 0;
- count -= skip;
+ else if (type == GL_FLOAT) {
+ _mesa_unpack_rgba_row(rb->Format, count, src,
+ (GLfloat (*)[4]) values + skip);
+ }
+ else {
+ _mesa_problem(ctx, "unexpected type in get_row()");
}
-
- rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
}
_swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb,
SWspan *span)
{
- const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
void *rbPixels;
/* Point rbPixels to a temporary space */
- rbPixels = span->array->attribs[FRAG_ATTRIB_MAX - 1];
+ rbPixels = span->array->attribs[VARYING_SLOT_MAX - 1];
/* Get destination values from renderbuffer */
if (span->arrayMask & SPAN_XY) {
- _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
- rbPixels, pixelSize);
+ get_values(ctx, rb, span->end, span->array->x, span->array->y,
+ rbPixels, span->array->ChanType);
}
else {
- _swrast_get_row(ctx, rb, span->end, span->x, span->y,
- rbPixels, pixelSize);
+ get_row(ctx, rb, span->end, span->x, span->y,
+ rbPixels, span->array->ChanType);
}
return rbPixels;