1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg 26848b8605Smrg/* 27848b8605Smrg * When the device driver doesn't implement triangle rasterization it 28848b8605Smrg * can hook in _swrast_Triangle, which eventually calls one of these 29848b8605Smrg * functions to draw triangles. 30848b8605Smrg */ 31848b8605Smrg 32848b8605Smrg#include "main/glheader.h" 33848b8605Smrg#include "main/context.h" 34848b8605Smrg#include "main/imports.h" 35848b8605Smrg#include "main/macros.h" 36848b8605Smrg#include "main/mtypes.h" 37848b8605Smrg#include "main/state.h" 38848b8605Smrg#include "main/samplerobj.h" 39b8e80941Smrg#include "main/stencil.h" 40b8e80941Smrg#include "main/teximage.h" 41848b8605Smrg#include "program/prog_instruction.h" 42848b8605Smrg 43848b8605Smrg#include "s_aatriangle.h" 44848b8605Smrg#include "s_context.h" 45848b8605Smrg#include "s_feedback.h" 46848b8605Smrg#include "s_span.h" 47848b8605Smrg#include "s_triangle.h" 48848b8605Smrg 49848b8605Smrg 50848b8605Smrg/** 51848b8605Smrg * Test if a triangle should be culled. Used for feedback and selection mode. 52848b8605Smrg * \return GL_TRUE if the triangle is to be culled, GL_FALSE otherwise. 53848b8605Smrg */ 54848b8605SmrgGLboolean 55848b8605Smrg_swrast_culltriangle( struct gl_context *ctx, 56848b8605Smrg const SWvertex *v0, 57848b8605Smrg const SWvertex *v1, 58848b8605Smrg const SWvertex *v2 ) 59848b8605Smrg{ 60848b8605Smrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 61848b8605Smrg GLfloat ex = v1->attrib[VARYING_SLOT_POS][0] - v0->attrib[VARYING_SLOT_POS][0]; 62848b8605Smrg GLfloat ey = v1->attrib[VARYING_SLOT_POS][1] - v0->attrib[VARYING_SLOT_POS][1]; 63848b8605Smrg GLfloat fx = v2->attrib[VARYING_SLOT_POS][0] - v0->attrib[VARYING_SLOT_POS][0]; 64848b8605Smrg GLfloat fy = v2->attrib[VARYING_SLOT_POS][1] - v0->attrib[VARYING_SLOT_POS][1]; 65848b8605Smrg GLfloat c = ex*fy-ey*fx; 66848b8605Smrg 67848b8605Smrg if (c * swrast->_BackfaceSign * swrast->_BackfaceCullSign <= 0.0F) 68848b8605Smrg return GL_FALSE; 69848b8605Smrg 70848b8605Smrg return GL_TRUE; 71848b8605Smrg} 72848b8605Smrg 73848b8605Smrg 74848b8605Smrg 75848b8605Smrg/* 76848b8605Smrg * Render a flat-shaded RGBA triangle. 77848b8605Smrg */ 78848b8605Smrg#define NAME flat_rgba_triangle 79848b8605Smrg#define INTERP_Z 1 80848b8605Smrg#define SETUP_CODE \ 81b8e80941Smrg assert(ctx->Texture._EnabledCoordUnits == 0);\ 82b8e80941Smrg assert(ctx->Light.ShadeModel==GL_FLAT); \ 83848b8605Smrg span.interpMask |= SPAN_RGBA; \ 84848b8605Smrg span.red = ChanToFixed(v2->color[0]); \ 85848b8605Smrg span.green = ChanToFixed(v2->color[1]); \ 86848b8605Smrg span.blue = ChanToFixed(v2->color[2]); \ 87848b8605Smrg span.alpha = ChanToFixed(v2->color[3]); \ 88848b8605Smrg span.redStep = 0; \ 89848b8605Smrg span.greenStep = 0; \ 90848b8605Smrg span.blueStep = 0; \ 91848b8605Smrg span.alphaStep = 0; 92848b8605Smrg#define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span); 93848b8605Smrg#include "s_tritemp.h" 94848b8605Smrg 95848b8605Smrg 96848b8605Smrg 97848b8605Smrg/* 98848b8605Smrg * Render a smooth-shaded RGBA triangle. 99848b8605Smrg */ 100848b8605Smrg#define NAME smooth_rgba_triangle 101848b8605Smrg#define INTERP_Z 1 102848b8605Smrg#define INTERP_RGB 1 103848b8605Smrg#define INTERP_ALPHA 1 104848b8605Smrg#define SETUP_CODE \ 105848b8605Smrg { \ 106848b8605Smrg /* texturing must be off */ \ 107b8e80941Smrg assert(ctx->Texture._EnabledCoordUnits == 0); \ 108b8e80941Smrg assert(ctx->Light.ShadeModel==GL_SMOOTH); \ 109848b8605Smrg } 110848b8605Smrg#define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span); 111848b8605Smrg#include "s_tritemp.h" 112848b8605Smrg 113848b8605Smrg 114848b8605Smrg 115848b8605Smrg/* 116848b8605Smrg * Render an RGB, GL_DECAL, textured triangle. 117848b8605Smrg * Interpolate S,T only w/out mipmapping or perspective correction. 118848b8605Smrg * 119848b8605Smrg * No fog. No depth testing. 120848b8605Smrg */ 121848b8605Smrg#define NAME simple_textured_triangle 122848b8605Smrg#define INTERP_INT_TEX 1 123848b8605Smrg#define S_SCALE twidth 124848b8605Smrg#define T_SCALE theight 125848b8605Smrg 126848b8605Smrg#define SETUP_CODE \ 127848b8605Smrg struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; \ 128848b8605Smrg const struct gl_texture_object *obj = \ 129848b8605Smrg ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ 130848b8605Smrg const struct gl_texture_image *texImg = \ 131b8e80941Smrg _mesa_base_tex_image(obj); \ 132848b8605Smrg const struct swrast_texture_image *swImg = \ 133848b8605Smrg swrast_texture_image_const(texImg); \ 134848b8605Smrg const GLfloat twidth = (GLfloat) texImg->Width; \ 135848b8605Smrg const GLfloat theight = (GLfloat) texImg->Height; \ 136848b8605Smrg const GLint twidth_log2 = texImg->WidthLog2; \ 137848b8605Smrg const GLubyte *texture = (const GLubyte *) swImg->ImageSlices[0]; \ 138848b8605Smrg const GLint smask = texImg->Width - 1; \ 139848b8605Smrg const GLint tmask = texImg->Height - 1; \ 140b8e80941Smrg assert(texImg->TexFormat == MESA_FORMAT_BGR_UNORM8); \ 141848b8605Smrg if (!rb || !texture) { \ 142848b8605Smrg return; \ 143848b8605Smrg } 144848b8605Smrg 145848b8605Smrg#define RENDER_SPAN( span ) \ 146848b8605Smrg GLuint i; \ 147848b8605Smrg GLubyte (*rgba)[4] = swrast->SpanArrays->rgba8; \ 148848b8605Smrg span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ 149848b8605Smrg span.intTex[1] -= FIXED_HALF; \ 150848b8605Smrg for (i = 0; i < span.end; i++) { \ 151848b8605Smrg GLint s = FixedToInt(span.intTex[0]) & smask; \ 152848b8605Smrg GLint t = FixedToInt(span.intTex[1]) & tmask; \ 153848b8605Smrg GLint pos = (t << twidth_log2) + s; \ 154848b8605Smrg pos = pos + pos + pos; /* multiply by 3 */ \ 155848b8605Smrg rgba[i][RCOMP] = texture[pos+2]; \ 156848b8605Smrg rgba[i][GCOMP] = texture[pos+1]; \ 157848b8605Smrg rgba[i][BCOMP] = texture[pos+0]; \ 158848b8605Smrg rgba[i][ACOMP] = 0xff; \ 159848b8605Smrg span.intTex[0] += span.intTexStep[0]; \ 160848b8605Smrg span.intTex[1] += span.intTexStep[1]; \ 161848b8605Smrg } \ 162848b8605Smrg _swrast_put_row(ctx, rb, GL_UNSIGNED_BYTE, span.end, \ 163848b8605Smrg span.x, span.y, rgba, NULL); 164848b8605Smrg 165848b8605Smrg#include "s_tritemp.h" 166848b8605Smrg 167848b8605Smrg 168848b8605Smrg 169848b8605Smrg/* 170848b8605Smrg * Render an RGB, GL_DECAL, textured triangle. 171848b8605Smrg * Interpolate S,T, GL_LESS depth test, w/out mipmapping or 172848b8605Smrg * perspective correction. 173848b8605Smrg * Depth buffer bits must be <= sizeof(DEFAULT_SOFTWARE_DEPTH_TYPE) 174848b8605Smrg * 175848b8605Smrg * No fog. 176848b8605Smrg */ 177848b8605Smrg#define NAME simple_z_textured_triangle 178848b8605Smrg#define INTERP_Z 1 179848b8605Smrg#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 180848b8605Smrg#define INTERP_INT_TEX 1 181848b8605Smrg#define S_SCALE twidth 182848b8605Smrg#define T_SCALE theight 183848b8605Smrg 184848b8605Smrg#define SETUP_CODE \ 185848b8605Smrg struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; \ 186848b8605Smrg const struct gl_texture_object *obj = \ 187848b8605Smrg ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ 188848b8605Smrg const struct gl_texture_image *texImg = \ 189b8e80941Smrg _mesa_base_tex_image(obj); \ 190848b8605Smrg const struct swrast_texture_image *swImg = \ 191848b8605Smrg swrast_texture_image_const(texImg); \ 192848b8605Smrg const GLfloat twidth = (GLfloat) texImg->Width; \ 193848b8605Smrg const GLfloat theight = (GLfloat) texImg->Height; \ 194848b8605Smrg const GLint twidth_log2 = texImg->WidthLog2; \ 195848b8605Smrg const GLubyte *texture = (const GLubyte *) swImg->ImageSlices[0]; \ 196848b8605Smrg const GLint smask = texImg->Width - 1; \ 197848b8605Smrg const GLint tmask = texImg->Height - 1; \ 198b8e80941Smrg assert(texImg->TexFormat == MESA_FORMAT_BGR_UNORM8); \ 199848b8605Smrg if (!rb || !texture) { \ 200848b8605Smrg return; \ 201848b8605Smrg } 202848b8605Smrg 203848b8605Smrg#define RENDER_SPAN( span ) \ 204848b8605Smrg GLuint i; \ 205848b8605Smrg GLubyte (*rgba)[4] = swrast->SpanArrays->rgba8; \ 206848b8605Smrg GLubyte *mask = swrast->SpanArrays->mask; \ 207848b8605Smrg span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ 208848b8605Smrg span.intTex[1] -= FIXED_HALF; \ 209848b8605Smrg for (i = 0; i < span.end; i++) { \ 210848b8605Smrg const GLuint z = FixedToDepth(span.z); \ 211848b8605Smrg if (z < zRow[i]) { \ 212848b8605Smrg GLint s = FixedToInt(span.intTex[0]) & smask; \ 213848b8605Smrg GLint t = FixedToInt(span.intTex[1]) & tmask; \ 214848b8605Smrg GLint pos = (t << twidth_log2) + s; \ 215848b8605Smrg pos = pos + pos + pos; /* multiply by 3 */ \ 216848b8605Smrg rgba[i][RCOMP] = texture[pos+2]; \ 217848b8605Smrg rgba[i][GCOMP] = texture[pos+1]; \ 218848b8605Smrg rgba[i][BCOMP] = texture[pos+0]; \ 219848b8605Smrg rgba[i][ACOMP] = 0xff; \ 220848b8605Smrg zRow[i] = z; \ 221848b8605Smrg mask[i] = 1; \ 222848b8605Smrg } \ 223848b8605Smrg else { \ 224848b8605Smrg mask[i] = 0; \ 225848b8605Smrg } \ 226848b8605Smrg span.intTex[0] += span.intTexStep[0]; \ 227848b8605Smrg span.intTex[1] += span.intTexStep[1]; \ 228848b8605Smrg span.z += span.zStep; \ 229848b8605Smrg } \ 230848b8605Smrg _swrast_put_row(ctx, rb, GL_UNSIGNED_BYTE, \ 231848b8605Smrg span.end, span.x, span.y, rgba, mask); 232848b8605Smrg 233848b8605Smrg#include "s_tritemp.h" 234848b8605Smrg 235848b8605Smrg 236848b8605Smrg#if CHAN_TYPE != GL_FLOAT 237848b8605Smrg 238848b8605Smrgstruct affine_info 239848b8605Smrg{ 240848b8605Smrg GLenum filter; 241848b8605Smrg GLenum format; 242848b8605Smrg GLenum envmode; 243848b8605Smrg GLint smask, tmask; 244848b8605Smrg GLint twidth_log2; 245848b8605Smrg const GLchan *texture; 246848b8605Smrg GLfixed er, eg, eb, ea; 247848b8605Smrg GLint tbytesline, tsize; 248848b8605Smrg}; 249848b8605Smrg 250848b8605Smrg 251848b8605Smrgstatic inline GLint 252848b8605Smrgilerp(GLint t, GLint a, GLint b) 253848b8605Smrg{ 254848b8605Smrg return a + ((t * (b - a)) >> FIXED_SHIFT); 255848b8605Smrg} 256848b8605Smrg 257848b8605Smrgstatic inline GLint 258848b8605Smrgilerp_2d(GLint ia, GLint ib, GLint v00, GLint v10, GLint v01, GLint v11) 259848b8605Smrg{ 260848b8605Smrg const GLint temp0 = ilerp(ia, v00, v10); 261848b8605Smrg const GLint temp1 = ilerp(ia, v01, v11); 262848b8605Smrg return ilerp(ib, temp0, temp1); 263848b8605Smrg} 264848b8605Smrg 265848b8605Smrg 266848b8605Smrg/* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA 267848b8605Smrg * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD 268848b8605Smrg * texture env modes. 269848b8605Smrg */ 270848b8605Smrgstatic inline void 271848b8605Smrgaffine_span(struct gl_context *ctx, SWspan *span, 272848b8605Smrg struct affine_info *info) 273848b8605Smrg{ 274848b8605Smrg GLchan sample[4]; /* the filtered texture sample */ 275848b8605Smrg const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits; 276848b8605Smrg 277848b8605Smrg /* Instead of defining a function for each mode, a test is done 278848b8605Smrg * between the outer and inner loops. This is to reduce code size 279848b8605Smrg * and complexity. Observe that an optimizing compiler kills 280848b8605Smrg * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). 281848b8605Smrg */ 282848b8605Smrg 283848b8605Smrg#define NEAREST_RGB \ 284848b8605Smrg sample[RCOMP] = tex00[2]; \ 285848b8605Smrg sample[GCOMP] = tex00[1]; \ 286848b8605Smrg sample[BCOMP] = tex00[0]; \ 287848b8605Smrg sample[ACOMP] = CHAN_MAX; 288848b8605Smrg 289848b8605Smrg#define LINEAR_RGB \ 290848b8605Smrg sample[RCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\ 291848b8605Smrg sample[GCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\ 292848b8605Smrg sample[BCOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0]);\ 293848b8605Smrg sample[ACOMP] = CHAN_MAX; 294848b8605Smrg 295848b8605Smrg#define NEAREST_RGBA \ 296848b8605Smrg sample[RCOMP] = tex00[3]; \ 297848b8605Smrg sample[GCOMP] = tex00[2]; \ 298848b8605Smrg sample[BCOMP] = tex00[1]; \ 299848b8605Smrg sample[ACOMP] = tex00[0]; 300848b8605Smrg 301848b8605Smrg#define LINEAR_RGBA \ 302848b8605Smrg sample[RCOMP] = ilerp_2d(sf, tf, tex00[3], tex01[3], tex10[3], tex11[3]);\ 303848b8605Smrg sample[GCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\ 304848b8605Smrg sample[BCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\ 305848b8605Smrg sample[ACOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0]) 306848b8605Smrg 307848b8605Smrg#define MODULATE \ 308848b8605Smrg dest[RCOMP] = span->red * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 309848b8605Smrg dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 310848b8605Smrg dest[BCOMP] = span->blue * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 311848b8605Smrg dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8) 312848b8605Smrg 313848b8605Smrg#define DECAL \ 314848b8605Smrg dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red + \ 315848b8605Smrg ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT)) \ 316848b8605Smrg >> (FIXED_SHIFT + 8); \ 317848b8605Smrg dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green + \ 318848b8605Smrg ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT)) \ 319848b8605Smrg >> (FIXED_SHIFT + 8); \ 320848b8605Smrg dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue + \ 321848b8605Smrg ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT)) \ 322848b8605Smrg >> (FIXED_SHIFT + 8); \ 323848b8605Smrg dest[ACOMP] = FixedToInt(span->alpha) 324848b8605Smrg 325848b8605Smrg#define BLEND \ 326848b8605Smrg dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red \ 327848b8605Smrg + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8); \ 328848b8605Smrg dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green \ 329848b8605Smrg + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8); \ 330848b8605Smrg dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue \ 331848b8605Smrg + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8); \ 332848b8605Smrg dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8) 333848b8605Smrg 334848b8605Smrg#define REPLACE COPY_CHAN4(dest, sample) 335848b8605Smrg 336848b8605Smrg#define ADD \ 337848b8605Smrg { \ 338848b8605Smrg GLint rSum = FixedToInt(span->red) + (GLint) sample[RCOMP]; \ 339848b8605Smrg GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP]; \ 340848b8605Smrg GLint bSum = FixedToInt(span->blue) + (GLint) sample[BCOMP]; \ 341848b8605Smrg dest[RCOMP] = MIN2(rSum, CHAN_MAX); \ 342848b8605Smrg dest[GCOMP] = MIN2(gSum, CHAN_MAX); \ 343848b8605Smrg dest[BCOMP] = MIN2(bSum, CHAN_MAX); \ 344848b8605Smrg dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \ 345848b8605Smrg } 346848b8605Smrg 347848b8605Smrg/* shortcuts */ 348848b8605Smrg 349848b8605Smrg#define NEAREST_RGB_REPLACE \ 350848b8605Smrg NEAREST_RGB; \ 351848b8605Smrg dest[0] = sample[0]; \ 352848b8605Smrg dest[1] = sample[1]; \ 353848b8605Smrg dest[2] = sample[2]; \ 354848b8605Smrg dest[3] = FixedToInt(span->alpha); 355848b8605Smrg 356848b8605Smrg#define NEAREST_RGBA_REPLACE \ 357848b8605Smrg dest[RCOMP] = tex00[3]; \ 358848b8605Smrg dest[GCOMP] = tex00[2]; \ 359848b8605Smrg dest[BCOMP] = tex00[1]; \ 360848b8605Smrg dest[ACOMP] = tex00[0] 361848b8605Smrg 362848b8605Smrg#define SPAN_NEAREST(DO_TEX, COMPS) \ 363848b8605Smrg for (i = 0; i < span->end; i++) { \ 364848b8605Smrg /* Isn't it necessary to use FixedFloor below?? */ \ 365848b8605Smrg GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 366848b8605Smrg GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 367848b8605Smrg GLint pos = (t << info->twidth_log2) + s; \ 368848b8605Smrg const GLchan *tex00 = info->texture + COMPS * pos; \ 369848b8605Smrg DO_TEX; \ 370848b8605Smrg span->red += span->redStep; \ 371848b8605Smrg span->green += span->greenStep; \ 372848b8605Smrg span->blue += span->blueStep; \ 373848b8605Smrg span->alpha += span->alphaStep; \ 374848b8605Smrg span->intTex[0] += span->intTexStep[0]; \ 375848b8605Smrg span->intTex[1] += span->intTexStep[1]; \ 376848b8605Smrg dest += 4; \ 377848b8605Smrg } 378848b8605Smrg 379848b8605Smrg#define SPAN_LINEAR(DO_TEX, COMPS) \ 380848b8605Smrg for (i = 0; i < span->end; i++) { \ 381848b8605Smrg /* Isn't it necessary to use FixedFloor below?? */ \ 382848b8605Smrg const GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 383848b8605Smrg const GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 384848b8605Smrg const GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK; \ 385848b8605Smrg const GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK; \ 386848b8605Smrg const GLint pos = (t << info->twidth_log2) + s; \ 387848b8605Smrg const GLchan *tex00 = info->texture + COMPS * pos; \ 388848b8605Smrg const GLchan *tex10 = tex00 + info->tbytesline; \ 389848b8605Smrg const GLchan *tex01 = tex00 + COMPS; \ 390848b8605Smrg const GLchan *tex11 = tex10 + COMPS; \ 391848b8605Smrg if (t == info->tmask) { \ 392848b8605Smrg tex10 -= info->tsize; \ 393848b8605Smrg tex11 -= info->tsize; \ 394848b8605Smrg } \ 395848b8605Smrg if (s == info->smask) { \ 396848b8605Smrg tex01 -= info->tbytesline; \ 397848b8605Smrg tex11 -= info->tbytesline; \ 398848b8605Smrg } \ 399848b8605Smrg DO_TEX; \ 400848b8605Smrg span->red += span->redStep; \ 401848b8605Smrg span->green += span->greenStep; \ 402848b8605Smrg span->blue += span->blueStep; \ 403848b8605Smrg span->alpha += span->alphaStep; \ 404848b8605Smrg span->intTex[0] += span->intTexStep[0]; \ 405848b8605Smrg span->intTex[1] += span->intTexStep[1]; \ 406848b8605Smrg dest += 4; \ 407848b8605Smrg } 408848b8605Smrg 409848b8605Smrg 410848b8605Smrg GLuint i; 411848b8605Smrg GLchan *dest = span->array->rgba[0]; 412848b8605Smrg 413848b8605Smrg /* Disable tex units so they're not re-applied in swrast_write_rgba_span */ 414848b8605Smrg ctx->Texture._EnabledCoordUnits = 0x0; 415848b8605Smrg 416848b8605Smrg span->intTex[0] -= FIXED_HALF; 417848b8605Smrg span->intTex[1] -= FIXED_HALF; 418848b8605Smrg switch (info->filter) { 419848b8605Smrg case GL_NEAREST: 420848b8605Smrg switch (info->format) { 421848b8605Smrg case MESA_FORMAT_BGR_UNORM8: 422848b8605Smrg switch (info->envmode) { 423848b8605Smrg case GL_MODULATE: 424848b8605Smrg SPAN_NEAREST(NEAREST_RGB;MODULATE,3); 425848b8605Smrg break; 426848b8605Smrg case GL_DECAL: 427848b8605Smrg case GL_REPLACE: 428848b8605Smrg SPAN_NEAREST(NEAREST_RGB_REPLACE,3); 429848b8605Smrg break; 430848b8605Smrg case GL_BLEND: 431848b8605Smrg SPAN_NEAREST(NEAREST_RGB;BLEND,3); 432848b8605Smrg break; 433848b8605Smrg case GL_ADD: 434848b8605Smrg SPAN_NEAREST(NEAREST_RGB;ADD,3); 435848b8605Smrg break; 436848b8605Smrg default: 437848b8605Smrg _mesa_problem(ctx, "bad tex env mode in SPAN_LINEAR"); 438848b8605Smrg return; 439848b8605Smrg } 440848b8605Smrg break; 441848b8605Smrg case MESA_FORMAT_A8B8G8R8_UNORM: 442848b8605Smrg switch(info->envmode) { 443848b8605Smrg case GL_MODULATE: 444848b8605Smrg SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); 445848b8605Smrg break; 446848b8605Smrg case GL_DECAL: 447848b8605Smrg SPAN_NEAREST(NEAREST_RGBA;DECAL,4); 448848b8605Smrg break; 449848b8605Smrg case GL_BLEND: 450848b8605Smrg SPAN_NEAREST(NEAREST_RGBA;BLEND,4); 451848b8605Smrg break; 452848b8605Smrg case GL_ADD: 453848b8605Smrg SPAN_NEAREST(NEAREST_RGBA;ADD,4); 454848b8605Smrg break; 455848b8605Smrg case GL_REPLACE: 456848b8605Smrg SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); 457848b8605Smrg break; 458848b8605Smrg default: 459848b8605Smrg _mesa_problem(ctx, "bad tex env mode (2) in SPAN_LINEAR"); 460848b8605Smrg return; 461848b8605Smrg } 462848b8605Smrg break; 463848b8605Smrg } 464848b8605Smrg break; 465848b8605Smrg 466848b8605Smrg case GL_LINEAR: 467848b8605Smrg span->intTex[0] -= FIXED_HALF; 468848b8605Smrg span->intTex[1] -= FIXED_HALF; 469848b8605Smrg switch (info->format) { 470848b8605Smrg case MESA_FORMAT_BGR_UNORM8: 471848b8605Smrg switch (info->envmode) { 472848b8605Smrg case GL_MODULATE: 473848b8605Smrg SPAN_LINEAR(LINEAR_RGB;MODULATE,3); 474848b8605Smrg break; 475848b8605Smrg case GL_DECAL: 476848b8605Smrg case GL_REPLACE: 477848b8605Smrg SPAN_LINEAR(LINEAR_RGB;REPLACE,3); 478848b8605Smrg break; 479848b8605Smrg case GL_BLEND: 480848b8605Smrg SPAN_LINEAR(LINEAR_RGB;BLEND,3); 481848b8605Smrg break; 482848b8605Smrg case GL_ADD: 483848b8605Smrg SPAN_LINEAR(LINEAR_RGB;ADD,3); 484848b8605Smrg break; 485848b8605Smrg default: 486848b8605Smrg _mesa_problem(ctx, "bad tex env mode (3) in SPAN_LINEAR"); 487848b8605Smrg return; 488848b8605Smrg } 489848b8605Smrg break; 490848b8605Smrg case MESA_FORMAT_A8B8G8R8_UNORM: 491848b8605Smrg switch (info->envmode) { 492848b8605Smrg case GL_MODULATE: 493848b8605Smrg SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); 494848b8605Smrg break; 495848b8605Smrg case GL_DECAL: 496848b8605Smrg SPAN_LINEAR(LINEAR_RGBA;DECAL,4); 497848b8605Smrg break; 498848b8605Smrg case GL_BLEND: 499848b8605Smrg SPAN_LINEAR(LINEAR_RGBA;BLEND,4); 500848b8605Smrg break; 501848b8605Smrg case GL_ADD: 502848b8605Smrg SPAN_LINEAR(LINEAR_RGBA;ADD,4); 503848b8605Smrg break; 504848b8605Smrg case GL_REPLACE: 505848b8605Smrg SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); 506848b8605Smrg break; 507848b8605Smrg default: 508848b8605Smrg _mesa_problem(ctx, "bad tex env mode (4) in SPAN_LINEAR"); 509848b8605Smrg return; 510848b8605Smrg } 511848b8605Smrg break; 512848b8605Smrg } 513848b8605Smrg break; 514848b8605Smrg } 515848b8605Smrg span->interpMask &= ~SPAN_RGBA; 516b8e80941Smrg assert(span->arrayMask & SPAN_RGBA); 517848b8605Smrg 518848b8605Smrg _swrast_write_rgba_span(ctx, span); 519848b8605Smrg 520848b8605Smrg /* re-enable texture units */ 521848b8605Smrg ctx->Texture._EnabledCoordUnits = texEnableSave; 522848b8605Smrg 523848b8605Smrg#undef SPAN_NEAREST 524848b8605Smrg#undef SPAN_LINEAR 525848b8605Smrg} 526848b8605Smrg 527848b8605Smrg 528848b8605Smrg 529848b8605Smrg/* 530848b8605Smrg * Render an RGB/RGBA textured triangle without perspective correction. 531848b8605Smrg */ 532848b8605Smrg#define NAME affine_textured_triangle 533848b8605Smrg#define INTERP_Z 1 534848b8605Smrg#define INTERP_RGB 1 535848b8605Smrg#define INTERP_ALPHA 1 536848b8605Smrg#define INTERP_INT_TEX 1 537848b8605Smrg#define S_SCALE twidth 538848b8605Smrg#define T_SCALE theight 539848b8605Smrg 540848b8605Smrg#define SETUP_CODE \ 541848b8605Smrg struct affine_info info; \ 542b8e80941Smrg struct gl_fixedfunc_texture_unit *unit = ctx->Texture.FixedFuncUnit+0; \ 543848b8605Smrg const struct gl_texture_object *obj = \ 544848b8605Smrg ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ 545848b8605Smrg const struct gl_texture_image *texImg = \ 546b8e80941Smrg _mesa_base_tex_image(obj); \ 547848b8605Smrg const struct swrast_texture_image *swImg = \ 548848b8605Smrg swrast_texture_image_const(texImg); \ 549848b8605Smrg const GLfloat twidth = (GLfloat) texImg->Width; \ 550848b8605Smrg const GLfloat theight = (GLfloat) texImg->Height; \ 551848b8605Smrg info.texture = (const GLchan *) swImg->ImageSlices[0]; \ 552848b8605Smrg info.twidth_log2 = texImg->WidthLog2; \ 553848b8605Smrg info.smask = texImg->Width - 1; \ 554848b8605Smrg info.tmask = texImg->Height - 1; \ 555848b8605Smrg info.format = texImg->TexFormat; \ 556848b8605Smrg info.filter = obj->Sampler.MinFilter; \ 557848b8605Smrg info.envmode = unit->EnvMode; \ 558848b8605Smrg info.er = 0; \ 559848b8605Smrg info.eg = 0; \ 560848b8605Smrg info.eb = 0; \ 561848b8605Smrg span.arrayMask |= SPAN_RGBA; \ 562848b8605Smrg \ 563848b8605Smrg if (info.envmode == GL_BLEND) { \ 564848b8605Smrg /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 565848b8605Smrg info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \ 566848b8605Smrg info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \ 567848b8605Smrg info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \ 568848b8605Smrg info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \ 569848b8605Smrg } \ 570848b8605Smrg if (!info.texture) { \ 571848b8605Smrg /* this shouldn't happen */ \ 572848b8605Smrg return; \ 573848b8605Smrg } \ 574848b8605Smrg \ 575848b8605Smrg switch (info.format) { \ 576848b8605Smrg case MESA_FORMAT_BGR_UNORM8: \ 577848b8605Smrg info.tbytesline = texImg->Width * 3; \ 578848b8605Smrg break; \ 579848b8605Smrg case MESA_FORMAT_A8B8G8R8_UNORM: \ 580848b8605Smrg info.tbytesline = texImg->Width * 4; \ 581848b8605Smrg break; \ 582848b8605Smrg default: \ 583848b8605Smrg _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\ 584848b8605Smrg return; \ 585848b8605Smrg } \ 586848b8605Smrg info.tsize = texImg->Height * info.tbytesline; 587848b8605Smrg 588848b8605Smrg#define RENDER_SPAN( span ) affine_span(ctx, &span, &info); 589848b8605Smrg 590848b8605Smrg#include "s_tritemp.h" 591848b8605Smrg 592848b8605Smrg 593848b8605Smrg 594848b8605Smrgstruct persp_info 595848b8605Smrg{ 596848b8605Smrg GLenum filter; 597848b8605Smrg GLenum format; 598848b8605Smrg GLenum envmode; 599848b8605Smrg GLint smask, tmask; 600848b8605Smrg GLint twidth_log2; 601848b8605Smrg const GLchan *texture; 602848b8605Smrg GLfixed er, eg, eb, ea; /* texture env color */ 603848b8605Smrg GLint tbytesline, tsize; 604848b8605Smrg}; 605848b8605Smrg 606848b8605Smrg 607848b8605Smrgstatic inline void 608848b8605Smrgfast_persp_span(struct gl_context *ctx, SWspan *span, 609848b8605Smrg struct persp_info *info) 610848b8605Smrg{ 611848b8605Smrg GLchan sample[4]; /* the filtered texture sample */ 612848b8605Smrg 613848b8605Smrg /* Instead of defining a function for each mode, a test is done 614848b8605Smrg * between the outer and inner loops. This is to reduce code size 615848b8605Smrg * and complexity. Observe that an optimizing compiler kills 616848b8605Smrg * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). 617848b8605Smrg */ 618848b8605Smrg#define SPAN_NEAREST(DO_TEX,COMP) \ 619848b8605Smrg for (i = 0; i < span->end; i++) { \ 620848b8605Smrg GLdouble invQ = tex_coord[2] ? \ 621848b8605Smrg (1.0 / tex_coord[2]) : 1.0; \ 622848b8605Smrg GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ 623848b8605Smrg GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ 624848b8605Smrg GLint s = IFLOOR(s_tmp) & info->smask; \ 625848b8605Smrg GLint t = IFLOOR(t_tmp) & info->tmask; \ 626848b8605Smrg GLint pos = (t << info->twidth_log2) + s; \ 627848b8605Smrg const GLchan *tex00 = info->texture + COMP * pos; \ 628848b8605Smrg DO_TEX; \ 629848b8605Smrg span->red += span->redStep; \ 630848b8605Smrg span->green += span->greenStep; \ 631848b8605Smrg span->blue += span->blueStep; \ 632848b8605Smrg span->alpha += span->alphaStep; \ 633848b8605Smrg tex_coord[0] += tex_step[0]; \ 634848b8605Smrg tex_coord[1] += tex_step[1]; \ 635848b8605Smrg tex_coord[2] += tex_step[2]; \ 636848b8605Smrg dest += 4; \ 637848b8605Smrg } 638848b8605Smrg 639848b8605Smrg#define SPAN_LINEAR(DO_TEX,COMP) \ 640848b8605Smrg for (i = 0; i < span->end; i++) { \ 641848b8605Smrg GLdouble invQ = tex_coord[2] ? \ 642848b8605Smrg (1.0 / tex_coord[2]) : 1.0; \ 643848b8605Smrg const GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ 644848b8605Smrg const GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ 645848b8605Smrg const GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF; \ 646848b8605Smrg const GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF; \ 647848b8605Smrg const GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \ 648848b8605Smrg const GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \ 649848b8605Smrg const GLfixed sf = s_fix & FIXED_FRAC_MASK; \ 650848b8605Smrg const GLfixed tf = t_fix & FIXED_FRAC_MASK; \ 651848b8605Smrg const GLint pos = (t << info->twidth_log2) + s; \ 652848b8605Smrg const GLchan *tex00 = info->texture + COMP * pos; \ 653848b8605Smrg const GLchan *tex10 = tex00 + info->tbytesline; \ 654848b8605Smrg const GLchan *tex01 = tex00 + COMP; \ 655848b8605Smrg const GLchan *tex11 = tex10 + COMP; \ 656848b8605Smrg if (t == info->tmask) { \ 657848b8605Smrg tex10 -= info->tsize; \ 658848b8605Smrg tex11 -= info->tsize; \ 659848b8605Smrg } \ 660848b8605Smrg if (s == info->smask) { \ 661848b8605Smrg tex01 -= info->tbytesline; \ 662848b8605Smrg tex11 -= info->tbytesline; \ 663848b8605Smrg } \ 664848b8605Smrg DO_TEX; \ 665848b8605Smrg span->red += span->redStep; \ 666848b8605Smrg span->green += span->greenStep; \ 667848b8605Smrg span->blue += span->blueStep; \ 668848b8605Smrg span->alpha += span->alphaStep; \ 669848b8605Smrg tex_coord[0] += tex_step[0]; \ 670848b8605Smrg tex_coord[1] += tex_step[1]; \ 671848b8605Smrg tex_coord[2] += tex_step[2]; \ 672848b8605Smrg dest += 4; \ 673848b8605Smrg } 674848b8605Smrg 675848b8605Smrg GLuint i; 676848b8605Smrg GLfloat tex_coord[3], tex_step[3]; 677848b8605Smrg GLchan *dest = span->array->rgba[0]; 678848b8605Smrg 679848b8605Smrg const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits; 680848b8605Smrg ctx->Texture._EnabledCoordUnits = 0; 681848b8605Smrg 682848b8605Smrg tex_coord[0] = span->attrStart[VARYING_SLOT_TEX0][0] * (info->smask + 1); 683848b8605Smrg tex_step[0] = span->attrStepX[VARYING_SLOT_TEX0][0] * (info->smask + 1); 684848b8605Smrg tex_coord[1] = span->attrStart[VARYING_SLOT_TEX0][1] * (info->tmask + 1); 685848b8605Smrg tex_step[1] = span->attrStepX[VARYING_SLOT_TEX0][1] * (info->tmask + 1); 686848b8605Smrg /* span->attrStart[VARYING_SLOT_TEX0][2] only if 3D-texturing, here only 2D */ 687848b8605Smrg tex_coord[2] = span->attrStart[VARYING_SLOT_TEX0][3]; 688848b8605Smrg tex_step[2] = span->attrStepX[VARYING_SLOT_TEX0][3]; 689848b8605Smrg 690848b8605Smrg switch (info->filter) { 691848b8605Smrg case GL_NEAREST: 692848b8605Smrg switch (info->format) { 693848b8605Smrg case MESA_FORMAT_BGR_UNORM8: 694848b8605Smrg switch (info->envmode) { 695848b8605Smrg case GL_MODULATE: 696848b8605Smrg SPAN_NEAREST(NEAREST_RGB;MODULATE,3); 697848b8605Smrg break; 698848b8605Smrg case GL_DECAL: 699848b8605Smrg case GL_REPLACE: 700848b8605Smrg SPAN_NEAREST(NEAREST_RGB_REPLACE,3); 701848b8605Smrg break; 702848b8605Smrg case GL_BLEND: 703848b8605Smrg SPAN_NEAREST(NEAREST_RGB;BLEND,3); 704848b8605Smrg break; 705848b8605Smrg case GL_ADD: 706848b8605Smrg SPAN_NEAREST(NEAREST_RGB;ADD,3); 707848b8605Smrg break; 708848b8605Smrg default: 709848b8605Smrg _mesa_problem(ctx, "bad tex env mode (5) in SPAN_LINEAR"); 710848b8605Smrg return; 711848b8605Smrg } 712848b8605Smrg break; 713848b8605Smrg case MESA_FORMAT_A8B8G8R8_UNORM: 714848b8605Smrg switch(info->envmode) { 715848b8605Smrg case GL_MODULATE: 716848b8605Smrg SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); 717848b8605Smrg break; 718848b8605Smrg case GL_DECAL: 719848b8605Smrg SPAN_NEAREST(NEAREST_RGBA;DECAL,4); 720848b8605Smrg break; 721848b8605Smrg case GL_BLEND: 722848b8605Smrg SPAN_NEAREST(NEAREST_RGBA;BLEND,4); 723848b8605Smrg break; 724848b8605Smrg case GL_ADD: 725848b8605Smrg SPAN_NEAREST(NEAREST_RGBA;ADD,4); 726848b8605Smrg break; 727848b8605Smrg case GL_REPLACE: 728848b8605Smrg SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); 729848b8605Smrg break; 730848b8605Smrg default: 731848b8605Smrg _mesa_problem(ctx, "bad tex env mode (6) in SPAN_LINEAR"); 732848b8605Smrg return; 733848b8605Smrg } 734848b8605Smrg break; 735848b8605Smrg } 736848b8605Smrg break; 737848b8605Smrg 738848b8605Smrg case GL_LINEAR: 739848b8605Smrg switch (info->format) { 740848b8605Smrg case MESA_FORMAT_BGR_UNORM8: 741848b8605Smrg switch (info->envmode) { 742848b8605Smrg case GL_MODULATE: 743848b8605Smrg SPAN_LINEAR(LINEAR_RGB;MODULATE,3); 744848b8605Smrg break; 745848b8605Smrg case GL_DECAL: 746848b8605Smrg case GL_REPLACE: 747848b8605Smrg SPAN_LINEAR(LINEAR_RGB;REPLACE,3); 748848b8605Smrg break; 749848b8605Smrg case GL_BLEND: 750848b8605Smrg SPAN_LINEAR(LINEAR_RGB;BLEND,3); 751848b8605Smrg break; 752848b8605Smrg case GL_ADD: 753848b8605Smrg SPAN_LINEAR(LINEAR_RGB;ADD,3); 754848b8605Smrg break; 755848b8605Smrg default: 756848b8605Smrg _mesa_problem(ctx, "bad tex env mode (7) in SPAN_LINEAR"); 757848b8605Smrg return; 758848b8605Smrg } 759848b8605Smrg break; 760848b8605Smrg case MESA_FORMAT_A8B8G8R8_UNORM: 761848b8605Smrg switch (info->envmode) { 762848b8605Smrg case GL_MODULATE: 763848b8605Smrg SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); 764848b8605Smrg break; 765848b8605Smrg case GL_DECAL: 766848b8605Smrg SPAN_LINEAR(LINEAR_RGBA;DECAL,4); 767848b8605Smrg break; 768848b8605Smrg case GL_BLEND: 769848b8605Smrg SPAN_LINEAR(LINEAR_RGBA;BLEND,4); 770848b8605Smrg break; 771848b8605Smrg case GL_ADD: 772848b8605Smrg SPAN_LINEAR(LINEAR_RGBA;ADD,4); 773848b8605Smrg break; 774848b8605Smrg case GL_REPLACE: 775848b8605Smrg SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); 776848b8605Smrg break; 777848b8605Smrg default: 778848b8605Smrg _mesa_problem(ctx, "bad tex env mode (8) in SPAN_LINEAR"); 779848b8605Smrg return; 780848b8605Smrg } 781848b8605Smrg break; 782848b8605Smrg } 783848b8605Smrg break; 784848b8605Smrg } 785848b8605Smrg 786b8e80941Smrg assert(span->arrayMask & SPAN_RGBA); 787848b8605Smrg _swrast_write_rgba_span(ctx, span); 788848b8605Smrg 789848b8605Smrg#undef SPAN_NEAREST 790848b8605Smrg#undef SPAN_LINEAR 791848b8605Smrg 792848b8605Smrg /* restore state */ 793848b8605Smrg ctx->Texture._EnabledCoordUnits = texEnableSave; 794848b8605Smrg} 795848b8605Smrg 796848b8605Smrg 797848b8605Smrg/* 798848b8605Smrg * Render an perspective corrected RGB/RGBA textured triangle. 799848b8605Smrg * The Q (aka V in Mesa) coordinate must be zero such that the divide 800848b8605Smrg * by interpolated Q/W comes out right. 801848b8605Smrg * 802848b8605Smrg */ 803848b8605Smrg#define NAME persp_textured_triangle 804848b8605Smrg#define INTERP_Z 1 805848b8605Smrg#define INTERP_RGB 1 806848b8605Smrg#define INTERP_ALPHA 1 807848b8605Smrg#define INTERP_ATTRIBS 1 808848b8605Smrg 809848b8605Smrg#define SETUP_CODE \ 810848b8605Smrg struct persp_info info; \ 811b8e80941Smrg const struct gl_fixedfunc_texture_unit *unit = ctx->Texture.FixedFuncUnit+0; \ 812848b8605Smrg const struct gl_texture_object *obj = \ 813848b8605Smrg ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \ 814848b8605Smrg const struct gl_texture_image *texImg = \ 815b8e80941Smrg _mesa_base_tex_image(obj); \ 816848b8605Smrg const struct swrast_texture_image *swImg = \ 817848b8605Smrg swrast_texture_image_const(texImg); \ 818848b8605Smrg info.texture = (const GLchan *) swImg->ImageSlices[0]; \ 819848b8605Smrg info.twidth_log2 = texImg->WidthLog2; \ 820848b8605Smrg info.smask = texImg->Width - 1; \ 821848b8605Smrg info.tmask = texImg->Height - 1; \ 822848b8605Smrg info.format = texImg->TexFormat; \ 823848b8605Smrg info.filter = obj->Sampler.MinFilter; \ 824848b8605Smrg info.envmode = unit->EnvMode; \ 825848b8605Smrg info.er = 0; \ 826848b8605Smrg info.eg = 0; \ 827848b8605Smrg info.eb = 0; \ 828848b8605Smrg \ 829848b8605Smrg if (info.envmode == GL_BLEND) { \ 830848b8605Smrg /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 831848b8605Smrg info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \ 832848b8605Smrg info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \ 833848b8605Smrg info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \ 834848b8605Smrg info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \ 835848b8605Smrg } \ 836848b8605Smrg if (!info.texture) { \ 837848b8605Smrg /* this shouldn't happen */ \ 838848b8605Smrg return; \ 839848b8605Smrg } \ 840848b8605Smrg \ 841848b8605Smrg switch (info.format) { \ 842848b8605Smrg case MESA_FORMAT_BGR_UNORM8: \ 843848b8605Smrg info.tbytesline = texImg->Width * 3; \ 844848b8605Smrg break; \ 845848b8605Smrg case MESA_FORMAT_A8B8G8R8_UNORM: \ 846848b8605Smrg info.tbytesline = texImg->Width * 4; \ 847848b8605Smrg break; \ 848848b8605Smrg default: \ 849848b8605Smrg _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\ 850848b8605Smrg return; \ 851848b8605Smrg } \ 852848b8605Smrg info.tsize = texImg->Height * info.tbytesline; 853848b8605Smrg 854848b8605Smrg#define RENDER_SPAN( span ) \ 855848b8605Smrg span.interpMask &= ~SPAN_RGBA; \ 856848b8605Smrg span.arrayMask |= SPAN_RGBA; \ 857848b8605Smrg fast_persp_span(ctx, &span, &info); 858848b8605Smrg 859848b8605Smrg#include "s_tritemp.h" 860848b8605Smrg 861848b8605Smrg#endif /*CHAN_TYPE != GL_FLOAT*/ 862848b8605Smrg 863848b8605Smrg 864848b8605Smrg 865848b8605Smrg/* 866848b8605Smrg * Render an RGBA triangle with arbitrary attributes. 867848b8605Smrg */ 868848b8605Smrg#define NAME general_triangle 869848b8605Smrg#define INTERP_Z 1 870848b8605Smrg#define INTERP_RGB 1 871848b8605Smrg#define INTERP_ALPHA 1 872848b8605Smrg#define INTERP_ATTRIBS 1 873848b8605Smrg#define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span); 874848b8605Smrg#include "s_tritemp.h" 875848b8605Smrg 876848b8605Smrg 877848b8605Smrg 878848b8605Smrg 879848b8605Smrg/* 880848b8605Smrg * Special tri function for occlusion testing 881848b8605Smrg */ 882848b8605Smrg#define NAME occlusion_zless_16_triangle 883848b8605Smrg#define INTERP_Z 1 884848b8605Smrg#define SETUP_CODE \ 885848b8605Smrg struct gl_renderbuffer *rb = \ 886848b8605Smrg ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; \ 887848b8605Smrg struct gl_query_object *q = ctx->Query.CurrentOcclusionObject; \ 888b8e80941Smrg assert(ctx->Depth.Test); \ 889b8e80941Smrg assert(!ctx->Depth.Mask); \ 890b8e80941Smrg assert(ctx->Depth.Func == GL_LESS); \ 891848b8605Smrg assert(rb->Format == MESA_FORMAT_Z_UNORM16); \ 892848b8605Smrg if (!q) { \ 893848b8605Smrg return; \ 894848b8605Smrg } 895848b8605Smrg#define RENDER_SPAN( span ) \ 896848b8605Smrg { \ 897848b8605Smrg GLuint i; \ 898848b8605Smrg const GLushort *zRow = (const GLushort *) \ 899848b8605Smrg _swrast_pixel_address(rb, span.x, span.y); \ 900848b8605Smrg for (i = 0; i < span.end; i++) { \ 901848b8605Smrg GLuint z = FixedToDepth(span.z); \ 902848b8605Smrg if (z < zRow[i]) { \ 903848b8605Smrg q->Result++; \ 904848b8605Smrg } \ 905848b8605Smrg span.z += span.zStep; \ 906848b8605Smrg } \ 907848b8605Smrg } 908848b8605Smrg#include "s_tritemp.h" 909848b8605Smrg 910848b8605Smrg 911848b8605Smrg 912848b8605Smrgstatic void 913848b8605Smrgnodraw_triangle( struct gl_context *ctx, 914848b8605Smrg const SWvertex *v0, 915848b8605Smrg const SWvertex *v1, 916848b8605Smrg const SWvertex *v2 ) 917848b8605Smrg{ 918848b8605Smrg (void) (ctx && v0 && v1 && v2); 919848b8605Smrg} 920848b8605Smrg 921848b8605Smrg 922848b8605Smrg/* 923848b8605Smrg * This is used when separate specular color is enabled, but not 924848b8605Smrg * texturing. We add the specular color to the primary color, 925848b8605Smrg * draw the triangle, then restore the original primary color. 926848b8605Smrg * Inefficient, but seldom needed. 927848b8605Smrg */ 928848b8605Smrgvoid 929848b8605Smrg_swrast_add_spec_terms_triangle(struct gl_context *ctx, const SWvertex *v0, 930848b8605Smrg const SWvertex *v1, const SWvertex *v2) 931848b8605Smrg{ 932848b8605Smrg SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */ 933848b8605Smrg SWvertex *ncv1 = (SWvertex *)v1; 934848b8605Smrg SWvertex *ncv2 = (SWvertex *)v2; 935848b8605Smrg GLfloat rSum, gSum, bSum; 936848b8605Smrg GLchan cSave[3][4]; 937848b8605Smrg 938848b8605Smrg /* save original colors */ 939848b8605Smrg COPY_CHAN4( cSave[0], ncv0->color ); 940848b8605Smrg COPY_CHAN4( cSave[1], ncv1->color ); 941848b8605Smrg COPY_CHAN4( cSave[2], ncv2->color ); 942848b8605Smrg /* sum v0 */ 943848b8605Smrg rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[VARYING_SLOT_COL1][0]; 944848b8605Smrg gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[VARYING_SLOT_COL1][1]; 945848b8605Smrg bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[VARYING_SLOT_COL1][2]; 946848b8605Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum); 947848b8605Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum); 948848b8605Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum); 949848b8605Smrg /* sum v1 */ 950848b8605Smrg rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[VARYING_SLOT_COL1][0]; 951848b8605Smrg gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[VARYING_SLOT_COL1][1]; 952848b8605Smrg bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[VARYING_SLOT_COL1][2]; 953848b8605Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum); 954848b8605Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum); 955848b8605Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum); 956848b8605Smrg /* sum v2 */ 957848b8605Smrg rSum = CHAN_TO_FLOAT(ncv2->color[0]) + ncv2->attrib[VARYING_SLOT_COL1][0]; 958848b8605Smrg gSum = CHAN_TO_FLOAT(ncv2->color[1]) + ncv2->attrib[VARYING_SLOT_COL1][1]; 959848b8605Smrg bSum = CHAN_TO_FLOAT(ncv2->color[2]) + ncv2->attrib[VARYING_SLOT_COL1][2]; 960848b8605Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[0], rSum); 961848b8605Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[1], gSum); 962848b8605Smrg UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[2], bSum); 963848b8605Smrg /* draw */ 964848b8605Smrg SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 ); 965848b8605Smrg /* restore original colors */ 966848b8605Smrg COPY_CHAN4( ncv0->color, cSave[0] ); 967848b8605Smrg COPY_CHAN4( ncv1->color, cSave[1] ); 968848b8605Smrg COPY_CHAN4( ncv2->color, cSave[2] ); 969848b8605Smrg} 970848b8605Smrg 971848b8605Smrg 972848b8605Smrg 973848b8605Smrg#ifdef DEBUG 974848b8605Smrg 975848b8605Smrg/* record the current triangle function name */ 976848b8605Smrgconst char *_mesa_triFuncName = NULL; 977848b8605Smrg 978848b8605Smrg#define USE(triFunc) \ 979848b8605Smrgdo { \ 980848b8605Smrg _mesa_triFuncName = #triFunc; \ 981848b8605Smrg /*printf("%s\n", _mesa_triFuncName);*/ \ 982848b8605Smrg swrast->Triangle = triFunc; \ 983848b8605Smrg} while (0) 984848b8605Smrg 985848b8605Smrg#else 986848b8605Smrg 987848b8605Smrg#define USE(triFunc) swrast->Triangle = triFunc; 988848b8605Smrg 989848b8605Smrg#endif 990848b8605Smrg 991848b8605Smrg 992848b8605Smrg 993848b8605Smrg 994848b8605Smrg/* 995848b8605Smrg * Determine which triangle rendering function to use given the current 996848b8605Smrg * rendering context. 997848b8605Smrg * 998848b8605Smrg * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or 999848b8605Smrg * remove tests to this code. 1000848b8605Smrg */ 1001848b8605Smrgvoid 1002848b8605Smrg_swrast_choose_triangle( struct gl_context *ctx ) 1003848b8605Smrg{ 1004848b8605Smrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 1005848b8605Smrg 1006848b8605Smrg if (ctx->Polygon.CullFlag && 1007848b8605Smrg ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { 1008848b8605Smrg USE(nodraw_triangle); 1009848b8605Smrg return; 1010848b8605Smrg } 1011848b8605Smrg 1012848b8605Smrg if (ctx->RenderMode==GL_RENDER) { 1013848b8605Smrg struct gl_renderbuffer *depthRb = 1014848b8605Smrg ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 1015848b8605Smrg 1016848b8605Smrg if (ctx->Polygon.SmoothFlag) { 1017848b8605Smrg _swrast_set_aa_triangle_function(ctx); 1018b8e80941Smrg assert(swrast->Triangle); 1019848b8605Smrg return; 1020848b8605Smrg } 1021848b8605Smrg 1022848b8605Smrg /* special case for occlusion testing */ 1023848b8605Smrg if (ctx->Query.CurrentOcclusionObject && 1024848b8605Smrg ctx->Depth.Test && 1025848b8605Smrg ctx->Depth.Mask == GL_FALSE && 1026848b8605Smrg ctx->Depth.Func == GL_LESS && 1027b8e80941Smrg !_mesa_stencil_is_enabled(ctx) && 1028848b8605Smrg depthRb && 1029848b8605Smrg depthRb->Format == MESA_FORMAT_Z_UNORM16) { 1030b8e80941Smrg if (GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0) == 0 && 1031b8e80941Smrg GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1) == 0 && 1032b8e80941Smrg GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2) == 0 && 1033b8e80941Smrg GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3) == 0) { 1034848b8605Smrg USE(occlusion_zless_16_triangle); 1035848b8605Smrg return; 1036848b8605Smrg } 1037848b8605Smrg } 1038848b8605Smrg 1039848b8605Smrg /* 1040848b8605Smrg * XXX should examine swrast->_ActiveAttribMask to determine what 1041848b8605Smrg * needs to be interpolated. 1042848b8605Smrg */ 1043848b8605Smrg if (ctx->Texture._EnabledCoordUnits || 1044848b8605Smrg _swrast_use_fragment_program(ctx) || 1045b8e80941Smrg _mesa_ati_fragment_shader_enabled(ctx) || 1046848b8605Smrg _mesa_need_secondary_color(ctx) || 1047848b8605Smrg swrast->_FogEnabled) { 1048848b8605Smrg /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ 1049848b8605Smrg const struct gl_texture_object *texObj2D; 1050848b8605Smrg const struct gl_sampler_object *samp; 1051848b8605Smrg const struct gl_texture_image *texImg; 1052848b8605Smrg const struct swrast_texture_image *swImg; 1053848b8605Smrg GLenum minFilter, magFilter, envMode; 1054848b8605Smrg mesa_format format; 1055848b8605Smrg texObj2D = ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; 1056848b8605Smrg if (ctx->Texture.Unit[0].Sampler) 1057848b8605Smrg samp = ctx->Texture.Unit[0].Sampler; 1058848b8605Smrg else if (texObj2D) 1059848b8605Smrg samp = &texObj2D->Sampler; 1060848b8605Smrg else 1061848b8605Smrg samp = NULL; 1062848b8605Smrg 1063b8e80941Smrg texImg = texObj2D ? _mesa_base_tex_image(texObj2D) : NULL; 1064848b8605Smrg swImg = swrast_texture_image_const(texImg); 1065848b8605Smrg 1066848b8605Smrg format = texImg ? texImg->TexFormat : MESA_FORMAT_NONE; 1067848b8605Smrg minFilter = texObj2D ? samp->MinFilter : GL_NONE; 1068848b8605Smrg magFilter = texObj2D ? samp->MagFilter : GL_NONE; 1069b8e80941Smrg envMode = ctx->Texture.FixedFuncUnit[0].EnvMode; 1070848b8605Smrg 1071848b8605Smrg /* First see if we can use an optimized 2-D texture function */ 1072848b8605Smrg if (ctx->Texture._EnabledCoordUnits == 0x1 1073848b8605Smrg && !_swrast_use_fragment_program(ctx) 1074b8e80941Smrg && !_mesa_ati_fragment_shader_enabled(ctx) 1075848b8605Smrg && ctx->Texture._MaxEnabledTexImageUnit == 0 1076848b8605Smrg && ctx->Texture.Unit[0]._Current->Target == GL_TEXTURE_2D 1077848b8605Smrg && samp->WrapS == GL_REPEAT 1078848b8605Smrg && samp->WrapT == GL_REPEAT 1079848b8605Smrg && texObj2D->_Swizzle == SWIZZLE_NOOP 1080848b8605Smrg && swImg->_IsPowerOfTwo 1081848b8605Smrg && texImg->Border == 0 1082848b8605Smrg && (_mesa_format_row_stride(format, texImg->Width) == 1083848b8605Smrg swImg->RowStride) 1084848b8605Smrg && (format == MESA_FORMAT_BGR_UNORM8 || format == MESA_FORMAT_A8B8G8R8_UNORM) 1085848b8605Smrg && minFilter == magFilter 1086848b8605Smrg && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR 1087848b8605Smrg && !swrast->_FogEnabled 1088b8e80941Smrg && ctx->Texture.FixedFuncUnit[0].EnvMode != GL_COMBINE_EXT 1089b8e80941Smrg && ctx->Texture.FixedFuncUnit[0].EnvMode != GL_COMBINE4_NV) { 1090848b8605Smrg if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) { 1091848b8605Smrg if (minFilter == GL_NEAREST 1092848b8605Smrg && format == MESA_FORMAT_BGR_UNORM8 1093848b8605Smrg && (envMode == GL_REPLACE || envMode == GL_DECAL) 1094848b8605Smrg && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT) 1095848b8605Smrg && ctx->Depth.Func == GL_LESS 1096848b8605Smrg && ctx->Depth.Mask == GL_TRUE) 1097848b8605Smrg || swrast->_RasterMask == TEXTURE_BIT) 1098848b8605Smrg && ctx->Polygon.StippleFlag == GL_FALSE 1099848b8605Smrg && ctx->DrawBuffer->Visual.depthBits <= 16) { 1100848b8605Smrg if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) { 1101848b8605Smrg USE(simple_z_textured_triangle); 1102848b8605Smrg } 1103848b8605Smrg else { 1104848b8605Smrg USE(simple_textured_triangle); 1105848b8605Smrg } 1106848b8605Smrg } 1107848b8605Smrg else { 1108848b8605Smrg#if CHAN_BITS != 8 1109848b8605Smrg USE(general_triangle); 1110848b8605Smrg#else 1111848b8605Smrg if (format == MESA_FORMAT_A8B8G8R8_UNORM && !_mesa_little_endian()) { 1112848b8605Smrg /* We only handle RGBA8888 correctly on little endian 1113848b8605Smrg * in the optimized code above. 1114848b8605Smrg */ 1115848b8605Smrg USE(general_triangle); 1116848b8605Smrg } 1117848b8605Smrg else { 1118848b8605Smrg USE(affine_textured_triangle); 1119848b8605Smrg } 1120848b8605Smrg#endif 1121848b8605Smrg } 1122848b8605Smrg } 1123848b8605Smrg else { 1124848b8605Smrg#if CHAN_BITS != 8 1125848b8605Smrg USE(general_triangle); 1126848b8605Smrg#else 1127848b8605Smrg USE(persp_textured_triangle); 1128848b8605Smrg#endif 1129848b8605Smrg } 1130848b8605Smrg } 1131848b8605Smrg else { 1132848b8605Smrg /* general case textured triangles */ 1133848b8605Smrg USE(general_triangle); 1134848b8605Smrg } 1135848b8605Smrg } 1136848b8605Smrg else { 1137b8e80941Smrg assert(!swrast->_FogEnabled); 1138b8e80941Smrg assert(!_mesa_need_secondary_color(ctx)); 1139848b8605Smrg if (ctx->Light.ShadeModel==GL_SMOOTH) { 1140848b8605Smrg /* smooth shaded, no texturing, stippled or some raster ops */ 1141848b8605Smrg#if CHAN_BITS != 8 1142848b8605Smrg USE(general_triangle); 1143848b8605Smrg#else 1144848b8605Smrg USE(smooth_rgba_triangle); 1145848b8605Smrg#endif 1146848b8605Smrg } 1147848b8605Smrg else { 1148848b8605Smrg /* flat shaded, no texturing, stippled or some raster ops */ 1149848b8605Smrg#if CHAN_BITS != 8 1150848b8605Smrg USE(general_triangle); 1151848b8605Smrg#else 1152848b8605Smrg USE(flat_rgba_triangle); 1153848b8605Smrg#endif 1154848b8605Smrg } 1155848b8605Smrg } 1156848b8605Smrg } 1157848b8605Smrg else if (ctx->RenderMode==GL_FEEDBACK) { 1158848b8605Smrg USE(_swrast_feedback_triangle); 1159848b8605Smrg } 1160848b8605Smrg else { 1161848b8605Smrg /* GL_SELECT mode */ 1162848b8605Smrg USE(_swrast_select_triangle); 1163848b8605Smrg } 1164848b8605Smrg} 1165