void i830_update_provoking_vertex(struct gl_context * ctx) { struct i830_context *i830 = i830_context(ctx); I830_STATECHANGE(i830, I830_UPLOAD_RASTER_RULES); i830->state.RasterRules[I830_RASTER_RULES] &= ~(LINE_STRIP_PROVOKE_VRTX_MASK | TRI_FAN_PROVOKE_VRTX_MASK | TRI_STRIP_PROVOKE_VRTX_MASK); /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION) { i830->state.RasterRules[I830_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(1) | TRI_FAN_PROVOKE_VRTX(2) | TRI_STRIP_PROVOKE_VRTX(2)); } else { i830->state.RasterRules[I830_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(0) | TRI_FAN_PROVOKE_VRTX(1) | TRI_STRIP_PROVOKE_VRTX(0)); } }
static void i830ColorMask(struct gl_context * ctx, GLboolean r, GLboolean g, GLboolean b, GLboolean a) { struct i830_context *i830 = i830_context(ctx); GLuint tmp = 0; DBG("%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a); tmp = ((i830->state.Ctx[I830_CTXREG_ENABLES_2] & ~WRITEMASK_MASK) | ENABLE_COLOR_MASK | ENABLE_COLOR_WRITE | ((!r) << WRITEMASK_RED_SHIFT) | ((!g) << WRITEMASK_GREEN_SHIFT) | ((!b) << WRITEMASK_BLUE_SHIFT) | ((!a) << WRITEMASK_ALPHA_SHIFT)); if (tmp != i830->state.Ctx[I830_CTXREG_ENABLES_2]) { I830_STATECHANGE(i830, I830_UPLOAD_CTX); i830->state.Ctx[I830_CTXREG_ENABLES_2] = tmp; } }
/* ============================================================= * Hardware clipping */ static void i830Scissor(struct gl_context * ctx, GLint x, GLint y, GLsizei w, GLsizei h) { struct i830_context *i830 = i830_context(ctx); int x1, y1, x2, y2; if (!ctx->DrawBuffer) return; DBG("%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h); if (ctx->DrawBuffer->Name == 0) { x1 = x; y1 = ctx->DrawBuffer->Height - (y + h); x2 = x + w - 1; y2 = y1 + h - 1; DBG("%s %d..%d,%d..%d (inverted)\n", __FUNCTION__, x1, x2, y1, y2); } else { /* FBO - not inverted */ x1 = x; y1 = y; x2 = x + w - 1; y2 = y + h - 1; DBG("%s %d..%d,%d..%d (not inverted)\n", __FUNCTION__, x1, x2, y1, y2); } x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1); y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1); x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1); y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1); DBG("%s %d..%d,%d..%d (clamped)\n", __FUNCTION__, x1, x2, y1, y2); I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS); i830->state.Buffer[I830_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff); i830->state.Buffer[I830_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff); }
/* In Mesa 3.5 we can reliably do native flatshading. */ static void i830ShadeModel(GLcontext *ctx, GLenum mode) { i830ContextPtr i830 = I830_CONTEXT(ctx); I830_STATECHANGE(i830, I830_UPLOAD_CTX); #define SHADE_MODE_MASK ((1<<10)|(1<<8)|(1<<6)|(1<<4)) i830->state.Ctx[I830_CTXREG_STATE3] &= ~SHADE_MODE_MASK; if (mode == GL_FLAT) { i830->state.Ctx[I830_CTXREG_STATE3] |= (ALPHA_SHADE_MODE(SHADE_MODE_FLAT) | FOG_SHADE_MODE(SHADE_MODE_FLAT) | SPEC_SHADE_MODE(SHADE_MODE_FLAT) | COLOR_SHADE_MODE(SHADE_MODE_FLAT)); } else { i830->state.Ctx[I830_CTXREG_STATE3] |= (ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) | FOG_SHADE_MODE(SHADE_MODE_LINEAR) | SPEC_SHADE_MODE(SHADE_MODE_LINEAR) | COLOR_SHADE_MODE(SHADE_MODE_LINEAR)); } }
static void i830ColorMask(GLcontext *ctx, GLboolean r, GLboolean g, GLboolean b, GLboolean a) { i830ContextPtr i830 = I830_CONTEXT( ctx ); GLuint tmp = 0; if (INTEL_DEBUG&DEBUG_DRI) fprintf(stderr, "%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a); tmp = ((i830->state.Ctx[I830_CTXREG_ENABLES_2] & ~WRITEMASK_MASK) | ENABLE_COLOR_MASK | ENABLE_COLOR_WRITE | ((!r) << WRITEMASK_RED_SHIFT) | ((!g) << WRITEMASK_GREEN_SHIFT) | ((!b) << WRITEMASK_BLUE_SHIFT) | ((!a) << WRITEMASK_ALPHA_SHIFT)); if (tmp != i830->state.Ctx[I830_CTXREG_ENABLES_2]) { I830_STATECHANGE(i830, I830_UPLOAD_CTX); i830->state.Ctx[I830_CTXREG_ENABLES_2] = tmp; } }
/** * Makes sure that the proper enables are set for LogicOp, Independant Alpha * Blend, and Blending. It needs to be called from numerous places where we * could change the LogicOp or Independant Alpha Blend without subsequent * calls to glEnable. * * \todo * This function is substantially different from the old i830-specific driver. * I'm not sure which is correct. */ static void i830EvalLogicOpBlendState(GLcontext *ctx) { i830ContextPtr i830 = I830_CONTEXT(ctx); I830_STATECHANGE(i830, I830_UPLOAD_CTX); if (RGBA_LOGICOP_ENABLED(ctx)) { i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | ENABLE_LOGIC_OP_MASK); i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND | ENABLE_LOGIC_OP); } else if (ctx->Color.BlendEnabled) { i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | ENABLE_LOGIC_OP_MASK); i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (ENABLE_COLOR_BLEND | DISABLE_LOGIC_OP); } else { i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | ENABLE_LOGIC_OP_MASK); i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND | DISABLE_LOGIC_OP); } }
static void i830StencilFuncSeparate(struct gl_context * ctx, GLenum face, GLenum func, GLint ref, GLuint mask) { struct i830_context *i830 = i830_context(ctx); int test = intel_translate_compare_func(func); mask = mask & 0xff; DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__, _mesa_lookup_enum_by_nr(func), ref, mask); I830_STATECHANGE(i830, I830_UPLOAD_CTX); i830->state.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK; i830->state.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(mask)); i830->state.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_REF_VALUE_MASK | ENABLE_STENCIL_TEST_FUNC_MASK); i830->state.Ctx[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_REF_VALUE | ENABLE_STENCIL_TEST_FUNC | STENCIL_REF_VALUE(ref) | STENCIL_TEST_FUNC(test)); }
static void i830_render_start(struct intel_context *intel) { GLcontext *ctx = &intel->ctx; struct i830_context *i830 = i830_context(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; DECLARE_RENDERINPUTS(index_bitset); GLuint v0 = _3DSTATE_VFT0_CMD; GLuint v2 = _3DSTATE_VFT1_CMD; GLuint mcsb1 = 0; RENDERINPUTS_COPY(index_bitset, tnl->render_inputs_bitset); /* Important: */ VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; intel->vertex_attr_count = 0; /* EMIT_ATTR's must be in order as they tell t_vertex.c how to * build up a hardware vertex. */ if (RENDERINPUTS_TEST_RANGE(index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX)) { EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VFT0_XYZW); intel->coloroffset = 4; } else { EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, VFT0_XYZ); intel->coloroffset = 3; } if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_POINTSIZE)) { EMIT_ATTR(_TNL_ATTRIB_POINTSIZE, EMIT_1F, VFT0_POINT_WIDTH); } EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VFT0_DIFFUSE); intel->specoffset = 0; if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_COLOR1) || RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_FOG)) { if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_COLOR1)) { intel->specoffset = intel->coloroffset + 1; EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VFT0_SPEC); } else EMIT_PAD(3); if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_FOG)) EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC); else EMIT_PAD(1); } if (RENDERINPUTS_TEST_RANGE(index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX)) { int i, count = 0; for (i = 0; i < I830_TEX_UNITS; i++) { if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_TEX(i))) { GLuint sz = VB->TexCoordPtr[i]->size; GLuint emit; GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] & ~TEXCOORDTYPE_MASK); switch (sz) { case 1: case 2: emit = EMIT_2F; sz = 2; mcs |= TEXCOORDTYPE_CARTESIAN; break; case 3: emit = EMIT_3F; sz = 3; mcs |= TEXCOORDTYPE_VECTOR; break; case 4: emit = EMIT_3F_XYW; sz = 3; mcs |= TEXCOORDTYPE_HOMOGENEOUS; break; default: continue; }; EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, emit, 0); v2 |= VRTX_TEX_SET_FMT(count, SZ_TO_HW(sz)); mcsb1 |= (count + 8) << (i * 4); if (mcs != i830->state.Tex[i][I830_TEXREG_MCS]) { I830_STATECHANGE(i830, I830_UPLOAD_TEX(i)); i830->state.Tex[i][I830_TEXREG_MCS] = mcs; } count++; } } v0 |= VFT0_TEX_COUNT(count); } /* Only need to change the vertex emit code if there has been a * statechange to a new hardware vertex format: */ if (v0 != i830->state.Ctx[I830_CTXREG_VF] || v2 != i830->state.Ctx[I830_CTXREG_VF2] || mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] || !RENDERINPUTS_EQUAL(index_bitset, i830->last_index_bitset)) { int k; I830_STATECHANGE(i830, I830_UPLOAD_CTX); /* Must do this *after* statechange, so as not to affect * buffered vertices reliant on the old state: */ intel->vertex_size = _tnl_install_attrs(ctx, intel->vertex_attrs, intel->vertex_attr_count, intel->ViewportMatrix.m, 0); intel->vertex_size >>= 2; i830->state.Ctx[I830_CTXREG_VF] = v0; i830->state.Ctx[I830_CTXREG_VF2] = v2; i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1; RENDERINPUTS_COPY(i830->last_index_bitset, index_bitset); k = i830_check_vertex_size(intel, intel->vertex_size); assert(k); }
void i830ChooseVertexState( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); i830ContextPtr imesa = I830_CONTEXT( ctx ); GLuint ind = I830_XYZW_BIT|I830_RGBA_BIT; if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ind |= I830_SPEC_BIT; if (ctx->Fog.Enabled) ind |= I830_FOG_BIT; /* unit 1 */ if (ctx->Texture._ReallyEnabled & TEXTURE1_ANY) ind |= I830_TEX1_BIT|I830_TEX0_BIT; /* unit 0 */ else if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY) ind |= I830_TEX0_BIT; imesa->SetupIndex = ind; if (I830_DEBUG & (DEBUG_VERTS|DEBUG_STATE)) i830PrintSetupFlags( __FUNCTION__, ind ); if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { tnl->Driver.Render.Interp = i830_interp_extras; tnl->Driver.Render.CopyPV = i830_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->vertex_format) { int vfmt = setup_tab[ind].vertex_format; I830_STATECHANGE(imesa, I830_UPLOAD_CTX); imesa->Setup[I830_CTXREG_VF] = ~(1<<31) & vfmt; if (vfmt & (1<<31)) { /* Proj texturing */ imesa->Setup[I830_CTXREG_VF2] = (STATE3D_VERTEX_FORMAT_2_CMD | VRTX_TEX_SET_0_FMT(TEXCOORDFMT_3D) | VRTX_TEX_SET_1_FMT(TEXCOORDFMT_3D) | VRTX_TEX_SET_2_FMT(TEXCOORDFMT_3D) | VRTX_TEX_SET_3_FMT(TEXCOORDFMT_3D)); i830UpdateTexUnitProj( ctx, 0, GL_TRUE ); i830UpdateTexUnitProj( ctx, 1, GL_TRUE ); } else { /* Normal texturing */ imesa->Setup[I830_CTXREG_VF2] = (STATE3D_VERTEX_FORMAT_2_CMD | VRTX_TEX_SET_0_FMT(TEXCOORDFMT_2D) | VRTX_TEX_SET_1_FMT(TEXCOORDFMT_2D) | VRTX_TEX_SET_2_FMT(TEXCOORDFMT_2D) | VRTX_TEX_SET_3_FMT(TEXCOORDFMT_2D)); i830UpdateTexUnitProj( ctx, 0, GL_FALSE ); i830UpdateTexUnitProj( ctx, 1, GL_FALSE ); } imesa->vertex_format = vfmt; imesa->vertex_size = setup_tab[ind].vertex_size; imesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift; } }
/* 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_object *tObj = ctx->Texture.Unit[unit]._Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage; GLuint *state = i830->state.Tex[unit], format, pitch; memset(state, 0, sizeof(state)); /*We need to refcount these. */ if (i830->state.tex_buffer[unit] != NULL) { dri_bo_unreference(i830->state.tex_buffer[unit]); i830->state.tex_buffer[unit] = NULL; } if (!intelObj->imageOverride && !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]; if (intelObj->imageOverride) { i830->state.tex_buffer[unit] = NULL; i830->state.tex_offset[unit] = intelObj->textureOffset; switch (intelObj->depthOverride) { case 32: format = MAPSURF_32BIT | MT_32BIT_ARGB8888; break; case 24: default: format = MAPSURF_32BIT | MT_32BIT_XRGB8888; break; case 16: format = MAPSURF_16BIT | MT_16BIT_RGB565; break; } pitch = intelObj->pitchOverride; } else { dri_bo_reference(intelObj->mt->region->buffer); i830->state.tex_buffer[unit] = intelObj->mt->region->buffer; i830->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt, 0, intelObj-> firstLevel); format = translate_texture_format(firstImage->TexFormat->MesaFormat); pitch = intelObj->mt->pitch * intelObj->mt->cpp; } state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 | (LOAD_TEXTURE_MAP0 << unit) | 4); /* state[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | */ /* t->intel.TextureOffset); */ state[I830_TEXREG_TM0S1] = (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) | ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format); 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; } } state[I830_TEXREG_TM0S3] = i830->lodbias_tm0s3[unit]; #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))); } state[I830_TEXREG_TM0S4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0], tObj->_BorderChan[1], tObj->_BorderChan[2], tObj->_BorderChan[3]); 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; }
static void i830StencilOpSeparate(struct gl_context * ctx, GLenum face, GLenum fail, GLenum zfail, GLenum zpass) { struct i830_context *i830 = i830_context(ctx); int fop, dfop, dpop; DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(fail), _mesa_lookup_enum_by_nr(zfail), _mesa_lookup_enum_by_nr(zpass)); fop = 0; dfop = 0; dpop = 0; switch (fail) { case GL_KEEP: fop = STENCILOP_KEEP; break; case GL_ZERO: fop = STENCILOP_ZERO; break; case GL_REPLACE: fop = STENCILOP_REPLACE; break; case GL_INCR: fop = STENCILOP_INCRSAT; break; case GL_DECR: fop = STENCILOP_DECRSAT; break; case GL_INCR_WRAP: fop = STENCILOP_INCR; break; case GL_DECR_WRAP: fop = STENCILOP_DECR; break; case GL_INVERT: fop = STENCILOP_INVERT; break; default: break; } switch (zfail) { case GL_KEEP: dfop = STENCILOP_KEEP; break; case GL_ZERO: dfop = STENCILOP_ZERO; break; case GL_REPLACE: dfop = STENCILOP_REPLACE; break; case GL_INCR: dfop = STENCILOP_INCRSAT; break; case GL_DECR: dfop = STENCILOP_DECRSAT; break; case GL_INCR_WRAP: dfop = STENCILOP_INCR; break; case GL_DECR_WRAP: dfop = STENCILOP_DECR; break; case GL_INVERT: dfop = STENCILOP_INVERT; break; default: break; } switch (zpass) { case GL_KEEP: dpop = STENCILOP_KEEP; break; case GL_ZERO: dpop = STENCILOP_ZERO; break; case GL_REPLACE: dpop = STENCILOP_REPLACE; break; case GL_INCR: dpop = STENCILOP_INCRSAT; break; case GL_DECR: dpop = STENCILOP_DECRSAT; break; case GL_INCR_WRAP: dpop = STENCILOP_INCR; break; case GL_DECR_WRAP: dpop = STENCILOP_DECR; break; case GL_INVERT: dpop = STENCILOP_INVERT; break; default: break; } I830_STATECHANGE(i830, I830_UPLOAD_CTX); i830->state.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK); i830->state.Ctx[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_PARMS | STENCIL_FAIL_OP(fop) | STENCIL_PASS_DEPTH_FAIL_OP (dfop) | STENCIL_PASS_DEPTH_PASS_OP (dpop)); }
static void i830Enable(struct gl_context * ctx, GLenum cap, GLboolean state) { struct i830_context *i830 = i830_context(ctx); switch (cap) { case GL_LIGHTING: case GL_COLOR_SUM: update_specular(ctx); break; case GL_ALPHA_TEST: I830_STATECHANGE(i830, I830_UPLOAD_CTX); i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_ALPHA_TEST_MASK; if (state) i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_ALPHA_TEST; else i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_ALPHA_TEST; break; case GL_BLEND: i830EvalLogicOpBlendState(ctx); break; case GL_COLOR_LOGIC_OP: i830EvalLogicOpBlendState(ctx); /* Logicop doesn't seem to work at 16bpp: */ if (i830->intel.ctx.Visual.rgbBits == 16) FALLBACK(&i830->intel, I830_FALLBACK_LOGICOP, state); break; case GL_DITHER: I830_STATECHANGE(i830, I830_UPLOAD_CTX); i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DITHER; if (state) i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_DITHER; else i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DITHER; break; case GL_DEPTH_TEST: I830_STATECHANGE(i830, I830_UPLOAD_CTX); i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK; if (state) i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_DEPTH_TEST; else i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST; /* Also turn off depth writes when GL_DEPTH_TEST is disabled: */ i830DepthMask(ctx, ctx->Depth.Mask); break; case GL_SCISSOR_TEST: I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS); if (state) i830->state.Buffer[I830_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT); else i830->state.Buffer[I830_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); break; case GL_LINE_SMOOTH: I830_STATECHANGE(i830, I830_UPLOAD_CTX); i830->state.Ctx[I830_CTXREG_AA] &= ~AA_LINE_ENABLE; if (state) i830->state.Ctx[I830_CTXREG_AA] |= AA_LINE_ENABLE; else i830->state.Ctx[I830_CTXREG_AA] |= AA_LINE_DISABLE; break; case GL_FOG: I830_STATECHANGE(i830, I830_UPLOAD_CTX); i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_FOG_MASK; if (state) i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_FOG; else i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_FOG; break; case GL_CULL_FACE: i830CullFaceFrontFace(ctx, 0); break; case GL_TEXTURE_2D: break; case GL_STENCIL_TEST: { GLboolean hw_stencil = GL_FALSE; if (ctx->DrawBuffer) { struct intel_renderbuffer *irbStencil = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); hw_stencil = (irbStencil && irbStencil->region); } if (hw_stencil) { I830_STATECHANGE(i830, I830_UPLOAD_CTX); if (state) { i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST; i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE; } else { i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST; i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE; i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST; i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE; } } else { FALLBACK(&i830->intel, I830_FALLBACK_STENCIL, state); } } break; case GL_POLYGON_STIPPLE: /* The stipple command worked on my 855GM box, but not my 845G. * I'll do more testing later to find out exactly which hardware * supports it. Disabled for now. */ if (i830->intel.hw_stipple && i830->intel.reduced_primitive == GL_TRIANGLES) { I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE); i830->state.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE; if (state) i830->state.Stipple[I830_STPREG_ST1] |= ST1_ENABLE; } break; default: ; } }
/** * Sets both the blend equation (called "function" in i830 docs) and the * blend function (called "factor" in i830 docs). This is done in a single * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX) * change the interpretation of the blend function. */ static void i830_set_blend_state(struct gl_context * ctx) { struct i830_context *i830 = i830_context(ctx); int funcA; int funcRGB; int eqnA; int eqnRGB; int iab; int s1; funcRGB = SRC_BLND_FACT(intel_translate_blend_factor(ctx->Color.Blend[0].SrcRGB)) | DST_BLND_FACT(intel_translate_blend_factor(ctx->Color.Blend[0].DstRGB)); switch (ctx->Color.Blend[0].EquationRGB) { case GL_FUNC_ADD: eqnRGB = BLENDFUNC_ADD; break; case GL_MIN: eqnRGB = BLENDFUNC_MIN; funcRGB = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); break; case GL_MAX: eqnRGB = BLENDFUNC_MAX; funcRGB = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); break; case GL_FUNC_SUBTRACT: eqnRGB = BLENDFUNC_SUB; break; case GL_FUNC_REVERSE_SUBTRACT: eqnRGB = BLENDFUNC_RVRSE_SUB; break; default: fprintf(stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n", __FUNCTION__, __LINE__, ctx->Color.Blend[0].EquationRGB); return; } funcA = SRC_ABLEND_FACT(intel_translate_blend_factor(ctx->Color.Blend[0].SrcA)) | DST_ABLEND_FACT(intel_translate_blend_factor(ctx->Color.Blend[0].DstA)); switch (ctx->Color.Blend[0].EquationA) { case GL_FUNC_ADD: eqnA = BLENDFUNC_ADD; break; case GL_MIN: eqnA = BLENDFUNC_MIN; funcA = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); break; case GL_MAX: eqnA = BLENDFUNC_MAX; funcA = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); break; case GL_FUNC_SUBTRACT: eqnA = BLENDFUNC_SUB; break; case GL_FUNC_REVERSE_SUBTRACT: eqnA = BLENDFUNC_RVRSE_SUB; break; default: fprintf(stderr, "[%s:%u] Invalid alpha blend equation (0x%04x).\n", __FUNCTION__, __LINE__, ctx->Color.Blend[0].EquationA); return; } iab = eqnA | funcA | _3DSTATE_INDPT_ALPHA_BLEND_CMD | ENABLE_SRC_ABLEND_FACTOR | ENABLE_DST_ABLEND_FACTOR | ENABLE_ALPHA_BLENDFUNC; s1 = eqnRGB | funcRGB | _3DSTATE_MODES_1_CMD | ENABLE_SRC_BLND_FACTOR | ENABLE_DST_BLND_FACTOR | ENABLE_COLR_BLND_FUNC; if ((eqnA | funcA) != (eqnRGB | funcRGB)) iab |= ENABLE_INDPT_ALPHA_BLEND; else iab |= DISABLE_INDPT_ALPHA_BLEND; if (iab != i830->state.Ctx[I830_CTXREG_IALPHAB] || s1 != i830->state.Ctx[I830_CTXREG_STATE1]) { I830_STATECHANGE(i830, I830_UPLOAD_CTX); i830->state.Ctx[I830_CTXREG_IALPHAB] = iab; i830->state.Ctx[I830_CTXREG_STATE1] = s1; } /* This will catch a logicop blend equation. It will also ensure * independant alpha blend is really in the correct state (either enabled * or disabled) if blending is already enabled. */ i830EvalLogicOpBlendState(ctx); if (0) { fprintf(stderr, "[%s:%u] STATE1: 0x%08x IALPHAB: 0x%08x blend is %sabled\n", __FUNCTION__, __LINE__, i830->state.Ctx[I830_CTXREG_STATE1], i830->state.Ctx[I830_CTXREG_IALPHAB], (ctx->Color.BlendEnabled) ? "en" : "dis"); } }
/* System to flush dma and emit state changes based on the rasterized * primitive. */ void i830RasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) { i830ContextPtr imesa = I830_CONTEXT(ctx); GLuint aa = imesa->Setup[I830_CTXREG_AA]; GLuint st1 = imesa->StippleSetup[I830_STPREG_ST1]; aa &= ~AA_LINE_ENABLE; if (I830_DEBUG & DEBUG_PRIMS) { /* Prints reduced prim, and hw prim */ char *prim_name = "Unknown"; switch(hwprim) { case PRIM3D_POINTLIST: prim_name = "PointList"; break; case PRIM3D_LINELIST: prim_name = "LineList"; break; case PRIM3D_LINESTRIP: prim_name = "LineStrip"; break; case PRIM3D_TRILIST: prim_name = "TriList"; break; case PRIM3D_TRISTRIP: prim_name = "TriStrip"; break; case PRIM3D_TRIFAN: prim_name = "TriFan"; break; case PRIM3D_POLY: 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: aa |= AA_LINE_DISABLE; if (ctx->Polygon.StippleFlag) st1 |= ST1_ENABLE; else st1 &= ~ST1_ENABLE; break; case GL_LINES: st1 &= ~ST1_ENABLE; if (ctx->Line.SmoothFlag) { aa |= AA_LINE_ENABLE; } else { aa |= AA_LINE_DISABLE; } break; case GL_POINTS: st1 &= ~ST1_ENABLE; aa |= AA_LINE_DISABLE; break; default: return; } imesa->reduced_primitive = rprim; if (aa != imesa->Setup[I830_CTXREG_AA]) { I830_STATECHANGE(imesa, I830_UPLOAD_CTX); imesa->Setup[I830_CTXREG_AA] = aa; } #if 0 if (st1 != imesa->StippleSetup[I830_STPREG_ST1]) { I830_STATECHANGE(imesa, I830_UPLOAD_STIPPLE); imesa->StippleSetup[I830_STPREG_ST1] = st1; } #endif if (hwprim != imesa->hw_primitive) { I830_STATECHANGE(imesa, 0); imesa->hw_primitive = hwprim; } }
/* 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; }
static void i830TexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param ) { i830ContextPtr i830 = I830_CONTEXT( ctx ); GLuint unit = ctx->Texture.CurrentUnit; switch (pname) { case GL_TEXTURE_ENV_COLOR: #if 0 { GLubyte r, g, b, a; GLuint col; UNCLAMPED_FLOAT_TO_UBYTE(r, param[RCOMP]); UNCLAMPED_FLOAT_TO_UBYTE(g, param[GCOMP]); UNCLAMPED_FLOAT_TO_UBYTE(b, param[BCOMP]); UNCLAMPED_FLOAT_TO_UBYTE(a, param[ACOMP]); col = ((a << 24) | (r << 16) | (g << 8) | b); if (col != i830->state.TexEnv[unit][I830_TEXENVREG_COL1]) { I830_STATECHANGE(i830, I830_UPLOAD_TEXENV); i830->state.TexEnv[unit][I830_TEXENVREG_COL1] = col; } break; } #endif case GL_TEXTURE_ENV_MODE: case GL_COMBINE_RGB: case GL_COMBINE_ALPHA: case GL_SOURCE0_RGB: case GL_SOURCE1_RGB: case GL_SOURCE2_RGB: case GL_SOURCE0_ALPHA: case GL_SOURCE1_ALPHA: case GL_SOURCE2_ALPHA: case GL_OPERAND0_RGB: case GL_OPERAND1_RGB: case GL_OPERAND2_RGB: case GL_OPERAND0_ALPHA: case GL_OPERAND1_ALPHA: case GL_OPERAND2_ALPHA: case GL_RGB_SCALE: case GL_ALPHA_SCALE: break; case GL_TEXTURE_LOD_BIAS: { int b = (int) ((*param) * 16.0); if (b > 63) b = 63; if (b < -64) b = -64; I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); i830->state.Tex[unit][I830_TEXREG_TM0S3] &= ~TM0S3_LOD_BIAS_MASK; i830->state.Tex[unit][I830_TEXREG_TM0S3] |= ((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK); break; } default: break; } }