X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fr300%2Fr300_state.c;h=aa9eb5e28bdc25ce49d0c79160030dd13bdcbd9f;hb=34dd4843d7b86eee8e0d18de275dd963ac2e3ffd;hp=f28c677bf1048a8f6f2951fd6bfc0413b835fd4a;hpb=d586540eaf43a61e53a0c0e4b087d2757f0f4ca5;p=mesa.git diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index f28c677bf10..aa9eb5e28bd 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -48,6 +48,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "swrast_setup/swrast_setup.h" #include "array_cache/acache.h" #include "tnl/tnl.h" +#include "texformat.h" #include "radeon_ioctl.h" #include "radeon_state.h" @@ -56,19 +57,485 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r300_state.h" #include "r300_reg.h" #include "r300_program.h" +#include "r300_emit.h" +#include "r300_fixed_pipelines.h" +#include "r300_tex.h" +#include "r300_maos.h" +#include "r300_texprog.h" + +static void r300AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + int pp_misc = rmesa->hw.at.cmd[R300_AT_ALPHA_TEST]; + GLubyte refByte; + + CLAMPED_FLOAT_TO_UBYTE(refByte, ref); + + R300_STATECHANGE(rmesa, at); + + pp_misc &= ~(R300_ALPHA_TEST_OP_MASK | R300_REF_ALPHA_MASK); + pp_misc |= (refByte & R300_REF_ALPHA_MASK); + + switch (func) { + case GL_NEVER: + pp_misc |= R300_ALPHA_TEST_FAIL; + break; + case GL_LESS: + pp_misc |= R300_ALPHA_TEST_LESS; + break; + case GL_EQUAL: + pp_misc |= R300_ALPHA_TEST_EQUAL; + break; + case GL_LEQUAL: + pp_misc |= R300_ALPHA_TEST_LEQUAL; + break; + case GL_GREATER: + pp_misc |= R300_ALPHA_TEST_GREATER; + break; + case GL_NOTEQUAL: + pp_misc |= R300_ALPHA_TEST_NEQUAL; + break; + case GL_GEQUAL: + pp_misc |= R300_ALPHA_TEST_GEQUAL; + break; + case GL_ALWAYS: + pp_misc |= R300_ALPHA_TEST_PASS; + //pp_misc &= ~R300_ALPHA_TEST_ENABLE; + break; + } + + rmesa->hw.at.cmd[R300_AT_ALPHA_TEST] = pp_misc; +} + +static void r300BlendColor(GLcontext * ctx, const GLfloat cf[4]) +{ + GLubyte color[4]; + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + R300_STATECHANGE(rmesa, unk4E10); + + /* Ordering might be wrong */ + 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.unk4E10.cmd[1]=r300PackColor(4, color[0], color[1], color[2], color[3]); + //fprintf(stderr, "%s:%s is not implemented yet. Fixme !\n", __FILE__, __FUNCTION__); +#if 0 + R200_STATECHANGE(rmesa, ctx); + 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]); + if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = + radeonPackColor(4, color[0], color[1], color[2], color[3]); +#endif +} + +/** + * 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) +{ + int func; + + switch (factor) { + case GL_ZERO: + func = R200_BLEND_GL_ZERO; + break; + case GL_ONE: + func = R200_BLEND_GL_ONE; + break; + case GL_DST_COLOR: + func = R200_BLEND_GL_DST_COLOR; + break; + case GL_ONE_MINUS_DST_COLOR: + func = R200_BLEND_GL_ONE_MINUS_DST_COLOR; + break; + case GL_SRC_COLOR: + func = R200_BLEND_GL_SRC_COLOR; + break; + case GL_ONE_MINUS_SRC_COLOR: + func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR; + break; + case GL_SRC_ALPHA: + func = R200_BLEND_GL_SRC_ALPHA; + break; + case GL_ONE_MINUS_SRC_ALPHA: + func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA; + break; + case GL_DST_ALPHA: + func = R200_BLEND_GL_DST_ALPHA; + break; + case GL_ONE_MINUS_DST_ALPHA: + func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA; + break; + case GL_SRC_ALPHA_SATURATE: + func = + (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : + R200_BLEND_GL_ZERO; + break; + case GL_CONSTANT_COLOR: + func = R200_BLEND_GL_CONST_COLOR; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR; + break; + case GL_CONSTANT_ALPHA: + func = R200_BLEND_GL_CONST_ALPHA; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA; + break; + default: + func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO; + } + return func; +} + +/** + * 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 r300_set_blend_cntl(r300ContextPtr rmesa, 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; + if(funcA == func){ + new_cblend |= R300_BLEND_NO_SEPARATE; + } + new_cblend |= cbits; + + if((new_ablend != rmesa->hw.bld.cmd[R300_BLD_ABLEND]) + || (new_cblend != rmesa->hw.bld.cmd[R300_BLD_CBLEND])){ + R300_STATECHANGE(rmesa, bld); + rmesa->hw.bld.cmd[R300_BLD_ABLEND]=new_ablend; + rmesa->hw.bld.cmd[R300_BLD_CBLEND]=new_cblend; + } +} + +static void r300_set_blend_state(GLcontext * ctx) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); +#if 0 + GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & + ~(R300_ROP_ENABLE | R300_ALPHA_BLEND_ENABLE | + R300_SEPARATE_ALPHA_ENABLE); +#endif + + int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); + int eqn = R200_COMB_FCN_ADD_CLAMP; + int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); + int eqnA = R200_COMB_FCN_ADD_CLAMP; + + + if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) { + if (ctx->Color._LogicOpEnabled) { +#if 0 + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = + cntl | R300_ROP_ENABLE; +#endif + r300_set_blend_cntl(rmesa, + func, eqn, 0, + func, eqn); + return; + } else if (ctx->Color.BlendEnabled) { +#if 0 + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = + cntl | R300_ALPHA_BLEND_ENABLE | + R300_SEPARATE_ALPHA_ENABLE; +#endif + } else { +#if 0 + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl; +#endif + r300_set_blend_cntl(rmesa, + func, eqn, 0, + func, eqn); + return; + } + } else { + if (ctx->Color._LogicOpEnabled) { +#if 0 + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = + cntl | R300_ROP_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; +#endif + return; + } else if (ctx->Color.BlendEnabled) { +#if 0 + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = + cntl | R300_ALPHA_BLEND_ENABLE; +#endif + } else { +#if 0 + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl; + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; +#endif + r300_set_blend_cntl(rmesa, + func, eqn, 0, + func, eqn); + return; + } + } + + func = + (blend_factor(ctx->Color.BlendSrcRGB, GL_TRUE) << + R200_SRC_BLEND_SHIFT) | (blend_factor(ctx->Color.BlendDstRGB, + GL_FALSE) << + R200_DST_BLEND_SHIFT); + + switch (ctx->Color.BlendEquationRGB) { + case GL_FUNC_ADD: + eqn = R300_COMB_FCN_ADD_CLAMP; + break; + + case GL_FUNC_SUBTRACT: + eqn = R300_COMB_FCN_SUB_CLAMP; + break; + + case GL_FUNC_REVERSE_SUBTRACT: + eqn = R200_COMB_FCN_RSUB_CLAMP; + break; + + case GL_MIN: + eqn = R200_COMB_FCN_MIN; + func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); + break; + + case GL_MAX: + eqn = R200_COMB_FCN_MAX; + func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); + break; + + default: + fprintf(stderr, + "[%s:%u] Invalid RGB blend equation (0x%04x).\n", + __func__, __LINE__, ctx->Color.BlendEquationRGB); + return; + } + + if (!rmesa->radeon.radeonScreen->drmSupportsBlendColor) { +#if 0 + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; +#endif + return; + } + + funcA = + (blend_factor(ctx->Color.BlendSrcA, GL_TRUE) << + R200_SRC_BLEND_SHIFT) | (blend_factor(ctx->Color.BlendDstA, + GL_FALSE) << + R200_DST_BLEND_SHIFT); + + switch (ctx->Color.BlendEquationA) { + case GL_FUNC_ADD: + eqnA = R300_COMB_FCN_ADD_CLAMP; + break; + + case GL_FUNC_SUBTRACT: + eqnA = R300_COMB_FCN_SUB_CLAMP; + break; + + case GL_FUNC_REVERSE_SUBTRACT: + eqnA = R200_COMB_FCN_RSUB_CLAMP; + break; + + case GL_MIN: + eqnA = R200_COMB_FCN_MIN; + funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); + break; + + case GL_MAX: + eqnA = R200_COMB_FCN_MAX; + funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | + (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); + break; + + default: + fprintf(stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n", + __func__, __LINE__, ctx->Color.BlendEquationA); + return; + } + + r300_set_blend_cntl(rmesa, + func, eqn, R300_BLEND_UNKNOWN | R300_BLEND_ENABLE, + funcA, eqnA); + r300_set_blend_cntl(rmesa, + func, eqn, R300_BLEND_UNKNOWN | R300_BLEND_ENABLE, + funcA, eqnA); +} + +static void r300BlendEquationSeparate(GLcontext * ctx, + GLenum modeRGB, GLenum modeA) +{ + r300_set_blend_state(ctx); +} + +static void r300BlendFuncSeparate(GLcontext * ctx, + GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + r300_set_blend_state(ctx); +} + +/** + * Update our tracked culling state based on Mesa's state. + */ +static void r300UpdateCulling(GLcontext* ctx) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + uint32_t val = 0; + + R300_STATECHANGE(r300, cul); + if (ctx->Polygon.CullFlag) { + if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) + val = R300_CULL_FRONT|R300_CULL_BACK; + else if (ctx->Polygon.CullFaceMode == GL_FRONT) + val = R300_CULL_FRONT; + else + val = R300_CULL_BACK; + + if (ctx->Polygon.FrontFace == GL_CW) + val |= R300_FRONT_FACE_CW; + else + val |= R300_FRONT_FACE_CCW; + } + r300->hw.cul.cmd[R300_CUL_CULL] = val; +} /** * Handle glEnable()/glDisable(). + * + * \note Mesa already filters redundant calls to glEnable/glDisable. */ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state) { + r300ContextPtr r300 = R300_CONTEXT(ctx); + uint32_t newval; + 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) { + /* Fast track this one... + */ + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + break; + + case GL_ALPHA_TEST: + R300_STATECHANGE(r300, at); + if (state) { + r300->hw.at.cmd[R300_AT_ALPHA_TEST] |= + R300_ALPHA_TEST_ENABLE; + } else { + r300->hw.at.cmd[R300_AT_ALPHA_TEST] &= + ~R300_ALPHA_TEST_ENABLE; + } + break; + + case GL_BLEND: + case GL_COLOR_LOGIC_OP: + r300_set_blend_state(ctx); + break; + + case GL_DEPTH_TEST: + R300_STATECHANGE(r300, zs); + + if (state) { + if (ctx->Depth.Mask) + newval = R300_RB3D_Z_TEST_AND_WRITE; + else + newval = R300_RB3D_Z_TEST; + } else + newval = R300_RB3D_Z_DISABLED_1; + + r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE; + r300->hw.zs.cmd[R300_ZS_CNTL_0] |= newval; + break; + + case GL_STENCIL_TEST: + WARN_ONCE("TODO - double side stencil !\n"); + if (r300->state.stencil.hw_stencil) { + R300_STATECHANGE(r300, zs); + if (state) { + r300->hw.zs.cmd[R300_ZS_CNTL_0] |= + R300_RB3D_STENCIL_ENABLE; + } else { + r300->hw.zs.cmd[R300_ZS_CNTL_0] &= + ~R300_RB3D_STENCIL_ENABLE; + } + } else { + FALLBACK(&r300->radeon, RADEON_FALLBACK_STENCIL, state); + } + break; + + case GL_CULL_FACE: + r300UpdateCulling(ctx); + break; + + case GL_POLYGON_OFFSET_POINT: + case GL_POLYGON_OFFSET_LINE: + WARN_ONCE("Don't know how to enable polygon offset point/line. Help me !\n"); + + /* Something is apparently blocking these from working */ + R300_STATECHANGE(r300, unk42B4); + if(state){ + r300->hw.unk42B4.cmd[1] |= ~(3<<0); + } else { + r300->hw.unk42B4.cmd[1] &= (3<<0); + } + break; + + case GL_POLYGON_OFFSET_FILL: + R300_STATECHANGE(r300, unk42B4); + if(state){ + r300->hw.unk42B4.cmd[1] |= (3<<0); + } else { + r300->hw.unk42B4.cmd[1] &= ~(3<<0); + } + break; + + case GL_VERTEX_PROGRAM_ARB: + //TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_TCL_DISABLE, state); + break; + default: radeonEnable(ctx, cap, state); return; @@ -76,6 +543,1408 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state) } +/** + * Change the culling mode. + * + * \note Mesa already filters redundant calls to this function. + */ +static void r300CullFace(GLcontext* ctx, GLenum mode) +{ + (void)mode; + + r300UpdateCulling(ctx); +} + + +/** + * Change the polygon orientation. + * + * \note Mesa already filters redundant calls to this function. + */ +static void r300FrontFace(GLcontext* ctx, GLenum mode) +{ + (void)mode; + + r300UpdateCulling(ctx); +} + + +/** + * Change the depth testing function. + * + * \note Mesa already filters redundant calls to this function. + */ +static void r300DepthFunc(GLcontext* ctx, GLenum func) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + + R300_STATECHANGE(r300, zs); + + r300->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT); + + switch(func) { + case GL_NEVER: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_NEVER << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_LESS: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_LESS << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_EQUAL: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_EQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_LEQUAL: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_LEQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_GREATER: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_GREATER << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_NOTEQUAL: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_NOTEQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_GEQUAL: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_GEQUAL << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + case GL_ALWAYS: + r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_ALWAYS << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT; + break; + } +} + + +/** + * Enable/Disable depth writing. + * + * \note Mesa already filters redundant calls to this function. + */ +static void r300DepthMask(GLcontext* ctx, GLboolean mask) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + + if (!ctx->Depth.Test) + return; + + R300_STATECHANGE(r300, zs); + r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE; + r300->hw.zs.cmd[R300_ZS_CNTL_0] |= mask + ? R300_RB3D_Z_TEST_AND_WRITE : R300_RB3D_Z_TEST; +} + + +/** + * Handle glColorMask() + */ +static void r300ColorMask(GLcontext* ctx, + GLboolean r, GLboolean g, GLboolean b, GLboolean a) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + int mask = (b << 0) | (g << 1) | (r << 2) | (a << 3); + + if (mask != r300->hw.cmk.cmd[R300_CMK_COLORMASK]) { + R300_STATECHANGE(r300, cmk); + r300->hw.cmk.cmd[R300_CMK_COLORMASK] = mask; + } +} + +/* ============================================================= + * Point state + */ +static void r300PointSize(GLcontext * ctx, GLfloat size) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + + size = ctx->Point._Size; + + R300_STATECHANGE(r300, ps); + r300->hw.ps.cmd[R300_PS_POINTSIZE] = + ((int)(size * 6) << R300_POINTSIZE_X_SHIFT) | + ((int)(size * 6) << R300_POINTSIZE_Y_SHIFT); + +#if 0 /* r200 reg? */ + /* This might need fixing later */ + R300_STATECHANGE(r300, vps); + r300->hw.vps.cmd[R300_VPS_POINTSIZE] = r300PackFloat32(1.0); +#endif +} + +/* ============================================================= + * Line state + */ +static void r300LineWidth(GLcontext *ctx, GLfloat widthf) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + + widthf = ctx->Line._Width; + + R300_STATECHANGE(r300, lcntl); + r300->hw.lcntl.cmd[1] = (int)(widthf * 6.0); + /* Doesnt look very good without this... */ + r300->hw.lcntl.cmd[1] |= R300_LINE_CNT_UNK1; +} + +/* + +glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); : 00000091 ( 1001 0001) +glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); : 00000001 ( 1) + +glPolygonMode(GL_FRONT, GL_LINE); : 00000111 (1 0001 0001) +glPolygonMode(GL_FRONT, GL_POINT); : 00000101 (1 0000 0001) + +glPolygonMode(GL_BACK, GL_LINE); : 000000a1 ( 1010 0001) +glPolygonMode(GL_BACK, GL_POINT); : 00000021 ( 10 0001) + +*/ + +/* exclusive */ +#define PM_NOT_BACK (1<<8) +#define PM_NOT_FRONT (1<<5) + +#define PM_FRONT_LINE (1<<4) +#define PM_BACK_LINE (1<<7) + +static void r300PolygonMode(GLcontext *ctx, GLenum face, GLenum mode) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + unsigned long hw_mode=0; + + //hw_mode=r300->hw.unk4288.cmd[1]; + hw_mode |= 1; /* enables point mode by default */ + + switch (ctx->Polygon.FrontMode) { + case GL_LINE: + hw_mode &= ~PM_NOT_FRONT; + hw_mode |= PM_FRONT_LINE; + break; + case GL_POINT: + hw_mode &= ~PM_NOT_FRONT; + hw_mode &= ~PM_FRONT_LINE; + break; + /* I dont think fgl properly handles these... In any case, test program is needed */ + case GL_FILL: + break; + } + + switch (ctx->Polygon.BackMode) { + case GL_LINE: + hw_mode &= ~PM_NOT_BACK; + hw_mode |= PM_BACK_LINE; + break; + case GL_POINT: + hw_mode &= ~PM_NOT_BACK; + hw_mode &= ~PM_BACK_LINE; + break; + case GL_FILL: + break; + } + + if(hw_mode == 1) + hw_mode = 0; + +#if 0 + switch (face) { + case GL_FRONT: + //fprintf(stderr, "front\n"); + hw_mode &= ~PM_NOT_FRONT; + switch (mode) { + case GL_LINE: + hw_mode |= PM_FRONT_LINE; + break; + case GL_POINT: + hw_mode &= ~PM_FRONT_LINE; + break; + case GL_FILL: + break; + } + break; + + case GL_BACK: + //fprintf(stderr, "back\n"); + hw_mode &= ~PM_NOT_BACK; + switch (mode) { + case GL_LINE: + hw_mode |= PM_BACK_LINE; + break; + case GL_POINT: + hw_mode &= ~PM_BACK_LINE; + break; + case GL_FILL: + break; + } + break; + + case GL_FRONT_AND_BACK: + //fprintf(stderr, "front and back\n"); + hw_mode &= ~PM_NOT_FRONT; + hw_mode &= ~PM_NOT_BACK; + switch (mode) { + case GL_LINE: + hw_mode |= PM_FRONT_LINE; + hw_mode |= PM_BACK_LINE; + break; + case GL_POINT: + hw_mode &= ~PM_FRONT_LINE; + hw_mode &= ~PM_BACK_LINE; + break; + case GL_FILL: + hw_mode = 0; + break; + } + break; + } +#endif + + //if( front and back fill) hw_mode=0; + + if(r300->hw.unk4288.cmd[1] != hw_mode){ + R300_STATECHANGE(r300, unk4288); + r300->hw.unk4288.cmd[1] = hw_mode; + } +} + +/* ============================================================= + * Stencil + */ + + static int translate_stencil_func(int func) + { + switch (func) { + case GL_NEVER: + return R300_ZS_NEVER; + break; + case GL_LESS: + return R300_ZS_LESS; + break; + case GL_EQUAL: + return R300_ZS_EQUAL; + break; + case GL_LEQUAL: + return R300_ZS_LEQUAL; + break; + case GL_GREATER: + return R300_ZS_GREATER; + break; + case GL_NOTEQUAL: + return R300_ZS_NOTEQUAL; + break; + case GL_GEQUAL: + return R300_ZS_GEQUAL; + break; + case GL_ALWAYS: + return R300_ZS_ALWAYS; + break; + } + return 0; + } + + static int translate_stencil_op(int op) +{ + switch (op) { + case GL_KEEP: + return R300_ZS_KEEP; + case GL_ZERO: + return R300_ZS_ZERO; + case GL_REPLACE: + return R300_ZS_REPLACE; + case GL_INCR: + return R300_ZS_INCR; + case GL_DECR: + return R300_ZS_DECR; + case GL_INCR_WRAP_EXT: + return R300_ZS_INCR_WRAP; + case GL_DECR_WRAP_EXT: + return R300_ZS_DECR_WRAP; + case GL_INVERT: + return R300_ZS_INVERT; + default: + WARN_ONCE("Do not know how to translate stencil op"); + return R300_ZS_KEEP; + } +} + +static void r300StencilFunc(GLcontext * ctx, GLenum func, + GLint ref, GLuint mask) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + GLuint refmask = ((ctx->Stencil.Ref[0] << R300_RB3D_ZS2_STENCIL_REF_SHIFT) | + (ctx->Stencil.ValueMask[0] << R300_RB3D_ZS2_STENCIL_MASK_SHIFT)); + + GLuint flag; + + R300_STATECHANGE(rmesa, zs); + + rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= ~( + (R300_ZS_MASK << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) + | (R300_ZS_MASK << R300_RB3D_ZS1_BACK_FUNC_SHIFT)); + + rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &= ~((R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_REF_SHIFT) | + (R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT)); + + flag = translate_stencil_func(ctx->Stencil.Function[0]); + + rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (flag << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) + | (flag << R300_RB3D_ZS1_BACK_FUNC_SHIFT); + rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= refmask; +} + +static void r300StencilMask(GLcontext * ctx, GLuint mask) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + R300_STATECHANGE(rmesa, zs); + rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &= ~(R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT); + rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT; +} + + +static void r300StencilOp(GLcontext * ctx, GLenum fail, + GLenum zfail, GLenum zpass) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + R300_STATECHANGE(rmesa, zs); + /* It is easier to mask what's left.. */ + rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= + (R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT) | + (R300_ZS_MASK << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) | + (R300_ZS_MASK << R300_RB3D_ZS1_BACK_FUNC_SHIFT); + + rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= + (translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT) + |(translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT) + |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT) + |(translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT) + |(translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT) + |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT); +} + +static void r300ClearStencil(GLcontext * ctx, GLint s) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + rmesa->state.stencil.clear = + ((GLuint) ctx->Stencil.Clear | + (R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT) | + (ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT)); +} + +/* ============================================================= + * Window position and viewport transformation + */ + +/* + * To correctly position primitives: + */ +#define SUBPIXEL_X 0.125 +#define SUBPIXEL_Y 0.125 + +void r300UpdateWindow(GLcontext * ctx) +{ + r300ContextPtr rmesa = R300_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; + + GLfloat sx = v[MAT_SX]; + GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X; + GLfloat sy = -v[MAT_SY]; + GLfloat ty = (-v[MAT_TY]) + yoffset + SUBPIXEL_Y; + GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale; + GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale; + + R300_FIREVERTICES(rmesa); + R300_STATECHANGE(rmesa, vpt); + + rmesa->hw.vpt.cmd[R300_VPT_XSCALE] = r300PackFloat32(sx); + rmesa->hw.vpt.cmd[R300_VPT_XOFFSET] = r300PackFloat32(tx); + rmesa->hw.vpt.cmd[R300_VPT_YSCALE] = r300PackFloat32(sy); + rmesa->hw.vpt.cmd[R300_VPT_YOFFSET] = r300PackFloat32(ty); + rmesa->hw.vpt.cmd[R300_VPT_ZSCALE] = r300PackFloat32(sz); + rmesa->hw.vpt.cmd[R300_VPT_ZOFFSET] = r300PackFloat32(tz); +} + +static void r300Viewport(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. + */ + R300_FIREVERTICES(R300_CONTEXT(ctx)); + r300UpdateWindow(ctx); +} + +static void r300DepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval) +{ + r300UpdateWindow(ctx); +} + +/* ============================================================= + * Polygon state + */ +static void r300PolygonOffset(GLcontext * ctx, GLfloat factor, GLfloat units) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + GLfloat constant = units * /*rmesa->state.depth.scale*/4; + + factor *= 12; + +/* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */ + + R300_STATECHANGE(rmesa, zbs); + rmesa->hw.zbs.cmd[R300_ZBS_T_FACTOR] = r300PackFloat32(factor); + rmesa->hw.zbs.cmd[R300_ZBS_T_CONSTANT] = r300PackFloat32(constant); + rmesa->hw.zbs.cmd[R300_ZBS_W_FACTOR] = r300PackFloat32(factor); + rmesa->hw.zbs.cmd[R300_ZBS_W_CONSTANT] = r300PackFloat32(constant); +} + +/* Routing and texture-related */ + +void r300_setup_routing(GLcontext *ctx, GLboolean immediate) +{ + int i, count=0,reg=0; + GLuint dw, mask; + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + r300ContextPtr r300 = R300_CONTEXT(ctx); + + + /* Stage 1 - input to VAP */ + + /* Assign register number automatically, retaining it in rmesa->state.reg */ + + /* Note: immediate vertex data includes all coordinates. + To save bandwidth use either VBUF or state-based vertex generation */ + +#define CONFIGURE_AOS(v, o, r, f) \ + {\ + if (RADEON_DEBUG & DEBUG_STATE)fprintf(stderr, "Enabling "#r "\n"); \ + r300->state.aos[count].aos_size=4; \ + r300->state.aos[count].aos_stride=4; \ + r300->state.aos[count].aos_offset=o; \ + r300->state.aos[count].aos_reg=reg; \ + r300->state.aos[count].aos_format=(f); \ + r300->state.vap_reg.r=reg; \ + count++; \ + reg++; \ + } + + /* All offsets are 0 - for use by immediate mode. + Should change later to handle vertex buffers */ + if(r300->current_vp!=NULL){ + + /* VERT_ATTRIB_WEIGHT, VERT_ATTRIB_SIX, VERT_ATTRIB_SEVEN, VERT_ATTRIB_GENERIC0, + VERT_ATTRIB_GENERIC1, VERT_ATTRIB_GENERIC2, VERT_ATTRIB_GENERIC3 */ + r300->state.render_inputs = 0; + + if(r300->current_vp->inputs[VERT_ATTRIB_POS] != -1){ + reg=r300->current_vp->inputs[VERT_ATTRIB_POS]; + CONFIGURE_AOS(VB->ObjPtr, 0, i_coords, AOS_FORMAT_FLOAT); + r300->state.render_inputs |= _TNL_BIT_POS; + } + if(r300->current_vp->inputs[VERT_ATTRIB_NORMAL] != -1){ + reg=r300->current_vp->inputs[VERT_ATTRIB_NORMAL]; + CONFIGURE_AOS(VB->NormalPtr, 0, i_normal, AOS_FORMAT_FLOAT); + r300->state.render_inputs |= _TNL_BIT_NORMAL; + } + if(r300->current_vp->inputs[VERT_ATTRIB_COLOR0] != -1){ + reg=r300->current_vp->inputs[VERT_ATTRIB_COLOR0]; + CONFIGURE_AOS(VB->ColorPtr[0], 0, i_color[0], AOS_FORMAT_FLOAT_COLOR); + r300->state.render_inputs |= _TNL_BIT_COLOR0; + } + if(r300->current_vp->inputs[VERT_ATTRIB_COLOR1] != -1){ + reg=r300->current_vp->inputs[VERT_ATTRIB_COLOR1]; + CONFIGURE_AOS(VB->SecondaryColorPtr[0], 0, i_color[1], AOS_FORMAT_FLOAT_COLOR); + r300->state.render_inputs |= _TNL_BIT_COLOR1; + } + if(r300->current_vp->inputs[VERT_ATTRIB_FOG] != -1){ + reg=r300->current_vp->inputs[VERT_ATTRIB_FOG]; + CONFIGURE_AOS(VB->FogCoordPtr, 0, i_fog, AOS_FORMAT_FLOAT); + r300->state.render_inputs |= _TNL_BIT_FOG; + } + for(i=0;i < ctx->Const.MaxTextureUnits;i++) // tex 7 is last + if(r300->current_vp->inputs[VERT_ATTRIB_TEX0+i] != -1){ + reg=r300->current_vp->inputs[VERT_ATTRIB_TEX0+i]; + CONFIGURE_AOS(VB->TexCoordPtr[i], 0, i_tex[i], AOS_FORMAT_FLOAT); + r300->state.render_inputs |= _TNL_BIT_TEX0<render_inputs & _TNL_BIT_INDEX)) + CONFIGURE_AOS(VB->IndexPtr[0], 0, i_index, AOS_FORMAT_FLOAT); + + if((tnl->render_inputs & _TNL_BIT_POINTSIZE)) + CONFIGURE_AOS(VB->PointSizePtr, 0, i_pointsize, AOS_FORMAT_FLOAT); +#endif + }else{ + + r300->state.render_inputs = tnl->render_inputs; + + if(tnl->render_inputs & _TNL_BIT_POS) + CONFIGURE_AOS(VB->ObjPtr, 0, i_coords, AOS_FORMAT_FLOAT); + if(tnl->render_inputs & _TNL_BIT_NORMAL) + CONFIGURE_AOS(VB->NormalPtr, 0, i_normal, AOS_FORMAT_FLOAT); + + if(tnl->render_inputs & _TNL_BIT_COLOR0) + CONFIGURE_AOS(VB->ColorPtr[0], 0, i_color[0], AOS_FORMAT_FLOAT_COLOR); + if(tnl->render_inputs & _TNL_BIT_COLOR1) + CONFIGURE_AOS(VB->SecondaryColorPtr[0], 0, i_color[1], AOS_FORMAT_FLOAT_COLOR); + + /*if(tnl->render_inputs & _TNL_BIT_FOG) // Causes lock ups when immediate mode is on + CONFIGURE_AOS(VB->FogCoordPtr, 0, i_fog, AOS_FORMAT_FLOAT);*/ + + for(i=0;i < ctx->Const.MaxTextureUnits;i++) + if(tnl->render_inputs & (_TNL_BIT_TEX0<TexCoordPtr[i], 0, i_tex[i], AOS_FORMAT_FLOAT); + + if(tnl->render_inputs & _TNL_BIT_INDEX) + CONFIGURE_AOS(VB->IndexPtr[0], 0, i_index, AOS_FORMAT_FLOAT); + if(tnl->render_inputs & _TNL_BIT_POINTSIZE) + CONFIGURE_AOS(VB->PointSizePtr, 0, i_pointsize, AOS_FORMAT_FLOAT); + } + + r300->state.aos_count=count; + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "aos_count=%d render_inputs=%08x\n", count, r300->state.render_inputs); + + + if(count>R300_MAX_AOS_ARRAYS){ + fprintf(stderr, "Aieee ! AOS array count exceeded !\n"); + exit(-1); + } + + /* Implement AOS */ + + /* setup INPUT_ROUTE */ + R300_STATECHANGE(r300, vir[0]); + for(i=0;i+1state.aos[i].aos_size-1) + | ((r300->state.aos[i].aos_reg)<<8) + | (r300->state.aos[i].aos_format<<14) + | (((r300->state.aos[i+1].aos_size-1) + | ((r300->state.aos[i+1].aos_reg)<<8) + | (r300->state.aos[i+1].aos_format<<14))<<16); + + if(i+2==count){ + dw|=(1<<(13+16)); + } + r300->hw.vir[0].cmd[R300_VIR_CNTL_0+(i>>1)]=dw; + } + if(count & 1){ + dw=(r300->state.aos[count-1].aos_size-1) + | (r300->state.aos[count-1].aos_format<<14) + | ((r300->state.aos[count-1].aos_reg)<<8) + | (1<<13); + r300->hw.vir[0].cmd[R300_VIR_CNTL_0+(count>>1)]=dw; + //fprintf(stderr, "vir0 dw=%08x\n", dw); + } + /* Set the rest of INPUT_ROUTE_0 to 0 */ + //for(i=((count+1)>>1); i<8; i++)r300->hw.vir[0].cmd[R300_VIR_CNTL_0+i]=(0x0); + ((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->unchecked_state.count = (count+1)>>1; + + + /* Mesa assumes that all missing components are from (0, 0, 0, 1) */ +#define ALL_COMPONENTS ((R300_INPUT_ROUTE_SELECT_X<state.aos[i].aos_size*3))-1; + dw=(ALL_COMPONENTS & mask) + | (ALL_DEFAULT & ~mask) + | R300_INPUT_ROUTE_ENABLE; + + /* i+1 */ + mask=(1<<(r300->state.aos[i+1].aos_size*3))-1; + dw|=( + (ALL_COMPONENTS & mask) + | (ALL_DEFAULT & ~mask) + | R300_INPUT_ROUTE_ENABLE + )<<16; + + r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(i>>1)]=dw; + } + if(count & 1){ + mask=(1<<(r300->state.aos[count-1].aos_size*3))-1; + dw=(ALL_COMPONENTS & mask) + | (ALL_DEFAULT & ~mask) + | R300_INPUT_ROUTE_ENABLE; + r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(count>>1)]=dw; + //fprintf(stderr, "vir1 dw=%08x\n", dw); + } + /* Set the rest of INPUT_ROUTE_1 to 0 */ + //for(i=((count+1)>>1); i<8; i++)r300->hw.vir[1].cmd[R300_VIR_CNTL_0+i]=0x0; + ((drm_r300_cmd_header_t*)r300->hw.vir[1].cmd)->unchecked_state.count = (count+1)>>1; + + /* Set up input_cntl */ + + R300_STATECHANGE(r300, vic); + r300->hw.vic.cmd[R300_VIC_CNTL_0]=0x5555; /* Hard coded value, no idea what it means */ + + r300->hw.vic.cmd[R300_VIC_CNTL_1]=0; + + if(r300->state.render_inputs & _TNL_BIT_POS) + r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_POS; + + if(r300->state.render_inputs & _TNL_BIT_NORMAL) + r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_NORMAL; + + if(r300->state.render_inputs & _TNL_BIT_COLOR0) + r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_COLOR; + + for(i=0;i < ctx->Const.MaxTextureUnits;i++) + if(r300->state.render_inputs & (_TNL_BIT_TEX0<hw.vic.cmd[R300_VIC_CNTL_1]|=(R300_INPUT_CNTL_TC0<hw.vof.cmd[R300_VOF_CNTL_0]=R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT + | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT; + + r300->hw.vof.cmd[R300_VOF_CNTL_1]=0; + for(i=0;i < ctx->Const.MaxTextureUnits;i++) + if(r300->state.render_inputs & (_TNL_BIT_TEX0<hw.vof.cmd[R300_VOF_CNTL_1]|=(4<<(3*i)); + +} + +static r300TexObj default_tex_obj={ + filter:R300_TX_MAG_FILTER_LINEAR | R300_TX_MIN_FILTER_LINEAR, + pitch: 0x8000, + size: (0xff << R300_TX_WIDTHMASK_SHIFT) + | (0xff << R300_TX_HEIGHTMASK_SHIFT) + | (0x8 << R300_TX_SIZE_SHIFT), + format: 0x88a0c, + offset: 0x0, + unknown4: 0x0, + unknown5: 0x0 + }; + + /* there is probably a system to these value, but, for now, + we just try by hand */ + +static int inline translate_src(int src) +{ + switch (src) { + case GL_TEXTURE: + return 1; + break; + case GL_CONSTANT: + return 2; + break; + case GL_PRIMARY_COLOR: + return 3; + break; + case GL_PREVIOUS: + return 4; + break; + case GL_ZERO: + return 5; + break; + case GL_ONE: + return 6; + break; + default: + return 0; + } +} + +/* r300 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 r300 completely ignores R300_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) << R300_TX_WRAP_S_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_S_SHIFT)){ + needs_fixing |= 1; + } + if((f & ((7-1) << R300_TX_WRAP_T_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_T_SHIFT)){ + needs_fixing |= 2; + } + if((f & ((7-1) << R300_TX_WRAP_Q_SHIFT)) == (R300_TX_CLAMP << R300_TX_WRAP_Q_SHIFT)){ + needs_fixing |= 4; + } + + if(!needs_fixing) + return f; + + mag=f & R300_TX_MAG_FILTER_MASK; + min=f & R300_TX_MIN_FILTER_MASK; + + /* TODO: Check for anisto filters too */ + if((mag != R300_TX_MAG_FILTER_NEAREST) && (min != R300_TX_MIN_FILTER_NEAREST)) + return f; + + /* r300 cant handle these modes hence we force nearest to linear */ + if((mag == R300_TX_MAG_FILTER_NEAREST) && (min != R300_TX_MIN_FILTER_NEAREST)){ + f &= ~R300_TX_MAG_FILTER_NEAREST; + f |= R300_TX_MAG_FILTER_LINEAR; + return f; + } + + if((min == R300_TX_MIN_FILTER_NEAREST) && (mag != R300_TX_MAG_FILTER_NEAREST)){ + f &= ~R300_TX_MIN_FILTER_NEAREST; + f |= R300_TX_MIN_FILTER_LINEAR; + return f; + } + + /* Both are nearest */ + if(needs_fixing & 1){ + f &= ~((7-1) << R300_TX_WRAP_S_SHIFT); + f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_S_SHIFT; + } + if(needs_fixing & 2){ + f &= ~((7-1) << R300_TX_WRAP_T_SHIFT); + f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_T_SHIFT; + } + if(needs_fixing & 4){ + f &= ~((7-1) << R300_TX_WRAP_Q_SHIFT); + f |= R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_Q_SHIFT; + } + return f; +} + +void r300_setup_textures(GLcontext *ctx) +{ + int i, mtu; + struct r300_tex_obj *t; + r300ContextPtr r300 = R300_CONTEXT(ctx); + int max_texture_unit=-1; /* -1 translates into no setup costs for fields */ + struct gl_texture_unit *texUnit; + + R300_STATECHANGE(r300, txe); + R300_STATECHANGE(r300, tex.filter); + R300_STATECHANGE(r300, tex.unknown1); + R300_STATECHANGE(r300, tex.size); + R300_STATECHANGE(r300, tex.format); + R300_STATECHANGE(r300, tex.offset); + R300_STATECHANGE(r300, tex.unknown4); + R300_STATECHANGE(r300, tex.border_color); + + r300->state.texture.tc_count=0; + + r300->hw.txe.cmd[R300_TXE_ENABLE]=0x0; + + mtu = r300->radeon.glCtx->Const.MaxTextureUnits; + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "mtu=%d\n", mtu); + + if(mtu > R300_MAX_TEXTURE_UNITS) { + fprintf(stderr, "Aiiee ! mtu=%d is greater than R300_MAX_TEXTURE_UNITS=%d\n", + mtu, R300_MAX_TEXTURE_UNITS); + exit(-1); + } + + for(i=0; i < mtu; i++) { + /*if(ctx->Texture.Unit[i].Enabled == 0) + continue;*/ + if( ((r300->state.render_inputs & (_TNL_BIT_TEX0<Texture.Unit[i].Enabled)!=0) ) { + WARN_ONCE("Mismatch between render_inputs and ctx->Texture.Unit[i].Enabled value.\n"); + } + + if(r300->state.render_inputs & (_TNL_BIT_TEX0<state.texture.unit[i].texobj; + //fprintf(stderr, "format=%08x\n", r300->state.texture.unit[i].format); + r300->state.texture.tc_count++; + + if(t == NULL){ + fprintf(stderr, "Texture unit %d enabled, but corresponding texobj is NULL, using default object.\n", i); + //exit(-1); + t=&default_tex_obj; + } + + //fprintf(stderr, "t->format=%08x\n", t->format); + if((t->format & 0xffffff00)==0xffffff00) { + WARN_ONCE("unknown texture format (entry %x) encountered. Help me !\n", t->format & 0xff); + //fprintf(stderr, "t->format=%08x\n", t->format); + } + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "Activating texture unit %d\n", i); + max_texture_unit=i; + r300->hw.txe.cmd[R300_TXE_ENABLE]|=(1<hw.tex.filter.cmd[R300_TEX_VALUE_0+i]=gen_fixed_filter(t->filter) | (i << 28); + r300->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+i]=0x0; + + /* No idea why linear filtered textures shake when puting random data */ + /*r300->hw.tex.unknown1.cmd[R300_TEX_VALUE_0+i]=(rand()%0xffffffff) & (~0x1fff);*/ + r300->hw.tex.size.cmd[R300_TEX_VALUE_0+i]=t->size; + r300->hw.tex.format.cmd[R300_TEX_VALUE_0+i]=t->format; + //fprintf(stderr, "t->format=%08x\n", t->format); + r300->hw.tex.offset.cmd[R300_TEX_VALUE_0+i]=r300->radeon.radeonScreen->fbLocation+t->offset; + r300->hw.tex.unknown4.cmd[R300_TEX_VALUE_0+i]=0x0; + r300->hw.tex.border_color.cmd[R300_TEX_VALUE_0+i]=t->pp_border_color; + } + } + + ((drm_r300_cmd_header_t*)r300->hw.tex.filter.cmd)->unchecked_state.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.unknown1.cmd)->unchecked_state.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.size.cmd)->unchecked_state.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.format.cmd)->unchecked_state.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.offset.cmd)->unchecked_state.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.unknown4.cmd)->unchecked_state.count = max_texture_unit+1; + ((drm_r300_cmd_header_t*)r300->hw.tex.border_color.cmd)->unchecked_state.count = max_texture_unit+1; + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "TX_ENABLE: %08x max_texture_unit=%d\n", r300->hw.txe.cmd[R300_TXE_ENABLE], max_texture_unit); +} + +void r300_setup_rs_unit(GLcontext *ctx) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + int i, cur_reg; + GLuint interp_magic[8] = { + 0x00, + 0x40, + 0x80, + 0xC0, + 0x00, + 0x00, + 0x00, + 0x00 + }; + + /* This needs to be rewritten - it is a hack at best */ + + R300_STATECHANGE(r300, ri); + R300_STATECHANGE(r300, rc); + R300_STATECHANGE(r300, rr); + +#if 1 + cur_reg = 0; + for (i=0;iConst.MaxTextureUnits;i++) { + r300->hw.ri.cmd[R300_RI_INTERP_0+i] = 0 + | R300_RS_INTERP_USED + | (cur_reg << R300_RS_INTERP_SRC_SHIFT) + | interp_magic[i]; +// fprintf(stderr, "RS_INTERP[%d] = 0x%x\n", i, r300->hw.ri.cmd[R300_RI_INTERP_0+i]); + + if (r300->state.render_inputs & (_TNL_BIT_TEX0<hw.rr.cmd[R300_RR_ROUTE_0 + cur_reg] = 0 + | R300_RS_ROUTE_ENABLE + | i /* source INTERP */ + | (cur_reg << R300_RS_ROUTE_DEST_SHIFT); +// fprintf(stderr, "RS_ROUTE[%d] = 0x%x\n", cur_reg, r300->hw.rr.cmd[R300_RR_ROUTE_0 + cur_reg]); + cur_reg++; + } + } + if (r300->state.render_inputs & _TNL_BIT_COLOR0) + r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0 + | R300_RS_ROUTE_0_COLOR + | (cur_reg << R300_RS_ROUTE_0_COLOR_DEST_SHIFT); + r300->hw.rr.cmd[R300_RR_CMD_0] = cmducs(R300_RS_ROUTE_0, cur_reg); +// fprintf(stderr, "ADJ_RR0 = 0x%x\n", r300->hw.rr.cmd[R300_RR_ROUTE_0]); + +// fprintf(stderr, "rendering with %d texture co-ordinate sets\n", cur_reg); + + r300->hw.rc.cmd[1] = 0 + | (cur_reg /* count */ << R300_RS_CNTL_TC_CNT_SHIFT) + | R300_RS_CNTL_0_UNKNOWN_7 + | R300_RS_CNTL_0_UNKNOWN_18; + r300->hw.rc.cmd[2] = (0xC0 | (cur_reg-1) /* index of highest */ ); +#else + for(i = 1; i <= 8; ++i) + r300->hw.ri.cmd[i] = 0x00d10000; + r300->hw.ri.cmd[R300_RI_INTERP_1] |= R300_RS_INTERP_1_UNKNOWN; + r300->hw.ri.cmd[R300_RI_INTERP_2] |= R300_RS_INTERP_2_UNKNOWN; + r300->hw.ri.cmd[R300_RI_INTERP_3] |= R300_RS_INTERP_3_UNKNOWN; + +#if 1 + for(i = 2; i <= 8; ++i) + r300->hw.ri.cmd[i] |= 4; +#endif + + for(i = 1; i <= 8; ++i) + r300->hw.rr.cmd[i] = 0; + /* textures enabled ? */ + if(r300->state.texture.tc_count>0){ + + /* This code only really works with one set of texture coordinates */ + + /* The second constant is needed to get glxgears display anything .. */ + r300->hw.rc.cmd[1] = R300_RS_CNTL_0_UNKNOWN_7 + | R300_RS_CNTL_0_UNKNOWN_18 + | (r300->state.texture.tc_count<hw.rc.cmd[2] = 0xc0; + + + ((drm_r300_cmd_header_t*)r300->hw.rr.cmd)->unchecked_state.count = 1; + r300->hw.rr.cmd[R300_RR_ROUTE_0] = 0x24008; + + } else { + + /* The second constant is needed to get glxgears display anything .. */ + r300->hw.rc.cmd[1] = R300_RS_CNTL_0_UNKNOWN_7 | R300_RS_CNTL_0_UNKNOWN_18; + r300->hw.rc.cmd[2] = 0; + + ((drm_r300_cmd_header_t*)r300->hw.rr.cmd)->unchecked_state.count = 1; + r300->hw.rr.cmd[R300_RR_ROUTE_0] = 0x4000; + + } +#endif +} + +#define vpucount(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count) + +#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; \ + if(_nc>_p->vpu.count)_p->vpu.count=_nc;\ + }while(0) + +void static inline setup_vertex_shader_fragment(r300ContextPtr r300, int dest, struct r300_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"); + exit(-1); + } + + switch((dest>>8) & 0xf){ + case 0: + R300_STATECHANGE(r300, vpi); + for(i=0;ilength;i++) + r300->hw.vpi.cmd[R300_VPI_INSTR_0+i+4*(dest & 0xff)]=(vsf->body.d[i]); + bump_vpu_count(r300->hw.vpi.cmd, vsf->length+4*(dest & 0xff)); + break; + + case 2: + R300_STATECHANGE(r300, vpp); + for(i=0;ilength;i++) + r300->hw.vpp.cmd[R300_VPP_PARAM_0+i+4*(dest & 0xff)]=(vsf->body.d[i]); + bump_vpu_count(r300->hw.vpp.cmd, vsf->length+4*(dest & 0xff)); + break; + case 4: + R300_STATECHANGE(r300, vps); + for(i=0;ilength;i++) + r300->hw.vps.cmd[1+i+4*(dest & 0xff)]=(vsf->body.d[i]); + bump_vpu_count(r300->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); + exit(-1); + } +} + +void r300SetupVertexProgram(r300ContextPtr rmesa); + +/* just a skeleton for now.. */ + +/* Generate a vertex shader that simply transforms vertex and texture coordinates, + while leaving colors intact. Nothing fancy (like lights) + + If implementing lights make a copy first, so it is easy to switch between the two versions */ +void r300GenerateSimpleVertexShader(r300ContextPtr r300) +{ + int i; + + /* Allocate parameters */ + r300->state.vap_param.transform_offset=0x0; /* transform matrix */ + r300->state.vertex_shader.param_offset=0x0; + r300->state.vertex_shader.param_count=0x4; /* 4 vector values - 4x4 matrix */ + + r300->state.vertex_shader.program_start=0x0; + r300->state.vertex_shader.unknown_ptr1=0x4; /* magic value ? */ + r300->state.vertex_shader.program_end=0x0; + + r300->state.vertex_shader.unknown_ptr2=0x0; /* magic value */ + r300->state.vertex_shader.unknown_ptr3=0x4; /* magic value */ + + /* Initialize matrix and vector parameters.. these should really be restructured */ + /* TODO: fix vertex_shader structure */ + r300->state.vertex_shader.matrix[0].length=16; + r300->state.vertex_shader.matrix[1].length=0; + r300->state.vertex_shader.matrix[2].length=0; + r300->state.vertex_shader.vector[0].length=0; + r300->state.vertex_shader.vector[1].length=0; + r300->state.vertex_shader.unknown1.length=0; + r300->state.vertex_shader.unknown2.length=0; + +#define WRITE_OP(oper,source1,source2,source3) {\ + r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].op=(oper); \ + r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].src1=(source1); \ + r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].src2=(source2); \ + r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].src3=(source3); \ + r300->state.vertex_shader.program_end++; \ + } + + /* Multiply vertex coordinates with transform matrix */ + + WRITE_OP( + EASY_VSF_OP(MUL, 0, ALL, TMP), + VSF_PARAM(3), + VSF_ATTR_W(0), + EASY_VSF_SOURCE(0, W, W, W, W, NONE, NONE) + ) + + WRITE_OP( + EASY_VSF_OP(MUL, 1, ALL, RESULT), + VSF_REG(1), + VSF_ATTR_UNITY(1), + VSF_UNITY(1) + ) + + WRITE_OP( + EASY_VSF_OP(MAD, 0, ALL, TMP), + VSF_PARAM(2), + VSF_ATTR_Z(0), + VSF_TMP(0) + ) + + WRITE_OP( + EASY_VSF_OP(MAD, 0, ALL, TMP), + VSF_PARAM(1), + VSF_ATTR_Y(0), + VSF_TMP(0) + ) + + WRITE_OP( + EASY_VSF_OP(MAD, 0, ALL, RESULT), + VSF_PARAM(0), + VSF_ATTR_X(0), + VSF_TMP(0) + ) + + /* Pass through texture coordinates, if any */ + for(i=0;i < r300->radeon.glCtx->Const.MaxTextureUnits;i++) + if(r300->state.render_inputs & (_TNL_BIT_TEX0<state.vap_reg.i_tex[i]); + WRITE_OP( + EASY_VSF_OP(MUL, 2+i, ALL, RESULT), + VSF_REG(r300->state.vap_reg.i_tex[i]), + VSF_ATTR_UNITY(r300->state.vap_reg.i_tex[i]), + VSF_UNITY(r300->state.vap_reg.i_tex[i]) + ) + } + + r300->state.vertex_shader.program_end--; /* r300 wants program length to be one more - no idea why */ + r300->state.vertex_shader.program.length=(r300->state.vertex_shader.program_end+1)*4; + + r300->state.vertex_shader.unknown_ptr1=r300->state.vertex_shader.program_end; /* magic value ? */ + r300->state.vertex_shader.unknown_ptr2=r300->state.vertex_shader.program_end; /* magic value ? */ + r300->state.vertex_shader.unknown_ptr3=r300->state.vertex_shader.program_end; /* magic value ? */ + +} + + +void r300SetupVertexShader(r300ContextPtr rmesa) +{ + GLcontext* ctx = rmesa->radeon.glCtx; + struct r300_vertex_shader_fragment unk4={ + length: 4, + body: { f: { + /*0.0*/(rand()%100)/10.0, + /*0.0*/(rand()%100)/10.0, + /*1.0*/(rand()%100)/10.0, + /*0.0*/(rand()%100)/10.0 + } } + }; + LOCAL_VARS + + /* 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(rmesa->current_vp != NULL){ + r300SetupVertexProgram(rmesa); + return ; + } + +/* This needs to be replaced by vertex shader generation code */ + + +#if 0 + /* textures enabled ? */ + if(rmesa->state.texture.tc_count>0){ + rmesa->state.vertex_shader=SINGLE_TEXTURE_VERTEX_SHADER; + } else { + rmesa->state.vertex_shader=FLAT_COLOR_VERTEX_SHADER; + } +#endif + + r300GenerateSimpleVertexShader(rmesa); + + rmesa->state.vertex_shader.matrix[0].length=16; + memcpy(rmesa->state.vertex_shader.matrix[0].body.f, ctx->_ModelProjectMatrix.m, 16*4); + + setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(rmesa->state.vertex_shader.program)); + + setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX0, &(rmesa->state.vertex_shader.matrix[0])); +#if 0 + setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX1, &(rmesa->state.vertex_shader.matrix[0])); + setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX2, &(rmesa->state.vertex_shader.matrix[0])); + + setup_vertex_shader_fragment(rmesa, VSF_DEST_VECTOR0, &(rmesa->state.vertex_shader.vector[0])); + setup_vertex_shader_fragment(rmesa, VSF_DEST_VECTOR1, &(rmesa->state.vertex_shader.vector[1])); +#endif + +#if 0 + setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN1, &(rmesa->state.vertex_shader.unknown1)); + setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN2, &(rmesa->state.vertex_shader.unknown2)); +#endif + + R300_STATECHANGE(rmesa, pvs); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_1]=(rmesa->state.vertex_shader.program_start << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) + | (rmesa->state.vertex_shader.unknown_ptr1 << R300_PVS_CNTL_1_UNKNOWN_SHIFT) + | (rmesa->state.vertex_shader.program_end << R300_PVS_CNTL_1_PROGRAM_END_SHIFT); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_2]=(rmesa->state.vertex_shader.param_offset << R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT) + | (rmesa->state.vertex_shader.param_count << R300_PVS_CNTL_2_PARAM_COUNT_SHIFT); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_3]=(rmesa->state.vertex_shader.unknown_ptr2 << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT) + | (rmesa->state.vertex_shader.unknown_ptr3 << 0); + + /* This is done for vertex shader fragments, but also needs to be done for vap_pvs, + so I leave it as a reminder */ +#if 0 + reg_start(R300_VAP_PVS_WAITIDLE,0); + e32(0x00000000); +#endif +} + +void r300SetupVertexProgram(r300ContextPtr rmesa) +{ + GLcontext* ctx = rmesa->radeon.glCtx; + int inst_count; + int param_count; + LOCAL_VARS + + + /* 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; + + r300VertexProgUpdateParams(ctx, rmesa->current_vp); + + setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(rmesa->current_vp->program)); + + setup_vertex_shader_fragment(rmesa, VSF_DEST_MATRIX0, &(rmesa->current_vp->params)); + +#if 0 + setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN1, &(rmesa->state.vertex_shader.unknown1)); + setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN2, &(rmesa->state.vertex_shader.unknown2)); +#endif + + inst_count=rmesa->current_vp->program.length/4 - 1; + param_count=rmesa->current_vp->params.length/4; + + R300_STATECHANGE(rmesa, pvs); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_1]=(0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) + | (inst_count/*0*/ << R300_PVS_CNTL_1_UNKNOWN_SHIFT) + | (inst_count << R300_PVS_CNTL_1_PROGRAM_END_SHIFT); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_2]=(0 << R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT) + | (param_count << R300_PVS_CNTL_2_PARAM_COUNT_SHIFT); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_3]=(0/*rmesa->state.vertex_shader.unknown_ptr2*/ << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT) + | ((inst_count-rmesa->current_vp->t2rs) /*rmesa->state.vertex_shader.unknown_ptr3*/ << 0); + + /* This is done for vertex shader fragments, but also needs to be done for vap_pvs, + so I leave it as a reminder */ +#if 0 + reg_start(R300_VAP_PVS_WAITIDLE,0); + e32(0x00000000); +#endif +} + + +/* just a skeleton for now.. */ +void r300GenerateTexturePixelShader(r300ContextPtr r300) +{ + int i, mtu; + mtu = r300->radeon.glCtx->Const.MaxTextureUnits; + GLenum envMode; + + int tex_inst=0, alu_inst=0; + + for(i=0;istate.render_inputs & (_TNL_BIT_TEX0<radeon.glCtx->Texture.Unit[i].EnvMode; + //fprintf(stderr, "envMode=%s\n", _mesa_lookup_enum_by_nr(envMode)); + + /* Fetch textured pixel */ + + r300->state.pixel_shader.program.tex.inst[tex_inst]=0x00018000; + tex_inst++; + + switch(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeRGB){ + case GL_REPLACE: + WARN_ONCE("ModeA==GL_REPLACE is possibly broken.\n"); + r300->state.pixel_shader.program.alu.inst[alu_inst].inst0= + EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst1= + EASY_PFS_INSTR1(0, 0, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, NONE, ALL); + break; + case GL_MODULATE: + WARN_ONCE("ModeRGB==GL_MODULATE is possibly broken.\n"); + r300->state.pixel_shader.program.alu.inst[alu_inst].inst0= + EASY_PFS_INSTR0(MAD, SRC0C_XYZ, SRC1C_XYZ, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst1= + EASY_PFS_INSTR1(0, 0, 1, 0 | PFS_FLAG_CONST, NONE, ALL); + + break; + default: + WARN_ONCE("ModeRGB=%s is not implemented yet !\n", + _mesa_lookup_enum_by_nr(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeRGB)); + /* PFS_NOP */ + r300->state.pixel_shader.program.alu.inst[alu_inst].inst0= + EASY_PFS_INSTR0(MAD, SRC0C_XYZ, ONE, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst1= + EASY_PFS_INSTR1(0, 0, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, NONE, ALL); + } + switch(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeA){ + case GL_REPLACE: + WARN_ONCE("ModeA==GL_REPLACE is possibly broken.\n"); + r300->state.pixel_shader.program.alu.inst[alu_inst].inst2= + EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst3= + EASY_PFS_INSTR3(0, 0, 0| PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, OUTPUT); + +#if 0 + fprintf(stderr, "numArgsA=%d sourceA[0]=%s op=%d\n", + r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->_NumArgsA, + _mesa_lookup_enum_by_nr(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->SourceA[0]), + r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->OperandA[0]-GL_SRC_ALPHA); +#endif + break; + case GL_MODULATE: + WARN_ONCE("ModeA==GL_MODULATE is possibly broken.\n"); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst2= + EASY_PFS_INSTR2(MAD, SRC0A, SRC1A, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst3= + EASY_PFS_INSTR3(0, 0, 1, 0 | PFS_FLAG_CONST, OUTPUT); + + break; + default: + WARN_ONCE("ModeA=%s is not implemented yet !\n", + _mesa_lookup_enum_by_nr(r300->radeon.glCtx->Texture.Unit[i]._CurrentCombine->ModeA)); + /* PFS_NOP */ + r300->state.pixel_shader.program.alu.inst[alu_inst].inst2= + EASY_PFS_INSTR2(MAD, SRC0A, ONE, ZERO); + + r300->state.pixel_shader.program.alu.inst[alu_inst].inst3= + EASY_PFS_INSTR3(0, 0, 0 | PFS_FLAG_CONST, 0 | PFS_FLAG_CONST, OUTPUT); + + } + + alu_inst++; + } + + r300->state.pixel_shader.program.tex.length=tex_inst; + r300->state.pixel_shader.program.tex_offset=0; + r300->state.pixel_shader.program.tex_end=tex_inst-1; + +#if 0 + /* saturate last instruction, like i915 driver does */ + r300->state.pixel_shader.program.alu.inst[alu_inst-1].inst0|=R300_FPI0_OUTC_SAT; + r300->state.pixel_shader.program.alu.inst[alu_inst-1].inst2|=R300_FPI2_OUTA_SAT; +#endif + + r300->state.pixel_shader.program.alu.length=alu_inst; + r300->state.pixel_shader.program.alu_offset=0; + r300->state.pixel_shader.program.alu_end=alu_inst-1; +} + +void r300SetupPixelShader(r300ContextPtr rmesa) +{ +int i,k; + + /* This needs to be replaced by pixel shader generation code */ + + /* textures enabled ? */ + if(rmesa->state.texture.tc_count>0){ +#if 1 + r300GenerateTextureFragmentShader(rmesa); +#else + rmesa->state.pixel_shader=SINGLE_TEXTURE_PIXEL_SHADER; + r300GenerateTexturePixelShader(rmesa); +#endif + } else { + rmesa->state.pixel_shader=FLAT_COLOR_PIXEL_SHADER; + } + + R300_STATECHANGE(rmesa, fpt); + for(i=0;istate.pixel_shader.program.tex.length;i++) + rmesa->hw.fpt.cmd[R300_FPT_INSTR_0+i]=rmesa->state.pixel_shader.program.tex.inst[i]; + rmesa->hw.fpt.cmd[R300_FPT_CMD_0]=cmducs(R300_PFS_TEXI_0, rmesa->state.pixel_shader.program.tex.length); + +#define OUTPUT_FIELD(st, reg, field) \ + R300_STATECHANGE(rmesa, st); \ + for(i=0;istate.pixel_shader.program.alu.length;i++) \ + rmesa->hw.st.cmd[R300_FPI_INSTR_0+i]=rmesa->state.pixel_shader.program.alu.inst[i].field;\ + rmesa->hw.st.cmd[R300_FPI_CMD_0]=cmducs(reg, rmesa->state.pixel_shader.program.alu.length); + + OUTPUT_FIELD(fpi[0], R300_PFS_INSTR0_0, inst0); + OUTPUT_FIELD(fpi[1], R300_PFS_INSTR1_0, inst1); + OUTPUT_FIELD(fpi[2], R300_PFS_INSTR2_0, inst2); + OUTPUT_FIELD(fpi[3], R300_PFS_INSTR3_0, inst3); +#undef OUTPUT_FIELD + + R300_STATECHANGE(rmesa, fp); + for(i=0;i<4;i++){ + rmesa->hw.fp.cmd[R300_FP_NODE0+i]= + (rmesa->state.pixel_shader.program.node[i].alu_offset << R300_PFS_NODE_ALU_OFFSET_SHIFT) + | (rmesa->state.pixel_shader.program.node[i].alu_end << R300_PFS_NODE_ALU_END_SHIFT) + | (rmesa->state.pixel_shader.program.node[i].tex_offset << R300_PFS_NODE_TEX_OFFSET_SHIFT) + | (rmesa->state.pixel_shader.program.node[i].tex_end << R300_PFS_NODE_TEX_END_SHIFT) + | ( (i==3) ? R300_PFS_NODE_LAST_NODE : 0); + } + + /* PFS_CNTL_0 */ + rmesa->hw.fp.cmd[R300_FP_CNTL0]= + (rmesa->state.pixel_shader.program.active_nodes-1) + | (rmesa->state.pixel_shader.program.first_node_has_tex<<3); + /* PFS_CNTL_1 */ + rmesa->hw.fp.cmd[R300_FP_CNTL1]=rmesa->state.pixel_shader.program.temp_register_count; + /* PFS_CNTL_2 */ + rmesa->hw.fp.cmd[R300_FP_CNTL2]= + (rmesa->state.pixel_shader.program.alu_offset << R300_PFS_CNTL_ALU_OFFSET_SHIFT) + | (rmesa->state.pixel_shader.program.alu_end << R300_PFS_CNTL_ALU_END_SHIFT) + | (rmesa->state.pixel_shader.program.tex_offset << R300_PFS_CNTL_TEX_OFFSET_SHIFT) + | (rmesa->state.pixel_shader.program.tex_end << R300_PFS_CNTL_TEX_END_SHIFT); + + R300_STATECHANGE(rmesa, fpp); + for(i=0;istate.pixel_shader.param_length;i++){ + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+0]=r300PackFloat32(rmesa->state.pixel_shader.param[i].x); + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+1]=r300PackFloat32(rmesa->state.pixel_shader.param[i].y); + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+2]=r300PackFloat32(rmesa->state.pixel_shader.param[i].z); + rmesa->hw.fpp.cmd[R300_FPP_PARAM_0+4*i+3]=r300PackFloat32(rmesa->state.pixel_shader.param[i].w); + } + rmesa->hw.fpp.cmd[R300_FPP_CMD_0]=cmducs(R300_PFS_PARAM_0_X, rmesa->state.pixel_shader.param_length); + +} + /** * Called by Mesa after an internal state update. */ @@ -93,51 +1962,144 @@ static void r300InvalidateState(GLcontext * ctx, GLuint new_state) r300ResetHwState(r300); } - +/* Checks that r300ResetHwState actually modifies all states. + Should probably be burried in somewhere else as this file is getting longish. */ +void verify_r300ResetHwState(r300ContextPtr r300, int stage) +{ + struct r300_state_atom* atom; + int i; + drm_r300_cmd_header_t cmd; + + if(stage){ /* mess around with states */ + unsigned long fp1, cb1; + + fp1=r300->hw.fp.cmd[R300_FP_CMD_1]; /* some special cases... */ + cb1=r300->hw.cb.cmd[R300_CB_CMD_1]; + + fprintf(stderr, "verify begin:\n"); + + foreach(atom, &r300->hw.atomlist) { + for(i=1; i < (*atom->check)(r300, atom); i++) + atom->cmd[i]=0xdeadbeef; + } + r300->hw.fp.cmd[R300_FP_CMD_1]=fp1; + r300->hw.cb.cmd[R300_CB_CMD_1]=cb1; + + foreach(atom, &r300->hw.atomlist) { + cmd.u=atom->cmd[0]; + switch(cmd.header.cmd_type){ + case R300_CMD_UNCHECKED_STATE: + case R300_CMD_VPU: + case R300_CMD_PACKET3: + case R300_CMD_END3D: + case R300_CMD_CP_DELAY: + case R300_CMD_DMA_DISCARD: + break; + default: fprintf(stderr, "unknown cmd_type %d in atom %s\n", + cmd.header.cmd_type, atom->name); + } + + } + } else { /* check that they were set */ + foreach(atom, &r300->hw.atomlist) { + for(i=1; i < (*atom->check)(r300, atom); i++) + if(atom->cmd[i]==0xdeadbeef) + fprintf(stderr, "atom %s is untouched\n", atom->name); + } + } +} + /** * Completely recalculates hardware state based on the Mesa state. */ void r300ResetHwState(r300ContextPtr r300) { + GLcontext* ctx = r300->radeon.glCtx; int i; if (RADEON_DEBUG & DEBUG_STATE) fprintf(stderr, "%s\n", __FUNCTION__); - { - __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable; - GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0; - GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0; - const GLfloat *v = r300->radeon.glCtx->Viewport._WindowMap.m; - - r300->hw.vpt.cmd[R300_VPT_XSCALE] = - r300PackFloat32(v[MAT_SX]); - r300->hw.vpt.cmd[R300_VPT_XOFFSET] = - r300PackFloat32(v[MAT_TX] + xoffset); - r300->hw.vpt.cmd[R300_VPT_YSCALE] = - r300PackFloat32(-v[MAT_SY]); - r300->hw.vpt.cmd[R300_VPT_YOFFSET] = - r300PackFloat32(-v[MAT_TY] + yoffset); - r300->hw.vpt.cmd[R300_VPT_YSCALE] = - r300PackFloat32(v[MAT_SZ]); - r300->hw.vpt.cmd[R300_VPT_YOFFSET] = - r300PackFloat32(v[MAT_TZ]); - } - -//BEGIN: TODO + //verify_r300ResetHwState(r300, 1); + + /* This is a place to initialize registers which + have bitfields accessed by different functions + and not all bits are used */ +#if 0 + /* initialize similiar to r200 */ + r300->hw.zs.cmd[R300_ZS_CNTL_0] = 0; + r300->hw.zs.cmd[R300_ZS_CNTL_1] = + (R300_ZS_ALWAYS << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT) | + (R300_ZS_ALWAYS << R300_RB3D_ZS1_BACK_FUNC_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT) | + (R300_ZS_KEEP << R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT); + r300->hw.zs.cmd[R300_ZS_CNTL_2] = 0x00ffff00; +#endif + + /* go and compute register values from GL state */ + + r300UpdateWindow(ctx); + + r300ColorMask(ctx, + ctx->Color.ColorMask[RCOMP], + ctx->Color.ColorMask[GCOMP], + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP]); + + r300Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test); + r300DepthMask(ctx, ctx->Depth.Mask); + r300DepthFunc(ctx, ctx->Depth.Func); + + /* stencil */ + r300Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); + r300StencilMask(ctx, ctx->Stencil.WriteMask[0]); + r300StencilFunc(ctx, ctx->Stencil.Function[0], ctx->Stencil.Ref[0], ctx->Stencil.ValueMask[0]); + r300StencilOp(ctx, ctx->Stencil.FailFunc[0], ctx->Stencil.ZFailFunc[0], ctx->Stencil.ZPassFunc[0]); + + r300UpdateCulling(ctx); + + r300UpdateTextureState(ctx); + +// r300_setup_routing(ctx, GL_TRUE); + r300EmitArrays(ctx, GL_TRUE); /* Just do the routing */ + r300_setup_textures(ctx); + r300_setup_rs_unit(ctx); + + r300SetupVertexShader(r300); + r300SetupPixelShader(r300); + + r300_set_blend_state(ctx); + + r300AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef); + r300Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled); + + /* Initialize magic registers + TODO : learn what they really do, or get rid of + those we don't have to touch */ r300->hw.unk2080.cmd[1] = 0x0030045A; - r300->hw.ovf.cmd[R300_OVF_FMT_0] = 0x00000003; - r300->hw.ovf.cmd[R300_OVF_FMT_1] = 0x00000000; - - r300->hw.unk20B0.cmd[1] = 0x0000040A; - r300->hw.unk20B0.cmd[2] = 0x00000008; + r300->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA + | R300_VPORT_X_OFFSET_ENA + | R300_VPORT_Y_SCALE_ENA + | R300_VPORT_Y_OFFSET_ENA + | R300_VPORT_Z_SCALE_ENA + | R300_VPORT_Z_OFFSET_ENA + | R300_VTX_W0_FMT; + r300->hw.vte.cmd[2] = 0x00000008; r300->hw.unk2134.cmd[1] = 0x00FFFFFF; r300->hw.unk2134.cmd[2] = 0x00000000; - +#ifdef MESA_BIG_ENDIAN + r300->hw.unk2140.cmd[1] = 0x00000002; +#else r300->hw.unk2140.cmd[1] = 0x00000000; +#endif +#if 0 /* Done in setup routing */ ((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->unchecked_state.count = 1; r300->hw.vir[0].cmd[1] = 0x21030003; @@ -146,6 +2108,7 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.vic.cmd[R300_VIR_CNTL_0] = 0x00000001; r300->hw.vic.cmd[R300_VIR_CNTL_1] = 0x00000405; +#endif r300->hw.unk21DC.cmd[1] = 0xAAAAAAAA; @@ -161,22 +2124,39 @@ void r300ResetHwState(r300ContextPtr r300) else r300->hw.unk2288.cmd[1] = R300_2288_RV350; +#if 0 + r300->hw.vof.cmd[R300_VOF_CNTL_0] = R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT + | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT; + r300->hw.vof.cmd[R300_VOF_CNTL_1] = 0; /* no textures */ + + r300->hw.pvs.cmd[R300_PVS_CNTL_1] = 0; r300->hw.pvs.cmd[R300_PVS_CNTL_2] = 0; r300->hw.pvs.cmd[R300_PVS_CNTL_3] = 0; +#endif - r300->hw.unk4008.cmd[1] = 0x00000007; + r300->hw.gb_enable.cmd[1] = R300_GB_POINT_STUFF_ENABLE + | R300_GB_LINE_STUFF_ENABLE + | R300_GB_TRIANGLE_STUFF_ENABLE; - r300->hw.unk4010.cmd[1] = 0x66666666; - r300->hw.unk4010.cmd[2] = 0x06666666; + r300->hw.gb_misc.cmd[R300_GB_MISC_MSPOS_0] = 0x66666666; + r300->hw.gb_misc.cmd[R300_GB_MISC_MSPOS_1] = 0x06666666; if (GET_CHIP(r300->radeon.radeonScreen) == RADEON_CHIP_R300) - r300->hw.unk4010.cmd[3] = 0x00000017; + r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE + | R300_GB_TILE_PIPE_COUNT_R300 + | R300_GB_TILE_SIZE_16; + else if (GET_CHIP(r300->radeon.radeonScreen) == RADEON_CHIP_R420) + r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE + | R300_GB_TILE_PIPE_COUNT_R420 + | R300_GB_TILE_SIZE_16; else - r300->hw.unk4010.cmd[3] = 0x00000011; - r300->hw.unk4010.cmd[4] = 0x00000000; - r300->hw.unk4010.cmd[5] = 0x00000000; + r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE + | R300_GB_TILE_PIPE_COUNT_RV300 + | R300_GB_TILE_SIZE_16; + r300->hw.gb_misc.cmd[R300_GB_MISC_SELECT] = 0x00000000; + r300->hw.gb_misc.cmd[R300_GB_MISC_AA_CONFIG] = 0x00000000; /* No antialiasing */ - r300->hw.txe.cmd[R300_TXE_ENABLE] = 0; + //r300->hw.txe.cmd[R300_TXE_ENABLE] = 0; r300->hw.unk4200.cmd[1] = r300PackFloat32(0.0); r300->hw.unk4200.cmd[2] = r300PackFloat32(0.0); @@ -185,13 +2165,22 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.unk4214.cmd[1] = 0x00050005; + r300PointSize(ctx, 0.0); +#if 0 r300->hw.ps.cmd[R300_PS_POINTSIZE] = (6 << R300_POINTSIZE_X_SHIFT) | (6 << R300_POINTSIZE_Y_SHIFT); +#endif r300->hw.unk4230.cmd[1] = 0x01800000; r300->hw.unk4230.cmd[2] = 0x00020006; r300->hw.unk4230.cmd[3] = r300PackFloat32(1.0 / 192.0); + r300LineWidth(ctx, 0.0); + +#ifdef EXP_C + static int foobar=0; + r300->hw.lsf.cmd[1] = foobar++; //0x3a088889; +#endif r300->hw.unk4260.cmd[1] = 0; r300->hw.unk4260.cmd[2] = r300PackFloat32(0.0); r300->hw.unk4260.cmd[3] = r300PackFloat32(1.0); @@ -201,7 +2190,8 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.unk4274.cmd[3] = 0x00000000; r300->hw.unk4274.cmd[4] = 0x00000000; - r300->hw.unk4288.cmd[1] = 0x00000000; + r300PolygonMode(ctx, GL_FRONT, ctx->Polygon.FrontMode); + r300PolygonMode(ctx, GL_BACK, ctx->Polygon.BackMode); r300->hw.unk4288.cmd[2] = 0x00000001; r300->hw.unk4288.cmd[3] = 0x00000000; r300->hw.unk4288.cmd[4] = 0x00000000; @@ -209,27 +2199,21 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.unk42A0.cmd[1] = 0x00000000; - r300->hw.unk42B4.cmd[1] = 0x00000000; - r300->hw.unk42B4.cmd[2] = 0x00000000; - + r300PolygonOffset(ctx, ctx->Polygon.OffsetFactor, ctx->Polygon.OffsetUnits); + r300Enable(ctx, GL_POLYGON_OFFSET_POINT, ctx->Polygon.OffsetPoint); + r300Enable(ctx, GL_POLYGON_OFFSET_LINE, ctx->Polygon.OffsetLine); + r300Enable(ctx, GL_POLYGON_OFFSET_FILL, ctx->Polygon.OffsetFill); + r300->hw.unk42C0.cmd[1] = 0x4B7FFFFF; r300->hw.unk42C0.cmd[2] = 0x00000000; - r300->hw.rc.cmd[1] = R300_RS_CNTL_0_UNKNOWN_7; - r300->hw.rc.cmd[2] = 0; - - for(i = 1; i <= 8; ++i) - r300->hw.ri.cmd[i] = 0; - - ((drm_r300_cmd_header_t*)r300->hw.rr.cmd)->unchecked_state.count = 1; - for(i = 1; i <= 8; ++i) - r300->hw.rr.cmd[1] = 0; r300->hw.unk43A4.cmd[1] = 0x0000001C; r300->hw.unk43A4.cmd[2] = 0x2DA49525; r300->hw.unk43E8.cmd[1] = 0x00FFFFFF; +#if 0 r300->hw.fp.cmd[R300_FP_CNTL0] = 0; r300->hw.fp.cmd[R300_FP_CNTL1] = 0; r300->hw.fp.cmd[R300_FP_CNTL2] = 0; @@ -237,6 +2221,7 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.fp.cmd[R300_FP_NODE1] = 0; r300->hw.fp.cmd[R300_FP_NODE2] = 0; r300->hw.fp.cmd[R300_FP_NODE3] = 0; +#endif r300->hw.unk46A4.cmd[1] = 0x00001B01; r300->hw.unk46A4.cmd[2] = 0x00001B0F; @@ -244,6 +2229,7 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.unk46A4.cmd[4] = 0x00001B0F; r300->hw.unk46A4.cmd[5] = 0x00000001; +#if 0 for(i = 1; i <= 64; ++i) { /* create NOP instructions */ r300->hw.fpi[0].cmd[i] = FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO)); @@ -251,6 +2237,7 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.fpi[2].cmd[i] = FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO)); r300->hw.fpi[3].cmd[i] = FP_SELA(0,W,NO,FP_TMP(0),0,0); } +#endif r300->hw.unk4BC0.cmd[1] = 0; @@ -258,27 +2245,37 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.unk4BC8.cmd[2] = 0; r300->hw.unk4BC8.cmd[3] = 0; - r300->hw.at.cmd[R300_AT_ALPHA_TEST] = 0; + r300->hw.at.cmd[R300_AT_UNKNOWN] = 0; r300->hw.unk4BD8.cmd[1] = 0; r300->hw.unk4E00.cmd[1] = 0; +#if 0 r300->hw.bld.cmd[R300_BLD_CBLEND] = 0; r300->hw.bld.cmd[R300_BLD_ABLEND] = 0; +#endif - r300->hw.cmk.cmd[R300_CMK_COLORMASK] = 0xF; - - r300->hw.unk4E10.cmd[1] = 0; + r300BlendColor(ctx, ctx->Color.BlendColor); r300->hw.unk4E10.cmd[2] = 0; r300->hw.unk4E10.cmd[3] = 0; - - r300->hw.cb.cmd[R300_CB_OFFSET] = - r300->radeon.radeonScreen->backOffset + - r300->radeon.radeonScreen->fbLocation; - r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.radeonScreen->backPitch - | R300_COLOR_UNKNOWN_22_23; - + + /* Again, r300ClearBuffer uses this */ + if(ctx->Visual.doubleBufferMode){ + r300->hw.cb.cmd[R300_CB_OFFSET] = + r300->radeon.radeonScreen->backOffset + + r300->radeon.radeonScreen->fbLocation; + r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.radeonScreen->backPitch + | R300_COLOR_UNKNOWN_22_23; + } else { + r300->hw.cb.cmd[R300_CB_OFFSET] = + r300->radeon.radeonScreen->frontOffset + + r300->radeon.radeonScreen->fbLocation; + r300->hw.cb.cmd[R300_CB_PITCH] = r300->radeon.radeonScreen->frontPitch + | R300_COLOR_UNKNOWN_22_23; + + } + r300->hw.unk4E50.cmd[1] = 0; r300->hw.unk4E50.cmd[2] = 0; r300->hw.unk4E50.cmd[3] = 0; @@ -291,16 +2288,17 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.unk4E88.cmd[1] = 0; - r300->hw.zc.cmd[R300_ZC_CNTL_0] = 0; - r300->hw.zc.cmd[R300_ZC_CNTL_1] = 0; - - r300->hw.unk4F08.cmd[1] = 0x00FFFF00; + r300->hw.unk4EA0.cmd[1] = 0x00000000; + r300->hw.unk4EA0.cmd[2] = 0xffffffff; r300->hw.unk4F10.cmd[1] = 0x00000002; // depthbuffer format? r300->hw.unk4F10.cmd[2] = 0x00000000; r300->hw.unk4F10.cmd[3] = 0x00000003; r300->hw.unk4F10.cmd[4] = 0x00000000; + /* experiment a bit */ + r300->hw.unk4F10.cmd[2] = 0x00000001; // depthbuffer format? + r300->hw.zb.cmd[R300_ZB_OFFSET] = r300->radeon.radeonScreen->depthOffset + r300->radeon.radeonScreen->fbLocation; @@ -315,6 +2313,7 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.unk4F54.cmd[1] = 0; +#if 0 ((drm_r300_cmd_header_t*)r300->hw.vpi.cmd)->vpu.count = 0; for(i = 1; i < R300_VPI_CMDSIZE; i += 4) { /* MOV t0, t0 */ @@ -327,13 +2326,15 @@ void r300ResetHwState(r300ContextPtr r300) ((drm_r300_cmd_header_t*)r300->hw.vpp.cmd)->vpu.count = 0; for(i = 1; i < R300_VPP_CMDSIZE; ++i) r300->hw.vpp.cmd[i] = 0; +#endif r300->hw.vps.cmd[R300_VPS_ZERO_0] = 0; r300->hw.vps.cmd[R300_VPS_ZERO_1] = 0; r300->hw.vps.cmd[R300_VPS_POINTSIZE] = r300PackFloat32(1.0); r300->hw.vps.cmd[R300_VPS_ZERO_3] = 0; -//END: TODO +//END: TODO + //verify_r300ResetHwState(r300, 0); r300->hw.all_dirty = GL_TRUE; } @@ -346,8 +2347,34 @@ void r300ResetHwState(r300ContextPtr r300) */ void r300InitState(r300ContextPtr r300) { + GLcontext *ctx = r300->radeon.glCtx; + GLuint depth_fmt; + radeonInitState(&r300->radeon); + switch (ctx->Visual.depthBits) { + case 16: + r300->state.depth.scale = 1.0 / (GLfloat) 0xffff; + depth_fmt = R200_DEPTH_FORMAT_16BIT_INT_Z; + r300->state.stencil.clear = 0x00000000; + break; + case 24: + r300->state.depth.scale = 1.0 / (GLfloat) 0xffffff; + depth_fmt = R200_DEPTH_FORMAT_24BIT_INT_Z; + r300->state.stencil.clear = 0x00ff0000; + break; + default: + fprintf(stderr, "Error: Unsupported depth %d... exiting\n", + ctx->Visual.depthBits); + exit(-1); + } + + /* Only have hw stencil when depth buffer is 24 bits deep */ + r300->state.stencil.hw_stencil = (ctx->Visual.stencilBits > 0 && + ctx->Visual.depthBits == 24); + + memset(&(r300->state.texture), 0, sizeof(r300->state.texture)); + r300ResetHwState(r300); } @@ -360,6 +2387,29 @@ void r300InitStateFuncs(struct dd_function_table* functions) radeonInitStateFuncs(functions); functions->UpdateState = r300InvalidateState; - functions->Enable= r300Enable; + functions->AlphaFunc = r300AlphaFunc; + functions->BlendColor = r300BlendColor; + functions->BlendEquationSeparate = r300BlendEquationSeparate; + functions->BlendFuncSeparate = r300BlendFuncSeparate; + functions->Enable = r300Enable; + functions->ColorMask = r300ColorMask; + functions->DepthFunc = r300DepthFunc; + functions->DepthMask = r300DepthMask; + functions->CullFace = r300CullFace; + functions->FrontFace = r300FrontFace; + + /* Stencil related */ + functions->ClearStencil = r300ClearStencil; + functions->StencilFunc = r300StencilFunc; + functions->StencilMask = r300StencilMask; + functions->StencilOp = r300StencilOp; + + /* Viewport related */ + functions->Viewport = r300Viewport; + functions->DepthRange = r300DepthRange; + functions->PointSize = r300PointSize; + functions->LineWidth = r300LineWidth; + + functions->PolygonOffset = r300PolygonOffset; + functions->PolygonMode = r300PolygonMode; } -