diff options
Diffstat (limited to 'src/mesa/drivers/dri/r600/r600_state.c')
-rw-r--r-- | src/mesa/drivers/dri/r600/r600_state.c | 2248 |
1 files changed, 0 insertions, 2248 deletions
diff --git a/src/mesa/drivers/dri/r600/r600_state.c b/src/mesa/drivers/dri/r600/r600_state.c deleted file mode 100644 index 5150f0c602..0000000000 --- a/src/mesa/drivers/dri/r600/r600_state.c +++ /dev/null @@ -1,2248 +0,0 @@ -/* -Copyright (C) The Weather Channel, Inc. 2002. -Copyright (C) 2004 Nicolai Haehnle. -All Rights Reserved. - -The Weather Channel (TM) funded Tungsten Graphics to develop the -initial release of the Radeon 8500 driver under the XFree86 license. -This notice must be preserved. - -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, sublicense, 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 NONINFRINGEMENT. -IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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. - -**************************************************************************/ - -/** - * \file - * - * \author Nicolai Haehnle <prefect_@gmx.net> - */ - -#include "main/glheader.h" -#include "main/state.h" -#include "main/imports.h" -#include "main/enums.h" -#include "main/macros.h" -#include "main/context.h" -#include "main/dd.h" -#include "main/framebuffer.h" -#include "main/simple_list.h" -#include "main/api_arrayelt.h" -#include "main/texformat.h" - -#include "swrast/swrast.h" -#include "swrast_setup/swrast_setup.h" -#include "shader/prog_parameter.h" -#include "shader/prog_statevars.h" -#include "vbo/vbo.h" -#include "tnl/tnl.h" - -#include "r600_context.h" -#include "r600_ioctl.h" -#include "r600_state.h" -#include "r600_reg.h" -#include "r600_emit.h" -#include "r600_fragprog.h" -#include "r600_tex.h" - -#include "drirenderbuffer.h" - -extern int future_hw_tcl_on; -extern void _tnl_UpdateFixedFunctionProgram(GLcontext * ctx); - -static void r600BlendColor(GLcontext * ctx, const GLfloat cf[4]) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - GLubyte color[4]; - - R600_STATECHANGE(rmesa, blend_color); - - CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]); - CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]); - CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]); - CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]); - - rmesa->hw.blend_color.cmd[1] = PACK_COLOR_8888(color[3], color[0], - color[1], color[2]); -} - -/** - * Calculate the hardware blend factor setting. This same function is used - * for source and destination of both alpha and RGB. - * - * \returns - * The hardware register value for the specified blend factor. This value - * will need to be shifted into the correct position for either source or - * destination factor. - * - * \todo - * Since the two cases where source and destination are handled differently - * are essentially error cases, they should never happen. Determine if these - * cases can be removed. - */ -static int blend_factor(GLenum factor, GLboolean is_src) -{ - switch (factor) { - case GL_ZERO: - return R600_BLEND_GL_ZERO; - break; - case GL_ONE: - return R600_BLEND_GL_ONE; - break; - case GL_DST_COLOR: - return R600_BLEND_GL_DST_COLOR; - break; - case GL_ONE_MINUS_DST_COLOR: - return R600_BLEND_GL_ONE_MINUS_DST_COLOR; - break; - case GL_SRC_COLOR: - return R600_BLEND_GL_SRC_COLOR; - break; - case GL_ONE_MINUS_SRC_COLOR: - return R600_BLEND_GL_ONE_MINUS_SRC_COLOR; - break; - case GL_SRC_ALPHA: - return R600_BLEND_GL_SRC_ALPHA; - break; - case GL_ONE_MINUS_SRC_ALPHA: - return R600_BLEND_GL_ONE_MINUS_SRC_ALPHA; - break; - case GL_DST_ALPHA: - return R600_BLEND_GL_DST_ALPHA; - break; - case GL_ONE_MINUS_DST_ALPHA: - return R600_BLEND_GL_ONE_MINUS_DST_ALPHA; - break; - case GL_SRC_ALPHA_SATURATE: - return (is_src) ? R600_BLEND_GL_SRC_ALPHA_SATURATE : - R600_BLEND_GL_ZERO; - break; - case GL_CONSTANT_COLOR: - return R600_BLEND_GL_CONST_COLOR; - break; - case GL_ONE_MINUS_CONSTANT_COLOR: - return R600_BLEND_GL_ONE_MINUS_CONST_COLOR; - break; - case GL_CONSTANT_ALPHA: - return R600_BLEND_GL_CONST_ALPHA; - break; - case GL_ONE_MINUS_CONSTANT_ALPHA: - return R600_BLEND_GL_ONE_MINUS_CONST_ALPHA; - break; - default: - fprintf(stderr, "unknown blend factor %x\n", factor); - return (is_src) ? R600_BLEND_GL_ONE : R600_BLEND_GL_ZERO; - break; - } -} - -/** - * Sets both the blend equation and the blend function. - * 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. - * Also, make sure that blend function and blend equation are set to their - * default value if color blending is not enabled, since at least blend - * equations GL_MIN and GL_FUNC_REVERSE_SUBTRACT will cause wrong results - * otherwise for unknown reasons. - */ - -/* helper function */ -static void r600SetBlendCntl(r600ContextPtr r600, int func, int eqn, - int cbits, int funcA, int eqnA) -{ - GLuint new_ablend, new_cblend; - -#if 0 - fprintf(stderr, - "eqnA=%08x funcA=%08x eqn=%08x func=%08x cbits=%08x\n", - eqnA, funcA, eqn, func, cbits); -#endif - new_ablend = eqnA | funcA; - new_cblend = eqn | func; - - /* Some blend factor combinations don't seem to work when the - * BLEND_NO_SEPARATE bit is set. - * - * Especially problematic candidates are the ONE_MINUS_* flags, - * but I can't see a real pattern. - */ -#if 0 - if (new_ablend == new_cblend) { - new_cblend |= R600_DISCARD_SRC_PIXELS_SRC_ALPHA_0; - } -#endif - new_cblend |= cbits; - - if ((new_ablend != r600->hw.bld.cmd[R600_BLD_ABLEND]) || - (new_cblend != r600->hw.bld.cmd[R600_BLD_CBLEND])) { - R600_STATECHANGE(r600, bld); - r600->hw.bld.cmd[R600_BLD_ABLEND] = new_ablend; - r600->hw.bld.cmd[R600_BLD_CBLEND] = new_cblend; - } -} - -static void r600SetBlendState(GLcontext * ctx) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - int func = (R600_BLEND_GL_ONE << R600_SRC_BLEND_SHIFT) | - (R600_BLEND_GL_ZERO << R600_DST_BLEND_SHIFT); - int eqn = R600_COMB_FCN_ADD_CLAMP; - int funcA = (R600_BLEND_GL_ONE << R600_SRC_BLEND_SHIFT) | - (R600_BLEND_GL_ZERO << R600_DST_BLEND_SHIFT); - int eqnA = R600_COMB_FCN_ADD_CLAMP; - - if (RGBA_LOGICOP_ENABLED(ctx) || !ctx->Color.BlendEnabled) { - r600SetBlendCntl(r600, func, eqn, 0, func, eqn); - return; - } - - func = - (blend_factor(ctx->Color.BlendSrcRGB, GL_TRUE) << - R600_SRC_BLEND_SHIFT) | (blend_factor(ctx->Color.BlendDstRGB, - GL_FALSE) << - R600_DST_BLEND_SHIFT); - - switch (ctx->Color.BlendEquationRGB) { - case GL_FUNC_ADD: - eqn = R600_COMB_FCN_ADD_CLAMP; - break; - - case GL_FUNC_SUBTRACT: - eqn = R600_COMB_FCN_SUB_CLAMP; - break; - - case GL_FUNC_REVERSE_SUBTRACT: - eqn = R600_COMB_FCN_RSUB_CLAMP; - break; - - case GL_MIN: - eqn = R600_COMB_FCN_MIN; - func = (R600_BLEND_GL_ONE << R600_SRC_BLEND_SHIFT) | - (R600_BLEND_GL_ONE << R600_DST_BLEND_SHIFT); - break; - - case GL_MAX: - eqn = R600_COMB_FCN_MAX; - func = (R600_BLEND_GL_ONE << R600_SRC_BLEND_SHIFT) | - (R600_BLEND_GL_ONE << R600_DST_BLEND_SHIFT); - break; - - default: - fprintf(stderr, - "[%s:%u] Invalid RGB blend equation (0x%04x).\n", - __FUNCTION__, __LINE__, ctx->Color.BlendEquationRGB); - return; - } - - funcA = - (blend_factor(ctx->Color.BlendSrcA, GL_TRUE) << - R600_SRC_BLEND_SHIFT) | (blend_factor(ctx->Color.BlendDstA, - GL_FALSE) << - R600_DST_BLEND_SHIFT); - - switch (ctx->Color.BlendEquationA) { - case GL_FUNC_ADD: - eqnA = R600_COMB_FCN_ADD_CLAMP; - break; - - case GL_FUNC_SUBTRACT: - eqnA = R600_COMB_FCN_SUB_CLAMP; - break; - - case GL_FUNC_REVERSE_SUBTRACT: - eqnA = R600_COMB_FCN_RSUB_CLAMP; - break; - - case GL_MIN: - eqnA = R600_COMB_FCN_MIN; - funcA = (R600_BLEND_GL_ONE << R600_SRC_BLEND_SHIFT) | - (R600_BLEND_GL_ONE << R600_DST_BLEND_SHIFT); - break; - - case GL_MAX: - eqnA = R600_COMB_FCN_MAX; - funcA = (R600_BLEND_GL_ONE << R600_SRC_BLEND_SHIFT) | - (R600_BLEND_GL_ONE << R600_DST_BLEND_SHIFT); - break; - - default: - fprintf(stderr, - "[%s:%u] Invalid A blend equation (0x%04x).\n", - __FUNCTION__, __LINE__, ctx->Color.BlendEquationA); - return; - } - - r600SetBlendCntl(r600, - func, eqn, - (R600_SEPARATE_ALPHA_ENABLE | - R600_READ_ENABLE | - R600_ALPHA_BLEND_ENABLE), funcA, eqnA); -} - -static void r600BlendEquationSeparate(GLcontext * ctx, - GLenum modeRGB, GLenum modeA) -{ - r600SetBlendState(ctx); -} - -static void r600BlendFuncSeparate(GLcontext * ctx, - GLenum sfactorRGB, GLenum dfactorRGB, - GLenum sfactorA, GLenum dfactorA) -{ - r600SetBlendState(ctx); -} - -/** - * Translate LogicOp enums into hardware representation. - * Both use a very logical bit-wise layout, but unfortunately the order - * of bits is reversed. - */ -static GLuint translate_logicop(GLenum logicop) -{ - GLuint bits = logicop - GL_CLEAR; - bits = ((bits & 1) << 3) | ((bits & 2) << 1) | ((bits & 4) >> 1) | ((bits & 8) >> 3); - return bits << R600_RB3D_ROPCNTL_ROP_SHIFT; -} - -/** - * Used internally to update the r600->hw hardware state to match the - * current OpenGL state. - */ -static void r600SetLogicOpState(GLcontext *ctx) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - R600_STATECHANGE(r600, rop); - if (RGBA_LOGICOP_ENABLED(ctx)) { - r600->hw.rop.cmd[1] = R600_RB3D_ROPCNTL_ROP_ENABLE | - translate_logicop(ctx->Color.LogicOp); - } else { - r600->hw.rop.cmd[1] = 0; - } -} - -/** - * Called by Mesa when an application program changes the LogicOp state - * via glLogicOp. - */ -static void r600LogicOpcode(GLcontext *ctx, GLenum logicop) -{ - if (RGBA_LOGICOP_ENABLED(ctx)) - r600SetLogicOpState(ctx); -} - -static void r600ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq ) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - GLint p; - GLint *ip; - - p = (GLint) plane - (GLint) GL_CLIP_PLANE0; - ip = (GLint *)ctx->Transform._ClipUserPlane[p]; - - R600_STATECHANGE( rmesa, vpucp[p] ); - rmesa->hw.vpucp[p].cmd[R600_VPUCP_X] = ip[0]; - rmesa->hw.vpucp[p].cmd[R600_VPUCP_Y] = ip[1]; - rmesa->hw.vpucp[p].cmd[R600_VPUCP_Z] = ip[2]; - rmesa->hw.vpucp[p].cmd[R600_VPUCP_W] = ip[3]; -} - -static void r600SetClipPlaneState(GLcontext * ctx, GLenum cap, GLboolean state) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - GLuint p; - - p = cap - GL_CLIP_PLANE0; - R600_STATECHANGE(r600, vap_clip_cntl); - if (state) { - r600->hw.vap_clip_cntl.cmd[1] |= (R600_VAP_UCP_ENABLE_0 << p); - r600ClipPlane(ctx, cap, NULL); - } else { - r600->hw.vap_clip_cntl.cmd[1] &= ~(R600_VAP_UCP_ENABLE_0 << p); - } -} - -/** - * Update our tracked culling state based on Mesa's state. - */ -static void r600UpdateCulling(GLcontext * ctx) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - uint32_t val = 0; - - if (ctx->Polygon.CullFlag) { - switch (ctx->Polygon.CullFaceMode) { - case GL_FRONT: - val = R600_CULL_FRONT; - break; - case GL_BACK: - val = R600_CULL_BACK; - break; - case GL_FRONT_AND_BACK: - val = R600_CULL_FRONT | R600_CULL_BACK; - break; - default: - break; - } - } - - switch (ctx->Polygon.FrontFace) { - case GL_CW: - val |= R600_FRONT_FACE_CW; - break; - case GL_CCW: - val |= R600_FRONT_FACE_CCW; - break; - default: - break; - } - - R600_STATECHANGE(r600, cul); - r600->hw.cul.cmd[R600_CUL_CULL] = val; -} - -static void r600SetPolygonOffsetState(GLcontext * ctx, GLboolean state) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - - R600_STATECHANGE(r600, occlusion_cntl); - if (state) { - r600->hw.occlusion_cntl.cmd[1] |= (3 << 0); - } else { - r600->hw.occlusion_cntl.cmd[1] &= ~(3 << 0); - } -} - -static GLboolean current_fragment_program_writes_depth(GLcontext* ctx) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - - struct r600_fragment_program *fp = (struct r600_fragment_program *) - (char *)ctx->FragmentProgram._Current; - return (fp && fp->WritesDepth); - -} - -static void r600SetEarlyZState(GLcontext * ctx) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - GLuint topZ = R600_ZTOP_ENABLE; - - if (ctx->Color.AlphaEnabled && ctx->Color.AlphaFunc != GL_ALWAYS) - topZ = R600_ZTOP_DISABLE; - if (current_fragment_program_writes_depth(ctx)) - topZ = R600_ZTOP_DISABLE; - - if (topZ != r600->hw.zstencil_format.cmd[2]) { - /* Note: This completely reemits the stencil format. - * I have not tested whether this is strictly necessary, - * or if emitting a write to ZB_ZTOP is enough. - */ - R600_STATECHANGE(r600, zstencil_format); - r600->hw.zstencil_format.cmd[2] = topZ; - } -} - -static void r600SetAlphaState(GLcontext * ctx) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - GLubyte refByte; - uint32_t pp_misc = 0x0; - GLboolean really_enabled = ctx->Color.AlphaEnabled; - - CLAMPED_FLOAT_TO_UBYTE(refByte, ctx->Color.AlphaRef); - - switch (ctx->Color.AlphaFunc) { - case GL_NEVER: - pp_misc |= R600_FG_ALPHA_FUNC_NEVER; - break; - case GL_LESS: - pp_misc |= R600_FG_ALPHA_FUNC_LESS; - break; - case GL_EQUAL: - pp_misc |= R600_FG_ALPHA_FUNC_EQUAL; - break; - case GL_LEQUAL: - pp_misc |= R600_FG_ALPHA_FUNC_LE; - break; - case GL_GREATER: - pp_misc |= R600_FG_ALPHA_FUNC_GREATER; - break; - case GL_NOTEQUAL: - pp_misc |= R600_FG_ALPHA_FUNC_NOTEQUAL; - break; - case GL_GEQUAL: - pp_misc |= R600_FG_ALPHA_FUNC_GE; - break; - case GL_ALWAYS: - /*pp_misc |= FG_ALPHA_FUNC_ALWAYS; */ - really_enabled = GL_FALSE; - break; - } - - if (really_enabled) { - pp_misc |= R600_FG_ALPHA_FUNC_ENABLE; - pp_misc |= (refByte & R600_FG_ALPHA_FUNC_VAL_MASK); - } else { - pp_misc = 0x0; - } - - R600_STATECHANGE(r600, at); - r600->hw.at.cmd[R600_AT_ALPHA_TEST] = pp_misc; - r600->hw.at.cmd[R600_AT_UNKNOWN] = 0; - - r600SetEarlyZState(ctx); -} - -static void r600AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref) -{ - (void)func; - (void)ref; - r600SetAlphaState(ctx); -} - -static int translate_func(int func) -{ - switch (func) { - case GL_NEVER: - return R600_ZS_NEVER; - case GL_LESS: - return R600_ZS_LESS; - case GL_EQUAL: - return R600_ZS_EQUAL; - case GL_LEQUAL: - return R600_ZS_LEQUAL; - case GL_GREATER: - return R600_ZS_GREATER; - case GL_NOTEQUAL: - return R600_ZS_NOTEQUAL; - case GL_GEQUAL: - return R600_ZS_GEQUAL; - case GL_ALWAYS: - return R600_ZS_ALWAYS; - } - return 0; -} - -static void r600SetDepthState(GLcontext * ctx) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - - R600_STATECHANGE(r600, zs); - r600->hw.zs.cmd[R600_ZS_CNTL_0] &= R600_STENCIL_ENABLE|R600_STENCIL_FRONT_BACK; - r600->hw.zs.cmd[R600_ZS_CNTL_1] &= ~(R600_ZS_MASK << R600_Z_FUNC_SHIFT); - - if (ctx->Depth.Test) { - r600->hw.zs.cmd[R600_ZS_CNTL_0] |= R600_Z_ENABLE; - if (ctx->Depth.Mask) - r600->hw.zs.cmd[R600_ZS_CNTL_0] |= R600_Z_WRITE_ENABLE; - r600->hw.zs.cmd[R600_ZS_CNTL_1] |= - translate_func(ctx->Depth.Func) << R600_Z_FUNC_SHIFT; - } - - r600SetEarlyZState(ctx); -} - -static void r600SetStencilState(GLcontext * ctx, GLboolean state) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - GLboolean hw_stencil = GL_FALSE; - if (ctx->DrawBuffer) { - struct radeon_renderbuffer *rrbStencil - = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); - hw_stencil = (rrbStencil && rrbStencil->bo); - } - - if (hw_stencil) { - R600_STATECHANGE(r600, zs); - if (state) { - r600->hw.zs.cmd[R600_ZS_CNTL_0] |= - R600_STENCIL_ENABLE; - } else { - r600->hw.zs.cmd[R600_ZS_CNTL_0] &= - ~R600_STENCIL_ENABLE; - } - } else { -#if R200_MERGED - FALLBACK(&r600->radeon, RADEON_FALLBACK_STENCIL, state); -#endif - } -} - -static void r600UpdatePolygonMode(GLcontext * ctx) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - uint32_t hw_mode = R600_GA_POLY_MODE_DISABLE; - - /* Only do something if a polygon mode is wanted, default is GL_FILL */ - if (ctx->Polygon.FrontMode != GL_FILL || - ctx->Polygon.BackMode != GL_FILL) { - GLenum f, b; - - /* Handle GL_CW (clock wise and GL_CCW (counter clock wise) - * correctly by selecting the correct front and back face - */ - if (ctx->Polygon.FrontFace == GL_CCW) { - f = ctx->Polygon.FrontMode; - b = ctx->Polygon.BackMode; - } else { - f = ctx->Polygon.BackMode; - b = ctx->Polygon.FrontMode; - } - - /* Enable polygon mode */ - hw_mode |= R600_GA_POLY_MODE_DUAL; - - switch (f) { - case GL_LINE: - hw_mode |= R600_GA_POLY_MODE_FRONT_PTYPE_LINE; - break; - case GL_POINT: - hw_mode |= R600_GA_POLY_MODE_FRONT_PTYPE_POINT; - break; - case GL_FILL: - hw_mode |= R600_GA_POLY_MODE_FRONT_PTYPE_TRI; - break; - } - - switch (b) { - case GL_LINE: - hw_mode |= R600_GA_POLY_MODE_BACK_PTYPE_LINE; - break; - case GL_POINT: - hw_mode |= R600_GA_POLY_MODE_BACK_PTYPE_POINT; - break; - case GL_FILL: - hw_mode |= R600_GA_POLY_MODE_BACK_PTYPE_TRI; - break; - } - } - - if (r600->hw.polygon_mode.cmd[1] != hw_mode) { - R600_STATECHANGE(r600, polygon_mode); - r600->hw.polygon_mode.cmd[1] = hw_mode; - } - - r600->hw.polygon_mode.cmd[2] = 0x00000001; - r600->hw.polygon_mode.cmd[3] = 0x00000000; -} - -/** - * Change the culling mode. - * - * \note Mesa already filters redundant calls to this function. - */ -static void r600CullFace(GLcontext * ctx, GLenum mode) -{ - (void)mode; - - r600UpdateCulling(ctx); -} - -/** - * Change the polygon orientation. - * - * \note Mesa already filters redundant calls to this function. - */ -static void r600FrontFace(GLcontext * ctx, GLenum mode) -{ - (void)mode; - - r600UpdateCulling(ctx); - r600UpdatePolygonMode(ctx); -} - -/** - * Change the depth testing function. - * - * \note Mesa already filters redundant calls to this function. - */ -static void r600DepthFunc(GLcontext * ctx, GLenum func) -{ - (void)func; - r600SetDepthState(ctx); -} - -/** - * Enable/Disable depth writing. - * - * \note Mesa already filters redundant calls to this function. - */ -static void r600DepthMask(GLcontext * ctx, GLboolean mask) -{ - (void)mask; - r600SetDepthState(ctx); -} - -/** - * Handle glColorMask() - */ -static void r600ColorMask(GLcontext * ctx, - GLboolean r, GLboolean g, GLboolean b, GLboolean a) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - int mask = (r ? RB3D_COLOR_CHANNEL_MASK_RED_MASK0 : 0) | - (g ? RB3D_COLOR_CHANNEL_MASK_GREEN_MASK0 : 0) | - (b ? RB3D_COLOR_CHANNEL_MASK_BLUE_MASK0 : 0) | - (a ? RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK0 : 0); - - if (mask != r600->hw.cmk.cmd[R600_CMK_COLORMASK]) { - R600_STATECHANGE(r600, cmk); - r600->hw.cmk.cmd[R600_CMK_COLORMASK] = mask; - } -} - -/* ============================================================= - * Point state - */ -static void r600PointSize(GLcontext * ctx, GLfloat size) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - /* same size limits for AA, non-AA points */ - size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize); - - R600_STATECHANGE(r600, ps); - r600->hw.ps.cmd[R600_PS_POINTSIZE] = - ((int)(size * 6) << R600_POINTSIZE_X_SHIFT) | - ((int)(size * 6) << R600_POINTSIZE_Y_SHIFT); -} - -static void r600PointParameter(GLcontext * ctx, GLenum pname, const GLfloat * param) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - - switch (pname) { - case GL_POINT_SIZE_MIN: - R600_STATECHANGE(r600, ga_point_minmax); - r600->hw.ga_point_minmax.cmd[1] &= ~R600_GA_POINT_MINMAX_MIN_MASK; - r600->hw.ga_point_minmax.cmd[1] |= (GLuint)(ctx->Point.MinSize * 6.0); - break; - case GL_POINT_SIZE_MAX: - R600_STATECHANGE(r600, ga_point_minmax); - r600->hw.ga_point_minmax.cmd[1] &= ~R600_GA_POINT_MINMAX_MAX_MASK; - r600->hw.ga_point_minmax.cmd[1] |= (GLuint)(ctx->Point.MaxSize * 6.0) - << R600_GA_POINT_MINMAX_MAX_SHIFT; - break; - case GL_POINT_DISTANCE_ATTENUATION: - break; - case GL_POINT_FADE_THRESHOLD_SIZE: - break; - default: - break; - } -} - -/* ============================================================= - * Line state - */ -static void r600LineWidth(GLcontext * ctx, GLfloat widthf) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - - widthf = CLAMP(widthf, - ctx->Const.MinPointSize, - ctx->Const.MaxPointSize); - R600_STATECHANGE(r600, lcntl); - r600->hw.lcntl.cmd[1] = - R600_LINE_CNT_HO | R600_LINE_CNT_VE | (int)(widthf * 6.0); -} - -static void r600PolygonMode(GLcontext * ctx, GLenum face, GLenum mode) -{ - (void)face; - (void)mode; - - r600UpdatePolygonMode(ctx); -} - -/* ============================================================= - * Stencil - */ - -static int translate_stencil_op(int op) -{ - switch (op) { - case GL_KEEP: - return R600_ZS_KEEP; - case GL_ZERO: - return R600_ZS_ZERO; - case GL_REPLACE: - return R600_ZS_REPLACE; - case GL_INCR: - return R600_ZS_INCR; - case GL_DECR: - return R600_ZS_DECR; - case GL_INCR_WRAP_EXT: - return R600_ZS_INCR_WRAP; - case GL_DECR_WRAP_EXT: - return R600_ZS_DECR_WRAP; - case GL_INVERT: - return R600_ZS_INVERT; - default: - WARN_ONCE("Do not know how to translate stencil op"); - return R600_ZS_KEEP; - } - return 0; -} - -static void r600ShadeModel(GLcontext * ctx, GLenum mode) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - - R600_STATECHANGE(rmesa, shade); - rmesa->hw.shade.cmd[1] = 0x00000002; - switch (mode) { - case GL_FLAT: - rmesa->hw.shade.cmd[2] = R600_RE_SHADE_MODEL_FLAT; - break; - case GL_SMOOTH: - rmesa->hw.shade.cmd[2] = R600_RE_SHADE_MODEL_SMOOTH; - break; - default: - return; - } - rmesa->hw.shade.cmd[3] = 0x00000000; - rmesa->hw.shade.cmd[4] = 0x00000000; -} - -static void r600StencilFuncSeparate(GLcontext * ctx, GLenum face, - GLenum func, GLint ref, GLuint mask) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - GLuint refmask = - ((ctx->Stencil.Ref[0] & 0xff) << R600_STENCILREF_SHIFT) - | ((ctx->Stencil.ValueMask[0] & 0xff) << R600_STENCILMASK_SHIFT); - const unsigned back = ctx->Stencil._BackFace; - GLuint flag; - - R600_STATECHANGE(rmesa, zs); - rmesa->hw.zs.cmd[R600_ZS_CNTL_0] |= R600_STENCIL_FRONT_BACK; - rmesa->hw.zs.cmd[R600_ZS_CNTL_1] &= ~((R600_ZS_MASK << - R600_S_FRONT_FUNC_SHIFT) - | (R600_ZS_MASK << - R600_S_BACK_FUNC_SHIFT)); - - rmesa->hw.zs.cmd[R600_ZS_CNTL_2] &= - ~((R600_STENCILREF_MASK << R600_STENCILREF_SHIFT) | - (R600_STENCILREF_MASK << R600_STENCILMASK_SHIFT)); - - flag = translate_func(ctx->Stencil.Function[0]); - rmesa->hw.zs.cmd[R600_ZS_CNTL_1] |= - (flag << R600_S_FRONT_FUNC_SHIFT); - - flag = translate_func(ctx->Stencil.Function[back]); - - rmesa->hw.zs.cmd[R600_ZS_CNTL_1] |= - (flag << R600_S_BACK_FUNC_SHIFT); - rmesa->hw.zs.cmd[R600_ZS_CNTL_2] |= refmask; -} - -static void r600StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - - R600_STATECHANGE(rmesa, zs); - rmesa->hw.zs.cmd[R600_ZS_CNTL_2] &= - ~(R600_STENCILREF_MASK << - R600_STENCILWRITEMASK_SHIFT); - rmesa->hw.zs.cmd[R600_ZS_CNTL_2] |= - (ctx->Stencil. - WriteMask[0] & R600_STENCILREF_MASK) << - R600_STENCILWRITEMASK_SHIFT; -} - -static void r600StencilOpSeparate(GLcontext * ctx, GLenum face, - GLenum fail, GLenum zfail, GLenum zpass) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - const unsigned back = ctx->Stencil._BackFace; - - R600_STATECHANGE(rmesa, zs); - /* It is easier to mask what's left.. */ - rmesa->hw.zs.cmd[R600_ZS_CNTL_1] &= - (R600_ZS_MASK << R600_Z_FUNC_SHIFT) | - (R600_ZS_MASK << R600_S_FRONT_FUNC_SHIFT) | - (R600_ZS_MASK << R600_S_BACK_FUNC_SHIFT); - - rmesa->hw.zs.cmd[R600_ZS_CNTL_1] |= - (translate_stencil_op(ctx->Stencil.FailFunc[0]) << - R600_S_FRONT_SFAIL_OP_SHIFT) - | (translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << - R600_S_FRONT_ZFAIL_OP_SHIFT) - | (translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << - R600_S_FRONT_ZPASS_OP_SHIFT); - - rmesa->hw.zs.cmd[R600_ZS_CNTL_1] |= - (translate_stencil_op(ctx->Stencil.FailFunc[back]) << - R600_S_BACK_SFAIL_OP_SHIFT) - | (translate_stencil_op(ctx->Stencil.ZFailFunc[back]) << - R600_S_BACK_ZFAIL_OP_SHIFT) - | (translate_stencil_op(ctx->Stencil.ZPassFunc[back]) << - R600_S_BACK_ZPASS_OP_SHIFT); -} - -/* ============================================================= - * Window position and viewport transformation - */ - -/* - * To correctly position primitives: - */ -#define SUBPIXEL_X 0.125 -#define SUBPIXEL_Y 0.125 - -static void r600UpdateWindow(GLcontext * ctx) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable; - GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0; - GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0; - const GLfloat *v = ctx->Viewport._WindowMap.m; - const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF; - const GLboolean render_to_fbo = (ctx->DrawBuffer->Name != 0); - GLfloat y_scale, y_bias; - - if (render_to_fbo) { - y_scale = 1.0; - y_bias = 0; - } else { - y_scale = -1.0; - y_bias = yoffset; - } - - GLfloat sx = v[MAT_SX]; - GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X; - GLfloat sy = v[MAT_SY] * y_scale; - GLfloat ty = (v[MAT_TY] * y_scale) + y_bias + SUBPIXEL_Y; - GLfloat sz = v[MAT_SZ] * depthScale; - GLfloat tz = v[MAT_TZ] * depthScale; - - R600_STATECHANGE(rmesa, vpt); - - rmesa->hw.vpt.cmd[R600_VPT_XSCALE] = r600PackFloat32(sx); - rmesa->hw.vpt.cmd[R600_VPT_XOFFSET] = r600PackFloat32(tx); - rmesa->hw.vpt.cmd[R600_VPT_YSCALE] = r600PackFloat32(sy); - rmesa->hw.vpt.cmd[R600_VPT_YOFFSET] = r600PackFloat32(ty); - rmesa->hw.vpt.cmd[R600_VPT_ZSCALE] = r600PackFloat32(sz); - rmesa->hw.vpt.cmd[R600_VPT_ZOFFSET] = r600PackFloat32(tz); -} - -static void r600Viewport(GLcontext * ctx, GLint x, GLint y, - GLsizei width, GLsizei height) -{ - /* Don't pipeline viewport changes, conflict with window offset - * setting below. Could apply deltas to rescue pipelined viewport - * values, or keep the originals hanging around. - */ - r600UpdateWindow(ctx); - - radeon_viewport(ctx, x, y, width, height); -} - -static void r600DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval) -{ - r600UpdateWindow(ctx); -} - -void r600UpdateViewportOffset(GLcontext * ctx) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - __DRIdrawablePrivate *dPriv = ((radeonContextPtr) rmesa)->dri.drawable; - GLfloat xoffset = (GLfloat) dPriv->x; - GLfloat yoffset = (GLfloat) dPriv->y + dPriv->h; - const GLfloat *v = ctx->Viewport._WindowMap.m; - - GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X; - GLfloat ty = (-v[MAT_TY]) + yoffset + SUBPIXEL_Y; - - if (rmesa->hw.vpt.cmd[R600_VPT_XOFFSET] != r600PackFloat32(tx) || - rmesa->hw.vpt.cmd[R600_VPT_YOFFSET] != r600PackFloat32(ty)) { - /* Note: this should also modify whatever data the context reset - * code uses... - */ - R600_STATECHANGE(rmesa, vpt); - rmesa->hw.vpt.cmd[R600_VPT_XOFFSET] = r600PackFloat32(tx); - rmesa->hw.vpt.cmd[R600_VPT_YOFFSET] = r600PackFloat32(ty); - - } - - radeonUpdateScissor(ctx); -} - -static void -r600FetchStateParameter(GLcontext * ctx, - const gl_state_index state[STATE_LENGTH], - GLfloat * value) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - - switch (state[0]) { - case STATE_INTERNAL: - switch (state[1]) { - case STATE_R600_WINDOW_DIMENSION: - value[0] = r600->radeon.dri.drawable->w * 0.5f; /* width*0.5 */ - value[1] = r600->radeon.dri.drawable->h * 0.5f; /* height*0.5 */ - value[2] = 0.5F; /* for moving range [-1 1] -> [0 1] */ - value[3] = 1.0F; /* not used */ - break; - - case STATE_R600_TEXRECT_FACTOR:{ - struct gl_texture_object *t = - ctx->Texture.Unit[state[2]].CurrentTex[TEXTURE_RECT_INDEX]; - - if (t && t->Image[0][t->BaseLevel]) { - struct gl_texture_image *image = - t->Image[0][t->BaseLevel]; - value[0] = 1.0 / image->Width2; - value[1] = 1.0 / image->Height2; - } else { - value[0] = 1.0; - value[1] = 1.0; - } - value[2] = 1.0; - value[3] = 1.0; - break; - } - - default: - break; - } - break; - - default: - break; - } -} - -/** - * Update R600's own internal state parameters. - * For now just STATE_R600_WINDOW_DIMENSION - */ -void r600UpdateStateParameters(GLcontext * ctx, GLuint new_state) -{ - struct r600_fragment_program *fp; - struct gl_program_parameter_list *paramList; - GLuint i; - - if (!(new_state & (_NEW_BUFFERS | _NEW_PROGRAM))) - return; - - fp = (struct r600_fragment_program *)ctx->FragmentProgram._Current; - if (!fp) - return; - - paramList = fp->mesa_program.Base.Parameters; - - if (!paramList) - return; - - for (i = 0; i < paramList->NumParameters; i++) { - if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { - r600FetchStateParameter(ctx, - paramList->Parameters[i]. - StateIndexes, - paramList->ParameterValues[i]); - } - } -} - -/* ============================================================= - * Polygon state - */ -static void r600PolygonOffset(GLcontext * ctx, GLfloat factor, GLfloat units) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - GLfloat constant = units; - - switch (ctx->Visual.depthBits) { - case 16: - constant *= 4.0; - break; - case 24: - constant *= 2.0; - break; - } - - factor *= 12.0; - -/* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */ - - R600_STATECHANGE(rmesa, zbs); - rmesa->hw.zbs.cmd[R600_ZBS_T_FACTOR] = r600PackFloat32(factor); - rmesa->hw.zbs.cmd[R600_ZBS_T_CONSTANT] = r600PackFloat32(constant); - rmesa->hw.zbs.cmd[R600_ZBS_W_FACTOR] = r600PackFloat32(factor); - rmesa->hw.zbs.cmd[R600_ZBS_W_CONSTANT] = r600PackFloat32(constant); -} - -/* Routing and texture-related */ - -/* r600 doesnt handle GL_CLAMP and GL_MIRROR_CLAMP_EXT correctly when filter is NEAREST. - * Since texwrap produces same results for GL_CLAMP and GL_CLAMP_TO_EDGE we use them instead. - * We need to recalculate wrap modes whenever filter mode is changed because someone might do: - * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - * Since r600 completely ignores R600_TX_CLAMP when either min or mag is nearest it cant handle - * combinations where only one of them is nearest. - */ -static unsigned long gen_fixed_filter(unsigned long f) -{ - unsigned long mag, min, needs_fixing = 0; - //return f; - - /* We ignore MIRROR bit so we dont have to do everything twice */ - if ((f & ((7 - 1) << R600_TX_WRAP_S_SHIFT)) == - (R600_TX_CLAMP << R600_TX_WRAP_S_SHIFT)) { - needs_fixing |= 1; - } - if ((f & ((7 - 1) << R600_TX_WRAP_T_SHIFT)) == - (R600_TX_CLAMP << R600_TX_WRAP_T_SHIFT)) { - needs_fixing |= 2; - } - if ((f & ((7 - 1) << R600_TX_WRAP_R_SHIFT)) == - (R600_TX_CLAMP << R600_TX_WRAP_R_SHIFT)) { - needs_fixing |= 4; - } - - if (!needs_fixing) - return f; - - mag = f & R600_TX_MAG_FILTER_MASK; - min = f & (R600_TX_MIN_FILTER_MASK|R600_TX_MIN_FILTER_MIP_MASK); - - /* TODO: Check for anisto filters too */ - if ((mag != R600_TX_MAG_FILTER_NEAREST) - && (min != R600_TX_MIN_FILTER_NEAREST)) - return f; - - /* r600 cant handle these modes hence we force nearest to linear */ - if ((mag == R600_TX_MAG_FILTER_NEAREST) - && (min != R600_TX_MIN_FILTER_NEAREST)) { - f &= ~R600_TX_MAG_FILTER_NEAREST; - f |= R600_TX_MAG_FILTER_LINEAR; - return f; - } - - if ((min == R600_TX_MIN_FILTER_NEAREST) - && (mag != R600_TX_MAG_FILTER_NEAREST)) { - f &= ~R600_TX_MIN_FILTER_NEAREST; - f |= R600_TX_MIN_FILTER_LINEAR; - return f; - } - - /* Both are nearest */ - if (needs_fixing & 1) { - f &= ~((7 - 1) << R600_TX_WRAP_S_SHIFT); - f |= R600_TX_CLAMP_TO_EDGE << R600_TX_WRAP_S_SHIFT; - } - if (needs_fixing & 2) { - f &= ~((7 - 1) << R600_TX_WRAP_T_SHIFT); - f |= R600_TX_CLAMP_TO_EDGE << R600_TX_WRAP_T_SHIFT; - } - if (needs_fixing & 4) { - f &= ~((7 - 1) << R600_TX_WRAP_R_SHIFT); - f |= R600_TX_CLAMP_TO_EDGE << R600_TX_WRAP_R_SHIFT; - } - return f; -} - -static void r600SetupFragmentShaderTextures(GLcontext *ctx, int *tmu_mappings) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - int i; - struct r600_fragment_program *fp = (struct r600_fragment_program *) - (char *)ctx->FragmentProgram._Current; - struct r600_fragment_program_code *code = &fp->code; - - R600_STATECHANGE(r600, fpt); - - for (i = 0; i < code->tex.length; i++) { - int unit; - int opcode; - unsigned long val; - - unit = code->tex.inst[i] >> R600_TEX_ID_SHIFT; - unit &= 15; - - val = code->tex.inst[i]; - val &= ~R600_TEX_ID_MASK; - - opcode = - (val & R600_TEX_INST_MASK) >> R600_TEX_INST_SHIFT; - if (opcode == R600_TEX_OP_KIL) { - r600->hw.fpt.cmd[R600_FPT_INSTR_0 + i] = val; - } else { - if (tmu_mappings[unit] >= 0) { - val |= - tmu_mappings[unit] << - R600_TEX_ID_SHIFT; - r600->hw.fpt.cmd[R600_FPT_INSTR_0 + i] = val; - } else { - // We get here when the corresponding texture image is incomplete - // (e.g. incomplete mipmaps etc.) - r600->hw.fpt.cmd[R600_FPT_INSTR_0 + i] = val; - } - } - } - - r600->hw.fpt.cmd[R600_FPT_CMD_0] = - cmdpacket0(r600->radeon.radeonScreen, - R600_US_TEX_INST_0, code->tex.length); -} - -static GLuint translate_lod_bias(GLfloat bias) -{ - GLint b = (int)(bias*32); - if (b >= (1 << 9)) - b = (1 << 9)-1; - else if (b < -(1 << 9)) - b = -(1 << 9); - return (((GLuint)b) << R600_LOD_BIAS_SHIFT) & R600_LOD_BIAS_MASK; -} - -static void r600SetupTextures(GLcontext * ctx) -{ - int i, mtu; - struct radeon_tex_obj *t; - r600ContextPtr r600 = R600_CONTEXT(ctx); - int hw_tmu = 0; - int last_hw_tmu = -1; /* -1 translates into no setup costs for fields */ - int tmu_mappings[R600_MAX_TEXTURE_UNITS] = { -1, }; - struct r600_fragment_program *fp = (struct r600_fragment_program *) - (char *)ctx->FragmentProgram._Current; - - R600_STATECHANGE(r600, txe); - R600_STATECHANGE(r600, tex.filter); - R600_STATECHANGE(r600, tex.filter_1); - R600_STATECHANGE(r600, tex.size); - R600_STATECHANGE(r600, tex.format); - R600_STATECHANGE(r600, tex.pitch); - R600_STATECHANGE(r600, tex.offset); - R600_STATECHANGE(r600, tex.chroma_key); - R600_STATECHANGE(r600, tex.border_color); - - r600->hw.txe.cmd[R600_TXE_ENABLE] = 0x0; - - mtu = r600->radeon.glCtx->Const.MaxTextureUnits; - if (RADEON_DEBUG & DEBUG_STATE) - fprintf(stderr, "mtu=%d\n", mtu); - - if (mtu > R600_MAX_TEXTURE_UNITS) { - fprintf(stderr, - "Aiiee ! mtu=%d is greater than R600_MAX_TEXTURE_UNITS=%d\n", - mtu, R600_MAX_TEXTURE_UNITS); - _mesa_exit(-1); - } - - /* We cannot let disabled tmu offsets pass DRM */ - for (i = 0; i < mtu; i++) { - if (ctx->Texture.Unit[i]._ReallyEnabled) { - tmu_mappings[i] = hw_tmu; - - t = radeon_tex_obj(ctx->Texture.Unit[i]._Current); - if (!t) - continue; - - if ((t->pp_txformat & 0xffffff00) == 0xffffff00) { - WARN_ONCE - ("unknown texture format (entry %x) encountered. Help me !\n", - t->pp_txformat & 0xff); - } - - if (RADEON_DEBUG & DEBUG_STATE) - fprintf(stderr, - "Activating texture unit %d\n", i); - - r600->hw.txe.cmd[R600_TXE_ENABLE] |= (1 << hw_tmu); - - r600->hw.tex.filter.cmd[R600_TEX_VALUE_0 + - hw_tmu] = - gen_fixed_filter(t->pp_txfilter) | (hw_tmu << 28); - /* Note: There is a LOD bias per texture unit and a LOD bias - * per texture object. We add them here to get the correct behaviour. - * (The per-texture object LOD bias was introduced in OpenGL 1.4 - * and is not present in the EXT_texture_object extension). - */ - r600->hw.tex.filter_1.cmd[R600_TEX_VALUE_0 + hw_tmu] = - t->pp_txfilter_1 | - translate_lod_bias(ctx->Texture.Unit[i].LodBias + t->base.LodBias); - r600->hw.tex.size.cmd[R600_TEX_VALUE_0 + hw_tmu] = - t->pp_txsize; - r600->hw.tex.format.cmd[R600_TEX_VALUE_0 + - hw_tmu] = t->pp_txformat; - r600->hw.tex.pitch.cmd[R600_TEX_VALUE_0 + hw_tmu] = - t->pp_txpitch; - r600->hw.textures[hw_tmu] = t; - - if (t->tile_bits & R600_TXO_MACRO_TILE) { - WARN_ONCE("macro tiling enabled!\n"); - } - - if (t->tile_bits & R600_TXO_MICRO_TILE) { - WARN_ONCE("micro tiling enabled!\n"); - } - - r600->hw.tex.chroma_key.cmd[R600_TEX_VALUE_0 + - hw_tmu] = 0x0; - r600->hw.tex.border_color.cmd[R600_TEX_VALUE_0 + - hw_tmu] = - t->pp_border_color; - - last_hw_tmu = hw_tmu; - - hw_tmu++; - } - } - - r600->hw.tex.filter.cmd[R600_TEX_CMD_0] = - cmdpacket0(r600->radeon.radeonScreen, R600_TX_FILTER0_0, last_hw_tmu + 1); - r600->hw.tex.filter_1.cmd[R600_TEX_CMD_0] = - cmdpacket0(r600->radeon.radeonScreen, R600_TX_FILTER1_0, last_hw_tmu + 1); - r600->hw.tex.size.cmd[R600_TEX_CMD_0] = - cmdpacket0(r600->radeon.radeonScreen, R600_TX_SIZE_0, last_hw_tmu + 1); - r600->hw.tex.format.cmd[R600_TEX_CMD_0] = - cmdpacket0(r600->radeon.radeonScreen, R600_TX_FORMAT_0, last_hw_tmu + 1); - r600->hw.tex.pitch.cmd[R600_TEX_CMD_0] = - cmdpacket0(r600->radeon.radeonScreen, R600_TX_FORMAT2_0, last_hw_tmu + 1); - r600->hw.tex.offset.cmd[R600_TEX_CMD_0] = - cmdpacket0(r600->radeon.radeonScreen, R600_TX_OFFSET_0, last_hw_tmu + 1); - r600->hw.tex.chroma_key.cmd[R600_TEX_CMD_0] = - cmdpacket0(r600->radeon.radeonScreen, R600_TX_CHROMA_KEY_0, last_hw_tmu + 1); - r600->hw.tex.border_color.cmd[R600_TEX_CMD_0] = - cmdpacket0(r600->radeon.radeonScreen, R600_TX_BORDER_COLOR_0, last_hw_tmu + 1); - - if (!fp) /* should only happenen once, just after context is created */ - return; - - if (fp->mesa_program.UsesKill && last_hw_tmu < 0) { - // The KILL operation requires the first texture unit - // to be enabled. - r600->hw.txe.cmd[R600_TXE_ENABLE] |= 1; - r600->hw.tex.filter.cmd[R600_TEX_VALUE_0] = 0; - r600->hw.tex.filter.cmd[R600_TEX_CMD_0] = - cmdpacket0(r600->radeon.radeonScreen, R600_TX_FILTER0_0, 1); - } - r600SetupFragmentShaderTextures(ctx, tmu_mappings); - - if (RADEON_DEBUG & DEBUG_STATE) - fprintf(stderr, "TX_ENABLE: %08x last_hw_tmu=%d\n", - r600->hw.txe.cmd[R600_TXE_ENABLE], last_hw_tmu); -} - -union r600_outputs_written { - GLuint vp_outputs; /* hw_tcl_on */ - DECLARE_RENDERINPUTS(index_bitset); /* !hw_tcl_on */ -}; - -#define R600_OUTPUTS_WRITTEN_TEST(ow, vp_result, tnl_attrib) \ - ((hw_tcl_on) ? (ow).vp_outputs & (1 << (vp_result)) : \ - RENDERINPUTS_TEST( (ow.index_bitset), (tnl_attrib) )) - -static void r600SetupRSUnit(GLcontext * ctx) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - union r600_outputs_written OutputsWritten; - GLuint InputsRead; - int fp_reg, high_rr; - int col_ip, tex_ip; - int rs_tex_count = 0; - int i, count, col_fmt; - - if (hw_tcl_on) - OutputsWritten.vp_outputs = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten; - else - RENDERINPUTS_COPY(OutputsWritten.index_bitset, r600->state.render_inputs_bitset); - - if (ctx->FragmentProgram._Current) - InputsRead = ctx->FragmentProgram._Current->Base.InputsRead; - else { - fprintf(stderr, "No ctx->FragmentProgram._Current!!\n"); - return; /* This should only ever happen once.. */ - } - - R600_STATECHANGE(r600, ri); - R600_STATECHANGE(r600, rc); - R600_STATECHANGE(r600, rr); - - fp_reg = col_ip = tex_ip = col_fmt = 0; - - r600->hw.rc.cmd[1] = 0; - r600->hw.rc.cmd[2] = 0; - for (i=0; i<R600_RR_CMDSIZE-1; ++i) - r600->hw.rr.cmd[R600_RR_INST_0 + i] = 0; - - for (i=0; i<R600_RI_CMDSIZE-1; ++i) - r600->hw.ri.cmd[R600_RI_INTERP_0 + i] = 0; - - - if (InputsRead & FRAG_BIT_COL0) { - if (R600_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_COL0, _TNL_ATTRIB_COLOR0)) { - count = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->size; - if (count == 4) - col_fmt = R600_RS_COL_FMT_RGBA; - else if (count == 3) - col_fmt = R600_RS_COL_FMT_RGB1; - else - col_fmt = R600_RS_COL_FMT_0001; - - r600->hw.ri.cmd[R600_RI_INTERP_0 + col_ip] = R600_RS_COL_PTR(col_ip) | R600_RS_COL_FMT(col_fmt); - r600->hw.rr.cmd[R600_RR_INST_0 + col_ip] = R600_RS_INST_COL_ID(col_ip) | R600_RS_INST_COL_CN_WRITE | R600_RS_INST_COL_ADDR(fp_reg); - InputsRead &= ~FRAG_BIT_COL0; - ++col_ip; - ++fp_reg; - } else { - WARN_ONCE("fragprog wants col0, vp doesn't provide it\n"); - } - } - - if (InputsRead & FRAG_BIT_COL1) { - if (R600_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_COL1, _TNL_ATTRIB_COLOR1)) { - count = VB->AttribPtr[_TNL_ATTRIB_COLOR1]->size; - if (count == 4) - col_fmt = R600_RS_COL_FMT_RGBA; - else if (count == 3) - col_fmt = R600_RS_COL_FMT_RGB1; - else - col_fmt = R600_RS_COL_FMT_0001; - - r600->hw.ri.cmd[R600_RI_INTERP_0 + col_ip] = R600_RS_COL_PTR(col_ip) | R600_RS_COL_FMT(col_fmt); - r600->hw.rr.cmd[R600_RR_INST_0 + col_ip] = R600_RS_INST_COL_ID(col_ip) | R600_RS_INST_COL_CN_WRITE | R600_RS_INST_COL_ADDR(fp_reg); - InputsRead &= ~FRAG_BIT_COL1; - ++col_ip; - ++fp_reg; - } else { - WARN_ONCE("fragprog wants col1, vp doesn't provide it\n"); - } - } - - for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { - if (! ( InputsRead & FRAG_BIT_TEX(i) ) ) - continue; - - if (!R600_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_TEX0 + i, _TNL_ATTRIB_TEX(i))) { - WARN_ONCE("fragprog wants coords for tex%d, vp doesn't provide them!\n", i); - continue; - } - - int swiz; - - /* with TCL we always seem to route 4 components */ - if (hw_tcl_on) - count = 4; - else - count = VB->AttribPtr[_TNL_ATTRIB_TEX(i)]->size; - - switch(count) { - case 4: swiz = R600_RS_SEL_S(0) | R600_RS_SEL_T(1) | R600_RS_SEL_R(2) | R600_RS_SEL_Q(3); break; - case 3: swiz = R600_RS_SEL_S(0) | R600_RS_SEL_T(1) | R600_RS_SEL_R(2) | R600_RS_SEL_Q(R600_RS_SEL_K1); break; - default: - case 1: - case 2: swiz = R600_RS_SEL_S(0) | R600_RS_SEL_T(1) | R600_RS_SEL_R(R600_RS_SEL_K0) | R600_RS_SEL_Q(R600_RS_SEL_K1); break; - }; - - r600->hw.ri.cmd[R600_RI_INTERP_0 + tex_ip] |= swiz | R600_RS_TEX_PTR(rs_tex_count); - r600->hw.rr.cmd[R600_RR_INST_0 + tex_ip] |= R600_RS_INST_TEX_ID(tex_ip) | R600_RS_INST_TEX_CN_WRITE | R600_RS_INST_TEX_ADDR(fp_reg); - InputsRead &= ~(FRAG_BIT_TEX0 << i); - rs_tex_count += count; - ++tex_ip; - ++fp_reg; - } - - if (InputsRead & FRAG_BIT_FOGC) { - if (R600_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_FOGC, _TNL_ATTRIB_FOG)) { - r600->hw.ri.cmd[R600_RI_INTERP_0 + tex_ip] |= R600_RS_SEL_S(0) | R600_RS_SEL_T(1) | R600_RS_SEL_R(2) | R600_RS_SEL_Q(3) | R600_RS_TEX_PTR(rs_tex_count); - r600->hw.rr.cmd[R600_RR_INST_0 + tex_ip] |= R600_RS_INST_TEX_ID(tex_ip) | R600_RS_INST_TEX_CN_WRITE | R600_RS_INST_TEX_ADDR(fp_reg); - InputsRead &= ~FRAG_BIT_FOGC; - rs_tex_count += 4; - ++tex_ip; - ++fp_reg; - } else { - WARN_ONCE("fragprog wants fogc, vp doesn't provide it\n"); - } - } - - if (InputsRead & FRAG_BIT_WPOS) { - r600->hw.ri.cmd[R600_RI_INTERP_0 + tex_ip] |= R600_RS_SEL_S(0) | R600_RS_SEL_T(1) | R600_RS_SEL_R(2) | R600_RS_SEL_Q(3) | R600_RS_TEX_PTR(rs_tex_count); - r600->hw.rr.cmd[R600_RR_INST_0 + tex_ip] |= R600_RS_INST_TEX_ID(tex_ip) | R600_RS_INST_TEX_CN_WRITE | R600_RS_INST_TEX_ADDR(fp_reg); - InputsRead &= ~FRAG_BIT_WPOS; - rs_tex_count += 4; - ++tex_ip; - ++fp_reg; - } - InputsRead &= ~FRAG_BIT_WPOS; - - /* Setup default color if no color or tex was set */ - if (rs_tex_count == 0 && col_ip == 0) { - r600->hw.rr.cmd[R600_RR_INST_0] = R600_RS_INST_COL_ID(0) | R600_RS_INST_COL_CN_WRITE | R600_RS_INST_COL_ADDR(0) | R600_RS_COL_FMT(R600_RS_COL_FMT_0001); - ++col_ip; - } - - high_rr = (col_ip > tex_ip) ? col_ip : tex_ip; - r600->hw.rc.cmd[1] |= (rs_tex_count << R600_IT_COUNT_SHIFT) | (col_ip << R600_IC_COUNT_SHIFT) | R600_HIRES_EN; - r600->hw.rc.cmd[2] |= high_rr - 1; - - r600->hw.rr.cmd[R600_RR_CMD_0] = cmdpacket0(r600->radeon.radeonScreen, R600_RS_INST_0, high_rr); - - if (InputsRead) - WARN_ONCE("Don't know how to satisfy InputsRead=0x%08x\n", InputsRead); -} - -#define bump_vpu_count(ptr, new_count) do{\ - drm_r300_cmd_header_t* _p=((drm_r300_cmd_header_t*)(ptr));\ - int _nc=(new_count)/4; \ - assert(_nc < 256); \ - if(_nc>_p->vpu.count)_p->vpu.count=_nc;\ - }while(0) - -static INLINE void r600SetupVertexProgramFragment(r600ContextPtr r600, int dest, struct r600_vertex_shader_fragment *vsf) -{ - int i; - - if (vsf->length == 0) - return; - - if (vsf->length & 0x3) { - fprintf(stderr, "VERTEX_SHADER_FRAGMENT must have length divisible by 4\n"); - _mesa_exit(-1); - } - - switch ((dest >> 8) & 0xf) { - case 0: - R600_STATECHANGE(r600, vpi); - for (i = 0; i < vsf->length; i++) - r600->hw.vpi.cmd[R600_VPI_INSTR_0 + i + 4 * (dest & 0xff)] = (vsf->body.d[i]); - bump_vpu_count(r600->hw.vpi.cmd, vsf->length + 4 * (dest & 0xff)); - break; - - case 2: - R600_STATECHANGE(r600, vpp); - for (i = 0; i < vsf->length; i++) - r600->hw.vpp.cmd[R600_VPP_PARAM_0 + i + 4 * (dest & 0xff)] = (vsf->body.d[i]); - bump_vpu_count(r600->hw.vpp.cmd, vsf->length + 4 * (dest & 0xff)); - break; - case 4: - R600_STATECHANGE(r600, vps); - for (i = 0; i < vsf->length; i++) - r600->hw.vps.cmd[1 + i + 4 * (dest & 0xff)] = (vsf->body.d[i]); - bump_vpu_count(r600->hw.vps.cmd, vsf->length + 4 * (dest & 0xff)); - break; - default: - fprintf(stderr, "%s:%s don't know how to handle dest %04x\n", __FILE__, __FUNCTION__, dest); - _mesa_exit(-1); - } -} - -#define MIN3(a, b, c) ((a) < (b) ? MIN2(a, c) : MIN2(b, c)) - - -static void r600VapCntl(r600ContextPtr rmesa, GLuint input_count, - GLuint output_count, GLuint temp_count) -{ - int vtx_mem_size; - int pvs_num_slots; - int pvs_num_cntrls; - - /* Flush PVS engine before changing PVS_NUM_SLOTS, PVS_NUM_CNTRLS. - * See r500 docs 6.5.2 - done in emit */ - - /* avoid division by zero */ - if (input_count == 0) input_count = 1; - if (output_count == 0) output_count = 1; - if (temp_count == 0) temp_count = 1; - - if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) - vtx_mem_size = 128; - else - vtx_mem_size = 72; - - pvs_num_slots = MIN3(10, vtx_mem_size/input_count, vtx_mem_size/output_count); - pvs_num_cntrls = MIN2(6, vtx_mem_size/temp_count); - - R600_STATECHANGE(rmesa, vap_cntl); - if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) { - rmesa->hw.vap_cntl.cmd[R600_VAP_CNTL_INSTR] = - (pvs_num_slots << R600_PVS_NUM_SLOTS_SHIFT) | - (pvs_num_cntrls << R600_PVS_NUM_CNTLRS_SHIFT) | - (12 << R600_VF_MAX_VTX_NUM_SHIFT); - } else - /* not sure about non-tcl */ - rmesa->hw.vap_cntl.cmd[R600_VAP_CNTL_INSTR] = ((10 << R600_PVS_NUM_SLOTS_SHIFT) | - (5 << R600_PVS_NUM_CNTLRS_SHIFT) | - (5 << R600_VF_MAX_VTX_NUM_SHIFT)); - - if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV515) - rmesa->hw.vap_cntl.cmd[R600_VAP_CNTL_INSTR] |= (2 << R600_PVS_NUM_FPUS_SHIFT); - else if ((rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) || - (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV560) || - (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV570)) - rmesa->hw.vap_cntl.cmd[R600_VAP_CNTL_INSTR] |= (5 << R600_PVS_NUM_FPUS_SHIFT); - else if ((rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV410) || - (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R420)) - rmesa->hw.vap_cntl.cmd[R600_VAP_CNTL_INSTR] |= (6 << R600_PVS_NUM_FPUS_SHIFT); - else if ((rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R520) || - (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R580)) - rmesa->hw.vap_cntl.cmd[R600_VAP_CNTL_INSTR] |= (8 << R600_PVS_NUM_FPUS_SHIFT); - else - rmesa->hw.vap_cntl.cmd[R600_VAP_CNTL_INSTR] |= (4 << R600_PVS_NUM_FPUS_SHIFT); - -} - -static void r600SetupDefaultVertexProgram(r600ContextPtr rmesa) -{ - struct r600_vertex_shader_state *prog = &(rmesa->state.vertex_shader); - GLuint o_reg = 0; - GLuint i_reg = 0; - int i; - int inst_count = 0; - int param_count = 0; - int program_end = 0; - - for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_MAX; i++) { - if (rmesa->state.sw_tcl_inputs[i] != -1) { - prog->program.body.i[program_end + 0] = PVS_OP_DST_OPERAND(VE_MULTIPLY, GL_FALSE, GL_FALSE, o_reg++, VSF_FLAG_ALL, PVS_DST_REG_OUT); - prog->program.body.i[program_end + 1] = PVS_SRC_OPERAND(rmesa->state.sw_tcl_inputs[i], PVS_SRC_SELECT_X, PVS_SRC_SELECT_Y, PVS_SRC_SELECT_Z, PVS_SRC_SELECT_W, PVS_SRC_REG_INPUT, VSF_FLAG_NONE); - prog->program.body.i[program_end + 2] = PVS_SRC_OPERAND(rmesa->state.sw_tcl_inputs[i], PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_REG_INPUT, VSF_FLAG_NONE); - prog->program.body.i[program_end + 3] = PVS_SRC_OPERAND(rmesa->state.sw_tcl_inputs[i], PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_SELECT_FORCE_1, PVS_SRC_REG_INPUT, VSF_FLAG_NONE); - program_end += 4; - i_reg++; - } - } - - prog->program.length = program_end; - - r600SetupVertexProgramFragment(rmesa, R600_PVS_CODE_START, - &(prog->program)); - inst_count = (prog->program.length / 4) - 1; - - r600VapCntl(rmesa, i_reg, o_reg, 0); - - R600_STATECHANGE(rmesa, pvs); - rmesa->hw.pvs.cmd[R600_PVS_CNTL_1] = - (0 << R600_PVS_FIRST_INST_SHIFT) | - (inst_count << R600_PVS_XYZW_VALID_INST_SHIFT) | - (inst_count << R600_PVS_LAST_INST_SHIFT); - rmesa->hw.pvs.cmd[R600_PVS_CNTL_2] = - (0 << R600_PVS_CONST_BASE_OFFSET_SHIFT) | - (param_count << R600_PVS_MAX_CONST_ADDR_SHIFT); - rmesa->hw.pvs.cmd[R600_PVS_CNTL_3] = - (inst_count << R600_PVS_LAST_VTX_SRC_INST_SHIFT); -} - -static int bit_count (int x) -{ - x = ((x & 0xaaaaaaaaU) >> 1) + (x & 0x55555555U); - x = ((x & 0xccccccccU) >> 2) + (x & 0x33333333U); - x = (x >> 16) + (x & 0xffff); - x = ((x & 0xf0f0) >> 4) + (x & 0x0f0f); - return (x >> 8) + (x & 0x00ff); -} - -static void r600SetupRealVertexProgram(r600ContextPtr rmesa) -{ - GLcontext *ctx = rmesa->radeon.glCtx; - struct r600_vertex_program *prog = (struct r600_vertex_program *)CURRENT_VERTEX_SHADER(ctx); - int inst_count = 0; - int param_count = 0; - - /* FIXME: r600SetupVertexProgramFragment */ - R600_STATECHANGE(rmesa, vpp); - param_count = - r600VertexProgUpdateParams(ctx, - (struct r600_vertex_program_cont *) - ctx->VertexProgram._Current, - (float *)&rmesa->hw.vpp. - cmd[R600_VPP_PARAM_0]); - bump_vpu_count(rmesa->hw.vpp.cmd, param_count); - param_count /= 4; - - r600SetupVertexProgramFragment(rmesa, R600_PVS_CODE_START, &(prog->program)); - inst_count = (prog->program.length / 4) - 1; - - r600VapCntl(rmesa, bit_count(prog->key.InputsRead), - bit_count(prog->key.OutputsWritten), prog->num_temporaries); - - R600_STATECHANGE(rmesa, pvs); - rmesa->hw.pvs.cmd[R600_PVS_CNTL_1] = - (0 << R600_PVS_FIRST_INST_SHIFT) | - (inst_count << R600_PVS_XYZW_VALID_INST_SHIFT) | - (inst_count << R600_PVS_LAST_INST_SHIFT); - rmesa->hw.pvs.cmd[R600_PVS_CNTL_2] = - (0 << R600_PVS_CONST_BASE_OFFSET_SHIFT) | - (param_count << R600_PVS_MAX_CONST_ADDR_SHIFT); - rmesa->hw.pvs.cmd[R600_PVS_CNTL_3] = - (inst_count << R600_PVS_LAST_VTX_SRC_INST_SHIFT); -} - - -static void r600SetupVertexProgram(r600ContextPtr rmesa) -{ - GLcontext *ctx = rmesa->radeon.glCtx; - - /* Reset state, in case we don't use something */ - ((drm_r300_cmd_header_t *) rmesa->hw.vpp.cmd)->vpu.count = 0; - ((drm_r300_cmd_header_t *) rmesa->hw.vpi.cmd)->vpu.count = 0; - ((drm_r300_cmd_header_t *) rmesa->hw.vps.cmd)->vpu.count = 0; - - /* Not sure why this doesnt work... - 0x400 area might have something to do with pixel shaders as it appears right after pfs programming. - 0x406 is set to { 0.0, 0.0, 1.0, 0.0 } most of the time but should change with smooth points and in other rare cases. */ - //setup_vertex_shader_fragment(rmesa, 0x406, &unk4); - if (hw_tcl_on && ((struct r600_vertex_program *)CURRENT_VERTEX_SHADER(ctx))->translated) { - r600SetupRealVertexProgram(rmesa); - } else { - /* FIXME: This needs to be replaced by vertex shader generation code. */ - r600SetupDefaultVertexProgram(rmesa); - } - -} - -/** - * Enable/Disable states. - * - * \note Mesa already filters redundant calls to this function. - */ -static void r600Enable(GLcontext * ctx, GLenum cap, GLboolean state) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - if (RADEON_DEBUG & DEBUG_STATE) - fprintf(stderr, "%s( %s = %s )\n", __FUNCTION__, - _mesa_lookup_enum_by_nr(cap), - state ? "GL_TRUE" : "GL_FALSE"); - - switch (cap) { - case GL_TEXTURE_1D: - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: - /* empty */ - break; - case GL_FOG: - /* empty */ - break; - case GL_ALPHA_TEST: - r600SetAlphaState(ctx); - break; - case GL_COLOR_LOGIC_OP: - r600SetLogicOpState(ctx); - /* fall-through, because logic op overrides blending */ - case GL_BLEND: - r600SetBlendState(ctx); - break; - case GL_CLIP_PLANE0: - case GL_CLIP_PLANE1: - case GL_CLIP_PLANE2: - case GL_CLIP_PLANE3: - case GL_CLIP_PLANE4: - case GL_CLIP_PLANE5: - r600SetClipPlaneState(ctx, cap, state); - break; - case GL_DEPTH_TEST: - r600SetDepthState(ctx); - break; - case GL_STENCIL_TEST: - r600SetStencilState(ctx, state); - break; - case GL_CULL_FACE: - r600UpdateCulling(ctx); - break; - case GL_POLYGON_OFFSET_POINT: - case GL_POLYGON_OFFSET_LINE: - case GL_POLYGON_OFFSET_FILL: - r600SetPolygonOffsetState(ctx, state); - break; - case GL_SCISSOR_TEST: - radeon_firevertices(&rmesa->radeon); - rmesa->radeon.state.scissor.enabled = state; - radeonUpdateScissor( ctx ); - break; - default: - break; - } -} - -/** - * Completely recalculates hardware state based on the Mesa state. - */ -static void r600ResetHwState(r600ContextPtr r600) -{ - GLcontext *ctx = r600->radeon.glCtx; - - if (RADEON_DEBUG & DEBUG_STATE) - fprintf(stderr, "%s\n", __FUNCTION__); - - radeon_firevertices(&r600->radeon); - - r600ColorMask(ctx, - ctx->Color.ColorMask[RCOMP], - ctx->Color.ColorMask[GCOMP], - ctx->Color.ColorMask[BCOMP], ctx->Color.ColorMask[ACOMP]); - - r600Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test); - r600DepthMask(ctx, ctx->Depth.Mask); - r600DepthFunc(ctx, ctx->Depth.Func); - - /* stencil */ - r600Enable(ctx, GL_STENCIL_TEST, ctx->Stencil._Enabled); - r600StencilMaskSeparate(ctx, 0, ctx->Stencil.WriteMask[0]); - r600StencilFuncSeparate(ctx, 0, ctx->Stencil.Function[0], - ctx->Stencil.Ref[0], ctx->Stencil.ValueMask[0]); - r600StencilOpSeparate(ctx, 0, ctx->Stencil.FailFunc[0], - ctx->Stencil.ZFailFunc[0], - ctx->Stencil.ZPassFunc[0]); - - r600UpdateCulling(ctx); - - r600SetBlendState(ctx); - r600SetLogicOpState(ctx); - - r600AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef); - r600Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled); - - r600->hw.vte.cmd[1] = R600_VPORT_X_SCALE_ENA - | R600_VPORT_X_OFFSET_ENA - | R600_VPORT_Y_SCALE_ENA - | R600_VPORT_Y_OFFSET_ENA - | R600_VPORT_Z_SCALE_ENA - | R600_VPORT_Z_OFFSET_ENA | R600_VTX_W0_FMT; - r600->hw.vte.cmd[2] = 0x00000008; - - r600->hw.vap_vf_max_vtx_indx.cmd[1] = 0x00FFFFFF; - r600->hw.vap_vf_max_vtx_indx.cmd[2] = 0x00000000; - -#ifdef MESA_LITTLE_ENDIAN - r600->hw.vap_cntl_status.cmd[1] = R600_VC_NO_SWAP; -#else - r600->hw.vap_cntl_status.cmd[1] = R600_VC_32BIT_SWAP; -#endif - - r600->hw.vap_psc_sgn_norm_cntl.cmd[1] = 0xAAAAAAAA; - - r600->hw.vap_clip_cntl.cmd[1] = R600_PS_UCP_MODE_DIST_COP; - - r600->hw.vap_clip.cmd[1] = r600PackFloat32(1.0); /* X */ - r600->hw.vap_clip.cmd[2] = r600PackFloat32(1.0); /* X */ - r600->hw.vap_clip.cmd[3] = r600PackFloat32(1.0); /* Y */ - r600->hw.vap_clip.cmd[4] = r600PackFloat32(1.0); /* Y */ - - switch (r600->radeon.radeonScreen->chip_family) { - case CHIP_FAMILY_R600: - r600->hw.vap_pvs_vtx_timeout_reg.cmd[1] = R600_2288_R600; - break; - default: - r600->hw.vap_pvs_vtx_timeout_reg.cmd[1] = R600_2288_RV350; - break; - } - - r600->hw.gb_enable.cmd[1] = R600_GB_POINT_STUFF_ENABLE - | R600_GB_LINE_STUFF_ENABLE - | R600_GB_TRIANGLE_STUFF_ENABLE; - - r600->hw.gb_misc.cmd[R600_GB_MISC_MSPOS_0] = 0x66666666; - r600->hw.gb_misc.cmd[R600_GB_MISC_MSPOS_1] = 0x06666666; - - r600->hw.gb_misc.cmd[R600_GB_MISC_TILE_CONFIG] = - R600_GB_TILE_ENABLE | R600_GB_TILE_SIZE_16 /*| R600_GB_SUBPIXEL_1_16*/; - switch (r600->radeon.radeonScreen->num_gb_pipes) { - case 1: - default: - r600->hw.gb_misc.cmd[R600_GB_MISC_TILE_CONFIG] |= - R600_GB_TILE_PIPE_COUNT_RV300; - break; - case 2: - r600->hw.gb_misc.cmd[R600_GB_MISC_TILE_CONFIG] |= - R600_GB_TILE_PIPE_COUNT_R600; - break; - case 3: - r600->hw.gb_misc.cmd[R600_GB_MISC_TILE_CONFIG] |= - R600_GB_TILE_PIPE_COUNT_R420_3P; - break; - case 4: - r600->hw.gb_misc.cmd[R600_GB_MISC_TILE_CONFIG] |= - R600_GB_TILE_PIPE_COUNT_R420; - break; - } - - /* XXX: Enable anti-aliasing? */ - r600->hw.gb_misc.cmd[R600_GB_MISC_AA_CONFIG] = GB_AA_CONFIG_AA_DISABLE; - r600->hw.gb_misc.cmd[R600_GB_MISC_SELECT] = 0; - - r600->hw.ga_point_s0.cmd[1] = r600PackFloat32(0.0); - r600->hw.ga_point_s0.cmd[2] = r600PackFloat32(0.0); - r600->hw.ga_point_s0.cmd[3] = r600PackFloat32(1.0); - r600->hw.ga_point_s0.cmd[4] = r600PackFloat32(1.0); - - r600->hw.ga_triangle_stipple.cmd[1] = 0x00050005; - - r600PointSize(ctx, 1.0); - - r600->hw.ga_point_minmax.cmd[1] = 0x18000006; - r600->hw.ga_point_minmax.cmd[2] = 0x00020006; - r600->hw.ga_point_minmax.cmd[3] = r600PackFloat32(1.0 / 192.0); - - r600LineWidth(ctx, 1.0); - - r600->hw.ga_line_stipple.cmd[1] = 0; - r600->hw.ga_line_stipple.cmd[2] = r600PackFloat32(0.0); - r600->hw.ga_line_stipple.cmd[3] = r600PackFloat32(1.0); - - r600ShadeModel(ctx, ctx->Light.ShadeModel); - - r600PolygonMode(ctx, GL_FRONT, ctx->Polygon.FrontMode); - r600PolygonMode(ctx, GL_BACK, ctx->Polygon.BackMode); - r600->hw.zbias_cntl.cmd[1] = 0x00000000; - - r600PolygonOffset(ctx, ctx->Polygon.OffsetFactor, - ctx->Polygon.OffsetUnits); - r600Enable(ctx, GL_POLYGON_OFFSET_POINT, ctx->Polygon.OffsetPoint); - r600Enable(ctx, GL_POLYGON_OFFSET_LINE, ctx->Polygon.OffsetLine); - r600Enable(ctx, GL_POLYGON_OFFSET_FILL, ctx->Polygon.OffsetFill); - - r600->hw.su_depth_scale.cmd[1] = 0x4B7FFFFF; - r600->hw.su_depth_scale.cmd[2] = 0x00000000; - - r600->hw.sc_hyperz.cmd[1] = 0x0000001C; - r600->hw.sc_hyperz.cmd[2] = 0x2DA49525; - - r600->hw.sc_screendoor.cmd[1] = 0x00FFFFFF; - - r600->hw.us_out_fmt.cmd[5] = R600_W_FMT_W0 | R600_W_SRC_US; - - /* disable fog unit */ - r600->hw.fogs.cmd[R600_FOGS_STATE] = 0; - r600->hw.fg_depth_src.cmd[1] = R600_FG_DEPTH_SRC_SCAN; - - r600->hw.rb3d_cctl.cmd[1] = 0; - - r600BlendColor(ctx, ctx->Color.BlendColor); - - r600->hw.rb3d_dither_ctl.cmd[1] = 0; - r600->hw.rb3d_dither_ctl.cmd[2] = 0; - r600->hw.rb3d_dither_ctl.cmd[3] = 0; - r600->hw.rb3d_dither_ctl.cmd[4] = 0; - r600->hw.rb3d_dither_ctl.cmd[5] = 0; - r600->hw.rb3d_dither_ctl.cmd[6] = 0; - r600->hw.rb3d_dither_ctl.cmd[7] = 0; - r600->hw.rb3d_dither_ctl.cmd[8] = 0; - r600->hw.rb3d_dither_ctl.cmd[9] = 0; - - r600->hw.rb3d_aaresolve_ctl.cmd[1] = 0; - - r600->hw.zb_depthclearvalue.cmd[1] = 0; - - r600->hw.zstencil_format.cmd[2] = R600_ZTOP_DISABLE; - r600->hw.zstencil_format.cmd[3] = 0x00000003; - r600->hw.zstencil_format.cmd[4] = 0x00000000; - r600SetEarlyZState(ctx); - - r600->hw.unk4F30.cmd[1] = 0; - r600->hw.unk4F30.cmd[2] = 0; - - r600->hw.zb_hiz_offset.cmd[1] = 0; - - r600->hw.zb_hiz_pitch.cmd[1] = 0; - - r600VapCntl(r600, 0, 0, 0); - - r600->hw.vps.cmd[R600_VPS_ZERO_0] = 0; - r600->hw.vps.cmd[R600_VPS_ZERO_1] = 0; - r600->hw.vps.cmd[R600_VPS_POINTSIZE] = r600PackFloat32(1.0); - r600->hw.vps.cmd[R600_VPS_ZERO_3] = 0; - - r600->radeon.hw.all_dirty = GL_TRUE; -} - -void r600UpdateShaders(r600ContextPtr rmesa) -{ - GLcontext *ctx; - struct r600_vertex_program *vp; - int i; - - ctx = rmesa->radeon.glCtx; - - if (rmesa->radeon.NewGLState && hw_tcl_on) { - rmesa->radeon.NewGLState = 0; - - for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) { - rmesa->temp_attrib[i] = - TNL_CONTEXT(ctx)->vb.AttribPtr[i]; - TNL_CONTEXT(ctx)->vb.AttribPtr[i] = - &rmesa->dummy_attrib[i]; - } - - _tnl_UpdateFixedFunctionProgram(ctx); - - for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) { - TNL_CONTEXT(ctx)->vb.AttribPtr[i] = - rmesa->temp_attrib[i]; - } - - r600SelectVertexShader(rmesa); - vp = (struct r600_vertex_program *) - CURRENT_VERTEX_SHADER(ctx); - /*if (vp->translated == GL_FALSE) - r600TranslateVertexShader(vp); */ - if (vp->translated == GL_FALSE) { - fprintf(stderr, "Failing back to sw-tcl\n"); - hw_tcl_on = future_hw_tcl_on = 0; - r600ResetHwState(rmesa); - - r600UpdateStateParameters(ctx, _NEW_PROGRAM); - return; - } - } - r600UpdateStateParameters(ctx, _NEW_PROGRAM); -} - -static const GLfloat *get_fragmentprogram_constant(GLcontext *ctx, - struct gl_program *program, struct prog_src_register srcreg) -{ - static const GLfloat dummy[4] = { 0, 0, 0, 0 }; - - switch(srcreg.File) { - case PROGRAM_LOCAL_PARAM: - return program->LocalParams[srcreg.Index]; - case PROGRAM_ENV_PARAM: - return ctx->FragmentProgram.Parameters[srcreg.Index]; - case PROGRAM_STATE_VAR: - case PROGRAM_NAMED_PARAM: - case PROGRAM_CONSTANT: - return program->Parameters->ParameterValues[srcreg.Index]; - default: - _mesa_problem(ctx, "get_fragmentprogram_constant: Unknown\n"); - return dummy; - } -} - - -static void r600SetupPixelShader(r600ContextPtr rmesa) -{ - GLcontext *ctx = rmesa->radeon.glCtx; - struct r600_fragment_program *fp = (struct r600_fragment_program *) - (char *)ctx->FragmentProgram._Current; - struct r600_fragment_program_code *code; - int i, k; - - if (!fp) /* should only happenen once, just after context is created */ - return; - - r600TranslateFragmentShader(rmesa, fp); - if (!fp->translated) { - fprintf(stderr, "%s: No valid fragment shader, exiting\n", - __FUNCTION__); - return; - } - code = &fp->code; - - r600SetupTextures(ctx); - - R600_STATECHANGE(rmesa, fpi[0]); - R600_STATECHANGE(rmesa, fpi[1]); - R600_STATECHANGE(rmesa, fpi[2]); - R600_STATECHANGE(rmesa, fpi[3]); - rmesa->hw.fpi[0].cmd[R600_FPI_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R600_US_ALU_RGB_INST_0, code->alu.length); - rmesa->hw.fpi[1].cmd[R600_FPI_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R600_US_ALU_RGB_ADDR_0, code->alu.length); - rmesa->hw.fpi[2].cmd[R600_FPI_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R600_US_ALU_ALPHA_INST_0, code->alu.length); - rmesa->hw.fpi[3].cmd[R600_FPI_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R600_US_ALU_ALPHA_ADDR_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) { - rmesa->hw.fpi[0].cmd[R600_FPI_INSTR_0 + i] = code->alu.inst[i].inst0; - rmesa->hw.fpi[1].cmd[R600_FPI_INSTR_0 + i] = code->alu.inst[i].inst1; - rmesa->hw.fpi[2].cmd[R600_FPI_INSTR_0 + i] = code->alu.inst[i].inst2; - rmesa->hw.fpi[3].cmd[R600_FPI_INSTR_0 + i] = code->alu.inst[i].inst3; - } - - R600_STATECHANGE(rmesa, fp); - rmesa->hw.fp.cmd[R600_FP_CNTL0] = code->cur_node | (code->first_node_has_tex << 3); - rmesa->hw.fp.cmd[R600_FP_CNTL1] = code->max_temp_idx; - rmesa->hw.fp.cmd[R600_FP_CNTL2] = - (0 << R600_PFS_CNTL_ALU_OFFSET_SHIFT) | - ((code->alu.length-1) << R600_PFS_CNTL_ALU_END_SHIFT) | - (0 << R600_PFS_CNTL_TEX_OFFSET_SHIFT) | - ((code->tex.length ? code->tex.length-1 : 0) << R600_PFS_CNTL_TEX_END_SHIFT); - /* I just want to say, the way these nodes are stored.. weird.. */ - for (i = 0, k = (4 - (code->cur_node + 1)); i < 4; i++, k++) { - if (i < (code->cur_node + 1)) { - rmesa->hw.fp.cmd[R600_FP_NODE0 + k] = - (code->node[i].alu_offset << R600_ALU_START_SHIFT) | - (code->node[i].alu_end << R600_ALU_SIZE_SHIFT) | - (code->node[i].tex_offset << R600_TEX_START_SHIFT) | - (code->node[i].tex_end << R600_TEX_SIZE_SHIFT) | - code->node[i].flags; - } else { - rmesa->hw.fp.cmd[R600_FP_NODE0 + (3 - i)] = 0; - } - } - - R600_STATECHANGE(rmesa, fpp); - rmesa->hw.fpp.cmd[R600_FPP_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R600_PFS_PARAM_0_X, code->const_nr * 4); - for (i = 0; i < code->const_nr; i++) { - const GLfloat *constant = get_fragmentprogram_constant(ctx, - &fp->mesa_program.Base, code->constant[i]); - rmesa->hw.fpp.cmd[R600_FPP_PARAM_0 + 4 * i + 0] = r600PackFloat24(constant[0]); - rmesa->hw.fpp.cmd[R600_FPP_PARAM_0 + 4 * i + 1] = r600PackFloat24(constant[1]); - rmesa->hw.fpp.cmd[R600_FPP_PARAM_0 + 4 * i + 2] = r600PackFloat24(constant[2]); - rmesa->hw.fpp.cmd[R600_FPP_PARAM_0 + 4 * i + 3] = r600PackFloat24(constant[3]); - } -} - -void r600UpdateShaderStates(r600ContextPtr rmesa) -{ - GLcontext *ctx; - ctx = rmesa->radeon.glCtx; - - r600SetEarlyZState(ctx); - - /* w_fmt value is set to get best performance - * see p.130 R5xx 3D acceleration guide v1.3 */ - GLuint w_fmt, fgdepthsrc; - if (current_fragment_program_writes_depth(ctx)) { - fgdepthsrc = R600_FG_DEPTH_SRC_SHADER; - w_fmt = R600_W_FMT_W24 | R600_W_SRC_US; - } else { - fgdepthsrc = R600_FG_DEPTH_SRC_SCAN; - w_fmt = R600_W_FMT_W0 | R600_W_SRC_US; - } - - if (w_fmt != rmesa->hw.us_out_fmt.cmd[5]) { - R600_STATECHANGE(rmesa, us_out_fmt); - rmesa->hw.us_out_fmt.cmd[5] = w_fmt; - } - - if (fgdepthsrc != rmesa->hw.fg_depth_src.cmd[1]) { - R600_STATECHANGE(rmesa, fg_depth_src); - rmesa->hw.fg_depth_src.cmd[1] = fgdepthsrc; - } - - r600SetupPixelShader(rmesa); - - r600SetupRSUnit(ctx); - - r600SetupVertexProgram(rmesa); - -} - -/** - * Called by Mesa after an internal state update. - */ -static void r600InvalidateState(GLcontext * ctx, GLuint new_state) -{ - r600ContextPtr r600 = R600_CONTEXT(ctx); - - _swrast_InvalidateState(ctx, new_state); - _swsetup_InvalidateState(ctx, new_state); - _vbo_InvalidateState(ctx, new_state); - _tnl_InvalidateState(ctx, new_state); - _ae_invalidate_state(ctx, new_state); - - if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { - _mesa_update_framebuffer(ctx); - /* this updates the DrawBuffer's Width/Height if it's a FBO */ - _mesa_update_draw_buffer_bounds(ctx); - - R600_STATECHANGE(r600, cb); - } - - r600UpdateStateParameters(ctx, new_state); - - r600->radeon.NewGLState |= new_state; -} - -/** - * Calculate initial hardware state and register state functions. - * Assumes that the command buffer and state atoms have been - * initialized already. - */ -void r600InitState(r600ContextPtr r600) -{ - memset(&(r600->state.texture), 0, sizeof(r600->state.texture)); - - r600ResetHwState(r600); -} - -static void r600RenderMode(GLcontext * ctx, GLenum mode) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - (void)rmesa; - (void)mode; -} - -void r600UpdateClipPlanes( GLcontext *ctx ) -{ - r600ContextPtr rmesa = R600_CONTEXT(ctx); - GLuint p; - - for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { - if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { - GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; - - R600_STATECHANGE( rmesa, vpucp[p] ); - rmesa->hw.vpucp[p].cmd[R600_VPUCP_X] = ip[0]; - rmesa->hw.vpucp[p].cmd[R600_VPUCP_Y] = ip[1]; - rmesa->hw.vpucp[p].cmd[R600_VPUCP_Z] = ip[2]; - rmesa->hw.vpucp[p].cmd[R600_VPUCP_W] = ip[3]; - } - } -} - -/** - * Initialize driver's state callback functions - */ -void r600InitStateFuncs(struct dd_function_table *functions) -{ - - functions->UpdateState = r600InvalidateState; - functions->AlphaFunc = r600AlphaFunc; - functions->BlendColor = r600BlendColor; - functions->BlendEquationSeparate = r600BlendEquationSeparate; - functions->BlendFuncSeparate = r600BlendFuncSeparate; - functions->Enable = r600Enable; - functions->ColorMask = r600ColorMask; - functions->DepthFunc = r600DepthFunc; - functions->DepthMask = r600DepthMask; - functions->CullFace = r600CullFace; - functions->FrontFace = r600FrontFace; - functions->ShadeModel = r600ShadeModel; - functions->LogicOpcode = r600LogicOpcode; - - /* ARB_point_parameters */ - functions->PointParameterfv = r600PointParameter; - - /* Stencil related */ - functions->StencilFuncSeparate = r600StencilFuncSeparate; - functions->StencilMaskSeparate = r600StencilMaskSeparate; - functions->StencilOpSeparate = r600StencilOpSeparate; - - /* Viewport related */ - functions->Viewport = r600Viewport; - functions->DepthRange = r600DepthRange; - functions->PointSize = r600PointSize; - functions->LineWidth = r600LineWidth; - - functions->PolygonOffset = r600PolygonOffset; - functions->PolygonMode = r600PolygonMode; - - functions->RenderMode = r600RenderMode; - - functions->ClipPlane = r600ClipPlane; - functions->Scissor = radeonScissor; - - functions->DrawBuffer = radeonDrawBuffer; - functions->ReadBuffer = radeonReadBuffer; -} |