static void i810AlphaFunc(struct gl_context *ctx, GLenum func, GLfloat ref) { i810ContextPtr imesa = I810_CONTEXT(ctx); GLuint a = (ZA_UPDATE_ALPHAFUNC|ZA_UPDATE_ALPHAREF); GLubyte refByte; CLAMPED_FLOAT_TO_UBYTE(refByte, ref); switch (ctx->Color.AlphaFunc) { case GL_NEVER: a |= ZA_ALPHA_NEVER; break; case GL_LESS: a |= ZA_ALPHA_LESS; break; case GL_GEQUAL: a |= ZA_ALPHA_GEQUAL; break; case GL_LEQUAL: a |= ZA_ALPHA_LEQUAL; break; case GL_GREATER: a |= ZA_ALPHA_GREATER; break; case GL_NOTEQUAL: a |= ZA_ALPHA_NOTEQUAL; break; case GL_EQUAL: a |= ZA_ALPHA_EQUAL; break; case GL_ALWAYS: a |= ZA_ALPHA_ALWAYS; break; default: return; } a |= ((refByte & 0xfc) << ZA_ALPHAREF_SHIFT); I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_ZA] &= ~(ZA_ALPHA_MASK|ZA_ALPHAREF_MASK); imesa->Setup[I810_CTXREG_ZA] |= a; }
static void set_color_stage( unsigned color, int stage, i810ContextPtr imesa ) { if ( color != imesa->Setup[I810_CTXREG_MC0 + stage] ) { I810_STATECHANGE( imesa, I810_UPLOAD_CTX ); imesa->Setup[I810_CTXREG_MC0 + stage] = color; } }
static void set_alpha_stage( unsigned alpha, int stage, i810ContextPtr imesa ) { if ( alpha != imesa->Setup[I810_CTXREG_MA0 + stage] ) { I810_STATECHANGE( imesa, I810_UPLOAD_CTX ); imesa->Setup[I810_CTXREG_MA0 + stage] = alpha; } }
/* In Mesa 3.5 we can reliably do native flatshading. */ static void i810ShadeModel(struct gl_context *ctx, GLenum mode) { i810ContextPtr imesa = I810_CONTEXT(ctx); I810_STATECHANGE(imesa, I810_UPLOAD_CTX); if (mode == GL_FLAT) imesa->Setup[I810_CTXREG_LCS] |= LCS_INTERP_FLAT; else imesa->Setup[I810_CTXREG_LCS] &= ~LCS_INTERP_FLAT; }
/* This is called with the lock held. May have to eject our own and/or * other client's texture objects to make room for the upload. */ int i810UploadTexImagesLocked( i810ContextPtr imesa, i810TextureObjectPtr t ) { int i; int ofs; int numLevels; /* Do we need to eject LRU texture objects? */ if (!t->base.memBlock) { int heap; heap = driAllocateTexture( imesa->texture_heaps, imesa->nr_heaps, (driTextureObject *) t); if ( heap == -1 ) { return -1; } ofs = t->base.memBlock->ofs; t->BufAddr = imesa->i810Screen->tex.map + ofs; t->Setup[I810_TEXREG_MI3] = imesa->i810Screen->textureOffset + ofs; if (t == imesa->CurrentTexObj[0]) I810_STATECHANGE(imesa, I810_UPLOAD_TEX0); if (t == imesa->CurrentTexObj[1]) I810_STATECHANGE(imesa, I810_UPLOAD_TEX1); /* i810UpdateTexLRU( imesa, t );*/ } driUpdateTextureLRU( (driTextureObject *) t ); if (imesa->texture_heaps[0]->timestamp >= GET_DISPATCH_AGE(imesa)) i810WaitAgeLocked( imesa, imesa->texture_heaps[0]->timestamp ); numLevels = t->base.lastLevel - t->base.firstLevel + 1; for (i = 0 ; i < numLevels ; i++) if (t->base.dirty_images[0] & (1<<i)) i810UploadTexLevel( imesa, t, i ); t->base.dirty_images[0] = 0; return 0; }
static void i810DepthMask(struct gl_context *ctx, GLboolean flag) { i810ContextPtr imesa = I810_CONTEXT(ctx); I810_STATECHANGE(imesa, I810_UPLOAD_CTX); if (flag) imesa->Setup[I810_CTXREG_B2] |= B2_ZB_WRITE_ENABLE; else imesa->Setup[I810_CTXREG_B2] &= ~B2_ZB_WRITE_ENABLE; }
static void i810BlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA ) { i810ContextPtr imesa = I810_CONTEXT(ctx); GLuint a = SDM_UPDATE_SRC_BLEND | SDM_UPDATE_DST_BLEND; GLboolean fallback = GL_FALSE; switch (ctx->Color.BlendSrcRGB) { case GL_ZERO: a |= SDM_SRC_ZERO; break; case GL_SRC_ALPHA: a |= SDM_SRC_SRC_ALPHA; break; case GL_ONE: a |= SDM_SRC_ONE; break; case GL_DST_COLOR: a |= SDM_SRC_DST_COLOR; break; case GL_ONE_MINUS_DST_COLOR: a |= SDM_SRC_INV_DST_COLOR; break; case GL_ONE_MINUS_SRC_ALPHA: a |= SDM_SRC_INV_SRC_ALPHA; break; case GL_DST_ALPHA: a |= SDM_SRC_ONE; break; case GL_ONE_MINUS_DST_ALPHA: a |= SDM_SRC_ZERO; break; case GL_SRC_ALPHA_SATURATE: /*a |= SDM_SRC_SRC_ALPHA; break;*/ case GL_CONSTANT_COLOR: case GL_ONE_MINUS_CONSTANT_COLOR: case GL_CONSTANT_ALPHA: case GL_ONE_MINUS_CONSTANT_ALPHA: fallback = GL_TRUE; break; default: return; } switch (ctx->Color.BlendDstRGB) { case GL_SRC_ALPHA: a |= SDM_DST_SRC_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: a |= SDM_DST_INV_SRC_ALPHA; break; case GL_ZERO: a |= SDM_DST_ZERO; break; case GL_ONE: a |= SDM_DST_ONE; break; case GL_SRC_COLOR: a |= SDM_DST_SRC_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: a |= SDM_DST_INV_SRC_COLOR; break; case GL_DST_ALPHA: a |= SDM_DST_ONE; break; case GL_ONE_MINUS_DST_ALPHA: a |= SDM_DST_ZERO; break; case GL_CONSTANT_COLOR: case GL_ONE_MINUS_CONSTANT_COLOR: case GL_CONSTANT_ALPHA: case GL_ONE_MINUS_CONSTANT_ALPHA: fallback = GL_TRUE; break; default: return; } FALLBACK( imesa, I810_FALLBACK_BLEND_FUNC, fallback); if (!fallback) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_SDM] &= ~(SDM_SRC_MASK|SDM_DST_MASK); imesa->Setup[I810_CTXREG_SDM] |= a; } }
/* ============================================================= * Fog */ static void i810Fogfv(struct gl_context *ctx, GLenum pname, const GLfloat *param) { i810ContextPtr imesa = I810_CONTEXT(ctx); if (pname == GL_FOG_COLOR) { GLuint color = (((GLubyte)(ctx->Fog.Color[0]*255.0F) << 16) | ((GLubyte)(ctx->Fog.Color[1]*255.0F) << 8) | ((GLubyte)(ctx->Fog.Color[2]*255.0F) << 0)); I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_FOG] = ((GFX_OP_FOG_COLOR | color) & ~FOG_RESERVED_MASK); } }
/* But the 815 has it... */ static void i810LightModelfv_i815(struct gl_context *ctx, GLenum pname, const GLfloat *param) { if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { i810ContextPtr imesa = I810_CONTEXT( ctx ); I810_STATECHANGE(imesa, I810_UPLOAD_CTX); if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) imesa->Setup[I810_CTXREG_B1] |= B1_SPEC_ENABLE; else imesa->Setup[I810_CTXREG_B1] &= ~B1_SPEC_ENABLE; } }
static void i810LineWidth( GLcontext *ctx, GLfloat widthf ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); int width = (int)ctx->Line._Width; imesa->LcsLineWidth = 0; if (width & 1) imesa->LcsLineWidth |= LCS_LINEWIDTH_1_0; if (width & 2) imesa->LcsLineWidth |= LCS_LINEWIDTH_2_0; if (imesa->reduced_primitive == GL_LINES) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_3_0; imesa->Setup[I810_CTXREG_LCS] |= imesa->LcsLineWidth; } }
static void i810PointSize( GLcontext *ctx, GLfloat sz ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); int size = (int)ctx->Point._Size; imesa->LcsPointSize = 0; if (size & 1) imesa->LcsPointSize |= LCS_LINEWIDTH_1_0; if (size & 2) imesa->LcsPointSize |= LCS_LINEWIDTH_2_0; if (imesa->reduced_primitive == GL_POINTS) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_3_0; imesa->Setup[I810_CTXREG_LCS] |= imesa->LcsPointSize; } }
static void i810TexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); GLuint unit = ctx->Texture.CurrentUnit; /* Only one env color. Need a fallback if env colors are different * and texture setup references env color in both units. */ switch (pname) { case GL_TEXTURE_ENV_COLOR: { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; GLfloat *fc = texUnit->EnvColor; GLuint r, g, b, a, col; CLAMPED_FLOAT_TO_UBYTE(r, fc[0]); CLAMPED_FLOAT_TO_UBYTE(g, fc[1]); CLAMPED_FLOAT_TO_UBYTE(b, fc[2]); CLAMPED_FLOAT_TO_UBYTE(a, fc[3]); col = ((a << 24) | (r << 16) | (g << 8) | (b << 0)); if (imesa->Setup[I810_CTXREG_CF1] != col) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_CF1] = col; } break; } case GL_TEXTURE_ENV_MODE: imesa->TexEnvImageFmt[unit] = 0; /* force recalc of env state */ break; case GL_TEXTURE_LOD_BIAS_EXT: { struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; i810TextureObjectPtr t = (i810TextureObjectPtr) tObj->DriverData; t->Setup[I810_TEXREG_MLC] &= ~(MLC_LOD_BIAS_MASK); t->Setup[I810_TEXREG_MLC] |= i810ComputeLodBias(*param); } break; default: break; } }
/* ============================================================= * Polygon stipple * * The i810 supports a 4x4 stipple natively, GL wants 32x32. * Fortunately stipple is usually a repeating pattern. */ static void i810PolygonStipple( struct gl_context *ctx, const GLubyte *mask ) { i810ContextPtr imesa = I810_CONTEXT(ctx); const GLubyte *m = mask; GLubyte p[4]; int i,j,k; int active = (ctx->Polygon.StippleFlag && imesa->reduced_primitive == GL_TRIANGLES); GLuint newMask; if (active) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_ST1] &= ~ST1_ENABLE; } p[0] = mask[12] & 0xf; p[0] |= p[0] << 4; p[1] = mask[8] & 0xf; p[1] |= p[1] << 4; p[2] = mask[4] & 0xf; p[2] |= p[2] << 4; p[3] = mask[0] & 0xf; p[3] |= p[3] << 4; for (k = 0 ; k < 8 ; k++) for (j = 0 ; j < 4; j++) for (i = 0 ; i < 4 ; i++) if (*m++ != p[j]) { imesa->stipple_in_hw = 0; return; } newMask = ((p[0] & 0xf) << 0) | ((p[1] & 0xf) << 4) | ((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12); if (newMask == 0xffff) { /* this is needed to make conform pass */ imesa->stipple_in_hw = 0; return; } imesa->Setup[I810_CTXREG_ST1] &= ~0xffff; imesa->Setup[I810_CTXREG_ST1] |= newMask; imesa->stipple_in_hw = 1; if (active) imesa->Setup[I810_CTXREG_ST1] |= ST1_ENABLE; }
void i810DrawBuffer(GLcontext *ctx, GLenum mode ) { i810ContextPtr imesa = I810_CONTEXT(ctx); int front = 0; /* * _DrawDestMask is easier to cope with than <mode>. */ switch ( ctx->Color._DrawDestMask[0] ) { case DD_FRONT_LEFT_BIT: front = 1; break; case DD_BACK_LEFT_BIT: front = 0; break; default: /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */ FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_TRUE ); return; } if ( imesa->sarea->pf_current_page == 1 ) front ^= 1; FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_FALSE ); I810_FIREVERTICES(imesa); I810_STATECHANGE(imesa, I810_UPLOAD_BUFFERS); if (front) { imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->fbOffset | imesa->i810Screen->backPitchBits); i810XMesaSetFrontClipRects( imesa ); } else { imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->backOffset | imesa->i810Screen->backPitchBits); i810XMesaSetBackClipRects( imesa ); } /* We want to update the s/w rast state too so that r200SetBuffer() * gets called. */ _swrast_DrawBuffer(ctx, mode); }
static void i810PointSize( struct gl_context *ctx, GLfloat sz ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); /* AA, non-AA limits are same */ const int size = (int) CLAMP(ctx->Point.Size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize); imesa->LcsPointSize = 0; if (size & 1) imesa->LcsPointSize |= LCS_LINEWIDTH_1_0; if (size & 2) imesa->LcsPointSize |= LCS_LINEWIDTH_2_0; if (imesa->reduced_primitive == GL_POINTS) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_3_0; imesa->Setup[I810_CTXREG_LCS] |= imesa->LcsPointSize; } }
static void i810LineWidth( struct gl_context *ctx, GLfloat widthf ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); /* AA, non-AA limits are same */ const int width = (int) CLAMP(ctx->Line.Width, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth); imesa->LcsLineWidth = 0; if (width & 1) imesa->LcsLineWidth |= LCS_LINEWIDTH_1_0; if (width & 2) imesa->LcsLineWidth |= LCS_LINEWIDTH_2_0; if (imesa->reduced_primitive == GL_LINES) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_3_0; imesa->Setup[I810_CTXREG_LCS] |= imesa->LcsLineWidth; } }
void i810DrawBuffer(struct gl_context *ctx, GLenum mode ) { i810ContextPtr imesa = I810_CONTEXT(ctx); int front = 0; if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) { /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */ FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_TRUE ); return; } switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0]) { case BUFFER_FRONT_LEFT: front = 1; break; case BUFFER_BACK_LEFT: front = 0; break; default: FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_TRUE ); return; } if ( imesa->sarea->pf_current_page == 1 ) front ^= 1; FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_FALSE ); I810_FIREVERTICES(imesa); I810_STATECHANGE(imesa, I810_UPLOAD_BUFFERS); if (front) { imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->fbOffset | imesa->i810Screen->backPitchBits); i810XMesaSetFrontClipRects( imesa ); } else { imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->backOffset | imesa->i810Screen->backPitchBits); i810XMesaSetBackClipRects( imesa ); } }
static GLboolean enable_tex_2d( struct gl_context *ctx, GLuint unit ) { i810ContextPtr imesa = I810_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData; GLint log2Width, log2Height; log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2; log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2; I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit)); t->Setup[I810_TEXREG_MCS] |= MCS_NORMALIZED_COORDS | MCS_UPDATE_NORMALIZED; t->Setup[I810_TEXREG_MI2] = (MI2_DIMENSIONS_ARE_LOG2 | (log2Height << MI2_HEIGHT_SHIFT) | log2Width); return GL_TRUE; }
static void i810DepthFunc(struct gl_context *ctx, GLenum func) { i810ContextPtr imesa = I810_CONTEXT(ctx); int zmode; switch(func) { case GL_NEVER: zmode = LCS_Z_NEVER; break; case GL_ALWAYS: zmode = LCS_Z_ALWAYS; break; case GL_LESS: zmode = LCS_Z_LESS; break; case GL_LEQUAL: zmode = LCS_Z_LEQUAL; break; case GL_EQUAL: zmode = LCS_Z_EQUAL; break; case GL_GREATER: zmode = LCS_Z_GREATER; break; case GL_GEQUAL: zmode = LCS_Z_GEQUAL; break; case GL_NOTEQUAL: zmode = LCS_Z_NOTEQUAL; break; default: return; } I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_LCS] &= ~LCS_Z_MASK; imesa->Setup[I810_CTXREG_LCS] |= zmode; }
/* ============================================================= * Culling - the i810 isn't quite as clean here as the rest of * its interfaces, but it's not bad. */ static void i810CullFaceFrontFace(struct gl_context *ctx, GLenum unused) { i810ContextPtr imesa = I810_CONTEXT(ctx); GLuint mode = LCS_CULL_BOTH; if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) { mode = LCS_CULL_CW; if (ctx->Polygon.CullFaceMode == GL_FRONT) mode ^= (LCS_CULL_CW ^ LCS_CULL_CCW); if (ctx->Polygon.FrontFace != GL_CCW) mode ^= (LCS_CULL_CW ^ LCS_CULL_CCW); } imesa->LcsCullMode = mode; if (ctx->Polygon.CullFlag) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_LCS] &= ~LCS_CULL_MASK; imesa->Setup[I810_CTXREG_LCS] |= mode; } }
void i810ChooseVertexState( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); i810ContextPtr imesa = I810_CONTEXT( ctx ); GLuint ind = I810_XYZW_BIT|I810_RGBA_BIT; if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ind |= I810_SPEC_BIT; if (ctx->Fog.Enabled) ind |= I810_FOG_BIT; if (ctx->Texture._EnabledUnits & 0x2) /* unit 1 enabled */ ind |= I810_TEX1_BIT|I810_TEX0_BIT; else if (ctx->Texture._EnabledUnits & 0x1) /* unit 0 enabled */ ind |= I810_TEX0_BIT; imesa->SetupIndex = ind; if (I810_DEBUG & (DEBUG_VERTS|DEBUG_STATE)) i810PrintSetupFlags( __FUNCTION__, ind ); if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { tnl->Driver.Render.Interp = i810_interp_extras; tnl->Driver.Render.CopyPV = i810_copy_pv_extras; } else { tnl->Driver.Render.Interp = setup_tab[ind].interp; tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv; } if (setup_tab[ind].vertex_format != imesa->Setup[I810_CTXREG_VF]) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_VF] = setup_tab[ind].vertex_format; imesa->vertex_size = setup_tab[ind].vertex_size; } }
static GLboolean enable_tex_common( struct gl_context *ctx, GLuint unit ) { i810ContextPtr imesa = I810_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData; if (tObj->Image[0][tObj->BaseLevel]->Border > 0) { return GL_FALSE; } /* Upload teximages (not pipelined) */ if (t->base.dirty_images[0]) { I810_FIREVERTICES(imesa); i810SetTexImages( imesa, tObj ); if (!t->base.memBlock) { return GL_FALSE; } } /* Update state if this is a different texture object to last * time. */ if (imesa->CurrentTexObj[unit] != t) { I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit)); imesa->CurrentTexObj[unit] = t; t->base.bound |= (1U << unit); /* XXX: should be locked */ driUpdateTextureLRU( (driTextureObject *) t ); } imesa->TexEnvImageFmt[unit] = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; return GL_TRUE; }
static void i810ColorMask(struct gl_context *ctx, GLboolean r, GLboolean g, GLboolean b, GLboolean a ) { i810ContextPtr imesa = I810_CONTEXT( ctx ); GLuint tmp = 0; if (r && g && b) { tmp = imesa->Setup[I810_CTXREG_B2] | B2_FB_WRITE_ENABLE; FALLBACK( imesa, I810_FALLBACK_COLORMASK, GL_FALSE ); } else if (!r && !g && !b) { tmp = imesa->Setup[I810_CTXREG_B2] & ~B2_FB_WRITE_ENABLE; FALLBACK( imesa, I810_FALLBACK_COLORMASK, GL_FALSE ); } else { FALLBACK( imesa, I810_FALLBACK_COLORMASK, GL_TRUE ); return; } if (tmp != imesa->Setup[I810_CTXREG_B2]) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_B2] = tmp; imesa->dirty |= I810_UPLOAD_CTX; } }
static void i810TexParameter( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLenum pname, const GLfloat *params ) { i810ContextPtr imesa = I810_CONTEXT(ctx); i810TextureObjectPtr t = (i810TextureObjectPtr) tObj->DriverData; if (!t) return; if ( target != GL_TEXTURE_2D ) return; /* Can't do the update now as we don't know whether to flush * vertices or not. Setting imesa->new_state means that * i810UpdateTextureState() will be called before any triangles are * rendered. If a statechange has occurred, it will be detected at * that point, and buffered vertices flushed. */ switch (pname) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: { GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias; i810SetTexFilter( imesa, t, tObj->MinFilter, tObj->MagFilter, bias ); } break; case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: i810SetTexWrapping( t, tObj->WrapS, tObj->WrapT ); break; case GL_TEXTURE_BORDER_COLOR: i810SetTexBorderColor( t, tObj->_BorderChan ); break; case GL_TEXTURE_BASE_LEVEL: case GL_TEXTURE_MAX_LEVEL: case GL_TEXTURE_MIN_LOD: case GL_TEXTURE_MAX_LOD: /* This isn't the most efficient solution but there doesn't appear to * be a nice alternative for Radeon. Since there's no LOD clamping, * we just have to rely on loading the right subset of mipmap levels * to simulate a clamped LOD. */ I810_FIREVERTICES( I810_CONTEXT(ctx) ); driSwapOutTextureObject( (driTextureObject *) t ); break; default: return; } if (t == imesa->CurrentTexObj[0]) { I810_STATECHANGE( imesa, I810_UPLOAD_TEX0 ); } if (t == imesa->CurrentTexObj[1]) { I810_STATECHANGE( imesa, I810_UPLOAD_TEX1 ); } }
/* ============================================================= */ static void i810Enable(struct gl_context *ctx, GLenum cap, GLboolean state) { i810ContextPtr imesa = I810_CONTEXT(ctx); switch(cap) { case GL_ALPHA_TEST: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_B1] &= ~B1_ALPHA_TEST_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_ALPHA_TEST_ENABLE; break; case GL_BLEND: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_B1] &= ~B1_BLEND_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_BLEND_ENABLE; /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled. */ FALLBACK( imesa, I810_FALLBACK_LOGICOP, (ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY)); break; case GL_DEPTH_TEST: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_B1] &= ~B1_Z_TEST_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_Z_TEST_ENABLE; break; case GL_SCISSOR_TEST: /* XXX without these next two lines, conform's scissor test fails */ I810_STATECHANGE(imesa, I810_UPLOAD_CTX); I810_STATECHANGE(imesa, I810_UPLOAD_BUFFERS); I810_FIREVERTICES(imesa); /* don't pipeline cliprect changes */ imesa->upload_cliprects = GL_TRUE; imesa->scissor = state; break; case GL_POLYGON_STIPPLE: if (imesa->stipple_in_hw && imesa->reduced_primitive == GL_TRIANGLES) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_ST1] &= ~ST1_ENABLE; if (state) imesa->Setup[I810_CTXREG_ST1] |= ST1_ENABLE; } break; case GL_LINE_SMOOTH: /* Need to fatten the lines by .5, or they disappear... */ if (imesa->reduced_primitive == GL_LINES) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE; imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_0_5; if (state) { imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; imesa->Setup[I810_CTXREG_LCS] |= LCS_LINEWIDTH_0_5; } } break; case GL_POINT_SMOOTH: if (imesa->reduced_primitive == GL_POINTS) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE; imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_0_5; if (state) { imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; imesa->Setup[I810_CTXREG_LCS] |= LCS_LINEWIDTH_0_5; } } break; case GL_POLYGON_SMOOTH: if (imesa->reduced_primitive == GL_TRIANGLES) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE; if (state) imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE; } break; case GL_FOG: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_B1] &= ~B1_FOG_ENABLE; if (state) imesa->Setup[I810_CTXREG_B1] |= B1_FOG_ENABLE; break; case GL_CULL_FACE: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_LCS] &= ~LCS_CULL_MASK; if (state) imesa->Setup[I810_CTXREG_LCS] |= imesa->LcsCullMode; else imesa->Setup[I810_CTXREG_LCS] |= LCS_CULL_DISABLE; break; case GL_TEXTURE_2D: case GL_TEXTURE_RECTANGLE_NV: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); if (ctx->Texture.CurrentUnit == 0) { imesa->Setup[I810_CTXREG_MT] &= ~MT_TEXEL0_ENABLE; if (state) imesa->Setup[I810_CTXREG_MT] |= MT_TEXEL0_ENABLE; } else { imesa->Setup[I810_CTXREG_MT] &= ~MT_TEXEL1_ENABLE; if (state) imesa->Setup[I810_CTXREG_MT] |= MT_TEXEL1_ENABLE; } break; case GL_COLOR_LOGIC_OP: FALLBACK( imesa, I810_FALLBACK_LOGICOP, (state && ctx->Color.LogicOp != GL_COPY)); break; case GL_STENCIL_TEST: FALLBACK( imesa, I810_FALLBACK_STENCIL, state ); break; default: ; } }
static void i810BlendFuncSeparate( struct gl_context *ctx, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA ) { i810ContextPtr imesa = I810_CONTEXT(ctx); GLuint a = SDM_UPDATE_SRC_BLEND | SDM_UPDATE_DST_BLEND; GLboolean fallback = GL_FALSE; switch (ctx->Color.Blend[0].SrcRGB) { case GL_ZERO: a |= SDM_SRC_ZERO; break; case GL_ONE: a |= SDM_SRC_ONE; break; case GL_SRC_COLOR: a |= SDM_SRC_SRC_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: a |= SDM_SRC_INV_SRC_COLOR; break; case GL_SRC_ALPHA: a |= SDM_SRC_SRC_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: a |= SDM_SRC_INV_SRC_ALPHA; break; case GL_DST_ALPHA: a |= SDM_SRC_ONE; break; case GL_ONE_MINUS_DST_ALPHA: a |= SDM_SRC_ZERO; break; case GL_DST_COLOR: a |= SDM_SRC_DST_COLOR; break; case GL_ONE_MINUS_DST_COLOR: a |= SDM_SRC_INV_DST_COLOR; break; /* (f, f, f, 1), f = min(As, 1 - Ad) = min(As, 1 - 1) = 0 * So (f, f, f, 1) = (0, 0, 0, 1). Since there is no destination alpha and * the only supported alpha operation is GL_FUNC_ADD, the result modulating * the source alpha with the alpha factor is largely irrelevant. */ case GL_SRC_ALPHA_SATURATE: a |= SDM_SRC_ZERO; break; case GL_CONSTANT_COLOR: case GL_ONE_MINUS_CONSTANT_COLOR: case GL_CONSTANT_ALPHA: case GL_ONE_MINUS_CONSTANT_ALPHA: fallback = GL_TRUE; break; default: return; } switch (ctx->Color.Blend[0].DstRGB) { case GL_ZERO: a |= SDM_DST_ZERO; break; case GL_ONE: a |= SDM_DST_ONE; break; case GL_SRC_COLOR: a |= SDM_DST_SRC_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: a |= SDM_DST_INV_SRC_COLOR; break; case GL_SRC_ALPHA: a |= SDM_DST_SRC_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: a |= SDM_DST_INV_SRC_ALPHA; break; case GL_DST_ALPHA: a |= SDM_DST_ONE; break; case GL_ONE_MINUS_DST_ALPHA: a |= SDM_DST_ZERO; break; case GL_DST_COLOR: a |= SDM_DST_DST_COLOR; break; case GL_ONE_MINUS_DST_COLOR: a |= SDM_DST_INV_DST_COLOR; break; case GL_CONSTANT_COLOR: case GL_ONE_MINUS_CONSTANT_COLOR: case GL_CONSTANT_ALPHA: case GL_ONE_MINUS_CONSTANT_ALPHA: fallback = GL_TRUE; break; default: return; } FALLBACK( imesa, I810_FALLBACK_BLEND_FUNC, fallback); if (!fallback) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->Setup[I810_CTXREG_SDM] &= ~(SDM_SRC_MASK|SDM_DST_MASK); imesa->Setup[I810_CTXREG_SDM] |= a; } }
/* System to flush dma and emit state changes based on the rasterized * primitive. */ void i810RasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) { i810ContextPtr imesa = I810_CONTEXT(ctx); GLuint st1 = imesa->Setup[I810_CTXREG_ST1]; GLuint aa = imesa->Setup[I810_CTXREG_AA]; GLuint lcs = imesa->Setup[I810_CTXREG_LCS]; st1 &= ~ST1_ENABLE; aa &= ~AA_ENABLE; if (I810_DEBUG & DEBUG_PRIMS) { /* Prints reduced prim, and hw prim */ char *prim_name = "Unknown"; switch(hwprim) { case PR_LINES: prim_name = "Lines"; break; case PR_LINESTRIP: prim_name = "LineStrip"; break; case PR_TRIANGLES: prim_name = "Triangles"; break; case PR_TRISTRIP_0: prim_name = "TriStrip_0"; break; case PR_TRIFAN: prim_name = "TriFan"; break; case PR_POLYGON: prim_name = "Polygons"; break; default: break; } fprintf(stderr, "%s : rprim(%s), hwprim(%s)\n", __FUNCTION__, _mesa_lookup_enum_by_nr(rprim), prim_name); } switch (rprim) { case GL_TRIANGLES: if (ctx->Polygon.StippleFlag) st1 |= ST1_ENABLE; if (ctx->Polygon.SmoothFlag) aa |= AA_ENABLE; break; case GL_LINES: lcs &= ~(LCS_LINEWIDTH_3_0|LCS_LINEWIDTH_0_5); lcs |= imesa->LcsLineWidth; if (ctx->Line.SmoothFlag) { aa |= AA_ENABLE; lcs |= LCS_LINEWIDTH_0_5; } break; case GL_POINTS: lcs &= ~(LCS_LINEWIDTH_3_0|LCS_LINEWIDTH_0_5); lcs |= imesa->LcsPointSize; if (ctx->Point.SmoothFlag) { aa |= AA_ENABLE; lcs |= LCS_LINEWIDTH_0_5; } break; default: return; } imesa->reduced_primitive = rprim; if (st1 != imesa->Setup[I810_CTXREG_ST1] || aa != imesa->Setup[I810_CTXREG_AA] || lcs != imesa->Setup[I810_CTXREG_LCS]) { I810_STATECHANGE(imesa, I810_UPLOAD_CTX); imesa->hw_primitive = hwprim; imesa->Setup[I810_CTXREG_LCS] = lcs; imesa->Setup[I810_CTXREG_ST1] = st1; imesa->Setup[I810_CTXREG_AA] = aa; } else if (hwprim != imesa->hw_primitive) { I810_STATECHANGE(imesa, 0); imesa->hw_primitive = hwprim; } }