typedef unsigned int GLenum; typedef unsigned char GLboolean; typedef unsigned int GLbitfield; typedef void GLvoid; typedef int GLint; typedef unsigned char GLubyte; typedef unsigned int GLuint; typedef float GLfloat; typedef int GLfixed; typedef union { GLfloat f; GLint i; } fi_type; static __inline__ int IS_INF_OR_NAN(float x) { fi_type tmp; tmp.f = x; return !(int)((unsigned int)((tmp.i & 0x7fffffff) - 0x7f800000) >> 31); } typedef enum { MESA_FORMAT_RGBA8888, MESA_FORMAT_RGB888, } gl_format; typedef enum { FRAG_ATTRIB_WPOS = 0, FRAG_ATTRIB_COL0 = 1, FRAG_ATTRIB_COL1 = 2, FRAG_ATTRIB_FOGC = 3, FRAG_ATTRIB_TEX0 = 4, FRAG_ATTRIB_TEX1 = 5, FRAG_ATTRIB_TEX2 = 6, FRAG_ATTRIB_TEX3 = 7, FRAG_ATTRIB_TEX4 = 8, FRAG_ATTRIB_TEX5 = 9, FRAG_ATTRIB_TEX6 = 10, FRAG_ATTRIB_TEX7 = 11, FRAG_ATTRIB_FACE = 12, FRAG_ATTRIB_PNTC = 13, FRAG_ATTRIB_VAR0 = 14, FRAG_ATTRIB_MAX = (FRAG_ATTRIB_VAR0 + 16) } gl_frag_result; struct gl_config { GLint depthBits; }; struct gl_lightmodel { GLenum ColorControl; }; struct gl_depthbuffer_attrib { GLenum Func; GLboolean Mask; }; struct gl_hint_attrib { GLenum PerspectiveCorrection; }; struct gl_light_attrib { struct gl_lightmodel Model; }; struct gl_polygon_attrib { GLboolean StippleFlag; }; typedef enum { TEXTURE_BUFFER_INDEX, TEXTURE_2D_ARRAY_INDEX, TEXTURE_1D_ARRAY_INDEX, TEXTURE_CUBE_INDEX, TEXTURE_3D_INDEX, TEXTURE_RECT_INDEX, TEXTURE_2D_INDEX, TEXTURE_1D_INDEX, NUM_TEXTURE_TARGETS } gl_texture_index; struct gl_texture_image { GLuint Border; GLuint Width; GLuint Height; GLuint WidthLog2; GLboolean _IsPowerOfTwo; GLuint RowStride; GLvoid *Data; }; typedef enum { MAX_FACES = 6 } gl_face_index; struct gl_sampler_object { GLenum WrapS; GLenum WrapT; }; struct gl_texture_object { struct gl_sampler_object Sampler; GLint BaseLevel; GLuint _Swizzle; struct gl_texture_image *Image[MAX_FACES][15]; }; struct gl_texture_unit { GLbitfield _ReallyEnabled; GLenum EnvMode; struct gl_texture_object *CurrentTex[NUM_TEXTURE_TARGETS]; }; struct gl_texture_attrib { struct gl_texture_unit Unit[(16 + 16)]; GLbitfield _EnabledUnits; GLbitfield _EnabledCoordUnits; }; struct gl_fragment_program_state { struct gl_fragment_program *_Current; }; struct gl_ati_fragment_shader_state { GLboolean _Enabled; }; struct gl_renderbuffer { void (*PutRowRGB) (struct gl_context * ctx, struct gl_renderbuffer * rb, GLuint count, GLint x, GLint y, const void *values, const GLubyte * mask); }; struct gl_framebuffer { struct gl_config Visual; struct gl_renderbuffer *_ColorDrawBuffers[8]; }; struct gl_context { struct gl_framebuffer *DrawBuffer; struct gl_depthbuffer_attrib Depth; struct gl_hint_attrib Hint; struct gl_light_attrib Light; struct gl_polygon_attrib Polygon; struct gl_texture_attrib Texture; struct gl_fragment_program_state FragmentProgram; struct gl_ati_fragment_shader_state ATIFragmentShader; GLenum RenderMode; }; typedef struct { GLfloat attrib[FRAG_ATTRIB_MAX][4]; } SWvertex; typedef struct sw_span { GLint x, y; GLuint end; GLfloat attrStepX[FRAG_ATTRIB_MAX][4]; GLfixed intTex[2], intTexStep[2]; } SWspan; typedef void (*swrast_tri_func) (struct gl_context * ctx, const SWvertex *, const SWvertex *, const SWvertex *); typedef struct { GLbitfield _RasterMask; GLboolean _FogEnabled; swrast_tri_func Triangle; } SWcontext; static void simple_textured_triangle(struct gl_context *ctx, const SWvertex * v0, const SWvertex * v1, const SWvertex * v2) { typedef struct { GLfloat dx; GLfloat dy; GLfixed fsx; GLfixed fx0; GLint lines; } EdgeT; EdgeT eMaj; EdgeT eTop; EdgeT eBot; GLfloat oneOverArea; const SWvertex *vMin; const SWvertex *vMid; const SWvertex *vMax; const GLint snapMask = ~(((1 << 11) / (1 << 4)) - 1); GLfixed vMin_fx; GLfixed vMin_fy; GLfixed vMid_fx; GLfixed vMid_fy; GLfixed vMax_fx; GLfixed vMax_fy; SWspan span; { const GLfixed fy0 = (((int) ((((v0->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) * ((float)(1 << 11))) >= 0.0F) ? (((v0->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) * ((float)(1 << 11))) + 0.5F) : (((v0->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) * ((float)(1 << 11))) - 0.5F)))) & snapMask; const GLfixed fy1 = (((int) ((((v1->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) * ((float)(1 << 11))) >= 0.0F) ? (((v1->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) * ((float)(1 << 11))) + 0.5F) : (((v1->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) * ((float)(1 << 11))) - 0.5F)))) & snapMask; const GLfixed fy2 = (((int) ((((v2->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) * ((float)(1 << 11))) >= 0.0F) ? (((v2->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) * ((float)(1 << 11))) + 0.5F) : (((v2->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) * ((float)(1 << 11))) - 0.5F)))) & snapMask; if (fy0 <= fy1) { if (fy1 <= fy2) { vMin = v0; vMax = v1; vMin_fy = fy0; } } vMin_fx = (((int) ((((vMin->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) * ((float)(1 << 11))) >= 0.0F) ? (((vMin->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) * ((float)(1 << 11))) + 0.5F) : (((vMin->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) * ((float)(1 << 11))) - 0.5F)))) & snapMask; vMid_fx = (((int) ((((vMid->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) * ((float)(1 << 11))) >= 0.0F) ? (((vMid->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) * ((float)(1 << 11))) + 0.5F) : (((vMid->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) * ((float)(1 << 11))) - 0.5F)))) & snapMask; } eMaj.dx = ((vMax_fx - vMin_fx) * (1.0F / ((float)(1 << 11)))); eMaj.dy = ((vMax_fy - vMin_fy) * (1.0F / ((float)(1 << 11)))); eTop.dx = ((vMax_fx - vMid_fx) * (1.0F / ((float)(1 << 11)))); eBot.dy = ((vMid_fy - vMin_fy) * (1.0F / ((float)(1 << 11)))); { const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy; if (IS_INF_OR_NAN(area) || area == 0.0F) return; oneOverArea = 1.0F / area; if (eBot.lines > 0) { eBot.fx0 = vMin_fx; } GLint scan_from_left_to_right; struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; const struct gl_texture_object *obj = ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; const struct gl_texture_image *texImg = obj->Image[0][obj->BaseLevel]; const GLfloat twidth = (GLfloat) texImg->Width; const GLint twidth_log2 = texImg->WidthLog2; const GLubyte *texture = (const GLubyte *)texImg->Data; const GLint smask = texImg->Width - 1; const GLint tmask = texImg->Height - 1; if (!rb || !texture) { return; } { GLfloat eMaj_ds = (vMax->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * twidth; GLfloat eBot_ds = (vMid->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * twidth; span.attrStepX[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds); span.intTexStep[0] = (((int) ((((span.attrStepX[FRAG_ATTRIB_TEX0][0]) * ((float)(1 << 11))) >= 0.0F) ? (((span.attrStepX[FRAG_ATTRIB_TEX0][0]) * ((float)(1 << 11))) + 0.5F) : (((span.attrStepX[FRAG_ATTRIB_TEX0][0]) * ((float)(1 << 11))) - 0.5F)))); GLint subTriangle; GLfixed fxLeftEdge = 0; GLfixed fxRightEdge = 0; GLfixed sLeft = 0; for (subTriangle = 0; subTriangle <= 1; subTriangle++) { EdgeT *eRight; int lines; if (subTriangle == 0) { if (scan_from_left_to_right) { eRight = &eBot; lines = eRight->lines; } else { eRight = &eMaj; } } else { if (scan_from_left_to_right) { eRight = &eTop; } fxRightEdge = eRight->fsx - 1; } while (lines > 0) { const GLint right = ((fxRightEdge) >> 11); span.x = ((fxLeftEdge) >> 11); if (right <= span.x) span.end = 0; else span.end = right - span.x; span.intTex[0] = sLeft; if (span.end > 0 && span.y >= 0) { { GLuint i; GLubyte rgb[16384][3]; for (i = 0; i < span.end; i++) { GLint s = ((span. intTex[0]) >> 11) & smask; GLint t = ((span. intTex[1]) >> 11) & tmask; GLint pos = (t << twidth_log2) + s; rgb[i][0] = texture[pos + 2]; span. intTex[0] += span. intTexStep [0]; } rb->PutRowRGB(ctx, rb, span.end, span.x, span.y, rgb, ((void *) 0)); } } } } } } } void _swrast_choose_triangle(struct gl_context *ctx) { SWcontext *swrast = SWRAST_CONTEXT(ctx); if (ctx->RenderMode == 0x1C00) { if (ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled || _mesa_need_secondary_color(ctx) || swrast->_FogEnabled) { const struct gl_texture_object *texObj2D; const struct gl_texture_image *texImg; GLenum minFilter; GLenum magFilter; GLenum envMode; gl_format format; if (ctx->Texture._EnabledCoordUnits == 0x1 && !ctx->FragmentProgram._Current && !ctx->ATIFragmentShader._Enabled && ctx->Texture._EnabledUnits == 0x1 && ctx->Texture.Unit[0]._ReallyEnabled == (1 << TEXTURE_2D_INDEX) && texObj2D->Sampler.WrapS == 0x2901 && texObj2D->Sampler.WrapT == 0x2901 && texObj2D->_Swizzle == (((0) << 0) | ((1) << 3) | ((2) << 6) | ((3) << 9)) && texImg->_IsPowerOfTwo && texImg->Border == 0 && texImg->Width == texImg->RowStride && (format == MESA_FORMAT_RGB888 || format == MESA_FORMAT_RGBA8888) && minFilter == magFilter && ctx->Light.Model.ColorControl == 0x81F9 && !swrast->_FogEnabled && ctx->Texture.Unit[0].EnvMode != 0x8570 && ctx->Texture.Unit[0].EnvMode != 0x8503) { if (ctx->Hint.PerspectiveCorrection == 0x1101) { if (minFilter == 0x2600 && format == MESA_FORMAT_RGB888 && (envMode == 0x1E01 || envMode == 0x2101) && ((swrast->_RasterMask == (0x004 | 0x1000) && ctx->Depth.Func == 0x0201 && ctx->Depth.Mask == 0x1) || swrast->_RasterMask == 0x1000) && ctx->Polygon.StippleFlag == 0x0 && ctx->DrawBuffer->Visual. depthBits <= 16) { if (swrast->_RasterMask == (0x004 | 0x1000)) { swrast->Triangle = simple_textured_triangle; } } } } } } }