#include "enums.h"
#include "colormac.h"
#include "light.h"
-#include "buffers.h"
#include "swrast/swrast.h"
#include "array_cache/acache.h"
#include "tnl/t_pipeline.h"
#include "swrast_setup/swrast_setup.h"
-
#include "r200_context.h"
#include "r200_ioctl.h"
#include "r200_state.h"
#include "r200_swtcl.h"
#include "r200_vtxfmt.h"
+#include "drirenderbuffer.h"
+
/* =============================================================
* Alpha blending
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
break;
case GL_FOG_COORD_SRC: {
- GLuint fmt_0 = rmesa->hw.vtx.cmd[VTX_VTXFMT_0];
GLuint out_0 = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0];
GLuint fog = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR];
fog &= ~R200_FOG_USE_MASK;
if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD ) {
fog |= R200_FOG_USE_VTX_FOG;
- fmt_0 |= R200_VTX_DISCRETE_FOG;
out_0 |= R200_VTX_DISCRETE_FOG;
}
else {
fog |= R200_FOG_USE_SPEC_ALPHA;
- fmt_0 &= ~R200_VTX_DISCRETE_FOG;
out_0 &= ~R200_VTX_DISCRETE_FOG;
}
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog;
}
- if ( (fmt_0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0])
- || (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0])) {
+ if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) {
R200_STATECHANGE( rmesa, vtx );
- rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0;
}
*/
static void r200PointSize( GLcontext *ctx, GLfloat size )
{
- if (0) fprintf(stderr, "%s: %f\n", __FUNCTION__, size );
+ r200ContextPtr rmesa = R200_CONTEXT(ctx);
+
+ R200_STATECHANGE( rmesa, cst );
+ rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff;
+ rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0));
}
/* =============================================================
}
}
-
-
+static void r200UpdateLocalViewer ( GLcontext *ctx )
+{
+/* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
+ GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
+ for these and only these modes). This means specular highlights may turn out
+ wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
+ is not set, though it seems to happen rarely and the effect seems quite
+ subtle. May need TCL fallback to fix it completely, though I'm not sure
+ how you'd identify the cases where the specular highlights indeed will
+ be wrong. Don't know if fglrx does something special in that case.
+*/
+ r200ContextPtr rmesa = R200_CONTEXT(ctx);
+ R200_STATECHANGE( rmesa, tcl );
+ if (ctx->Light.Model.LocalViewer ||
+ ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
+ else
+ rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
+}
static void r200LightModelfv( GLcontext *ctx, GLenum pname,
const GLfloat *param )
break;
case GL_LIGHT_MODEL_LOCAL_VIEWER:
- R200_STATECHANGE( rmesa, tcl );
- if (ctx->Light.Model.LocalViewer)
- rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
- else
- rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
+ r200UpdateLocalViewer( ctx );
break;
case GL_LIGHT_MODEL_TWO_SIDE:
* Stencil
*/
-static void r200StencilFunc( GLcontext *ctx, GLenum func,
- GLint ref, GLuint mask )
+static void
+r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
+ GLint ref, GLuint mask )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint refmask = ((ctx->Stencil.Ref[0] << R200_STENCIL_REF_SHIFT) |
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
}
-static void r200StencilMask( GLcontext *ctx, GLuint mask )
+static void
+r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
(ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT);
}
-static void r200StencilOp( GLcontext *ctx, GLenum fail,
- GLenum zfail, GLenum zpass )
+static void
+r200StencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
+ GLenum zfail, GLenum zpass )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height )
{
- /* update size of Mesa/software ancillary buffers */
- _mesa_ResizeBuffersMESA();
/* 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.
R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
/*
- * _DrawDestMask is easier to cope with than <mode>.
+ * _ColorDrawBufferMask is easier to cope with than <mode>.
+ * Check for software fallback, update cliprects.
*/
- switch ( ctx->Color._DrawDestMask[0] ) {
- case DD_FRONT_LEFT_BIT:
+ switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
+ case BUFFER_BIT_FRONT_LEFT:
FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
r200SetCliprects( rmesa, GL_FRONT_LEFT );
break;
- case DD_BACK_LEFT_BIT:
+ case BUFFER_BIT_BACK_LEFT:
FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
r200SetCliprects( rmesa, GL_BACK_LEFT );
break;
return;
}
- /* We want to update the s/w rast state too so that r200SetBuffer()
- * gets called.
+ /* We'll set the drawing engine's offset/pitch parameters later
+ * when we update other state.
*/
- _swrast_DrawBuffer(ctx, mode);
-
- R200_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = ((rmesa->state.color.drawOffset +
- rmesa->r200Screen->fbLocation)
- & R200_COLOROFFSET_MASK);
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
- if (rmesa->sarea->tiling_enabled) {
- rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
- }
}
R200_STATECHANGE(rmesa, ctx );
if ( state ) {
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
- r200Fogfv( ctx, GL_FOG_MODE, 0 );
+ r200Fogfv( ctx, GL_FOG_MODE, NULL );
} else {
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
R200_STATECHANGE(rmesa, tcl);
}
break;
- /* Pointsize registers on r200 don't seem to do anything. Maybe
- * have to pass pointsizes as vertex parameters? In any case,
- * setting pointmin == pointsizemax == 1.0, and doing nothing
- * for aa is enough to satisfy conform.
+ /* Pointsize registers on r200 only work for point sprites, and point smooth
+ * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
+ * In any case, setting pointmin == pointsizemax == 1.0 for aa points
+ * is enough to satisfy conform.
*/
case GL_POINT_SMOOTH:
break;
break;
case GL_VERTEX_PROGRAM_ARB:
- TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_TCL_DISABLE, state);
+ TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_VERTEX_PROGRAM, state);
+ break;
+
+ case GL_FRAGMENT_SHADER_ATI:
+ if ( !state ) {
+ /* restore normal tex env colors and make sure tex env combine will get updated
+ mark env atoms dirty (as their data was overwritten by afs even
+ if they didn't change) and restore tex coord routing */
+ GLuint unit;
+ for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
+ ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
+ /* need to guard this with drmSupportsFragmentShader? Should never get here if
+ we don't announce ATI_fs, right? */
+ rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
+ R200_STATECHANGE( rmesa, pix[unit] );
+ R200_STATECHANGE( rmesa, tex[unit] );
+ }
+ rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
+ R200_STATECHANGE( rmesa, cst );
+ R200_STATECHANGE( rmesa, tf );
+ }
+ else {
+ /* need to mark this dirty as pix/tf atoms have overwritten the data
+ even if the data in the atoms didn't change */
+ R200_STATECHANGE( rmesa, atf );
+ R200_STATECHANGE( rmesa, afs[1] );
+ /* everything else picked up in r200UpdateTextureState hopefully */
+ }
break;
-
default:
return;
}
+/**
+ * Tell the card where to render (offset, pitch).
+ * Effected by glDrawBuffer, etc
+ */
+void
+r200UpdateDrawBuffer(GLcontext *ctx)
+{
+ r200ContextPtr rmesa = R200_CONTEXT(ctx);
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ driRenderbuffer *drb;
+
+ if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
+ /* draw to front */
+ drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+ }
+ else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) {
+ /* draw to back */
+ drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ }
+ else {
+ /* drawing to multiple buffers, or none */
+ return;
+ }
+
+ assert(drb);
+ assert(drb->flippedPitch);
+
+ R200_STATECHANGE( rmesa, ctx );
+
+ /* Note: we used the (possibly) page-flipped values */
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
+ = ((drb->flippedOffset + rmesa->r200Screen->fbLocation)
+ & R200_COLOROFFSET_MASK);
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
+ if (rmesa->sarea->tiling_enabled) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
+ }
+}
+
+
+
void r200ValidateState( GLcontext *ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
GLuint new_state = rmesa->NewGLState;
- if (new_state & _NEW_TEXTURE) {
+ if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
+ r200UpdateDrawBuffer(ctx);
+ }
+
+ if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) {
r200UpdateTextureState( ctx );
new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
+ r200UpdateLocalViewer( ctx );
}
/* Need an event driven matrix update?
*/
if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
update_texturematrix( ctx );
- }
+ }
if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
update_light( ctx );
functions->RenderMode = r200RenderMode;
functions->Scissor = r200Scissor;
functions->ShadeModel = r200ShadeModel;
- functions->StencilFunc = r200StencilFunc;
- functions->StencilMask = r200StencilMask;
- functions->StencilOp = r200StencilOp;
+ functions->StencilFuncSeparate = r200StencilFuncSeparate;
+ functions->StencilMaskSeparate = r200StencilMaskSeparate;
+ functions->StencilOpSeparate = r200StencilOpSeparate;
functions->Viewport = r200Viewport;
/* Swrast hooks for imaging extensions: