/** * Make sure we have texture image data for all the textures we may need * for subsequent rendering. */ static void _swrast_validate_texture_images(GLcontext *ctx) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLuint u; if (!swrast->ValidateTextureImage || !ctx->Texture._EnabledUnits) { /* no textures enabled, or no way to validate images! */ return; } for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) { if (ctx->Texture.Unit[u]._ReallyEnabled) { struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current; ASSERT(texObj); if (texObj) { GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; GLuint face; for (face = 0; face < numFaces; face++) { GLint lvl; for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) { struct gl_texture_image *texImg = texObj->Image[face][lvl]; if (texImg && !texImg->Data) { swrast->ValidateTextureImage(ctx, texObj, face, lvl); ASSERT(texObj->Image[face][lvl]->Data); } } } } } } }
/** * Called via swrast->BlendFunc. Examine GL state to choose a blending * function, then call it. */ static void _swrast_validate_blend_func(struct gl_context *ctx, GLuint n, const GLubyte mask[], GLvoid *src, const GLvoid *dst, GLenum chanType ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); _swrast_validate_derived( ctx ); /* why is this needed? */ _swrast_choose_blend_func( ctx, chanType ); swrast->BlendFunc( ctx, n, mask, src, dst, chanType ); }
/** * Called via swrast->BlendFunc. Examine GL state to choose a blending * function, then call it. */ static void _ASMAPI _swrast_validate_blend_func( GLcontext *ctx, GLuint n, const GLubyte mask[], GLchan src[][4], CONST GLchan dst[][4] ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); _swrast_validate_derived( ctx ); _swrast_choose_blend_func( ctx ); swrast->BlendFunc( ctx, n, mask, src, dst ); }
/** * Called via swrast->Point. Examine current GL state and choose a software * point routine. Then call it. */ static void _swrast_validate_point( struct gl_context *ctx, const SWvertex *v0 ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); _swrast_validate_derived( ctx ); swrast->choose_point( ctx ); if (swrast->SpecularVertexAdd) { swrast->SpecPoint = swrast->Point; swrast->Point = _swrast_add_spec_terms_point; } swrast->Point( ctx, v0 ); }
/** * Called via swrast->Line. Examine current GL state and choose a software * line routine. Then call it. */ static void _swrast_validate_line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); _swrast_validate_derived( ctx ); swrast->choose_line( ctx ); assert(swrast->Line); if (swrast->SpecularVertexAdd) { swrast->SpecLine = swrast->Line; swrast->Line = _swrast_add_spec_terms_line; } swrast->Line( ctx, v0, v1 ); }
/** * Called via swrast->Point. Examine current GL state and choose a software * point routine. Then call it. */ static void _swrast_validate_point( GLcontext *ctx, const SWvertex *v0 ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); _swrast_validate_derived( ctx ); swrast->choose_point( ctx ); if (ctx->Texture._EnabledUnits == 0 && NEED_SECONDARY_COLOR(ctx) && !ctx->FragmentProgram._Enabled) { swrast->SpecPoint = swrast->Point; swrast->Point = _swrast_add_spec_terms_point; } swrast->Point( ctx, v0 ); }
/** * Called via swrast->Line. Examine current GL state and choose a software * line routine. Then call it. */ static void _swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); _swrast_validate_derived( ctx ); swrast->choose_line( ctx ); ASSERT(swrast->Line); if (ctx->Texture._EnabledUnits == 0 && NEED_SECONDARY_COLOR(ctx) && !ctx->FragmentProgram._Current) { swrast->SpecLine = swrast->Line; swrast->Line = _swrast_add_spec_terms_line; } swrast->Line( ctx, v0, v1 ); }
/** * Stub for swrast->Triangle to select a true triangle function * after a state change. */ static void _swrast_validate_triangle( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1, const SWvertex *v2 ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); _swrast_validate_derived( ctx ); swrast->choose_triangle( ctx ); assert(swrast->Triangle); if (swrast->SpecularVertexAdd) { /* separate specular color, but no texture */ swrast->SpecTriangle = swrast->Triangle; swrast->Triangle = _swrast_add_spec_terms_triangle; } swrast->Triangle( ctx, v0, v1, v2 ); }
/** * Stub for swrast->Triangle to select a true triangle function * after a state change. */ static void _swrast_validate_triangle( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1, const SWvertex *v2 ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); _swrast_validate_derived( ctx ); swrast->choose_triangle( ctx ); if (ctx->Texture._EnabledUnits == 0 && NEED_SECONDARY_COLOR(ctx) && !ctx->FragmentProgram._Enabled) { /* separate specular color, but no texture */ swrast->SpecTriangle = swrast->Triangle; swrast->Triangle = _swrast_add_spec_terms_triangle; } swrast->Triangle( ctx, v0, v1, v2 ); }
/** * Apply texture mapping to a span of fragments. */ void _swrast_texture_span( struct gl_context *ctx, SWspan *span ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); float4_array primary_rgba; if (!swrast->TexelBuffer) { #ifdef _OPENMP const GLint maxThreads = omp_get_max_threads(); #else const GLint maxThreads = 1; #endif /* TexelBuffer is also global and normally shared by all SWspan * instances; when running with multiple threads, create one per * thread. */ swrast->TexelBuffer = (GLfloat *) MALLOC(maxThreads * MAX_WIDTH * 4 * sizeof(GLfloat)); if (!swrast->TexelBuffer) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine"); return; } } primary_rgba = (float4_array) malloc(span->end * 4 * sizeof(GLfloat)); if (!primary_rgba) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_span"); return; } ASSERT(span->end <= MAX_WIDTH); /* * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR) */ if (swrast->_TextureCombinePrimary) { GLuint i; for (i = 0; i < span->end; i++) { primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]); primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]); primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]); primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]); } } /* * Must do all texture sampling before combining in order to * accomodate GL_ARB_texture_env_crossbar. */ { const struct gl_texture_unit *texUnit = &ctx->Texture.Unit; if (texUnit->_ReallyEnabled) { const GLfloat (*texcoords)[4] = (const GLfloat (*)[4]) span->array->attribs[FRAG_ATTRIB_TEX]; const struct gl_texture_object *curObj = texUnit->_Current; GLfloat *lambda = span->array->lambda; float4_array texels = get_texel_array(swrast); if (curObj->Sampler.MaxAnisotropy > 1.0 && curObj->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) { /* sample_lambda_2d_aniso is beeing used as texture_sample_func, * it requires the current SWspan *span as an additional parameter. * In order to keep the same function signature, the unused lambda * parameter will be modified to actually contain the SWspan pointer. * This is a Hack. To make it right, the texture_sample_func * signature and all implementing functions need to be modified. */ /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */ lambda = (GLfloat *)span; } /* Sample the texture (span->end = number of fragments) */ swrast->TextureSample( ctx, texUnit->_Current, span->end, texcoords, lambda, texels ); } } /* * OK, now apply the texture (aka texture combine/blend). * We modify the span->color.rgba values. */ if (ctx->Texture.Unit._ReallyEnabled) texture_combine(ctx, primary_rgba, swrast->TexelBuffer, span); free(primary_rgba); }