📄 i915_state.c
字号:
/************************************************************************** * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/#include "glheader.h"#include "context.h"#include "macros.h"#include "enums.h"#include "dd.h"#include "tnl/tnl.h"#include "tnl/t_context.h"#include "texmem.h"#include "drivers/common/driverfuncs.h"#include "intel_fbo.h"#include "intel_screen.h"#include "intel_batchbuffer.h"#include "i915_context.h"#include "i915_reg.h"#define FILE_DEBUG_FLAG DEBUG_STATEstatic voidi915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref, GLuint mask){ struct i915_context *i915 = I915_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); I915_STATECHANGE(i915, I915_UPLOAD_CTX); i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK; i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(mask)); i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK | S5_STENCIL_TEST_FUNC_MASK); i915->state.Ctx[I915_CTXREG_LIS5] |= ((ref << S5_STENCIL_REF_SHIFT) | (test << S5_STENCIL_TEST_FUNC_SHIFT));}static voidi915StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask){ struct i915_context *i915 = I915_CONTEXT(ctx); DBG("%s : mask 0x%x\n", __FUNCTION__, mask); mask = mask & 0xff; I915_STATECHANGE(i915, I915_UPLOAD_CTX); i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK; i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(mask));}static voidi915StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail, GLenum zfail, GLenum zpass){ struct i915_context *i915 = I915_CONTEXT(ctx); int fop = intel_translate_stencil_op(fail); int dfop = intel_translate_stencil_op(zfail); int dpop = intel_translate_stencil_op(zpass); 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)); I915_STATECHANGE(i915, I915_UPLOAD_CTX); i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK | S5_STENCIL_PASS_Z_FAIL_MASK | S5_STENCIL_PASS_Z_PASS_MASK); i915->state.Ctx[I915_CTXREG_LIS5] |= ((fop << S5_STENCIL_FAIL_SHIFT) | (dfop << S5_STENCIL_PASS_Z_FAIL_SHIFT) | (dpop << S5_STENCIL_PASS_Z_PASS_SHIFT));}static voidi915AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref){ struct i915_context *i915 = I915_CONTEXT(ctx); int test = intel_translate_compare_func(func); GLubyte refByte; UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref); I915_STATECHANGE(i915, I915_UPLOAD_CTX); i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_ALPHA_TEST_FUNC_MASK | S6_ALPHA_REF_MASK); i915->state.Ctx[I915_CTXREG_LIS6] |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) | (((GLuint) refByte) << S6_ALPHA_REF_SHIFT));}/* This function 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. */static voidi915EvalLogicOpBlendState(GLcontext * ctx){ struct i915_context *i915 = I915_CONTEXT(ctx); I915_STATECHANGE(i915, I915_UPLOAD_CTX); if (RGBA_LOGICOP_ENABLED(ctx)) { i915->state.Ctx[I915_CTXREG_LIS5] |= S5_LOGICOP_ENABLE; i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE; } else { i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_LOGICOP_ENABLE; if (ctx->Color.BlendEnabled) { i915->state.Ctx[I915_CTXREG_LIS6] |= S6_CBUF_BLEND_ENABLE; } else { i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE; } }}static voidi915BlendColor(GLcontext * ctx, const GLfloat color[4]){ struct i915_context *i915 = I915_CONTEXT(ctx); GLubyte r, g, b, a; DBG("%s\n", __FUNCTION__); UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]); UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]); UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]); UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]); I915_STATECHANGE(i915, I915_UPLOAD_CTX); i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = (a << 24) | (r << 16) | (g << 8) | b;}#define DST_BLND_FACT(f) ((f)<<S6_CBUF_DST_BLEND_FACT_SHIFT)#define SRC_BLND_FACT(f) ((f)<<S6_CBUF_SRC_BLEND_FACT_SHIFT)#define DST_ABLND_FACT(f) ((f)<<IAB_DST_FACTOR_SHIFT)#define SRC_ABLND_FACT(f) ((f)<<IAB_SRC_FACTOR_SHIFT)static GLuinttranslate_blend_equation(GLenum mode){ switch (mode) { case GL_FUNC_ADD: return BLENDFUNC_ADD; case GL_MIN: return BLENDFUNC_MIN; case GL_MAX: return BLENDFUNC_MAX; case GL_FUNC_SUBTRACT: return BLENDFUNC_SUBTRACT; case GL_FUNC_REVERSE_SUBTRACT: return BLENDFUNC_REVERSE_SUBTRACT; default: return 0; }}static voidi915UpdateBlendState(GLcontext * ctx){ struct i915_context *i915 = I915_CONTEXT(ctx); GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] & ~(IAB_SRC_FACTOR_MASK | IAB_DST_FACTOR_MASK | (BLENDFUNC_MASK << IAB_FUNC_SHIFT) | IAB_ENABLE)); GLuint lis6 = (i915->state.Ctx[I915_CTXREG_LIS6] & ~(S6_CBUF_SRC_BLEND_FACT_MASK | S6_CBUF_DST_BLEND_FACT_MASK | S6_CBUF_BLEND_FUNC_MASK)); GLuint eqRGB = ctx->Color.BlendEquationRGB; GLuint eqA = ctx->Color.BlendEquationA; GLuint srcRGB = ctx->Color.BlendSrcRGB; GLuint dstRGB = ctx->Color.BlendDstRGB; GLuint srcA = ctx->Color.BlendSrcA; GLuint dstA = ctx->Color.BlendDstA; if (eqRGB == GL_MIN || eqRGB == GL_MAX) { srcRGB = dstRGB = GL_ONE; } if (eqA == GL_MIN || eqA == GL_MAX) { srcA = dstA = GL_ONE; } lis6 |= SRC_BLND_FACT(intel_translate_blend_factor(srcRGB)); lis6 |= DST_BLND_FACT(intel_translate_blend_factor(dstRGB)); lis6 |= translate_blend_equation(eqRGB) << S6_CBUF_BLEND_FUNC_SHIFT; iab |= SRC_ABLND_FACT(intel_translate_blend_factor(srcA)); iab |= DST_ABLND_FACT(intel_translate_blend_factor(dstA)); iab |= translate_blend_equation(eqA) << IAB_FUNC_SHIFT; if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) iab |= IAB_ENABLE; if (iab != i915->state.Ctx[I915_CTXREG_IAB] || lis6 != i915->state.Ctx[I915_CTXREG_LIS6]) { I915_STATECHANGE(i915, I915_UPLOAD_CTX); i915->state.Ctx[I915_CTXREG_IAB] = iab; i915->state.Ctx[I915_CTXREG_LIS6] = lis6; } /* This will catch a logicop blend equation */ i915EvalLogicOpBlendState(ctx);}static voidi915BlendFuncSeparate(GLcontext * ctx, GLenum srcRGB, GLenum dstRGB, GLenum srcA, GLenum dstA){ i915UpdateBlendState(ctx);}static voidi915BlendEquationSeparate(GLcontext * ctx, GLenum eqRGB, GLenum eqA){ i915UpdateBlendState(ctx);}static voidi915DepthFunc(GLcontext * ctx, GLenum func){ struct i915_context *i915 = I915_CONTEXT(ctx); int test = intel_translate_compare_func(func); DBG("%s\n", __FUNCTION__); I915_STATECHANGE(i915, I915_UPLOAD_CTX); i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK; i915->state.Ctx[I915_CTXREG_LIS6] |= test << S6_DEPTH_TEST_FUNC_SHIFT;}static voidi915DepthMask(GLcontext * ctx, GLboolean flag){ struct i915_context *i915 = I915_CONTEXT(ctx); DBG("%s flag (%d)\n", __FUNCTION__, flag); I915_STATECHANGE(i915, I915_UPLOAD_CTX); if (flag && ctx->Depth.Test) i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_WRITE_ENABLE; else i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_WRITE_ENABLE;}/* ============================================================= * Polygon stipple * * The i915 supports a 4x4 stipple natively, GL wants 32x32. * Fortunately stipple is usually a repeating pattern. */static voidi915PolygonStipple(GLcontext * ctx, const GLubyte * mask){ struct i915_context *i915 = I915_CONTEXT(ctx); const GLubyte *m; GLubyte p[4]; int i, j, k; int active = (ctx->Polygon.StippleFlag && i915->intel.reduced_primitive == GL_TRIANGLES); GLuint newMask; if (active) { I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE; } /* Use the already unpacked stipple data from the context rather than the * uninterpreted mask passed in. */ mask = (const GLubyte *)ctx->PolygonStipple; m = mask; 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 = 3; j >= 0; j--) for (i = 0; i < 4; i++, m++) if (*m != p[j]) { i915->intel.hw_stipple = 0; return; } newMask = (((p[0] & 0xf) << 0) | ((p[1] & 0xf) << 4) | ((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12)); if (newMask == 0xffff || newMask == 0x0) { /* this is needed to make conform pass */ i915->intel.hw_stipple = 0; return; } i915->state.Stipple[I915_STPREG_ST1] &= ~0xffff; i915->state.Stipple[I915_STPREG_ST1] |= newMask; i915->intel.hw_stipple = 1; if (active) i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE;}/* ============================================================= * Hardware clipping */static voidi915Scissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h){ struct i915_context *i915 = I915_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); I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); i915->state.Buffer[I915_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff); i915->state.Buffer[I915_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff);}static voidi915LogicOp(GLcontext * ctx, GLenum opcode){ struct i915_context *i915 = I915_CONTEXT(ctx); int tmp = intel_translate_logic_op(opcode); DBG("%s\n", __FUNCTION__); I915_STATECHANGE(i915, I915_UPLOAD_CTX); i915->state.Ctx[I915_CTXREG_STATE4] &= ~LOGICOP_MASK; i915->state.Ctx[I915_CTXREG_STATE4] |= LOGIC_OP_FUNC(tmp);}static voidi915CullFaceFrontFace(GLcontext * ctx, GLenum unused){ struct i915_context *i915 = I915_CONTEXT(ctx); GLuint mode; DBG("%s %d\n", __FUNCTION__, ctx->DrawBuffer ? ctx->DrawBuffer->Name : 0); if (!ctx->Polygon.CullFlag) { mode = S4_CULLMODE_NONE; } else if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) { mode = S4_CULLMODE_CW; if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0) mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); if (ctx->Polygon.CullFaceMode == GL_FRONT) mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); if (ctx->Polygon.FrontFace != GL_CCW) mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); } else { mode = S4_CULLMODE_BOTH; } I915_STATECHANGE(i915, I915_UPLOAD_CTX); i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_CULLMODE_MASK; i915->state.Ctx[I915_CTXREG_LIS4] |= mode;}static voidi915LineWidth(GLcontext * ctx, GLfloat widthf){ struct i915_context *i915 = I915_CONTEXT(ctx); int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK; int width; DBG("%s\n", __FUNCTION__); width = (int) (widthf * 2); CLAMP_SELF(width, 1, 0xf); lis4 |= width << S4_LINE_WIDTH_SHIFT; if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) { I915_STATECHANGE(i915, I915_UPLOAD_CTX); i915->state.Ctx[I915_CTXREG_LIS4] = lis4; }}static voidi915PointSize(GLcontext * ctx, GLfloat size){ struct i915_context *i915 = I915_CONTEXT(ctx); int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK; GLint point_size = (int) size; DBG("%s\n", __FUNCTION__); CLAMP_SELF(point_size, 1, 255); lis4 |= point_size << S4_POINT_WIDTH_SHIFT; if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) { I915_STATECHANGE(i915, I915_UPLOAD_CTX); i915->state.Ctx[I915_CTXREG_LIS4] = lis4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -