insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.mtl[i] );
for (i = 0; i < 6; ++i)
insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ucp[i] );
- /* FIXME: is this a good place to insert that atom ? */
insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.spr );
+ insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ptp );
insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.prf );
insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.pvs );
insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vpp[0] );
#define need_GL_EXT_blend_equation_separate
#define need_GL_EXT_blend_func_separate
#define need_GL_NV_vertex_program
+#define need_GL_ARB_point_parameters
#include "extension_helper.h"
#define DRIVER_DATE "20060602"
{ "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions },
{ NULL, NULL }
};
-
+
const struct dri_extension ARB_vp_extension[] = {
{ "GL_ARB_vertex_program", GL_ARB_vertex_program_functions }
};
{ "GL_ATI_fragment_shader", GL_ATI_fragment_shader_functions }
};
+const struct dri_extension point_extensions[] = {
+ { "GL_ARB_point_sprite", NULL },
+ { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions },
+ { NULL, NULL }
+};
+
extern const struct tnl_pipeline_stage _r200_render_stage;
extern const struct tnl_pipeline_stage _r200_tcl_stage;
&_tnl_fog_coordinate_stage,
&_tnl_texgen_stage,
&_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
&_tnl_arb_vertex_program_stage,
&_tnl_vertex_program_stage,
-
/* Try again to go to tcl?
* - no good for asymmetric-twoside (do with multipass)
* - no good for asymmetric-unfilled (do with multipass)
if ((ctx->Const.MaxTextureUnits == 6) && rmesa->r200Screen->drmSupportsFragShader)
driInitSingleExtension( ctx, ATI_fs_extension );
+ if (rmesa->r200Screen->drmSupportsPointSprites)
+ driInitExtensions( ctx, point_extensions, GL_FALSE );
#if 0
r200InitDriverFuncs( ctx );
r200InitIoctlFuncs( ctx );
/* SPR - point sprite state
*/
-#define SPR_CMD_0 0
-#define SPR_POINT_SPRITE_CNTL 1
-#define SPR_STATE_SIZE 2
+#define SPR_CMD_0 0
+#define SPR_POINT_SPRITE_CNTL 1
+#define SPR_STATE_SIZE 2
+
+#define PTP_CMD_0 0
+#define PTP_VPORT_SCALE_0 1
+#define PTP_VPORT_SCALE_1 2
+#define PTP_VPORT_SCALE_PTSIZE 3
+#define PTP_VPORT_SCALE_3 4
+#define PTP_CMD_1 5
+#define PTP_ATT_CONST_QUAD 6
+#define PTP_ATT_CONST_LIN 7
+#define PTP_ATT_CONST_CON 8
+#define PTP_ATT_CONST_3 9
+#define PTP_EYE_X 10
+#define PTP_EYE_Y 11
+#define PTP_EYE_Z 12
+#define PTP_EYE_3 13
+#define PTP_CLAMP_MIN 14
+#define PTP_CLAMP_MAX 15
+#define PTP_CLAMP_2 16
+#define PTP_CLAMP_3 17
+#define PTP_STATE_SIZE 18
#define VTX_COLOR(v,n) (((v)>>(R200_VTX_COLOR_0_SHIFT+(n)*2))&\
R200_VTX_COLOR_MASK)
struct r200_state_atom vpp[2];
struct r200_state_atom atf;
struct r200_state_atom spr;
+ struct r200_state_atom ptp;
int max_state_size; /* Number of bytes necessary for a full state emit. */
GLboolean is_dirty, all_dirty;
#define R200_ZBIAS_ENABLE_LINE (1 << 17)
#define R200_ZBIAS_ENABLE_TRI (1 << 18)
#define R200_WIDELINE_ENABLE (1 << 20)
+#define R200_DISC_FOG_SHADE_SOLID (0 << 24)
+#define R200_DISC_FOG_SHADE_FLAT (1 << 24)
+#define R200_DISC_FOG_SHADE_GOURAUD (2 << 24)
+#define R200_DISC_FOG_SHADE_MASK (3 << 24)
#define R200_VTX_PIX_CENTER_D3D (0 << 27)
#define R200_VTX_PIX_CENTER_OGL (1 << 27)
#define R200_ROUND_MODE_TRUNC (0 << 28)
#define R200_CULL_FRONT (1<<29)
#define R200_CULL_BACK (1<<30)
#define R200_SE_TCL_POINT_SPRITE_CNTL 0x22c4
-#define R200_POINTSIZE_SEL_STATE (1<<16)
+#define R200_PS_MULT_PVATTENCONST (0<<0)
+#define R200_PS_MULT_PVATTEN (1<<0)
+#define R200_PS_MULT_ATTENCONST (2<<0)
+#define R200_PS_MULT_PVCONST (3<<0)
+#define R200_PS_MULT_CONST (4<<0)
+#define R200_PS_MULT_MASK (7<<0)
+#define R200_PS_LIN_ATT_ZERO (1<<3)
+#define R200_PS_USE_MODEL_EYE_VEC (1<<4)
+#define R200_PS_ATT_ALPHA (1<<5)
+#define R200_PS_UCP_MODE_MASK (3<<6)
+#define R200_PS_GEN_TEX_0 (1<<8)
+#define R200_PS_GEN_TEX_1 (1<<9)
+#define R200_PS_GEN_TEX_2 (1<<10)
+#define R200_PS_GEN_TEX_3 (1<<11)
+#define R200_PS_GEN_TEX_4 (1<<12)
+#define R200_PS_GEN_TEX_5 (1<<13)
+#define R200_PS_GEN_TEX_0_SHIFT (8)
+#define R200_PS_GEN_TEX_MASK (0x3f<<8)
+#define R200_PS_SE_SEL_STATE (1<<16)
/* gap */
/* taken from r300, see comments there */
#define R200_VAP_PVS_CNTL_1 0x22d0
static void r200PointSize( GLcontext *ctx, GLfloat size )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
+ GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
R200_STATECHANGE( rmesa, cst );
+ R200_STATECHANGE( rmesa, ptp );
rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff;
rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0));
+/* this is the size param of the point size calculation (point size reg value
+ is not used when calculation is active). */
+ fcmd[PTP_VPORT_SCALE_PTSIZE] = ctx->Point.Size;
+}
+
+static void r200PointParameter( GLcontext *ctx, GLenum pname, const GLfloat *params)
+{
+ r200ContextPtr rmesa = R200_CONTEXT(ctx);
+ GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
+
+ switch (pname) {
+ case GL_POINT_SIZE_MIN:
+ /* Can clamp both in tcl and setup - just set both (as does fglrx) */
+ R200_STATECHANGE( rmesa, lin );
+ R200_STATECHANGE( rmesa, ptp );
+ rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= 0xffff;
+ rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Point.MinSize * 16.0) << 16;
+ fcmd[PTP_CLAMP_MIN] = ctx->Point.MinSize;
+ break;
+ case GL_POINT_SIZE_MAX:
+ R200_STATECHANGE( rmesa, cst );
+ R200_STATECHANGE( rmesa, ptp );
+ rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= 0xffff;
+ rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= (GLuint)(ctx->Point.MaxSize * 16.0) << 16;
+ fcmd[PTP_CLAMP_MAX] = ctx->Point.MaxSize;
+ break;
+ case GL_POINT_DISTANCE_ATTENUATION:
+ R200_STATECHANGE( rmesa, vtx );
+ R200_STATECHANGE( rmesa, spr );
+ R200_STATECHANGE( rmesa, ptp );
+ GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
+ rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &=
+ ~(R200_PS_MULT_MASK | R200_PS_LIN_ATT_ZERO | R200_PS_SE_SEL_STATE);
+ /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
+ r200ValidateState looks like overkill */
+ if (ctx->Point.Params[0] != 1.0 ||
+ ctx->Point.Params[1] != 0.0 ||
+ ctx->Point.Params[2] != 0.0 ||
+ (ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled)) {
+ /* all we care for vp would be the ps_se_sel_state setting */
+ fcmd[PTP_ATT_CONST_QUAD] = ctx->Point.Params[2];
+ fcmd[PTP_ATT_CONST_LIN] = ctx->Point.Params[1];
+ fcmd[PTP_ATT_CONST_CON] = ctx->Point.Params[0];
+ rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_MULT_ATTENCONST;
+ if (ctx->Point.Params[1] == 0.0)
+ rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_LIN_ATT_ZERO;
+/* FIXME: setting this here doesn't look quite ok - we only want to do
+ that if we're actually drawing points probably */
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_PT_SIZE;
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= R200_VTX_POINT_SIZE;
+ }
+ else {
+ rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
+ R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST;
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_PT_SIZE;
+ rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~R200_VTX_POINT_SIZE;
+ }
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE:
+ /* don't support multisampling, so doesn't matter. */
+ break;
+ /* can't do these but don't need them.
+ case GL_POINT_SPRITE_R_MODE_NV:
+ case GL_POINT_SPRITE_COORD_ORIGIN: */
+ default:
+ fprintf(stderr, "bad pname parameter in r200PointParameter\n");
+ return;
+ }
}
/* =============================================================
s &= ~(R200_DIFFUSE_SHADE_MASK |
R200_ALPHA_SHADE_MASK |
R200_SPECULAR_SHADE_MASK |
- R200_FOG_SHADE_MASK);
+ R200_FOG_SHADE_MASK |
+ R200_DISC_FOG_SHADE_MASK);
switch ( mode ) {
case GL_FLAT:
s |= (R200_DIFFUSE_SHADE_FLAT |
R200_ALPHA_SHADE_FLAT |
R200_SPECULAR_SHADE_FLAT |
- R200_FOG_SHADE_FLAT);
+ R200_FOG_SHADE_FLAT |
+ R200_DISC_FOG_SHADE_FLAT);
break;
case GL_SMOOTH:
s |= (R200_DIFFUSE_SHADE_GOURAUD |
R200_ALPHA_SHADE_GOURAUD |
R200_SPECULAR_SHADE_GOURAUD |
- R200_FOG_SHADE_GOURAUD);
+ R200_FOG_SHADE_GOURAUD |
+ R200_DISC_FOG_SHADE_GOURAUD);
break;
default:
return;
break;
#endif
+ case GL_POINT_SPRITE_ARB:
+ R200_STATECHANGE( rmesa, spr );
+ if ( state ) {
+ int i;
+ for (i = 0; i < 6; i++) {
+ rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
+ ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i);
+ }
+ } else {
+ rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
+ }
+ break;
+
case GL_POLYGON_OFFSET_FILL:
R200_STATECHANGE( rmesa, set );
if ( state ) {
else {
/* picked up later */
}
+ r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
+ break;
+
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
break;
case GL_FRAGMENT_SHADER_ATI:
functions->PolygonMode = r200PolygonMode;
functions->PolygonOffset = r200PolygonOffset;
functions->PolygonStipple = r200PolygonStipple;
+ functions->PointParameterfv = r200PointParameter;
functions->PointSize = r200PointSize;
functions->RenderMode = r200RenderMode;
functions->Scissor = r200Scissor;
else {
ALLOC_STATE( prf, never, PRF_STATE_SIZE, "PRF/performance-tri", 0 );
}
- if (rmesa->r200Screen->drmSupportsPointSprites)
+ if (rmesa->r200Screen->drmSupportsPointSprites) {
ALLOC_STATE( spr, always, SPR_STATE_SIZE, "SPR/pointsprite", 0 );
- else
+ ALLOC_STATE( ptp, tcl, PTP_STATE_SIZE, "PTP/pointparams", 0 );
+ }
+ else {
ALLOC_STATE (spr, never, SPR_STATE_SIZE, "SPR/pointsprite", 0 );
+ ALLOC_STATE (ptp, never, PTP_STATE_SIZE, "PTP/pointparams", 0 );
+ }
r200SetUpAtomList( rmesa );
cmdvec( R200_VS_UCP_ADDR + i, 1, 4 );
}
+ rmesa->hw.ptp.cmd[PTP_CMD_0] =
+ cmdvec( R200_VS_PNT_SPRITE_VPORT_SCALE, 1, 4 );
+ rmesa->hw.ptp.cmd[PTP_CMD_1] =
+ cmdvec( R200_VS_PNT_SPRITE_ATT_CONST, 1, 12 );
+
/* Initial Harware state:
*/
rmesa->hw.ctx.cmd[CTX_PP_MISC] = (R200_ALPHA_TEST_PASS
R200_ALPHA_SHADE_GOURAUD |
R200_SPECULAR_SHADE_GOURAUD |
R200_FOG_SHADE_GOURAUD |
+ R200_DISC_FOG_SHADE_GOURAUD |
R200_VTX_PIX_CENTER_OGL |
R200_ROUND_MODE_TRUNC |
R200_ROUND_PREC_8TH_PIX);
rmesa->hw.eye.cmd[EYE_Z] = IEEE_ONE;
rmesa->hw.eye.cmd[EYE_RESCALE_FACTOR] = IEEE_ONE;
- rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] = R200_POINTSIZE_SEL_STATE;
+ rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] =
+ R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST;
+
+ /* ptp_eye is presumably used to calculate the attenuation wrt a different
+ location? In any case, since point attenuation triggers _needeyecoords,
+ it is constant. Probably ignored as long as R200_PS_USE_MODEL_EYE_VEC
+ isn't set */
+ rmesa->hw.ptp.cmd[PTP_EYE_X] = 0;
+ rmesa->hw.ptp.cmd[PTP_EYE_Y] = 0;
+ rmesa->hw.ptp.cmd[PTP_EYE_Z] = IEEE_ONE | 0x80000000; /* -1.0 */
+ rmesa->hw.ptp.cmd[PTP_EYE_3] = 0;
+ /* no idea what the ptp_vport_scale values are good for, except the
+ PTSIZE one - hopefully doesn't matter */
+ rmesa->hw.ptp.cmd[PTP_VPORT_SCALE_0] = IEEE_ONE;
+ rmesa->hw.ptp.cmd[PTP_VPORT_SCALE_1] = IEEE_ONE;
+ rmesa->hw.ptp.cmd[PTP_VPORT_SCALE_PTSIZE] = IEEE_ONE;
+ rmesa->hw.ptp.cmd[PTP_VPORT_SCALE_3] = IEEE_ONE;
+ rmesa->hw.ptp.cmd[PTP_ATT_CONST_QUAD] = 0;
+ rmesa->hw.ptp.cmd[PTP_ATT_CONST_LIN] = 0;
+ rmesa->hw.ptp.cmd[PTP_ATT_CONST_CON] = IEEE_ONE;
+ rmesa->hw.ptp.cmd[PTP_ATT_CONST_3] = 0;
+ rmesa->hw.ptp.cmd[PTP_CLAMP_MIN] = IEEE_ONE;
+ rmesa->hw.ptp.cmd[PTP_CLAMP_MAX] = 0x44ffe000; /* 2047 */
+ rmesa->hw.ptp.cmd[PTP_CLAMP_2] = 0;
+ rmesa->hw.ptp.cmd[PTP_CLAMP_3] = 0;
r200LightingSpaceChange( ctx );
offset = 3;
}
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) {
+ EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, R200_VTX_POINT_SIZE );
+ offset += 1;
+ }
+
rmesa->swtcl.coloroffset = offset;
#if MESA_LITTLE_ENDIAN
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
{
switch (prim) {
case GL_POINTS:
- return (ctx->_TriangleCaps & DD_POINT_SIZE) ?
+ return (ctx->Point.PointSprite ||
+ ((ctx->_TriangleCaps & (DD_POINT_SIZE | DD_POINT_ATTEN)) &&
+ !(ctx->_TriangleCaps & (DD_POINT_SMOOTH)))) ?
R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS;
case GL_LINES:
/* fallthrough */
r200ContextPtr rmesa = R200_CONTEXT(ctx);
if (rmesa->swtcl.hw_primitive != hwprim) {
+ /* need to disable perspective-correct texturing for point sprites */
+ if ((hwprim & 0xf) == R200_VF_PRIM_POINT_SPRITES && ctx->Point.PointSprite) {
+ if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) {
+ R200_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE;
+ }
+ }
+ else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) {
+ R200_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE;
+ }
R200_NEWPRIM( rmesa );
rmesa->swtcl.hw_primitive = hwprim;
}
#define HAVE_ELTS 1
-#define HW_POINTS ((ctx->_TriangleCaps & DD_POINT_SIZE) ? \
+#define HW_POINTS ((ctx->Point.PointSprite || \
+ ((ctx->_TriangleCaps & (DD_POINT_SIZE | DD_POINT_ATTEN)) && \
+ !(ctx->_TriangleCaps & (DD_POINT_SMOOTH)))) ? \
R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS)
#define HW_LINES R200_VF_PRIM_LINES
#define HW_LINE_LOOP 0
if (newprim != rmesa->tcl.hw_primitive ||
!discrete_prim[hw_prim&0xf]) {
+ /* need to disable perspective-correct texturing for point sprites */
+ if ((prim & PRIM_MODE_MASK) == GL_POINTS && ctx->Point.PointSprite) {
+ if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) {
+ R200_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE;
+ }
+ }
+ else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) {
+ R200_STATECHANGE( rmesa, set );
+ rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE;
+ }
R200_NEWPRIM( rmesa );
rmesa->tcl.hw_primitive = newprim;
}
out_vtxfmt0 |= R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT;
out_compsel |= R200_OUTPUT_COLOR_1;
}
- /* FIXME: probably not everything is set up for fogc and psiz to work correctly */
+ /* FIXME: probably not everything is set up for fogc to work correctly */
if (vp_out & (1 << VERT_RESULT_FOGC)) {
out_vtxfmt0 |= R200_VTX_DISCRETE_FOG;
out_compsel |= R200_OUTPUT_DISCRETE_FOG;
t->pp_txfilter |= R200_CLAMP_T_CLAMP_LAST;
break;
case GL_CLAMP_TO_BORDER:
- t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL | R200_BORDER_MODE_D3D;
+ t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL;
is_clamp_to_border = GL_TRUE;
break;
case GL_MIRRORED_REPEAT:
}
break;
}
-
+ case GL_COORD_REPLACE_ARB:
+ if (ctx->Point.PointSprite) {
+ R200_STATECHANGE( rmesa, spr );
+ if ((GLenum)param[0]) {
+ rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_GEN_TEX_0 << unit;
+ } else {
+ rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~(R200_PS_GEN_TEX_0 << unit);
+ }
+ }
+ break;
default:
return;
}
extern const struct dri_extension ARB_vp_extension[];
extern const struct dri_extension NV_vp_extension[];
extern const struct dri_extension ATI_fs_extension[];
+extern const struct dri_extension point_extensions[];
#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R300)
driInitSingleExtension( NULL, ARB_vp_extension );
driInitSingleExtension( NULL, NV_vp_extension );
driInitSingleExtension( NULL, ATI_fs_extension );
+ driInitExtensions( NULL, point_extensions, GL_FALSE );
#endif
}