static void mgaSetTexBorderColor(mgaTextureObjectPtr t, const GLfloat color[4]) { GLubyte c[4]; CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); t->setup.texbordercol = PACK_COLOR_8888(c[3], c[0], c[1], c[2] ); }
static void r128SetTexBorderColor( r128TexObjPtr t, const GLfloat color[4] ) { GLubyte c[4]; CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); t->setup.tex_border_color = r128PackColor( 4, c[0], c[1], c[2], c[3] ); }
static void r200SetTexBorderColor( radeonTexObjPtr t, const GLfloat color[4] ) { GLubyte c[4]; CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] ); }
static void i810ClearColor(struct gl_context *ctx, const GLfloat color[4] ) { i810ContextPtr imesa = I810_CONTEXT(ctx); GLubyte c[4]; CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); imesa->ClearColor = i810PackColor( imesa->i810Screen->fbFormat, c[0], c[1], c[2], c[3] ); }
static void mach64DDTexEnv( struct gl_context *ctx, GLenum target, GLenum pname, const GLfloat *param ) { mach64ContextPtr mmesa = MACH64_CONTEXT(ctx); #if 0 struct gl_texture_unit *texUnit; GLubyte c[4]; #endif if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "%s( %s )\n", __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) ); } switch ( pname ) { case GL_TEXTURE_ENV_MODE: FLUSH_BATCH( mmesa ); mmesa->new_state |= MACH64_NEW_TEXTURE | MACH64_NEW_ALPHA; break; #if 0 case GL_TEXTURE_ENV_COLOR: texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; CLAMPED_FLOAT_TO_UBYTE( c[0], texUnit->EnvColor[0] ); CLAMPED_FLOAT_TO_UBYTE( c[1], texUnit->EnvColor[1] ); CLAMPED_FLOAT_TO_UBYTE( c[2], texUnit->EnvColor[2] ); CLAMPED_FLOAT_TO_UBYTE( c[3], texUnit->EnvColor[3] ); mmesa->env_color = mach64PackColor( 32, c[0], c[1], c[2], c[3] ); if ( mmesa->setup.constant_color_c != mmesa->env_color ) { FLUSH_BATCH( mmesa ); mmesa->setup.constant_color_c = mmesa->env_color; mmesa->new_state |= MACH64_NEW_TEXTURE; /* More complex multitexture/multipass fallbacks for GL_BLEND * can be done later, but this allows a single pass GL_BLEND * in some cases (ie. Performer town demo). */ mmesa->blend_flags &= ~MACH64_BLEND_ENV_COLOR; if ( mmesa->env_color != 0x00000000 && mmesa->env_color != 0xff000000 && mmesa->env_color != 0x00ffffff && mmesa->env_color != 0xffffffff )) { mmesa->blend_flags |= MACH64_BLEND_ENV_COLOR; } } break; #endif default: return; }
static void tdfxDDClearColor( GLcontext *ctx, const GLfloat color[4] ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); GLubyte c[4]; FLUSH_BATCH( fxMesa ); CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); fxMesa->Color.ClearColor = TDFXPACKCOLOR888( c[0], c[1], c[2] ); fxMesa->Color.ClearAlpha = c[3]; }
static void nv30BlendColor(GLcontext *ctx, const GLfloat color[4]) { nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); GLubyte cf[4]; CLAMPED_FLOAT_TO_UBYTE(cf[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(cf[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(cf[2], color[2]); CLAMPED_FLOAT_TO_UBYTE(cf[3], color[3]); BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_COLOR, 1); OUT_RING_CACHE(PACK_COLOR_8888(cf[3], cf[1], cf[2], cf[0])); }
static void mgaDDClearColor(GLcontext *ctx, const GLfloat color[4] ) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); GLubyte c[4]; CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp, c[0], c[1], c[2], c[3]); }
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 intelClearColor(GLcontext * ctx, const GLfloat color[4]) { struct intel_context *intel = intel_context(ctx); GLubyte clear[4]; CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]); CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]); /* compute both 32 and 16-bit clear values */ intel->ClearColor8888 = INTEL_PACKCOLOR8888(clear[0], clear[1], clear[2], clear[3]); intel->ClearColor565 = INTEL_PACKCOLOR565(clear[0], clear[1], clear[2]); }
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; } }
static void nv30AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) { nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); GLubyte ubRef; CLAMPED_FLOAT_TO_UBYTE(ubRef, ref); BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2); OUT_RING_CACHE(func); /* NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC */ OUT_RING_CACHE(ubRef); /* NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF */ }
static void gl_ggiSetClearColor(GLcontext *ctx, const GLfloat color[4]) { ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx; ggi_color rgb; ggi_pixel col; GLubyte byteColor[3]; GGIMESADPRINT_CORE("gl_ggiSetClearColor() called\n"); CLAMPED_FLOAT_TO_UBYTE(byteColor[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(byteColor[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(byteColor[2], color[2]); rgb.r = (uint16)byteColor[0] << SHIFT; rgb.g = (uint16)byteColor[1] << SHIFT; rgb.b = (uint16)byteColor[2] << SHIFT; col = ggiMapColor(ggi_ctx->ggi_visual, &rgb); ggiSetGCForeground(ggi_ctx->ggi_visual, col); ggi_ctx->clearcolor = col; }
static void clear_color( GLcontext *ctx, const GLfloat color[4] ) { if (ctx->DrawBuffer->Name == 0) { const XMesaContext xmesa = XMESA_CONTEXT(ctx); XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]); CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]); xmesa->clearpixel = xmesa_color_to_pixel( ctx, xmesa->clearcolor[0], xmesa->clearcolor[1], xmesa->clearcolor[2], xmesa->clearcolor[3], xmesa->xm_visual->undithered_pf ); _glthread_LOCK_MUTEX(_xmesa_lock); XMesaSetForeground( xmesa->display, xmbuf->cleargc, xmesa->clearpixel ); _glthread_UNLOCK_MUTEX(_xmesa_lock); } }
static void sis6326DDAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref ) { sisContextPtr smesa = SIS_CONTEXT(ctx); GLubyte refbyte; __GLSiSHardware *prev = &smesa->prev; __GLSiSHardware *current = &smesa->current; CLAMPED_FLOAT_TO_UBYTE(refbyte, ref); current->hwAlpha = refbyte << 16; /* Alpha Test function */ switch (func) { case GL_NEVER: current->hwAlpha |= S_ASET_PASS_NEVER; break; case GL_LESS: current->hwAlpha |= S_ASET_PASS_LESS; break; case GL_EQUAL: current->hwAlpha |= S_ASET_PASS_EQUAL; break; case GL_LEQUAL: current->hwAlpha |= S_ASET_PASS_LEQUAL; break; case GL_GREATER: current->hwAlpha |= S_ASET_PASS_GREATER; break; case GL_NOTEQUAL: current->hwAlpha |= S_ASET_PASS_NOTEQUAL; break; case GL_GEQUAL: current->hwAlpha |= S_ASET_PASS_GEQUAL; break; case GL_ALWAYS: current->hwAlpha |= S_ASET_PASS_ALWAYS; break; } prev->hwAlpha = current->hwAlpha; smesa->GlobalFlag |= GFLAG_ALPHASETTING; }
static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); GLubyte refByte; GLuint a; CLAMPED_FLOAT_TO_UBYTE(refByte, ref); switch ( func ) { case GL_NEVER: a = AC_atmode_alt; refByte = 0; break; case GL_LESS: a = AC_atmode_alt; break; case GL_GEQUAL: a = AC_atmode_agte; break; case GL_LEQUAL: a = AC_atmode_alte; break; case GL_GREATER: a = AC_atmode_agt; break; case GL_NOTEQUAL: a = AC_atmode_ane; break; case GL_EQUAL: a = AC_atmode_ae; break; case GL_ALWAYS: a = AC_atmode_noacmp; break; default: a = 0; break; } MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT ); mmesa->hw.alpha_func = a | MGA_FIELD( AC_atref, refByte ); }
static void nv04_emit_control(GLcontext *ctx) { nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); uint32_t control,cull; GLubyte alpha_ref; CLAMPED_FLOAT_TO_UBYTE(alpha_ref, ctx->Color.AlphaRef); control=alpha_ref; control|=(nv04_compare_func(ctx->Color.AlphaFunc)<<8); control|=(ctx->Color.AlphaEnabled<<12); control|=(1<<13); control|=(ctx->Depth.Test<<14); control|=(nv04_compare_func(ctx->Depth.Func)<<16); if ((ctx->Polygon.CullFlag)&&(ctx->Polygon.CullFaceMode!=GL_FRONT_AND_BACK)) { if ((ctx->Polygon.FrontFace==GL_CW)&&(ctx->Polygon.CullFaceMode==GL_FRONT)) cull=2; if ((ctx->Polygon.FrontFace==GL_CW)&&(ctx->Polygon.CullFaceMode==GL_BACK)) cull=3; if ((ctx->Polygon.FrontFace==GL_CCW)&&(ctx->Polygon.CullFaceMode==GL_FRONT)) cull=3; if ((ctx->Polygon.FrontFace==GL_CCW)&&(ctx->Polygon.CullFaceMode==GL_BACK)) cull=2; } else if (ctx->Polygon.CullFaceMode==GL_FRONT_AND_BACK) cull=0; else cull=1; control|=(cull<<20); control|=(ctx->Color.DitherFlag<<22); if ((ctx->Depth.Test)&&(ctx->Depth.Mask)) control|=(1<<24); control|=(1<<30); // integer zbuffer format BEGIN_RING_CACHE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1); OUT_RING_CACHE(control); }
static void r128TexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); struct gl_texture_unit *texUnit; GLubyte c[4]; if ( R128_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "%s( %s )\n", __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) ); } switch ( pname ) { case GL_TEXTURE_ENV_MODE: FLUSH_BATCH( rmesa ); rmesa->new_state |= R128_NEW_ALPHA; break; case GL_TEXTURE_ENV_COLOR: texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; CLAMPED_FLOAT_TO_UBYTE( c[0], texUnit->EnvColor[0] ); CLAMPED_FLOAT_TO_UBYTE( c[1], texUnit->EnvColor[1] ); CLAMPED_FLOAT_TO_UBYTE( c[2], texUnit->EnvColor[2] ); CLAMPED_FLOAT_TO_UBYTE( c[3], texUnit->EnvColor[3] ); rmesa->env_color = r128PackColor( 4, c[0], c[1], c[2], c[3] ); if ( rmesa->setup.constant_color_c != rmesa->env_color ) { FLUSH_BATCH( rmesa ); rmesa->setup.constant_color_c = rmesa->env_color; /* More complex multitexture/multipass fallbacks for GL_BLEND * can be done later, but this allows a single pass GL_BLEND * in some cases (ie. Performer town demo). This is only * applicable to the regular Rage 128, as the Pro and M3 can * handle true single-pass GL_BLEND texturing. */ rmesa->blend_flags &= ~R128_BLEND_ENV_COLOR; if ( R128_IS_PLAIN( rmesa ) && rmesa->env_color != 0x00000000 && rmesa->env_color != 0xff000000 && rmesa->env_color != 0x00ffffff && rmesa->env_color != 0xffffffff ) { rmesa->blend_flags |= R128_BLEND_ENV_COLOR; } } break; case GL_TEXTURE_LOD_BIAS: { uint32_t t = rmesa->setup.tex_cntl_c; GLint bias; uint32_t b; /* GTH: This isn't exactly correct, but gives good results up to a * certain point. It is better than completely ignoring the LOD * bias. Unfortunately there isn't much range in the bias, the * spec mentions strides that vary between 0.5 and 2.0 but these * numbers don't seem to relate to the GL LOD bias value at all. */ if ( param[0] >= 1.0 ) { bias = -128; } else if ( param[0] >= 0.5 ) { bias = -64; } else if ( param[0] >= 0.25 ) { bias = 0; } else if ( param[0] >= 0.0 ) { bias = 63; } else { bias = 127; } b = (uint32_t)bias & 0xff; t &= ~R128_LOD_BIAS_MASK; t |= (b << R128_LOD_BIAS_SHIFT); if ( rmesa->setup.tex_cntl_c != t ) { FLUSH_BATCH( rmesa ); rmesa->setup.tex_cntl_c = t; rmesa->dirty |= R128_UPLOAD_CONTEXT; } } break; default: return; } }
/* Recalculate all state from scratch. Perhaps not the most * efficient, but this has gotten complex enough that we need * something which is understandable and reliable. */ static GLboolean i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) { GLcontext *ctx = &intel->ctx; struct i830_context *i830 = i830_context(ctx); struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = tUnit->_Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage; GLuint *state = i830->state.Tex[unit], format, pitch; GLint lodbias; GLubyte border[4]; GLuint dst_x, dst_y; memset(state, 0, sizeof(state)); /*We need to refcount these. */ if (i830->state.tex_buffer[unit] != NULL) { drm_intel_bo_unreference(i830->state.tex_buffer[unit]); i830->state.tex_buffer[unit] = NULL; } if (!intel_finalize_mipmap_tree(intel, unit)) return GL_FALSE; /* Get first image here, since intelObj->firstLevel will get set in * the intel_finalize_mipmap_tree() call above. */ firstImage = tObj->Image[0][intelObj->firstLevel]; intel_miptree_get_image_offset(intelObj->mt, intelObj->firstLevel, 0, 0, &dst_x, &dst_y); drm_intel_bo_reference(intelObj->mt->region->buffer); i830->state.tex_buffer[unit] = intelObj->mt->region->buffer; pitch = intelObj->mt->region->pitch * intelObj->mt->cpp; /* XXX: This calculation is probably broken for tiled images with * a non-page-aligned offset. */ i830->state.tex_offset[unit] = dst_x * intelObj->mt->cpp + dst_y * pitch; format = translate_texture_format(firstImage->TexFormat, firstImage->InternalFormat); state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 | (LOAD_TEXTURE_MAP0 << unit) | 4); state[I830_TEXREG_TM0S1] = (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) | ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format); if (intelObj->mt->region->tiling != I915_TILING_NONE) { state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE; if (intelObj->mt->region->tiling == I915_TILING_Y) state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK; } state[I830_TEXREG_TM0S2] = ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK); { if (tObj->Target == GL_TEXTURE_CUBE_MAP) state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) | CUBE_NEGX_ENABLE | CUBE_POSX_ENABLE | CUBE_NEGY_ENABLE | CUBE_POSY_ENABLE | CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE); else state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit)); } { GLuint minFilt, mipFilt, magFilt; switch (tObj->MinFilter) { case GL_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NONE; break; case GL_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NONE; break; case GL_NEAREST_MIPMAP_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NEAREST; break; case GL_LINEAR_MIPMAP_NEAREST: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NEAREST; break; case GL_NEAREST_MIPMAP_LINEAR: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_LINEAR; break; case GL_LINEAR_MIPMAP_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_LINEAR; break; default: return GL_FALSE; } if (tObj->MaxAnisotropy > 1.0) { minFilt = FILTER_ANISOTROPIC; magFilt = FILTER_ANISOTROPIC; } else { switch (tObj->MagFilter) { case GL_NEAREST: magFilt = FILTER_NEAREST; break; case GL_LINEAR: magFilt = FILTER_LINEAR; break; default: return GL_FALSE; } } lodbias = (int) ((tUnit->LodBias + tObj->LodBias) * 16.0); if (lodbias < -64) lodbias = -64; if (lodbias > 63) lodbias = 63; state[I830_TEXREG_TM0S3] = ((lodbias << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK); #if 0 /* YUV conversion: */ if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR || firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV) state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION; #endif state[I830_TEXREG_TM0S3] |= ((intelObj->lastLevel - intelObj->firstLevel) * 4) << TM0S3_MIN_MIP_SHIFT; state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) | (mipFilt << TM0S3_MIP_FILTER_SHIFT) | (magFilt << TM0S3_MAG_FILTER_SHIFT)); } { GLenum ws = tObj->WrapS; GLenum wt = tObj->WrapT; /* 3D textures not available on i830 */ if (tObj->Target == GL_TEXTURE_3D) return GL_FALSE; state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD | MAP_UNIT(unit) | ENABLE_TEXCOORD_PARAMS | ss3 | ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt)) | ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(translate_wrap_mode (ws))); } /* convert border color from float to ubyte */ CLAMPED_FLOAT_TO_UBYTE(border[0], tObj->BorderColor.f[0]); CLAMPED_FLOAT_TO_UBYTE(border[1], tObj->BorderColor.f[1]); CLAMPED_FLOAT_TO_UBYTE(border[2], tObj->BorderColor.f[2]); CLAMPED_FLOAT_TO_UBYTE(border[3], tObj->BorderColor.f[3]); state[I830_TEXREG_TM0S4] = PACK_COLOR_8888(border[3], border[0], border[1], border[2]); I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE); /* memcmp was already disabled, but definitely won't work as the * region might now change and that wouldn't be detected: */ I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); return GL_TRUE; }
/* Recalculate all state from scratch. Perhaps not the most * efficient, but this has gotten complex enough that we need * something which is understandable and reliable. */ static bool i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) { struct gl_context *ctx = &intel->ctx; struct i915_context *i915 = i915_context(ctx); struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = tUnit->_Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage; struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); GLuint *state = i915->state.Tex[unit], format, pitch; GLint lodbias, aniso = 0; GLubyte border[4]; GLfloat maxlod; memset(state, 0, sizeof(state)); /*We need to refcount these. */ if (i915->state.tex_buffer[unit] != NULL) { drm_intel_bo_unreference(i915->state.tex_buffer[unit]); i915->state.tex_buffer[unit] = NULL; } if (!intel_finalize_mipmap_tree(intel, unit)) return false; /* Get first image here, since intelObj->firstLevel will get set in * the intel_finalize_mipmap_tree() call above. */ firstImage = tObj->Image[0][tObj->BaseLevel]; drm_intel_bo_reference(intelObj->mt->region->bo); i915->state.tex_buffer[unit] = intelObj->mt->region->bo; i915->state.tex_offset[unit] = intelObj->mt->offset; format = translate_texture_format(firstImage->TexFormat, tObj->DepthMode); pitch = intelObj->mt->region->pitch * intelObj->mt->cpp; state[I915_TEXREG_MS3] = (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) | ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format); if (intelObj->mt->region->tiling != I915_TILING_NONE) { state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE; if (intelObj->mt->region->tiling == I915_TILING_Y) state[I915_TEXREG_MS3] |= MS3_TILE_WALK; } /* We get one field with fraction bits for the maximum addressable * (lowest resolution) LOD. Use it to cover both MAX_LEVEL and * MAX_LOD. */ maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel); state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) | MS4_CUBE_FACE_ENA_MASK | (U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) | ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); { GLuint minFilt, mipFilt, magFilt; switch (sampler->MinFilter) { case GL_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NONE; break; case GL_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NONE; break; case GL_NEAREST_MIPMAP_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NEAREST; break; case GL_LINEAR_MIPMAP_NEAREST: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NEAREST; break; case GL_NEAREST_MIPMAP_LINEAR: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_LINEAR; break; case GL_LINEAR_MIPMAP_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_LINEAR; break; default: return false; } if (sampler->MaxAnisotropy > 1.0) { minFilt = FILTER_ANISOTROPIC; magFilt = FILTER_ANISOTROPIC; if (sampler->MaxAnisotropy > 2.0) aniso = SS2_MAX_ANISO_4; else aniso = SS2_MAX_ANISO_2; } else { switch (sampler->MagFilter) { case GL_NEAREST: magFilt = FILTER_NEAREST; break; case GL_LINEAR: magFilt = FILTER_LINEAR; break; default: return false; } } lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0); if (lodbias < -256) lodbias = -256; if (lodbias > 255) lodbias = 255; state[I915_TEXREG_SS2] = ((lodbias << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); /* YUV conversion: */ if (firstImage->TexFormat == MESA_FORMAT_YCBCR || firstImage->TexFormat == MESA_FORMAT_YCBCR_REV) state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION; /* Shadow: */ if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && tObj->Target != GL_TEXTURE_3D) { if (tObj->Target == GL_TEXTURE_1D) return false; state[I915_TEXREG_SS2] |= (SS2_SHADOW_ENABLE | intel_translate_shadow_compare_func(sampler->CompareFunc)); minFilt = FILTER_4X4_FLAT; magFilt = FILTER_4X4_FLAT; } state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | (mipFilt << SS2_MIP_FILTER_SHIFT) | (magFilt << SS2_MAG_FILTER_SHIFT) | aniso); } { GLenum ws = sampler->WrapS; GLenum wt = sampler->WrapT; GLenum wr = sampler->WrapR; float minlod; /* We program 1D textures as 2D textures, so the 2D texcoord could * result in sampling border values if we don't set the T wrap to * repeat. */ if (tObj->Target == GL_TEXTURE_1D) wt = GL_REPEAT; /* 3D textures don't seem to respect the border color. * Fallback if there's ever a danger that they might refer to * it. * * Effectively this means fallback on 3D clamp or * clamp_to_border. */ if (tObj->Target == GL_TEXTURE_3D && (sampler->MinFilter != GL_NEAREST || sampler->MagFilter != GL_NEAREST) && (ws == GL_CLAMP || wt == GL_CLAMP || wr == GL_CLAMP || ws == GL_CLAMP_TO_BORDER || wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER)) return false; /* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not * used) when using cube map texture coordinates */ if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB && (((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) || ((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE)))) return false; /* * According to 3DSTATE_MAP_STATE at page of 104 in Bspec * Vol3d 3D Instructions: * [DevGDG and DevAlv]: Must be a power of 2 for cube maps. * [DevLPT, DevCST and DevBLB]: If not a power of 2, cube maps * must have all faces enabled. * * But, as I tested on pineview(DevBLB derived), the rendering is * bad(you will find the color isn't samplered right in some * fragments). After checking, it seems that the texture layout is * wrong: making the width and height align of 4(although this * doesn't make much sense) will fix this issue and also broke some * others. Well, Bspec mentioned nothing about the layout alignment * and layout for NPOT cube map. I guess the Bspec just assume it's * a POT cube map. * * Thus, I guess we need do this for other platforms as well. */ if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB && !is_power_of_two(firstImage->Height)) return false; state[I915_TEXREG_SS3] = ss3; /* SS3_NORMALIZED_COORDS */ state[I915_TEXREG_SS3] |= ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) | (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) | (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT)); minlod = MIN2(sampler->MinLod, tObj->_MaxLevel - tObj->BaseLevel); state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT); state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(minlod, 0.0, 11.0), 4) << SS3_MIN_LOD_SHIFT); } /* convert border color from float to ubyte */ CLAMPED_FLOAT_TO_UBYTE(border[0], sampler->BorderColor.f[0]); CLAMPED_FLOAT_TO_UBYTE(border[1], sampler->BorderColor.f[1]); CLAMPED_FLOAT_TO_UBYTE(border[2], sampler->BorderColor.f[2]); CLAMPED_FLOAT_TO_UBYTE(border[3], sampler->BorderColor.f[3]); if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) { /* GL specs that border color for depth textures is taken from the * R channel, while the hardware uses A. Spam R into all the channels * for safety. */ state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[0], border[0], border[0], border[0]); } else { state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[3], border[0], border[1], border[2]); } I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), true); /* memcmp was already disabled, but definitely won't work as the * region might now change and that wouldn't be detected: */ I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); #if 0 DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]); DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]); DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]); DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]); DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]); DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]); #endif return true; }
/** * Update/replace all or part of a color table. Helper function * used by _mesa_ColorTable() and _mesa_ColorSubTable(). * The table->Table buffer should already be allocated. * \param start first entry to update * \param count number of entries to update * \param format format of user-provided table data * \param type datatype of user-provided table data * \param data user-provided table data * \param [rgba]Scale - RGBA scale factors * \param [rgba]Bias - RGBA bias factors */ static void store_colortable_entries(GLcontext *ctx, struct gl_color_table *table, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data, GLfloat rScale, GLfloat rBias, GLfloat gScale, GLfloat gBias, GLfloat bScale, GLfloat bBias, GLfloat aScale, GLfloat aBias) { if (ctx->Unpack.BufferObj->Name) { /* Get/unpack the color table data from a PBO */ GLubyte *buf; if (!_mesa_validate_pbo_access(1, &ctx->Unpack, count, 1, 1, format, type, data)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glColor[Sub]Table(bad PBO access)"); return; } buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, GL_READ_ONLY_ARB, ctx->Unpack.BufferObj); if (!buf) { _mesa_error(ctx, GL_INVALID_OPERATION, "glColor[Sub]Table(PBO mapped)"); return; } data = ADD_POINTERS(buf, data); } { /* convert user-provided data to GLfloat values */ GLfloat tempTab[MAX_COLOR_TABLE_SIZE * 4]; GLfloat *tableF; GLint i; _mesa_unpack_color_span_float(ctx, count, /* number of pixels */ table->_BaseFormat, /* dest format */ tempTab, /* dest address */ format, type, /* src format/type */ data, /* src data */ &ctx->Unpack, IMAGE_CLAMP_BIT); /* transfer ops */ /* the destination */ tableF = table->TableF; /* Apply scale & bias & clamp now */ switch (table->_BaseFormat) { case GL_INTENSITY: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F); } break; case GL_LUMINANCE: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F); } break; case GL_ALPHA: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j] = CLAMP(tempTab[i] * aScale + aBias, 0.0F, 1.0F); } break; case GL_LUMINANCE_ALPHA: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j*2+0] = CLAMP(tempTab[i*2+0] * rScale + rBias, 0.0F, 1.0F); tableF[j*2+1] = CLAMP(tempTab[i*2+1] * aScale + aBias, 0.0F, 1.0F); } break; case GL_RGB: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j*3+0] = CLAMP(tempTab[i*3+0] * rScale + rBias, 0.0F, 1.0F); tableF[j*3+1] = CLAMP(tempTab[i*3+1] * gScale + gBias, 0.0F, 1.0F); tableF[j*3+2] = CLAMP(tempTab[i*3+2] * bScale + bBias, 0.0F, 1.0F); } break; case GL_RGBA: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j*4+0] = CLAMP(tempTab[i*4+0] * rScale + rBias, 0.0F, 1.0F); tableF[j*4+1] = CLAMP(tempTab[i*4+1] * gScale + gBias, 0.0F, 1.0F); tableF[j*4+2] = CLAMP(tempTab[i*4+2] * bScale + bBias, 0.0F, 1.0F); tableF[j*4+3] = CLAMP(tempTab[i*4+3] * aScale + aBias, 0.0F, 1.0F); } break; default: _mesa_problem(ctx, "Bad format in store_colortable_entries"); return; } } /* update the ubyte table */ { const GLint comps = _mesa_components_in_format(table->_BaseFormat); const GLfloat *tableF = table->TableF + start * comps; GLubyte *tableUB = table->TableUB + start * comps; GLint i; for (i = 0; i < count * comps; i++) { CLAMPED_FLOAT_TO_UBYTE(tableUB[i], tableF[i]); } } if (ctx->Unpack.BufferObj->Name) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } }
void gld_Clear_DX7( struct gl_context *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height) { GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); DWORD dwFlags = 0; D3DCOLOR Color = 0; float Z = 0.0f; DWORD Stencil = 0; D3DRECT d3dClearRect; // TODO: Colourmask const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask[0]; if (!gld->pDev) return; if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) { GLubyte col[4]; CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]); CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]); CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]); CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]); dwFlags |= D3DCLEAR_TARGET; Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]); // ctx->Color.ClearColor[1], // ctx->Color.ClearColor[2], // ctx->Color.ClearColor[3]); } if (mask & DD_DEPTH_BIT) { // D3D7 will fail the Clear call if we try and clear a // depth buffer and we haven't created one. // Also, some apps try and clear a depth buffer, // when a depth buffer hasn't been requested by the app. if (ctx->Visual.depthBits == 0) { mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask } else { dwFlags |= D3DCLEAR_ZBUFFER; Z = ctx->Depth.Clear; } } if (mask & DD_STENCIL_BIT) { if (ctx->Visual.stencilBits == 0) { // No stencil bits in depth buffer mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask } else { dwFlags |= D3DCLEAR_STENCIL; Stencil = ctx->Stencil.Clear; } } // Some apps do really weird things with the rect, such as Quake3. if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) { all = GL_TRUE; } if (!all) { // Calculate clear subrect d3dClearRect.x1 = x; d3dClearRect.y1 = gldCtx->dwHeight - (y + height); d3dClearRect.x2 = x + width; d3dClearRect.y2 = d3dClearRect.y1 + height; } // dwFlags will be zero if there's nothing to clear if (dwFlags) { _GLD_DX7_DEV(Clear( gld->pDev, all ? 0 : 1, all ? NULL : &d3dClearRect, dwFlags, Color, Z, Stencil)); } if (mask & DD_ACCUM_BIT) { // Clear accumulation buffer } }
/* Recalculate all state from scratch. Perhaps not the most * efficient, but this has gotten complex enough that we need * something which is understandable and reliable. */ static GLboolean i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) { struct gl_context *ctx = &intel->ctx; struct i915_context *i915 = i915_context(ctx); struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = tUnit->_Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage; GLuint *state = i915->state.Tex[unit], format, pitch; GLint lodbias, aniso = 0; GLubyte border[4]; GLfloat maxlod; memset(state, 0, sizeof(state)); /*We need to refcount these. */ if (i915->state.tex_buffer[unit] != NULL) { drm_intel_bo_unreference(i915->state.tex_buffer[unit]); i915->state.tex_buffer[unit] = NULL; } if (!intel_finalize_mipmap_tree(intel, unit)) return GL_FALSE; /* Get first image here, since intelObj->firstLevel will get set in * the intel_finalize_mipmap_tree() call above. */ firstImage = tObj->Image[0][intelObj->firstLevel]; drm_intel_bo_reference(intelObj->mt->region->buffer); i915->state.tex_buffer[unit] = intelObj->mt->region->buffer; i915->state.tex_offset[unit] = 0; /* Always the origin of the miptree */ format = translate_texture_format(firstImage->TexFormat, firstImage->InternalFormat, tObj->DepthMode); pitch = intelObj->mt->region->pitch * intelObj->mt->cpp; state[I915_TEXREG_MS3] = (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) | ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format); if (intelObj->mt->region->tiling != I915_TILING_NONE) { state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE; if (intelObj->mt->region->tiling == I915_TILING_Y) state[I915_TEXREG_MS3] |= MS3_TILE_WALK; } /* We get one field with fraction bits for the maximum addressable * (lowest resolution) LOD. Use it to cover both MAX_LEVEL and * MAX_LOD. */ maxlod = MIN2(tObj->MaxLod, tObj->_MaxLevel - tObj->BaseLevel); state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) | MS4_CUBE_FACE_ENA_MASK | (U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) | ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); { GLuint minFilt, mipFilt, magFilt; switch (tObj->MinFilter) { case GL_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NONE; break; case GL_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NONE; break; case GL_NEAREST_MIPMAP_NEAREST: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_NEAREST; break; case GL_LINEAR_MIPMAP_NEAREST: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_NEAREST; break; case GL_NEAREST_MIPMAP_LINEAR: minFilt = FILTER_NEAREST; mipFilt = MIPFILTER_LINEAR; break; case GL_LINEAR_MIPMAP_LINEAR: minFilt = FILTER_LINEAR; mipFilt = MIPFILTER_LINEAR; break; default: return GL_FALSE; } if (tObj->MaxAnisotropy > 1.0) { minFilt = FILTER_ANISOTROPIC; magFilt = FILTER_ANISOTROPIC; if (tObj->MaxAnisotropy > 2.0) aniso = SS2_MAX_ANISO_4; else aniso = SS2_MAX_ANISO_2; } else { switch (tObj->MagFilter) { case GL_NEAREST: magFilt = FILTER_NEAREST; break; case GL_LINEAR: magFilt = FILTER_LINEAR; break; default: return GL_FALSE; } } lodbias = (int) ((tUnit->LodBias + tObj->LodBias) * 16.0); if (lodbias < -256) lodbias = -256; if (lodbias > 255) lodbias = 255; state[I915_TEXREG_SS2] = ((lodbias << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); /* YUV conversion: */ if (firstImage->TexFormat == MESA_FORMAT_YCBCR || firstImage->TexFormat == MESA_FORMAT_YCBCR_REV) state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION; /* Shadow: */ if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && tObj->Target != GL_TEXTURE_3D) { if (tObj->Target == GL_TEXTURE_1D) return GL_FALSE; state[I915_TEXREG_SS2] |= (SS2_SHADOW_ENABLE | intel_translate_shadow_compare_func(tObj->CompareFunc)); minFilt = FILTER_4X4_FLAT; magFilt = FILTER_4X4_FLAT; } state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | (mipFilt << SS2_MIP_FILTER_SHIFT) | (magFilt << SS2_MAG_FILTER_SHIFT) | aniso); } { GLenum ws = tObj->WrapS; GLenum wt = tObj->WrapT; GLenum wr = tObj->WrapR; float minlod; /* We program 1D textures as 2D textures, so the 2D texcoord could * result in sampling border values if we don't set the T wrap to * repeat. */ if (tObj->Target == GL_TEXTURE_1D) wt = GL_REPEAT; /* 3D textures don't seem to respect the border color. * Fallback if there's ever a danger that they might refer to * it. * * Effectively this means fallback on 3D clamp or * clamp_to_border. */ if (tObj->Target == GL_TEXTURE_3D && (tObj->MinFilter != GL_NEAREST || tObj->MagFilter != GL_NEAREST) && (ws == GL_CLAMP || wt == GL_CLAMP || wr == GL_CLAMP || ws == GL_CLAMP_TO_BORDER || wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER)) return GL_FALSE; /* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not * used) when using cube map texture coordinates */ if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB && (((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) || ((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE)))) return GL_FALSE; state[I915_TEXREG_SS3] = ss3; /* SS3_NORMALIZED_COORDS */ state[I915_TEXREG_SS3] |= ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) | (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) | (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT)); minlod = MIN2(tObj->MinLod, tObj->_MaxLevel - tObj->BaseLevel); state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT); state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(minlod, 0.0, 11.0), 4) << SS3_MIN_LOD_SHIFT); } /* convert border color from float to ubyte */ CLAMPED_FLOAT_TO_UBYTE(border[0], tObj->BorderColor.f[0]); CLAMPED_FLOAT_TO_UBYTE(border[1], tObj->BorderColor.f[1]); CLAMPED_FLOAT_TO_UBYTE(border[2], tObj->BorderColor.f[2]); CLAMPED_FLOAT_TO_UBYTE(border[3], tObj->BorderColor.f[3]); if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) { /* GL specs that border color for depth textures is taken from the * R channel, while the hardware uses A. Spam R into all the channels * for safety. */ state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[0], border[0], border[0], border[0]); } else { state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[3], border[0], border[1], border[2]); } I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE); /* memcmp was already disabled, but definitely won't work as the * region might now change and that wouldn't be detected: */ I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); #if 0 DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]); DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]); DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]); DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]); DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]); DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]); #endif return GL_TRUE; }
/* Returns 0 if a software fallback is necessary */ static GLboolean sis_set_texobj_parm( struct gl_context *ctx, struct gl_texture_object *texObj, int hw_unit ) { sisContextPtr smesa = SIS_CONTEXT(ctx); int ok = 1; __GLSiSHardware *prev = &smesa->prev; __GLSiSHardware *current = &smesa->current; sisTexObjPtr t = texObj->DriverData; GLint firstLevel, lastLevel; GLint i; current->texture[hw_unit].hwTextureMip = 0UL; current->texture[hw_unit].hwTextureSet = t->hwformat; if ((texObj->MinFilter == GL_NEAREST) || (texObj->MinFilter == GL_LINEAR)) { firstLevel = lastLevel = texObj->BaseLevel; } else { /* Compute which mipmap levels we really want to send to the hardware. * This depends on the base image size, GL_TEXTURE_MIN_LOD, * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL and GL_TEXTURE_MAX_LEVEL. * Yes, this looks overly complicated, but it's all needed. */ firstLevel = texObj->BaseLevel + (GLint)(texObj->MinLod + 0.5); firstLevel = MAX2(firstLevel, texObj->BaseLevel); lastLevel = texObj->BaseLevel + (GLint)(texObj->MaxLod + 0.5); lastLevel = MAX2(lastLevel, texObj->BaseLevel); lastLevel = MIN2(lastLevel, texObj->BaseLevel + texObj->Image[0][texObj->BaseLevel]->MaxLog2); lastLevel = MIN2(lastLevel, texObj->MaxLevel); lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ } current->texture[hw_unit].hwTextureSet |= (lastLevel << 8); switch (texObj->MagFilter) { case GL_NEAREST: current->texture[hw_unit].hwTextureMip |= TEXTURE_FILTER_NEAREST; break; case GL_LINEAR: current->texture[hw_unit].hwTextureMip |= (TEXTURE_FILTER_LINEAR << 3); break; } { GLint b; /* The mipmap lod biasing is based on experiment. It seems there's a * limit of around +4/-4 to the bias value; we're being conservative. */ b = (GLint) (ctx->Texture.Unit[hw_unit].LodBias * 32.0); if (b > 127) b = 127; else if (b < -128) b = -128; current->texture[hw_unit].hwTextureMip |= ((b << 4) & MASK_TextureMipmapLodBias); } switch (texObj->MinFilter) { case GL_NEAREST: current->texture[hw_unit].hwTextureMip |= TEXTURE_FILTER_NEAREST; break; case GL_LINEAR: current->texture[hw_unit].hwTextureMip |= TEXTURE_FILTER_LINEAR; break; case GL_NEAREST_MIPMAP_NEAREST: current->texture[hw_unit].hwTextureMip |= TEXTURE_FILTER_NEAREST_MIP_NEAREST; break; case GL_NEAREST_MIPMAP_LINEAR: current->texture[hw_unit].hwTextureMip |= TEXTURE_FILTER_NEAREST_MIP_LINEAR; break; case GL_LINEAR_MIPMAP_NEAREST: current->texture[hw_unit].hwTextureMip |= TEXTURE_FILTER_LINEAR_MIP_NEAREST; break; case GL_LINEAR_MIPMAP_LINEAR: current->texture[hw_unit].hwTextureMip |= TEXTURE_FILTER_LINEAR_MIP_LINEAR; break; } switch (texObj->WrapS) { case GL_REPEAT: current->texture[hw_unit].hwTextureSet |= MASK_TextureWrapU; break; case GL_MIRRORED_REPEAT: current->texture[hw_unit].hwTextureSet |= MASK_TextureMirrorU; break; case GL_CLAMP: current->texture[hw_unit].hwTextureSet |= MASK_TextureClampU; /* XXX: GL_CLAMP isn't conformant, but falling back makes the situation * worse in other programs at the moment. */ /*ok = 0;*/ break; case GL_CLAMP_TO_EDGE: current->texture[hw_unit].hwTextureSet |= MASK_TextureClampU; break; case GL_CLAMP_TO_BORDER: current->texture[hw_unit].hwTextureSet |= MASK_TextureBorderU; break; } switch (texObj->WrapT) { case GL_REPEAT: current->texture[hw_unit].hwTextureSet |= MASK_TextureWrapV; break; case GL_MIRRORED_REPEAT: current->texture[hw_unit].hwTextureSet |= MASK_TextureMirrorV; break; case GL_CLAMP: current->texture[hw_unit].hwTextureSet |= MASK_TextureClampV; /* XXX: GL_CLAMP isn't conformant, but falling back makes the situation * worse in other programs at the moment. */ /*ok = 0;*/ break; case GL_CLAMP_TO_EDGE: current->texture[hw_unit].hwTextureSet |= MASK_TextureClampV; break; case GL_CLAMP_TO_BORDER: current->texture[hw_unit].hwTextureSet |= MASK_TextureBorderV; break; } { GLubyte c[4]; CLAMPED_FLOAT_TO_UBYTE(c[0], texObj->BorderColor.f[0]); CLAMPED_FLOAT_TO_UBYTE(c[1], texObj->BorderColor.f[1]); CLAMPED_FLOAT_TO_UBYTE(c[2], texObj->BorderColor.f[2]); CLAMPED_FLOAT_TO_UBYTE(c[3], texObj->BorderColor.f[3]); current->texture[hw_unit].hwTextureBorderColor = PACK_COLOR_8888(c[3], c[0], c[1], c[2]); } if (current->texture[hw_unit].hwTextureBorderColor != prev->texture[hw_unit].hwTextureBorderColor) { prev->texture[hw_unit].hwTextureBorderColor = current->texture[hw_unit].hwTextureBorderColor; if (hw_unit == 1) smesa->GlobalFlag |= GFLAG_TEXBORDERCOLOR_1; else smesa->GlobalFlag |= GFLAG_TEXBORDERCOLOR; } current->texture[hw_unit].hwTextureSet |= texObj->Image[0][firstLevel]->WidthLog2 << 4; current->texture[hw_unit].hwTextureSet |= texObj->Image[0][firstLevel]->HeightLog2; if (hw_unit == 0) smesa->GlobalFlag |= GFLAG_TEXTUREADDRESS; else smesa->GlobalFlag |= GFLAG_TEXTUREADDRESS_1; for (i = firstLevel; i <= lastLevel; i++) { GLuint texOffset = 0; GLuint texPitch = TransferTexturePitch( t->image[i].pitch ); switch (t->image[i].memType) { case VIDEO_TYPE: texOffset = ((unsigned long)t->image[i].Data - (unsigned long)smesa->FbBase); break; case AGP_TYPE: texOffset = ((unsigned long)t->image[i].Data - (unsigned long)smesa->AGPBase) + (unsigned long) smesa->AGPAddr; current->texture[hw_unit].hwTextureMip |= (MASK_TextureLevel0InSystem << i); break; } switch (i) { case 0: prev->texture[hw_unit].texOffset0 = texOffset; prev->texture[hw_unit].texPitch01 = texPitch << 16; break; case 1: prev->texture[hw_unit].texOffset1 = texOffset; prev->texture[hw_unit].texPitch01 |= texPitch; break; case 2: prev->texture[hw_unit].texOffset2 = texOffset; prev->texture[hw_unit].texPitch23 = texPitch << 16; break; case 3: prev->texture[hw_unit].texOffset3 = texOffset; prev->texture[hw_unit].texPitch23 |= texPitch; break; case 4: prev->texture[hw_unit].texOffset4 = texOffset; prev->texture[hw_unit].texPitch45 = texPitch << 16; break; case 5: prev->texture[hw_unit].texOffset5 = texOffset; prev->texture[hw_unit].texPitch45 |= texPitch; break; case 6: prev->texture[hw_unit].texOffset6 = texOffset; prev->texture[hw_unit].texPitch67 = texPitch << 16; break; case 7: prev->texture[hw_unit].texOffset7 = texOffset; prev->texture[hw_unit].texPitch67 |= texPitch; break; case 8: prev->texture[hw_unit].texOffset8 = texOffset; prev->texture[hw_unit].texPitch89 = texPitch << 16; break; case 9: prev->texture[hw_unit].texOffset9 = texOffset; prev->texture[hw_unit].texPitch89 |= texPitch; break; case 10: prev->texture[hw_unit].texOffset10 = texOffset; prev->texture[hw_unit].texPitch10 = texPitch << 16; break; case 11: prev->texture[hw_unit].texOffset11 = texOffset; prev->texture[hw_unit].texPitch10 |= texPitch; break; } } if (current->texture[hw_unit].hwTextureSet != prev->texture[hw_unit].hwTextureSet) { prev->texture[hw_unit].hwTextureSet = current->texture[hw_unit].hwTextureSet; if (hw_unit == 1) smesa->GlobalFlag |= CFLAG_TEXTURERESET_1; else smesa->GlobalFlag |= CFLAG_TEXTURERESET; } if (current->texture[hw_unit].hwTextureMip != prev->texture[hw_unit].hwTextureMip) { prev->texture[hw_unit].hwTextureMip = current->texture[hw_unit].hwTextureMip; if (hw_unit == 1) smesa->GlobalFlag |= GFLAG_TEXTUREMIPMAP_1; else smesa->GlobalFlag |= GFLAG_TEXTUREMIPMAP; } return ok; }
/** * Update/replace all or part of a color table. Helper function * used by _mesa_ColorTable() and _mesa_ColorSubTable(). * The table->Table buffer should already be allocated. * \param start first entry to update * \param count number of entries to update * \param format format of user-provided table data * \param type datatype of user-provided table data * \param data user-provided table data * \param [rgba]Scale - RGBA scale factors * \param [rgba]Bias - RGBA bias factors */ static void store_colortable_entries(GLcontext *ctx, struct gl_color_table *table, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data, GLfloat rScale, GLfloat rBias, GLfloat gScale, GLfloat gBias, GLfloat bScale, GLfloat bBias, GLfloat aScale, GLfloat aBias) { data = _mesa_map_validate_pbo_source(ctx, 1, &ctx->Unpack, count, 1, 1, format, type, data, "glColor[Sub]Table"); if (!data) return; { /* convert user-provided data to GLfloat values */ GLfloat tempTab[MAX_COLOR_TABLE_SIZE * 4]; GLfloat *tableF; GLint i; _mesa_unpack_color_span_float(ctx, count, /* number of pixels */ table->_BaseFormat, /* dest format */ tempTab, /* dest address */ format, type, /* src format/type */ data, /* src data */ &ctx->Unpack, IMAGE_CLAMP_BIT); /* transfer ops */ /* the destination */ tableF = table->TableF; /* Apply scale & bias & clamp now */ switch (table->_BaseFormat) { case GL_INTENSITY: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F); } break; case GL_LUMINANCE: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F); } break; case GL_ALPHA: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j] = CLAMP(tempTab[i] * aScale + aBias, 0.0F, 1.0F); } break; case GL_LUMINANCE_ALPHA: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j*2+0] = CLAMP(tempTab[i*2+0] * rScale + rBias, 0.0F, 1.0F); tableF[j*2+1] = CLAMP(tempTab[i*2+1] * aScale + aBias, 0.0F, 1.0F); } break; case GL_RGB: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j*3+0] = CLAMP(tempTab[i*3+0] * rScale + rBias, 0.0F, 1.0F); tableF[j*3+1] = CLAMP(tempTab[i*3+1] * gScale + gBias, 0.0F, 1.0F); tableF[j*3+2] = CLAMP(tempTab[i*3+2] * bScale + bBias, 0.0F, 1.0F); } break; case GL_RGBA: for (i = 0; i < count; i++) { GLuint j = start + i; tableF[j*4+0] = CLAMP(tempTab[i*4+0] * rScale + rBias, 0.0F, 1.0F); tableF[j*4+1] = CLAMP(tempTab[i*4+1] * gScale + gBias, 0.0F, 1.0F); tableF[j*4+2] = CLAMP(tempTab[i*4+2] * bScale + bBias, 0.0F, 1.0F); tableF[j*4+3] = CLAMP(tempTab[i*4+3] * aScale + aBias, 0.0F, 1.0F); } break; default: _mesa_problem(ctx, "Bad format in store_colortable_entries"); return; } } /* update the ubyte table */ { const GLint comps = _mesa_components_in_format(table->_BaseFormat); const GLfloat *tableF = table->TableF + start * comps; GLubyte *tableUB = table->TableUB + start * comps; GLint i; for (i = 0; i < count * comps; i++) { CLAMPED_FLOAT_TO_UBYTE(tableUB[i], tableF[i]); } } _mesa_unmap_pbo_source(ctx, &ctx->Unpack); }
/** * Use blitting to clear the renderbuffers named by 'flags'. * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field * since that might include software renderbuffers or renderbuffers * which we're clearing with triangles. * \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear */ GLbitfield intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) { struct intel_context *intel = intel_context(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; GLuint clear_depth_value, clear_depth_mask; GLboolean all; GLint cx, cy, cw, ch; GLbitfield fail_mask = 0; BATCH_LOCALS; /* * Compute values for clearing the buffers. */ clear_depth_value = 0; clear_depth_mask = 0; if (mask & BUFFER_BIT_DEPTH) { clear_depth_value = (GLuint) (fb->_DepthMax * ctx->Depth.Clear); clear_depth_mask = XY_BLT_WRITE_RGB; } if (mask & BUFFER_BIT_STENCIL) { clear_depth_value |= (ctx->Stencil.Clear & 0xff) << 24; clear_depth_mask |= XY_BLT_WRITE_ALPHA; } cx = fb->_Xmin; if (fb->Name == 0) cy = ctx->DrawBuffer->Height - fb->_Ymax; else cy = fb->_Ymin; cw = fb->_Xmax - fb->_Xmin; ch = fb->_Ymax - fb->_Ymin; if (cw == 0 || ch == 0) return 0; all = (cw == fb->Width && ch == fb->Height); /* Loop over all renderbuffers */ mask &= (1 << BUFFER_COUNT) - 1; while (mask) { GLuint buf = _mesa_ffs(mask) - 1; GLboolean is_depth_stencil = buf == BUFFER_DEPTH || buf == BUFFER_STENCIL; struct intel_renderbuffer *irb; drm_intel_bo *write_buffer; int x1, y1, x2, y2; uint32_t clear_val; uint32_t BR13, CMD; int pitch, cpp; drm_intel_bo *aper_array[2]; mask &= ~(1 << buf); irb = intel_get_renderbuffer(fb, buf); if (irb == NULL || irb->region == NULL || irb->region->buffer == NULL) { fail_mask |= 1 << buf; continue; } /* OK, clear this renderbuffer */ write_buffer = intel_region_buffer(intel, irb->region, all ? INTEL_WRITE_FULL : INTEL_WRITE_PART); x1 = cx + irb->draw_x; y1 = cy + irb->draw_y; x2 = cx + cw + irb->draw_x; y2 = cy + ch + irb->draw_y; pitch = irb->region->pitch; cpp = irb->region->cpp; DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n", __FUNCTION__, irb->region->buffer, (pitch * cpp), x1, y1, x2 - x1, y2 - y1); BR13 = 0xf0 << 16; CMD = XY_COLOR_BLT_CMD; /* Setup the blit command */ if (cpp == 4) { if (is_depth_stencil) { CMD |= clear_depth_mask; } else { /* clearing RGBA */ CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; } } assert(irb->region->tiling != I915_TILING_Y); #ifndef I915 if (irb->region->tiling != I915_TILING_NONE) { CMD |= XY_DST_TILED; pitch /= 4; } #endif BR13 |= (pitch * cpp); if (is_depth_stencil) { clear_val = clear_depth_value; } else { uint8_t clear[4]; GLclampf *color = ctx->Color.ClearColor; CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]); CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]); switch (irb->Base.Format) { case MESA_FORMAT_ARGB8888: case MESA_FORMAT_XRGB8888: clear_val = PACK_COLOR_8888(clear[3], clear[0], clear[1], clear[2]); break; case MESA_FORMAT_RGB565: clear_val = PACK_COLOR_565(clear[0], clear[1], clear[2]); break; case MESA_FORMAT_ARGB4444: clear_val = PACK_COLOR_4444(clear[3], clear[0], clear[1], clear[2]); break; case MESA_FORMAT_ARGB1555: clear_val = PACK_COLOR_1555(clear[3], clear[0], clear[1], clear[2]); break; case MESA_FORMAT_A8: clear_val = PACK_COLOR_8888(clear[3], clear[3], clear[3], clear[3]); break; default: fail_mask |= 1 << buf; continue; } } BR13 |= br13_for_cpp(cpp); assert(x1 < x2); assert(y1 < y2); /* do space check before going any further */ aper_array[0] = intel->batch.bo; aper_array[1] = write_buffer; if (drm_intel_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array)) != 0) { intel_batchbuffer_flush(intel); } BEGIN_BATCH_BLT(6); OUT_BATCH(CMD); OUT_BATCH(BR13); OUT_BATCH((y1 << 16) | x1); OUT_BATCH((y2 << 16) | x2); OUT_RELOC_FENCED(write_buffer, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); OUT_BATCH(clear_val); ADVANCE_BATCH(); if (intel->always_flush_cache) intel_batchbuffer_emit_mi_flush(intel); if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); } return fail_mask; }