From 2ef8eba4841c8083de73b100c49a97674770c00e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 15 Aug 2007 10:17:48 +0000 Subject: [PATCH] - mesa-7.0.1-stable-branch.patch - Add patches from stable branch includes support for some Intel chipsets - mesa-7.0-use_master-r300.patch - Add r300 driver from master --- mesa-7.0-use_master-r300.patch | 5957 ++++++++++++++++++++++++++++++++ mesa-7.0.1-stable-branch.patch | 1447 ++++++++ mesa.spec | 11 +- 3 files changed, 7414 insertions(+), 1 deletion(-) create mode 100644 mesa-7.0-use_master-r300.patch create mode 100644 mesa-7.0.1-stable-branch.patch diff --git a/mesa-7.0-use_master-r300.patch b/mesa-7.0-use_master-r300.patch new file mode 100644 index 0000000..bf1d568 --- /dev/null +++ b/mesa-7.0-use_master-r300.patch @@ -0,0 +1,5957 @@ +diff --git a/src/mesa/drivers/dri/r300/Makefile b/src/mesa/drivers/dri/r300/Makefile +index c1d223c..4424896 100644 +--- a/src/mesa/drivers/dri/r300/Makefile ++++ b/src/mesa/drivers/dri/r300/Makefile +@@ -41,6 +41,7 @@ DRIVER_SOURCES = \ + r300_fragprog.c \ + r300_shader.c \ + r300_emit.c \ ++ r300_swtcl.c \ + $(EGL_SOURCES) + + C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES) +diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c +index d13649d..9eca41f 100644 +--- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c ++++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c +@@ -133,13 +133,15 @@ static void r300PrintStateAtom(r300ContextPtr r300, struct r300_state_atom *stat + int i; + int dwords = (*state->check) (r300, state); + +- fprintf(stderr, " emit %s/%d/%d\n", state->name, dwords, ++ fprintf(stderr, " emit %s %d/%d\n", state->name, dwords, + state->cmd_size); + +- if (RADEON_DEBUG & DEBUG_VERBOSE) +- for (i = 0; i < dwords; i++) +- fprintf(stderr, " %s[%d]: %08X\n", ++ if (RADEON_DEBUG & DEBUG_VERBOSE) { ++ for (i = 0; i < dwords; i++) { ++ fprintf(stderr, " %s[%d]: %08x\n", + state->name, i, state->cmd[i]); ++ } ++ } + } + + /** +@@ -148,28 +150,14 @@ static void r300PrintStateAtom(r300ContextPtr r300, struct r300_state_atom *stat + * The caller must have ensured that there is enough space in the command + * buffer. + */ +-static __inline__ void r300EmitAtoms(r300ContextPtr r300, GLboolean dirty) ++static inline void r300EmitAtoms(r300ContextPtr r300, GLboolean dirty) + { + struct r300_state_atom *atom; + uint32_t *dest; ++ int dwords; + + dest = r300->cmdbuf.cmd_buf + r300->cmdbuf.count_used; + +- if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) { +- foreach(atom, &r300->hw.atomlist) { +- if ((atom->dirty || r300->hw.all_dirty) == dirty) { +- int dwords = (*atom->check) (r300, atom); +- +- if (dwords) +- r300PrintStateAtom(r300, atom); +- else +- fprintf(stderr, +- " skip state %s\n", +- atom->name); +- } +- } +- } +- + /* Emit WAIT */ + *dest = cmdwait(R300_WAIT_3D | R300_WAIT_3D_CLEAN); + dest++; +@@ -193,13 +181,20 @@ static __inline__ void r300EmitAtoms(r300ContextPtr r300, GLboolean dirty) + + foreach(atom, &r300->hw.atomlist) { + if ((atom->dirty || r300->hw.all_dirty) == dirty) { +- int dwords = (*atom->check) (r300, atom); +- ++ dwords = (*atom->check) (r300, atom); + if (dwords) { ++ if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) { ++ r300PrintStateAtom(r300, atom); ++ } + memcpy(dest, atom->cmd, dwords * 4); + dest += dwords; + r300->cmdbuf.count_used += dwords; + atom->dirty = GL_FALSE; ++ } else { ++ if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) { ++ fprintf(stderr, " skip state %s\n", ++ atom->name); ++ } + } + } + } +@@ -245,22 +240,28 @@ void r300EmitState(r300ContextPtr r300) + r300->hw.all_dirty = GL_FALSE; + } + +-#define CHECK( NM, COUNT ) \ +-static int check_##NM( r300ContextPtr r300, \ +- struct r300_state_atom* atom ) \ +-{ \ +- (void) atom; (void) r300; \ +- return (COUNT); \ +-} +- + #define packet0_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->packet0.count) + #define vpu_count(ptr) (((drm_r300_cmd_header_t*)(ptr))->vpu.count) + +-CHECK(always, atom->cmd_size) +- CHECK(variable, packet0_count(atom->cmd) ? (1 + packet0_count(atom->cmd)) : 0) +- CHECK(vpu, vpu_count(atom->cmd) ? (1 + vpu_count(atom->cmd) * 4) : 0) +-#undef packet0_count +-#undef vpu_count ++static int check_always(r300ContextPtr r300, struct r300_state_atom *atom) ++{ ++ return atom->cmd_size; ++} ++ ++static int check_variable(r300ContextPtr r300, struct r300_state_atom *atom) ++{ ++ int cnt; ++ cnt = packet0_count(atom->cmd); ++ return cnt ? cnt + 1 : 0; ++} ++ ++static int check_vpu(r300ContextPtr r300, struct r300_state_atom *atom) ++{ ++ int cnt; ++ cnt = vpu_count(atom->cmd); ++ return cnt ? (cnt * 4) + 1 : 0; ++} ++ + #define ALLOC_STATE( ATOM, CHK, SZ, IDX ) \ + do { \ + r300->hw.ATOM.cmd_size = (SZ); \ +@@ -318,10 +319,14 @@ void r300InitCmdBuf(r300ContextPtr r300) + r300->hw.unk21DC.cmd[0] = cmdpacket0(0x21DC, 1); + ALLOC_STATE(unk221C, always, 2, 0); + r300->hw.unk221C.cmd[0] = cmdpacket0(R300_VAP_UNKNOWN_221C, 1); +- ALLOC_STATE(unk2220, always, 5, 0); +- r300->hw.unk2220.cmd[0] = cmdpacket0(0x2220, 4); +- ALLOC_STATE(unk2288, always, 2, 0); +- r300->hw.unk2288.cmd[0] = cmdpacket0(R300_VAP_UNKNOWN_2288, 1); ++ ALLOC_STATE(vap_clip, always, 5, 0); ++ r300->hw.vap_clip.cmd[0] = cmdpacket0(R300_VAP_CLIP_X_0, 4); ++ ++ if (has_tcl) { ++ ALLOC_STATE(unk2288, always, 2, 0); ++ r300->hw.unk2288.cmd[0] = cmdpacket0(R300_VAP_UNKNOWN_2288, 1); ++ } ++ + ALLOC_STATE(vof, always, R300_VOF_CMDSIZE, 0); + r300->hw.vof.cmd[R300_VOF_CMD_0] = + cmdpacket0(R300_VAP_OUTPUT_VTX_FMT_0, 2); +diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.h b/src/mesa/drivers/dri/r300/r300_cmdbuf.h +index bfb2eda..acb6e38 100644 +--- a/src/mesa/drivers/dri/r300/r300_cmdbuf.h ++++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.h +@@ -52,7 +52,7 @@ extern void r300DestroyCmdBuf(r300ContextPtr r300); + * + * \param dwords The number of dwords we need to be free on the command buffer + */ +-static __inline__ void r300EnsureCmdBufSpace(r300ContextPtr r300, ++static inline void r300EnsureCmdBufSpace(r300ContextPtr r300, + int dwords, const char *caller) + { + assert(dwords < r300->cmdbuf.size); +@@ -68,7 +68,7 @@ static __inline__ void r300EnsureCmdBufSpace(r300ContextPtr r300, + * causes state reemission after a flush. This is necessary to ensure + * correct hardware state after an unlock. + */ +-static __inline__ uint32_t *r300RawAllocCmdBuf(r300ContextPtr r300, ++static inline uint32_t *r300RawAllocCmdBuf(r300ContextPtr r300, + int dwords, const char *caller) + { + uint32_t *ptr; +@@ -80,7 +80,7 @@ static __inline__ uint32_t *r300RawAllocCmdBuf(r300ContextPtr r300, + return ptr; + } + +-static __inline__ uint32_t *r300AllocCmdBuf(r300ContextPtr r300, ++static inline uint32_t *r300AllocCmdBuf(r300ContextPtr r300, + int dwords, const char *caller) + { + uint32_t *ptr; +diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c +index 9ea14ab..14e0f05 100644 +--- a/src/mesa/drivers/dri/r300/r300_context.c ++++ b/src/mesa/drivers/dri/r300/r300_context.c +@@ -63,6 +63,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + #include "r300_ioctl.h" + #include "r300_tex.h" + #include "r300_emit.h" ++#include "r300_swtcl.h" + + #ifdef USER_BUFFERS + #include "r300_mem.h" +@@ -317,15 +318,17 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual, + _tnl_allow_vertex_fog(ctx, GL_TRUE); + + /* currently bogus data */ +- ctx->Const.VertexProgram.MaxInstructions = VSF_MAX_FRAGMENT_LENGTH / 4; +- ctx->Const.VertexProgram.MaxNativeInstructions = +- VSF_MAX_FRAGMENT_LENGTH / 4; +- ctx->Const.VertexProgram.MaxNativeAttribs = 16; /* r420 */ +- ctx->Const.VertexProgram.MaxTemps = 32; +- ctx->Const.VertexProgram.MaxNativeTemps = +- /*VSF_MAX_FRAGMENT_TEMPS */ 32; +- ctx->Const.VertexProgram.MaxNativeParameters = 256; /* r420 */ +- ctx->Const.VertexProgram.MaxNativeAddressRegs = 1; ++ if (screen->chip_flags & RADEON_CHIPSET_TCL) { ++ ctx->Const.VertexProgram.MaxInstructions = VSF_MAX_FRAGMENT_LENGTH / 4; ++ ctx->Const.VertexProgram.MaxNativeInstructions = ++ VSF_MAX_FRAGMENT_LENGTH / 4; ++ ctx->Const.VertexProgram.MaxNativeAttribs = 16; /* r420 */ ++ ctx->Const.VertexProgram.MaxTemps = 32; ++ ctx->Const.VertexProgram.MaxNativeTemps = ++ /*VSF_MAX_FRAGMENT_TEMPS */ 32; ++ ctx->Const.VertexProgram.MaxNativeParameters = 256; /* r420 */ ++ ctx->Const.VertexProgram.MaxNativeAddressRegs = 1; ++ } + + ctx->Const.FragmentProgram.MaxNativeTemps = PFS_NUM_TEMP_REGS; + ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* copy i915... */ +@@ -363,6 +366,8 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual, + radeonInitSpanFuncs(ctx); + r300InitCmdBuf(r300); + r300InitState(r300); ++ if (!(screen->chip_flags & RADEON_CHIPSET_TCL)) ++ r300InitSwtcl(ctx); + + TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline; + +diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h +index 4149867..be69097 100644 +--- a/src/mesa/drivers/dri/r300/r300_context.h ++++ b/src/mesa/drivers/dri/r300/r300_context.h +@@ -49,8 +49,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + #define USER_BUFFERS + +-//#define OPTIMIZE_ELTS +- + struct r300_context; + typedef struct r300_context r300ContextRec; + typedef struct r300_context *r300ContextPtr; +@@ -80,7 +78,7 @@ typedef struct r300_context *r300ContextPtr; + /** + * This function takes a float and packs it into a uint32_t + */ +-static __inline__ uint32_t r300PackFloat32(float fl) ++static inline uint32_t r300PackFloat32(float fl) + { + union { + float fl; +@@ -97,7 +95,7 @@ static __inline__ uint32_t r300PackFloat32(float fl) + * But it works for most things. I'll fix it later if someone + * else with a better clue doesn't + */ +-static __inline__ uint32_t r300PackFloat24(float f) ++static inline uint32_t r300PackFloat24(float f) + { + float mantissa; + int exponent; +@@ -149,7 +147,6 @@ struct r300_dma_region { + int aos_offset; /* address in GART memory */ + int aos_stride; /* distance between elements, in dwords */ + int aos_size; /* number of components (1-4) */ +- int aos_reg; /* VAP register assignment */ + }; + + struct r300_dma { +@@ -455,7 +452,7 @@ struct r300_hw_state { + struct r300_state_atom vic; /* vap input control (2180) */ + struct r300_state_atom unk21DC; /* (21DC) */ + struct r300_state_atom unk221C; /* (221C) */ +- struct r300_state_atom unk2220; /* (2220) */ ++ struct r300_state_atom vap_clip; + struct r300_state_atom unk2288; /* (2288) */ + struct r300_state_atom pvs; /* pvs_cntl (22D0) */ + struct r300_state_atom gb_enable; /* (4008) */ +@@ -571,38 +568,21 @@ struct r300_vertex_shader_fragment { + union { + GLuint d[VSF_MAX_FRAGMENT_LENGTH]; + float f[VSF_MAX_FRAGMENT_LENGTH]; +- VERTEX_SHADER_INSTRUCTION i[VSF_MAX_FRAGMENT_LENGTH / 4]; ++ GLuint i[VSF_MAX_FRAGMENT_LENGTH]; + } body; + }; + +-#define VSF_DEST_PROGRAM 0x0 +-#define VSF_DEST_MATRIX0 0x200 +-#define VSF_DEST_MATRIX1 0x204 +-#define VSF_DEST_MATRIX2 0x208 +-#define VSF_DEST_VECTOR0 0x20c +-#define VSF_DEST_VECTOR1 0x20d +-#define VSF_DEST_UNKNOWN1 0x400 +-#define VSF_DEST_UNKNOWN2 0x406 +- + struct r300_vertex_shader_state { + struct r300_vertex_shader_fragment program; +- +- struct r300_vertex_shader_fragment unknown1; +- struct r300_vertex_shader_fragment unknown2; +- +- int program_start; +- int unknown_ptr1; /* pointer within program space */ +- int program_end; +- +- int param_offset; +- int param_count; +- +- int unknown_ptr2; /* pointer within program space */ +- int unknown_ptr3; /* pointer within program space */ + }; + + extern int hw_tcl_on; + ++#define COLOR_IS_RGBA ++#define TAG(x) r300##x ++#include "tnl_dd/t_dd_vertex.h" ++#undef TAG ++ + //#define CURRENT_VERTEX_SHADER(ctx) (ctx->VertexProgram._Current) + #define CURRENT_VERTEX_SHADER(ctx) (R300_CONTEXT(ctx)->selected_vp) + +@@ -783,37 +763,10 @@ struct r300_fragment_program { + + #define R300_MAX_AOS_ARRAYS 16 + +-#define AOS_FORMAT_USHORT 0 +-#define AOS_FORMAT_FLOAT 1 +-#define AOS_FORMAT_UBYTE 2 +-#define AOS_FORMAT_FLOAT_COLOR 3 +- + #define REG_COORDS 0 + #define REG_COLOR0 1 + #define REG_TEX0 2 + +-struct dt { +- GLint size; +- GLenum type; +- GLsizei stride; +- void *data; +-}; +- +-struct radeon_vertex_buffer { +- int Count; +- void *Elts; +- int elt_size; +- int elt_min, elt_max; /* debug */ +- +- struct dt AttribPtr[VERT_ATTRIB_MAX]; +- +- const struct _mesa_prim *Primitive; +- GLuint PrimitiveCount; +- GLint LockFirst; +- GLsizei LockCount; +- int lock_uptodate; +-}; +- + struct r300_state { + struct r300_depthbuffer_state depth; + struct r300_texture_state texture; +@@ -822,18 +775,14 @@ struct r300_state { + struct r300_pfs_compile_state pfs_compile; + struct r300_dma_region aos[R300_MAX_AOS_ARRAYS]; + int aos_count; +- struct radeon_vertex_buffer VB; + + GLuint *Elts; + struct r300_dma_region elt_dma; + +- DECLARE_RENDERINPUTS(render_inputs_bitset); /* actual render inputs that R300 was configured for. ++ struct r300_dma_region swtcl_dma; ++ DECLARE_RENDERINPUTS(render_inputs_bitset); /* actual render inputs that R300 was configured for. + They are the same as tnl->render_inputs for fixed pipeline */ + +- struct { +- int transform_offset; /* Transform matrix offset, -1 if none */ +- } vap_param; /* vertex processor parameter allocation - tells where to write parameters */ +- + struct r300_stencilbuffer_state stencil; + + }; +@@ -842,6 +791,62 @@ struct r300_state { + #define R300_FALLBACK_TCL 1 + #define R300_FALLBACK_RAST 2 + ++/* r300_swtcl.c ++ */ ++struct r300_swtcl_info { ++ GLuint RenderIndex; ++ ++ /** ++ * Size of a hardware vertex. This is calculated when \c ::vertex_attrs is ++ * installed in the Mesa state vector. ++ */ ++ GLuint vertex_size; ++ ++ /** ++ * Attributes instructing the Mesa TCL pipeline where / how to put vertex ++ * data in the hardware buffer. ++ */ ++ struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX]; ++ ++ /** ++ * Number of elements of \c ::vertex_attrs that are actually used. ++ */ ++ GLuint vertex_attr_count; ++ ++ /** ++ * Cached pointer to the buffer where Mesa will store vertex data. ++ */ ++ GLubyte *verts; ++ ++ /* Fallback rasterization functions ++ */ ++ // r200_point_func draw_point; ++ // r200_line_func draw_line; ++ // r200_tri_func draw_tri; ++ ++ GLuint hw_primitive; ++ GLenum render_primitive; ++ GLuint numverts; ++ ++ /** ++ * Offset of the 4UB color data within a hardware (swtcl) vertex. ++ */ ++ GLuint coloroffset; ++ ++ /** ++ * Offset of the 3UB specular color data within a hardware (swtcl) vertex. ++ */ ++ GLuint specoffset; ++ ++ /** ++ * Should Mesa project vertex data or will the hardware do it? ++ */ ++ GLboolean needproj; ++ ++ struct r300_dma_region indexed_verts; ++}; ++ ++ + /** + * \brief R300 context structure. + */ +@@ -880,6 +885,9 @@ struct r300_context { + GLvector4f *temp_attrib[_TNL_ATTRIB_MAX]; + + GLboolean disable_lowimpact_fallback; ++ ++ DECLARE_RENDERINPUTS(tnl_index_bitset); /* index of bits for last tnl_install_attrs */ ++ struct r300_swtcl_info swtcl; + }; + + struct r300_buffer_object { +diff --git a/src/mesa/drivers/dri/r300/r300_emit.c b/src/mesa/drivers/dri/r300/r300_emit.c +index 2c26069..424bf44 100644 +--- a/src/mesa/drivers/dri/r300/r300_emit.c ++++ b/src/mesa/drivers/dri/r300/r300_emit.c +@@ -86,16 +86,15 @@ do { \ + } while (0) + #endif + +-static void r300EmitVec4(GLcontext * ctx, +- struct r300_dma_region *rvb, ++static void r300EmitVec4(GLcontext * ctx, struct r300_dma_region *rvb, + GLvoid * data, int stride, int count) + { + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) +- fprintf(stderr, "%s count %d stride %d\n", +- __FUNCTION__, count, stride); ++ fprintf(stderr, "%s count %d stride %d out %p data %p\n", ++ __FUNCTION__, count, stride, (void *)out, (void *)data); + + if (stride == 4) + COPY_DWORDS(out, data, count); +@@ -107,16 +106,15 @@ static void r300EmitVec4(GLcontext * ctx, + } + } + +-static void r300EmitVec8(GLcontext * ctx, +- struct r300_dma_region *rvb, ++static void r300EmitVec8(GLcontext * ctx, struct r300_dma_region *rvb, + GLvoid * data, int stride, int count) + { + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) +- fprintf(stderr, "%s count %d stride %d\n", +- __FUNCTION__, count, stride); ++ fprintf(stderr, "%s count %d stride %d out %p data %p\n", ++ __FUNCTION__, count, stride, (void *)out, (void *)data); + + if (stride == 8) + COPY_DWORDS(out, data, count * 2); +@@ -129,8 +127,7 @@ static void r300EmitVec8(GLcontext * ctx, + } + } + +-static void r300EmitVec12(GLcontext * ctx, +- struct r300_dma_region *rvb, ++static void r300EmitVec12(GLcontext * ctx, struct r300_dma_region *rvb, + GLvoid * data, int stride, int count) + { + int i; +@@ -152,16 +149,15 @@ static void r300EmitVec12(GLcontext * ctx, + } + } + +-static void r300EmitVec16(GLcontext * ctx, +- struct r300_dma_region *rvb, ++static void r300EmitVec16(GLcontext * ctx, struct r300_dma_region *rvb, + GLvoid * data, int stride, int count) + { + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) +- fprintf(stderr, "%s count %d stride %d\n", +- __FUNCTION__, count, stride); ++ fprintf(stderr, "%s count %d stride %d out %p data %p\n", ++ __FUNCTION__, count, stride, (void *)out, (void *)data); + + if (stride == 16) + COPY_DWORDS(out, data, count * 4); +@@ -176,32 +172,22 @@ static void r300EmitVec16(GLcontext * ctx, + } + } + +-static void r300EmitVec(GLcontext * ctx, +- struct r300_dma_region *rvb, ++static void r300EmitVec(GLcontext * ctx, struct r300_dma_region *rvb, + GLvoid * data, int size, int stride, int count) + { + r300ContextPtr rmesa = R300_CONTEXT(ctx); + +- if (RADEON_DEBUG & DEBUG_VERTS) +- fprintf(stderr, "%s count %d size %d stride %d\n", +- __FUNCTION__, count, size, stride); +- +- /* Gets triggered when playing with future_hw_tcl_on ... */ +- //assert(!rvb->buf); +- + if (stride == 0) { + r300AllocDmaRegion(rmesa, rvb, size * 4, 4); + count = 1; + rvb->aos_offset = GET_START(rvb); + rvb->aos_stride = 0; + } else { +- r300AllocDmaRegion(rmesa, rvb, size * count * 4, 4); /* alignment? */ ++ r300AllocDmaRegion(rmesa, rvb, size * count * 4, 4); + rvb->aos_offset = GET_START(rvb); + rvb->aos_stride = size; + } + +- /* Emit the data +- */ + switch (size) { + case 1: + r300EmitVec4(ctx, rvb, data, stride, count); +@@ -217,95 +203,35 @@ static void r300EmitVec(GLcontext * ctx, + break; + default: + assert(0); +- _mesa_exit(-1); +- break; +- } +- +-} +- +-static GLuint t_type(struct dt *dt) +-{ +- switch (dt->type) { +- case GL_UNSIGNED_BYTE: +- return AOS_FORMAT_UBYTE; +- case GL_SHORT: +- return AOS_FORMAT_USHORT; +- case GL_FLOAT: +- return AOS_FORMAT_FLOAT; +- default: +- assert(0); +- break; +- } +- +- return AOS_FORMAT_FLOAT; +-} +- +-static GLuint t_vir0_size(struct dt *dt) +-{ +- switch (dt->type) { +- case GL_UNSIGNED_BYTE: +- return 4; +- case GL_SHORT: +- return 7; +- case GL_FLOAT: +- return dt->size - 1; +- default: +- assert(0); + break; + } +- +- return 0; + } + +-static GLuint t_aos_size(struct dt *dt) +-{ +- switch (dt->type) { +- case GL_UNSIGNED_BYTE: +- return 1; +- case GL_SHORT: +- return 2; +- case GL_FLOAT: +- return dt->size; +- default: +- assert(0); +- break; +- } +- +- return 0; +-} +- +-static GLuint t_vir0(uint32_t * dst, struct dt *dt, int *inputs, +- GLint * tab, GLuint nr) ++static GLuint r300VAPInputRoute0(uint32_t * dst, GLvector4f ** attribptr, ++ int *inputs, GLint * tab, GLuint nr) + { + GLuint i, dw; + ++ /* type, inputs, stop bit, size */ + for (i = 0; i + 1 < nr; i += 2) { +- dw = t_vir0_size(&dt[tab[i]]) | (inputs[tab[i]] << 8) | +- (t_type(&dt[tab[i]]) << 14); +- dw |= +- (t_vir0_size(&dt[tab[i + 1]]) | +- (inputs[tab[i + 1]] << 8) | (t_type(&dt[tab[i + 1]]) +- << 14)) << 16; +- ++ dw = R300_INPUT_ROUTE_FLOAT | (inputs[tab[i]] << 8) | (attribptr[tab[i]]->size - 1); ++ dw |= (R300_INPUT_ROUTE_FLOAT | (inputs[tab[i + 1]] << 8) | (attribptr[tab[i + 1]]->size - 1)) << 16; + if (i + 2 == nr) { +- dw |= (1 << (13 + 16)); ++ dw |= (R300_VAP_INPUT_ROUTE_END << 16); + } + dst[i >> 1] = dw; + } + + if (nr & 1) { +- dw = t_vir0_size(&dt[tab[nr - 1]]) | (inputs[tab[nr - 1]] +- << 8) | +- (t_type(&dt[tab[nr - 1]]) << 14); +- dw |= 1 << 13; +- ++ dw = R300_INPUT_ROUTE_FLOAT | (inputs[tab[nr - 1]] << 8) | (attribptr[tab[nr - 1]]->size - 1); ++ dw |= R300_VAP_INPUT_ROUTE_END; + dst[nr >> 1] = dw; + } + + return (nr + 1) >> 1; + } + +-static GLuint t_swizzle(int swizzle[4]) ++static GLuint r300VAPInputRoute1Swizzle(int swizzle[4]) + { + return (swizzle[0] << R300_INPUT_ROUTE_X_SHIFT) | + (swizzle[1] << R300_INPUT_ROUTE_Y_SHIFT) | +@@ -313,32 +239,32 @@ static GLuint t_swizzle(int swizzle[4]) + (swizzle[3] << R300_INPUT_ROUTE_W_SHIFT); + } + +-static GLuint t_vir1(uint32_t * dst, int swizzle[][4], GLuint nr) ++GLuint r300VAPInputRoute1(uint32_t * dst, int swizzle[][4], GLuint nr) + { + GLuint i; + + for (i = 0; i + 1 < nr; i += 2) { +- dst[i >> 1] = t_swizzle(swizzle[i]) | R300_INPUT_ROUTE_ENABLE; +- dst[i >> 1] |= +- (t_swizzle(swizzle[i + 1]) | R300_INPUT_ROUTE_ENABLE) +- << 16; ++ dst[i >> 1] = r300VAPInputRoute1Swizzle(swizzle[i]) | R300_INPUT_ROUTE_ENABLE; ++ dst[i >> 1] |= (r300VAPInputRoute1Swizzle(swizzle[i + 1]) | R300_INPUT_ROUTE_ENABLE) << 16; + } + +- if (nr & 1) +- dst[nr >> 1] = +- t_swizzle(swizzle[nr - 1]) | R300_INPUT_ROUTE_ENABLE; ++ if (nr & 1) { ++ dst[nr >> 1] = r300VAPInputRoute1Swizzle(swizzle[nr - 1]) | R300_INPUT_ROUTE_ENABLE; ++ } + + return (nr + 1) >> 1; + } + +-static GLuint t_emit_size(struct dt *dt) ++GLuint r300VAPInputCntl0(GLcontext * ctx, GLuint InputsRead) + { +- return dt->size; ++ /* No idea what this value means. I have seen other values written to ++ * this register... */ ++ return 0x5555; + } + +-static GLuint t_vic(GLcontext * ctx, GLuint InputsRead) ++GLuint r300VAPInputCntl1(GLcontext * ctx, GLuint InputsRead) + { +- r300ContextPtr r300 = R300_CONTEXT(ctx); ++ r300ContextPtr rmesa = R300_CONTEXT(ctx); + GLuint i, vic_1 = 0; + + if (InputsRead & (1 << VERT_ATTRIB_POS)) +@@ -350,177 +276,188 @@ static GLuint t_vic(GLcontext * ctx, GLuint InputsRead) + if (InputsRead & (1 << VERT_ATTRIB_COLOR0)) + vic_1 |= R300_INPUT_CNTL_COLOR; + +- r300->state.texture.tc_count = 0; ++ rmesa->state.texture.tc_count = 0; + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) + if (InputsRead & (1 << (VERT_ATTRIB_TEX0 + i))) { +- r300->state.texture.tc_count++; ++ rmesa->state.texture.tc_count++; + vic_1 |= R300_INPUT_CNTL_TC0 << i; + } + + return vic_1; + } + ++GLuint r300VAPOutputCntl0(GLcontext * ctx, GLuint OutputsWritten) ++{ ++ GLuint ret = 0; ++ ++ if (OutputsWritten & (1 << VERT_RESULT_HPOS)) ++ ret |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; ++ ++ if (OutputsWritten & (1 << VERT_RESULT_COL0)) ++ ret |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT; ++ ++ if (OutputsWritten & (1 << VERT_RESULT_COL1)) ++ ret |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT; ++ ++ if (OutputsWritten & (1 << VERT_RESULT_BFC0) ++ || OutputsWritten & (1 << VERT_RESULT_BFC1)) ++ ret |= ++ R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT | ++ R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT | ++ R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT; ++ ++#if 0 ++ if (OutputsWritten & (1 << VERT_RESULT_FOGC)) ; ++#endif ++ ++ if (OutputsWritten & (1 << VERT_RESULT_PSIZ)) ++ ret |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; ++ ++ return ret; ++} ++ ++GLuint r300VAPOutputCntl1(GLcontext * ctx, GLuint OutputsWritten) ++{ ++ GLuint i, ret = 0; ++ ++ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { ++ if (OutputsWritten & (1 << (VERT_RESULT_TEX0 + i))) { ++ ret |= (4 << (3 * i)); ++ } ++ } ++ ++ return ret; ++} ++ + /* Emit vertex data to GART memory + * Route inputs to the vertex processor + * This function should never return R300_FALLBACK_TCL when using software tcl. + */ +- + int r300EmitArrays(GLcontext * ctx) + { + r300ContextPtr rmesa = R300_CONTEXT(ctx); +- r300ContextPtr r300 = rmesa; +- struct radeon_vertex_buffer *VB = &rmesa->state.VB; ++ TNLcontext *tnl = TNL_CONTEXT(ctx); ++ struct vertex_buffer *vb = &tnl->vb; + GLuint nr; +- GLuint count = VB->Count; ++ GLuint count = vb->Count; + GLuint i; + GLuint InputsRead = 0, OutputsWritten = 0; + int *inputs = NULL; + int vir_inputs[VERT_ATTRIB_MAX]; + GLint tab[VERT_ATTRIB_MAX]; + int swizzle[VERT_ATTRIB_MAX][4]; ++ struct r300_vertex_program *prog = ++ (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); + + if (hw_tcl_on) { +- struct r300_vertex_program *prog = +- (struct r300_vertex_program *) +- CURRENT_VERTEX_SHADER(ctx); + inputs = prog->inputs; +- InputsRead = CURRENT_VERTEX_SHADER(ctx)->key.InputsRead; +- OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten; ++ InputsRead = prog->key.InputsRead; ++ OutputsWritten = prog->key.OutputsWritten; + } else { +- DECLARE_RENDERINPUTS(inputs_bitset); +- inputs = r300->state.sw_tcl_inputs; ++ inputs = rmesa->state.sw_tcl_inputs; ++ ++ DECLARE_RENDERINPUTS(render_inputs_bitset); ++ RENDERINPUTS_COPY(render_inputs_bitset, tnl->render_inputs_bitset); + +- RENDERINPUTS_COPY(inputs_bitset, +- TNL_CONTEXT(ctx)->render_inputs_bitset); ++ vb->AttribPtr[VERT_ATTRIB_POS] = vb->ClipPtr; + +- assert(RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_POS)); +- InputsRead |= 1 << VERT_ATTRIB_POS; +- OutputsWritten |= 1 << VERT_RESULT_HPOS; ++ assert(RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_POS)); ++ assert(RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_NORMAL) == 0); ++ //assert(RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_COLOR0)); + +- assert(RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_NORMAL) +- == 0); ++ if (RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_POS)) { ++ InputsRead |= 1 << VERT_ATTRIB_POS; ++ OutputsWritten |= 1 << VERT_RESULT_HPOS; ++ } + +- assert(RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_COLOR0)); +- InputsRead |= 1 << VERT_ATTRIB_COLOR0; +- OutputsWritten |= 1 << VERT_RESULT_COL0; ++ if (RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_COLOR0)) { ++ InputsRead |= 1 << VERT_ATTRIB_COLOR0; ++ OutputsWritten |= 1 << VERT_RESULT_COL0; ++ } + +- if (RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_COLOR1)) { ++ if (RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_COLOR1)) { + InputsRead |= 1 << VERT_ATTRIB_COLOR1; + OutputsWritten |= 1 << VERT_RESULT_COL1; + } + +- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) +- if (RENDERINPUTS_TEST +- (inputs_bitset, _TNL_ATTRIB_TEX(i))) { ++ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { ++ if (RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_TEX(i))) { + InputsRead |= 1 << (VERT_ATTRIB_TEX0 + i); + OutputsWritten |= 1 << (VERT_RESULT_TEX0 + i); + } ++ } + +- for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) +- if (InputsRead & (1 << i)) ++ for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) { ++ if (InputsRead & (1 << i)) { + inputs[i] = nr++; +- else ++ } else { + inputs[i] = -1; +- +- if (! +- (r300->radeon.radeonScreen-> +- chip_flags & RADEON_CHIPSET_TCL)) { +- /* Fixed, apply to vir0 only */ +- memcpy(vir_inputs, inputs, +- VERT_ATTRIB_MAX * sizeof(int)); +- inputs = vir_inputs; +- +- if (InputsRead & VERT_ATTRIB_POS) +- inputs[VERT_ATTRIB_POS] = 0; +- +- if (InputsRead & (1 << VERT_ATTRIB_COLOR0)) +- inputs[VERT_ATTRIB_COLOR0] = 2; +- +- if (InputsRead & (1 << VERT_ATTRIB_COLOR1)) +- inputs[VERT_ATTRIB_COLOR1] = 3; +- +- for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) +- if (InputsRead & (1 << i)) +- inputs[i] = 6 + (i - VERT_ATTRIB_TEX0); ++ } + } + +- RENDERINPUTS_COPY(rmesa->state.render_inputs_bitset, +- inputs_bitset); ++ /* Fixed, apply to vir0 only */ ++ memcpy(vir_inputs, inputs, VERT_ATTRIB_MAX * sizeof(int)); ++ inputs = vir_inputs; ++ if (InputsRead & VERT_ATTRIB_POS) ++ inputs[VERT_ATTRIB_POS] = 0; ++ if (InputsRead & (1 << VERT_ATTRIB_COLOR0)) ++ inputs[VERT_ATTRIB_COLOR0] = 2; ++ if (InputsRead & (1 << VERT_ATTRIB_COLOR1)) ++ inputs[VERT_ATTRIB_COLOR1] = 3; ++ for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) ++ if (InputsRead & (1 << i)) ++ inputs[i] = 6 + (i - VERT_ATTRIB_TEX0); ++ ++ RENDERINPUTS_COPY(rmesa->state.render_inputs_bitset, render_inputs_bitset); + } ++ + assert(InputsRead); + assert(OutputsWritten); + +- for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) +- if (InputsRead & (1 << i)) ++ for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) { ++ if (InputsRead & (1 << i)) { + tab[nr++] = i; ++ } ++ } + +- if (nr > R300_MAX_AOS_ARRAYS) ++ if (nr > R300_MAX_AOS_ARRAYS) { + return R300_FALLBACK_TCL; ++ } + + for (i = 0; i < nr; i++) { +- int ci; +- int comp_size, fix, found = 0; ++ int ci, fix, found = 0; + + swizzle[i][0] = SWIZZLE_ZERO; + swizzle[i][1] = SWIZZLE_ZERO; + swizzle[i][2] = SWIZZLE_ZERO; + swizzle[i][3] = SWIZZLE_ONE; + +- for (ci = 0; ci < VB->AttribPtr[tab[i]].size; ci++) ++ for (ci = 0; ci < vb->AttribPtr[tab[i]]->size; ci++) { + swizzle[i][ci] = ci; +- +-#if MESA_BIG_ENDIAN +-#define SWAP_INT(a, b) do { \ +- int __temp; \ +- __temp = a;\ +- a = b; \ +- b = __temp; \ +-} while (0) +- +- if (VB->AttribPtr[tab[i]].type == GL_UNSIGNED_BYTE) { +- SWAP_INT(swizzle[i][0], swizzle[i][3]); +- SWAP_INT(swizzle[i][1], swizzle[i][2]); + } +-#endif /* MESA_BIG_ENDIAN */ + +- if (r300IsGartMemory(rmesa, VB->AttribPtr[tab[i]].data, +- /*(count-1)*stride */ 4)) { +- if (VB->AttribPtr[tab[i]].stride % 4) ++ if (r300IsGartMemory(rmesa, vb->AttribPtr[tab[i]]->data, 4)) { ++ if (vb->AttribPtr[tab[i]]->stride % 4) { + return R300_FALLBACK_TCL; +- +- rmesa->state.aos[i].address = +- VB->AttribPtr[tab[i]].data; ++ } ++ rmesa->state.aos[i].address = (void *)(vb->AttribPtr[tab[i]]->data); + rmesa->state.aos[i].start = 0; +- rmesa->state.aos[i].aos_offset = +- r300GartOffsetFromVirtual(rmesa, +- VB-> +- AttribPtr[tab[i]].data); +- rmesa->state.aos[i].aos_stride = +- VB->AttribPtr[tab[i]].stride / 4; +- +- rmesa->state.aos[i].aos_size = +- t_emit_size(&VB->AttribPtr[tab[i]]); ++ rmesa->state.aos[i].aos_offset = r300GartOffsetFromVirtual(rmesa, vb->AttribPtr[tab[i]]->data); ++ rmesa->state.aos[i].aos_stride = vb->AttribPtr[tab[i]]->stride / 4; ++ rmesa->state.aos[i].aos_size = vb->AttribPtr[tab[i]]->size; + } else { +- /* TODO: r300EmitVec can only handle 4 byte vectors */ +- if (VB->AttribPtr[tab[i]].type != GL_FLOAT) +- return R300_FALLBACK_TCL; +- + r300EmitVec(ctx, &rmesa->state.aos[i], +- VB->AttribPtr[tab[i]].data, +- t_emit_size(&VB->AttribPtr[tab[i]]), +- VB->AttribPtr[tab[i]].stride, count); ++ vb->AttribPtr[tab[i]]->data, ++ vb->AttribPtr[tab[i]]->size, ++ vb->AttribPtr[tab[i]]->stride, count); + } + +- rmesa->state.aos[i].aos_size = +- t_aos_size(&VB->AttribPtr[tab[i]]); +- +- comp_size = _mesa_sizeof_type(VB->AttribPtr[tab[i]].type); ++ rmesa->state.aos[i].aos_size = vb->AttribPtr[tab[i]]->size; + +- for (fix = 0; fix <= 4 - VB->AttribPtr[tab[i]].size; fix++) { +- if ((rmesa->state.aos[i].aos_offset - +- comp_size * fix) % 4) ++ for (fix = 0; fix <= 4 - vb->AttribPtr[tab[i]]->size; fix++) { ++ if ((rmesa->state.aos[i].aos_offset - _mesa_sizeof_type(GL_FLOAT) * fix) % 4) { + continue; +- ++ } + found = 1; + break; + } +@@ -529,70 +466,41 @@ int r300EmitArrays(GLcontext * ctx) + if (fix > 0) { + WARN_ONCE("Feeling lucky?\n"); + } +- +- rmesa->state.aos[i].aos_offset -= comp_size * fix; +- +- for (ci = 0; ci < VB->AttribPtr[tab[i]].size; ci++) ++ rmesa->state.aos[i].aos_offset -= _mesa_sizeof_type(GL_FLOAT) * fix; ++ for (ci = 0; ci < vb->AttribPtr[tab[i]]->size; ci++) { + swizzle[i][ci] += fix; ++ } + } else { + WARN_ONCE + ("Cannot handle offset %x with stride %d, comp %d\n", + rmesa->state.aos[i].aos_offset, + rmesa->state.aos[i].aos_stride, +- VB->AttribPtr[tab[i]].size); ++ vb->AttribPtr[tab[i]]->size); + return R300_FALLBACK_TCL; + } + } + +- /* setup INPUT_ROUTE */ +- R300_STATECHANGE(r300, vir[0]); +- ((drm_r300_cmd_header_t *) r300->hw.vir[0].cmd)->packet0.count = +- t_vir0(&r300->hw.vir[0].cmd[R300_VIR_CNTL_0], VB->AttribPtr, +- inputs, tab, nr); +- +- R300_STATECHANGE(r300, vir[1]); +- ((drm_r300_cmd_header_t *) r300->hw.vir[1].cmd)->packet0.count = +- t_vir1(&r300->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle, nr); +- +- /* Set up input_cntl */ +- /* I don't think this is needed for vertex buffers, but it doesn't hurt anything */ +- 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] = t_vic(ctx, InputsRead); +- +- /* Stage 3: VAP output */ +- +- R300_STATECHANGE(r300, vof); +- +- r300->hw.vof.cmd[R300_VOF_CNTL_0] = 0; +- r300->hw.vof.cmd[R300_VOF_CNTL_1] = 0; +- +- if (OutputsWritten & (1 << VERT_RESULT_HPOS)) +- r300->hw.vof.cmd[R300_VOF_CNTL_0] |= +- R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; +- +- if (OutputsWritten & (1 << VERT_RESULT_COL0)) +- r300->hw.vof.cmd[R300_VOF_CNTL_0] |= +- R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT; +- +- if (OutputsWritten & (1 << VERT_RESULT_COL1)) +- r300->hw.vof.cmd[R300_VOF_CNTL_0] |= +- R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT; +- +- /*if(OutputsWritten & (1 << VERT_RESULT_BFC0)) +- r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT; +- +- if(OutputsWritten & (1 << VERT_RESULT_BFC1)) +- r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT; */ +- //if(OutputsWritten & (1 << VERT_RESULT_FOGC)) +- +- if (OutputsWritten & (1 << VERT_RESULT_PSIZ)) +- r300->hw.vof.cmd[R300_VOF_CNTL_0] |= +- R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; +- +- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) +- if (OutputsWritten & (1 << (VERT_RESULT_TEX0 + i))) +- r300->hw.vof.cmd[R300_VOF_CNTL_1] |= (4 << (3 * i)); ++ /* Setup INPUT_ROUTE. */ ++ R300_STATECHANGE(rmesa, vir[0]); ++ ((drm_r300_cmd_header_t *) rmesa->hw.vir[0].cmd)->packet0.count = ++ r300VAPInputRoute0(&rmesa->hw.vir[0].cmd[R300_VIR_CNTL_0], ++ vb->AttribPtr, inputs, tab, nr); ++ R300_STATECHANGE(rmesa, vir[1]); ++ ((drm_r300_cmd_header_t *) rmesa->hw.vir[1].cmd)->packet0.count = ++ r300VAPInputRoute1(&rmesa->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle, ++ nr); ++ ++ /* Setup INPUT_CNTL. */ ++ R300_STATECHANGE(rmesa, vic); ++ rmesa->hw.vic.cmd[R300_VIC_CNTL_0] = r300VAPInputCntl0(ctx, InputsRead); ++ rmesa->hw.vic.cmd[R300_VIC_CNTL_1] = r300VAPInputCntl1(ctx, InputsRead); ++ ++ /* Setup OUTPUT_VTX_FMT. */ ++ R300_STATECHANGE(rmesa, vof); ++ rmesa->hw.vof.cmd[R300_VOF_CNTL_0] = ++ r300VAPOutputCntl0(ctx, OutputsWritten); ++ rmesa->hw.vof.cmd[R300_VOF_CNTL_1] = ++ r300VAPOutputCntl1(ctx, OutputsWritten); + + rmesa->state.aos_count = nr; + +@@ -625,3 +533,19 @@ void r300ReleaseArrays(GLcontext * ctx) + r300ReleaseDmaRegion(rmesa, &rmesa->state.aos[i], __FUNCTION__); + } + } ++ ++void r300EmitCacheFlush(r300ContextPtr rmesa) ++{ ++ int cmd_reserved = 0; ++ int cmd_written = 0; ++ ++ drm_radeon_cmd_header_t *cmd = NULL; ++ ++ reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0); ++ e32(R300_RB3D_DSTCACHE_UNKNOWN_0A); ++ ++ reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0); ++ e32(R300_RB3D_ZCACHE_UNKNOWN_03); ++ ++ ++} +diff --git a/src/mesa/drivers/dri/r300/r300_emit.h b/src/mesa/drivers/dri/r300/r300_emit.h +index 7be098f..a6d69ec 100644 +--- a/src/mesa/drivers/dri/r300/r300_emit.h ++++ b/src/mesa/drivers/dri/r300/r300_emit.h +@@ -44,22 +44,13 @@ + #include "r300_cmdbuf.h" + #include "radeon_reg.h" + +-/* +- * CP type-3 packets +- */ +-#define RADEON_CP_PACKET3_UNK1B 0xC0001B00 +-#define RADEON_CP_PACKET3_INDX_BUFFER 0xC0003300 +-#define RADEON_CP_PACKET3_3D_DRAW_VBUF_2 0xC0003400 +-#define RADEON_CP_PACKET3_3D_DRAW_IMMD_2 0xC0003500 +-#define RADEON_CP_PACKET3_3D_DRAW_INDX_2 0xC0003600 +-#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00 +-#define RADEON_CP_PACKET3_3D_CLEAR_ZMASK 0xC0003202 +-#define RADEON_CP_PACKET3_3D_CLEAR_CMASK 0xC0003802 +-#define RADEON_CP_PACKET3_3D_CLEAR_HIZ 0xC0003702 +- ++/* TODO: move these defines (and the ones from DRM) into r300_reg.h and sync up ++ * with DRM */ + #define CP_PACKET0(reg, n) (RADEON_CP_PACKET0 | ((n)<<16) | ((reg)>>2)) ++#define CP_PACKET3( pkt, n ) \ ++ (RADEON_CP_PACKET3 | (pkt) | ((n) << 16)) + +-static __inline__ uint32_t cmdpacket0(int reg, int count) ++static inline uint32_t cmdpacket0(int reg, int count) + { + drm_r300_cmd_header_t cmd; + +@@ -71,7 +62,7 @@ static __inline__ uint32_t cmdpacket0(int reg, int count) + return cmd.u; + } + +-static __inline__ uint32_t cmdvpu(int addr, int count) ++static inline uint32_t cmdvpu(int addr, int count) + { + drm_r300_cmd_header_t cmd; + +@@ -83,7 +74,7 @@ static __inline__ uint32_t cmdvpu(int addr, int count) + return cmd.u; + } + +-static __inline__ uint32_t cmdpacket3(int packet) ++static inline uint32_t cmdpacket3(int packet) + { + drm_r300_cmd_header_t cmd; + +@@ -93,7 +84,7 @@ static __inline__ uint32_t cmdpacket3(int packet) + return cmd.u; + } + +-static __inline__ uint32_t cmdcpdelay(unsigned short count) ++static inline uint32_t cmdcpdelay(unsigned short count) + { + drm_r300_cmd_header_t cmd; + +@@ -103,7 +94,7 @@ static __inline__ uint32_t cmdcpdelay(unsigned short count) + return cmd.u; + } + +-static __inline__ uint32_t cmdwait(unsigned char flags) ++static inline uint32_t cmdwait(unsigned char flags) + { + drm_r300_cmd_header_t cmd; + +@@ -113,7 +104,7 @@ static __inline__ uint32_t cmdwait(unsigned char flags) + return cmd.u; + } + +-static __inline__ uint32_t cmdpacify(void) ++static inline uint32_t cmdpacify(void) + { + drm_r300_cmd_header_t cmd; + +@@ -234,5 +225,15 @@ void r300UseArrays(GLcontext * ctx); + #endif + + extern void r300ReleaseArrays(GLcontext * ctx); ++extern int r300PrimitiveType(r300ContextPtr rmesa, int prim); ++extern int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim); ++ ++extern void r300EmitCacheFlush(r300ContextPtr rmesa); ++ ++extern GLuint r300VAPInputRoute1(uint32_t * dst, int swizzle[][4], GLuint nr); ++extern GLuint r300VAPInputCntl0(GLcontext * ctx, GLuint InputsRead); ++extern GLuint r300VAPInputCntl1(GLcontext * ctx, GLuint InputsRead); ++extern GLuint r300VAPOutputCntl0(GLcontext * ctx, GLuint OutputsWritten); ++extern GLuint r300VAPOutputCntl1(GLcontext * ctx, GLuint OutputsWritten); + + #endif +diff --git a/src/mesa/drivers/dri/r300/r300_ioctl.c b/src/mesa/drivers/dri/r300/r300_ioctl.c +index 416ea7f..90f5027 100644 +--- a/src/mesa/drivers/dri/r300/r300_ioctl.c ++++ b/src/mesa/drivers/dri/r300/r300_ioctl.c +@@ -172,11 +172,7 @@ static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer) + cmd2[7].u = r300PackFloat32(ctx->Color.ClearColor[2]); + cmd2[8].u = r300PackFloat32(ctx->Color.ClearColor[3]); + +- reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0); +- e32(R300_RB3D_DSTCACHE_UNKNOWN_0A); +- +- reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0); +- e32(R300_RB3D_ZCACHE_UNKNOWN_03); ++ r300EmitCacheFlush(rmesa); + cp_wait(rmesa, R300_WAIT_3D | R300_WAIT_3D_CLEAN); + } + +@@ -224,25 +220,23 @@ static void r300EmitClearState(GLcontext * ctx) + e32(R300_INPUT_CNTL_0_COLOR); + e32(R300_INPUT_CNTL_POS | R300_INPUT_CNTL_COLOR | R300_INPUT_CNTL_TC0); + +- if (!has_tcl) { +- R300_STATECHANGE(r300, vte); +- /* comes from fglrx startup of clear */ +- reg_start(R300_SE_VTE_CNTL, 1); +- e32(R300_VTX_W0_FMT | 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); +- e32(0x8); +- +- reg_start(0x21dc, 0); +- e32(0xaaaaaaaa); +- } ++ R300_STATECHANGE(r300, vte); ++ /* comes from fglrx startup of clear */ ++ reg_start(R300_SE_VTE_CNTL, 1); ++ e32(R300_VTX_W0_FMT | 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); ++ e32(0x8); ++ ++ reg_start(0x21dc, 0); ++ e32(0xaaaaaaaa); + + R300_STATECHANGE(r300, vof); + reg_start(R300_VAP_OUTPUT_VTX_FMT_0, 1); + e32(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT | + R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT); +- e32(0x0); /* no textures */ ++ e32(0x0); /* no textures */ + + R300_STATECHANGE(r300, txe); + reg_start(R300_TX_ENABLE, 0); +@@ -414,19 +408,22 @@ static void r300Clear(GLcontext * ctx, GLbitfield mask) + + void r300Flush(GLcontext * ctx) + { +- r300ContextPtr r300 = R300_CONTEXT(ctx); ++ r300ContextPtr rmesa = R300_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s\n", __FUNCTION__); + +- if (r300->cmdbuf.count_used > r300->cmdbuf.count_reemit) +- r300FlushCmdBuf(r300, __FUNCTION__); ++ if (rmesa->dma.flush) ++ rmesa->dma.flush( rmesa ); ++ ++ if (rmesa->cmdbuf.count_used > rmesa->cmdbuf.count_reemit) ++ r300FlushCmdBuf(rmesa, __FUNCTION__); + } + + #ifdef USER_BUFFERS + #include "r300_mem.h" + +-static void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size) ++void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size) + { + struct r300_dma_buffer *dmabuf; + size = MAX2(size, RADEON_BUFFER_SIZE * 16); +@@ -438,9 +435,12 @@ static void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size) + rmesa->dma.flush(rmesa); + } + +- if (rmesa->dma.current.buf) ++ if (rmesa->dma.current.buf) { ++#ifdef USER_BUFFERS ++ r300_mem_use(rmesa, rmesa->dma.current.buf->id); ++#endif + r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__); +- ++ } + if (rmesa->dma.nr_released_bufs > 4) + r300FlushCmdBuf(rmesa, __FUNCTION__); + +diff --git a/src/mesa/drivers/dri/r300/r300_ioctl.h b/src/mesa/drivers/dri/r300/r300_ioctl.h +index 7a19a2c..e1143fb 100644 +--- a/src/mesa/drivers/dri/r300/r300_ioctl.h ++++ b/src/mesa/drivers/dri/r300/r300_ioctl.h +@@ -56,4 +56,5 @@ extern void r300AllocDmaRegion(r300ContextPtr rmesa, + + extern void r300InitIoctlFuncs(struct dd_function_table *functions); + ++extern void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size); + #endif /* __R300_IOCTL_H__ */ +diff --git a/src/mesa/drivers/dri/r300/r300_reg.h b/src/mesa/drivers/dri/r300/r300_reg.h +index 0a31f0b..1baa74c 100644 +--- a/src/mesa/drivers/dri/r300/r300_reg.h ++++ b/src/mesa/drivers/dri/r300/r300_reg.h +@@ -116,6 +116,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. + # define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */ + + #define R300_VAP_OUTPUT_VTX_FMT_1 0x2094 ++ /* each of the following is 3 bits wide, specifies number ++ of components */ + # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0 + # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3 + # define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6 +@@ -280,9 +282,32 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + #define R300_VAP_PVS_UPLOAD_ADDRESS 0x2200 + # define R300_PVS_UPLOAD_PROGRAM 0x00000000 ++/* gap */ + # define R300_PVS_UPLOAD_PARAMETERS 0x00000200 ++/* gap */ ++# define R300_PVS_UPLOAD_CLIP_PLANE0 0x00000400 ++# define R300_PVS_UPLOAD_CLIP_PLANE1 0x00000401 ++# define R300_PVS_UPLOAD_CLIP_PLANE2 0x00000402 ++# define R300_PVS_UPLOAD_CLIP_PLANE3 0x00000403 ++# define R300_PVS_UPLOAD_CLIP_PLANE4 0x00000404 ++# define R300_PVS_UPLOAD_CLIP_PLANE5 0x00000405 + # define R300_PVS_UPLOAD_POINTSIZE 0x00000406 + ++/* ++ * These are obsolete defines form r300_context.h, but they might give some ++ * clues when investigating the addresses further... ++ */ ++#if 0 ++#define VSF_DEST_PROGRAM 0x0 ++#define VSF_DEST_MATRIX0 0x200 ++#define VSF_DEST_MATRIX1 0x204 ++#define VSF_DEST_MATRIX2 0x208 ++#define VSF_DEST_VECTOR0 0x20c ++#define VSF_DEST_VECTOR1 0x20d ++#define VSF_DEST_UNKNOWN1 0x400 ++#define VSF_DEST_UNKNOWN2 0x406 ++#endif ++ + /* gap */ + + #define R300_VAP_PVS_UPLOAD_DATA 0x2208 +@@ -299,6 +324,18 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. + # define R300_221C_NORMAL 0x00000000 + # define R300_221C_CLEAR 0x0001C000 + ++/* These seem to be per-pixel and per-vertex X and Y clipping planes. The first ++ * plane is per-pixel and the second plane is per-vertex. ++ * ++ * This was determined by experimentation alone but I believe it is correct. ++ * ++ * These registers are called X_QUAD0_1_FL to X_QUAD0_4_FL by glxtest. ++ */ ++#define R300_VAP_CLIP_X_0 0x2220 ++#define R300_VAP_CLIP_X_1 0x2224 ++#define R300_VAP_CLIP_Y_0 0x2228 ++#define R300_VAP_CLIP_Y_1 0x2230 ++ + /* gap */ + + /* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between +@@ -322,13 +359,15 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. + * The meaning of the two UNKNOWN fields is obviously not known. However, + * experiments so far have shown that both *must* point to an instruction + * inside the vertex program, otherwise the GPU locks up. ++ * + * fglrx usually sets CNTL_3_UNKNOWN to the end of the program and +- * CNTL_1_UNKNOWN points to instruction where last write to position takes +- * place. ++ * R300_PVS_CNTL_1_POS_END_SHIFT points to instruction where last write to ++ * position takes place. ++ * + * Most likely this is used to ignore rest of the program in cases + * where group of verts arent visible. For some reason this "section" + * is sometimes accepted other instruction that have no relationship with +- *position calculations. ++ * position calculations. + */ + #define R300_VAP_PVS_CNTL_1 0x22D0 + # define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0 +@@ -967,7 +1006,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. + * first node is stored in NODE_2, the second node is stored in NODE_3. + * + * Offsets are relative to the master offset from PFS_CNTL_2. +- * LAST_NODE is set for the last node, and only for the last node. + */ + #define R300_PFS_NODE_0 0x4610 + #define R300_PFS_NODE_1 0x4614 +@@ -981,7 +1019,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. + # define R300_PFS_NODE_TEX_OFFSET_MASK (31 << 12) + # define R300_PFS_NODE_TEX_END_SHIFT 17 + # define R300_PFS_NODE_TEX_END_MASK (31 << 17) +-/*# define R300_PFS_NODE_LAST_NODE (1 << 22) */ + # define R300_PFS_NODE_OUTPUT_COLOR (1 << 22) + # define R300_PFS_NODE_OUTPUT_DEPTH (1 << 23) + +@@ -1591,6 +1628,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. + # define R300_EB_UNK1_SHIFT 24 + # define R300_EB_UNK1 (0x80<<24) + # define R300_EB_UNK2 0x0810 ++#define R300_PACKET3_3D_DRAW_VBUF_2 0x00003400 + #define R300_PACKET3_3D_DRAW_INDX_2 0x00003600 + + /* END: Packet 3 commands */ +diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c +index cc13e9a..eee1e80 100644 +--- a/src/mesa/drivers/dri/r300/r300_render.c ++++ b/src/mesa/drivers/dri/r300/r300_render.c +@@ -45,6 +45,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. + * obviously this does work... Further investigation is needed. + * + * \author Nicolai Haehnle ++ * ++ * \todo Add immediate implementation back? Perhaps this is useful if there are ++ * no bugs... + */ + + #include "glheader.h" +@@ -76,7 +79,7 @@ extern int future_hw_tcl_on; + /** + * \brief Convert a OpenGL primitive type into a R300 primitive type. + */ +-static int r300PrimitiveType(r300ContextPtr rmesa, GLcontext * ctx, int prim) ++int r300PrimitiveType(r300ContextPtr rmesa, int prim) + { + switch (prim & PRIM_MODE_MASK) { + case GL_POINTS: +@@ -116,7 +119,7 @@ static int r300PrimitiveType(r300ContextPtr rmesa, GLcontext * ctx, int prim) + } + } + +-static int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim) ++int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim) + { + int verts_off = 0; + +@@ -168,16 +171,13 @@ static int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim) + return num_verts - verts_off; + } + +-static void r300EmitElts(GLcontext * ctx, void *elts, unsigned long n_elts, +- int elt_size) ++static void r300EmitElts(GLcontext * ctx, void *elts, unsigned long n_elts) + { + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct r300_dma_region *rvb = &rmesa->state.elt_dma; + void *out; + +- assert(elt_size == 2 || elt_size == 4); +- +- if (r300IsGartMemory(rmesa, elts, n_elts * elt_size)) { ++ if (r300IsGartMemory(rmesa, elts, n_elts * 4)) { + rvb->address = rmesa->radeon.radeonScreen->gartTextures.map; + rvb->start = ((char *)elts) - rvb->address; + rvb->aos_offset = +@@ -189,66 +189,27 @@ static void r300EmitElts(GLcontext * ctx, void *elts, unsigned long n_elts, + _mesa_exit(-1); + } + +- r300AllocDmaRegion(rmesa, rvb, n_elts * elt_size, elt_size); ++ r300AllocDmaRegion(rmesa, rvb, n_elts * 4, 4); + rvb->aos_offset = GET_START(rvb); + + out = rvb->address + rvb->start; +- memcpy(out, elts, n_elts * elt_size); ++ memcpy(out, elts, n_elts * 4); + } + + static void r300FireEB(r300ContextPtr rmesa, unsigned long addr, +- int vertex_count, int type, int elt_size) ++ int vertex_count, int type) + { + int cmd_reserved = 0; + int cmd_written = 0; + drm_radeon_cmd_header_t *cmd = NULL; +- unsigned long t_addr; +- unsigned long magic_1, magic_2; +- +- assert(elt_size == 2 || elt_size == 4); +- +- if (addr & (elt_size - 1)) { +- WARN_ONCE("Badly aligned buffer\n"); +- return; +- } + +- magic_1 = (addr % 32) / 4; +- t_addr = addr & ~0x1d; +- magic_2 = (vertex_count + 1 + (t_addr & 0x2)) / 2 + magic_1; ++ start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_INDX_2, 0), 0); ++ e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count << 16) | type | R300_VAP_VF_CNTL__INDEX_SIZE_32bit); + +- start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, 0); +- if (elt_size == 4) { +- e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | +- (vertex_count << 16) | type | +- R300_VAP_VF_CNTL__INDEX_SIZE_32bit); +- } else { +- e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | +- (vertex_count << 16) | type); +- } +- +- start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2); +-#ifdef OPTIMIZE_ELTS +- if (elt_size == 4) { +- e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2); +- e32(addr); +- } else { +- e32(R300_EB_UNK1 | (magic_1 << 16) | R300_EB_UNK2); +- e32(t_addr); +- } +-#else ++ start_packet3(CP_PACKET3(R300_PACKET3_INDX_BUFFER, 2), 2); + e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2); + e32(addr); +-#endif +- +- if (elt_size == 4) { +- e32(vertex_count); +- } else { +-#ifdef OPTIMIZE_ELTS +- e32(magic_2); +-#else +- e32((vertex_count + 1) / 2); +-#endif +- } ++ e32(vertex_count); + } + + static void r300EmitAOS(r300ContextPtr rmesa, GLuint nr, GLuint offset) +@@ -263,26 +224,23 @@ static void r300EmitAOS(r300ContextPtr rmesa, GLuint nr, GLuint offset) + fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__, nr, + offset); + +- start_packet3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, sz - 1); ++ start_packet3(CP_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1), sz - 1); + e32(nr); ++ + for (i = 0; i + 1 < nr; i += 2) { +- e32((rmesa->state.aos[i].aos_size << 0) +- | (rmesa->state.aos[i].aos_stride << 8) +- | (rmesa->state.aos[i + 1].aos_size << 16) +- | (rmesa->state.aos[i + 1].aos_stride << 24) +- ); +- e32(rmesa->state.aos[i].aos_offset + +- offset * 4 * rmesa->state.aos[i].aos_stride); +- e32(rmesa->state.aos[i + 1].aos_offset + +- offset * 4 * rmesa->state.aos[i + 1].aos_stride); ++ e32((rmesa->state.aos[i].aos_size << 0) | ++ (rmesa->state.aos[i].aos_stride << 8) | ++ (rmesa->state.aos[i + 1].aos_size << 16) | ++ (rmesa->state.aos[i + 1].aos_stride << 24)); ++ ++ e32(rmesa->state.aos[i].aos_offset + offset * 4 * rmesa->state.aos[i].aos_stride); ++ e32(rmesa->state.aos[i + 1].aos_offset + offset * 4 * rmesa->state.aos[i + 1].aos_stride); + } + + if (nr & 1) { +- e32((rmesa->state.aos[nr - 1].aos_size << 0) +- | (rmesa->state.aos[nr - 1].aos_stride << 8) +- ); +- e32(rmesa->state.aos[nr - 1].aos_offset + +- offset * 4 * rmesa->state.aos[nr - 1].aos_stride); ++ e32((rmesa->state.aos[nr - 1].aos_size << 0) | ++ (rmesa->state.aos[nr - 1].aos_stride << 8)); ++ e32(rmesa->state.aos[nr - 1].aos_offset + offset * 4 * rmesa->state.aos[nr - 1].aos_stride); + } + } + +@@ -292,130 +250,67 @@ static void r300FireAOS(r300ContextPtr rmesa, int vertex_count, int type) + int cmd_written = 0; + drm_radeon_cmd_header_t *cmd = NULL; + +- start_packet3(RADEON_CP_PACKET3_3D_DRAW_VBUF_2, 0); +- e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (vertex_count << 16) +- | type); ++ start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0), 0); ++ e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (vertex_count << 16) | type); + } + + static void r300RunRenderPrimitive(r300ContextPtr rmesa, GLcontext * ctx, + int start, int end, int prim) + { + int type, num_verts; ++ TNLcontext *tnl = TNL_CONTEXT(ctx); ++ struct vertex_buffer *vb = &tnl->vb; + +- type = r300PrimitiveType(rmesa, ctx, prim); ++ type = r300PrimitiveType(rmesa, prim); + num_verts = r300NumVerts(rmesa, end - start, prim); + + if (type < 0 || num_verts <= 0) + return; + +- if (rmesa->state.VB.Elts) { ++ if (vb->Elts) { + r300EmitAOS(rmesa, rmesa->state.aos_count, start); + if (num_verts > 65535) { + /* not implemented yet */ + WARN_ONCE("Too many elts\n"); + return; + } +- r300EmitElts(ctx, rmesa->state.VB.Elts, num_verts, +- rmesa->state.VB.elt_size); +- r300FireEB(rmesa, rmesa->state.elt_dma.aos_offset, +- num_verts, type, rmesa->state.VB.elt_size); ++ r300EmitElts(ctx, vb->Elts, num_verts); ++ r300FireEB(rmesa, rmesa->state.elt_dma.aos_offset, num_verts, type); + } else { + r300EmitAOS(rmesa, rmesa->state.aos_count, start); + r300FireAOS(rmesa, num_verts, type); + } + } + +-#define CONV_VB(a, b) rvb->AttribPtr[(a)].size = vb->b->size, \ +- rvb->AttribPtr[(a)].type = GL_FLOAT, \ +- rvb->AttribPtr[(a)].stride = vb->b->stride, \ +- rvb->AttribPtr[(a)].data = vb->b->data +- +-static void radeon_vb_to_rvb(r300ContextPtr rmesa, +- struct radeon_vertex_buffer *rvb, +- struct vertex_buffer *vb) +-{ +- int i; +- GLcontext *ctx; +- ctx = rmesa->radeon.glCtx; +- +- memset(rvb, 0, sizeof(*rvb)); +- +- rvb->Elts = vb->Elts; +- rvb->elt_size = 4; +- rvb->elt_min = 0; +- rvb->elt_max = vb->Count; +- +- rvb->Count = vb->Count; +- +- if (hw_tcl_on) { +- CONV_VB(VERT_ATTRIB_POS, ObjPtr); +- } else { +- assert(vb->ClipPtr); +- CONV_VB(VERT_ATTRIB_POS, ClipPtr); +- } +- +- CONV_VB(VERT_ATTRIB_NORMAL, NormalPtr); +- CONV_VB(VERT_ATTRIB_COLOR0, ColorPtr[0]); +- CONV_VB(VERT_ATTRIB_COLOR1, SecondaryColorPtr[0]); +- CONV_VB(VERT_ATTRIB_FOG, FogCoordPtr); +- +- for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) +- CONV_VB(VERT_ATTRIB_TEX0 + i, TexCoordPtr[i]); +- +- for (i = 0; i < MAX_VERTEX_PROGRAM_ATTRIBS; i++) +- CONV_VB(VERT_ATTRIB_GENERIC0 + i, +- AttribPtr[VERT_ATTRIB_GENERIC0 + i]); +- +- rvb->Primitive = vb->Primitive; +- rvb->PrimitiveCount = vb->PrimitiveCount; +- rvb->LockFirst = rvb->LockCount = 0; +- rvb->lock_uptodate = GL_FALSE; +-} +- + static GLboolean r300RunRender(GLcontext * ctx, + struct tnl_pipeline_stage *stage) + { + r300ContextPtr rmesa = R300_CONTEXT(ctx); +- struct radeon_vertex_buffer *VB = &rmesa->state.VB; + int i; +- int cmd_reserved = 0; +- int cmd_written = 0; +- drm_radeon_cmd_header_t *cmd = NULL; ++ TNLcontext *tnl = TNL_CONTEXT(ctx); ++ struct vertex_buffer *vb = &tnl->vb; ++ + + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s\n", __FUNCTION__); + +- if (stage) { +- TNLcontext *tnl = TNL_CONTEXT(ctx); +- radeon_vb_to_rvb(rmesa, VB, &tnl->vb); +- } +- + r300UpdateShaders(rmesa); + if (r300EmitArrays(ctx)) + return GL_TRUE; + + r300UpdateShaderStates(rmesa); + +- reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0); +- e32(R300_RB3D_DSTCACHE_UNKNOWN_0A); +- +- reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0); +- e32(R300_RB3D_ZCACHE_UNKNOWN_03); +- ++ r300EmitCacheFlush(rmesa); + r300EmitState(rmesa); + +- for (i = 0; i < VB->PrimitiveCount; i++) { +- GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); +- GLuint start = VB->Primitive[i].start; +- GLuint end = VB->Primitive[i].start + VB->Primitive[i].count; ++ for (i = 0; i < vb->PrimitiveCount; i++) { ++ GLuint prim = _tnl_translate_prim(&vb->Primitive[i]); ++ GLuint start = vb->Primitive[i].start; ++ GLuint end = vb->Primitive[i].start + vb->Primitive[i].count; + r300RunRenderPrimitive(rmesa, ctx, start, end, prim); + } + +- reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0); +- e32(R300_RB3D_DSTCACHE_UNKNOWN_0A); +- +- reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0); +- e32(R300_RB3D_ZCACHE_UNKNOWN_03); ++ r300EmitCacheFlush(rmesa); + + #ifdef USER_BUFFERS + r300UseArrays(ctx); +@@ -463,8 +358,6 @@ static int r300Fallback(GLcontext * ctx) + FALLBACK_IF(ctx->Point.PointSprite); + + if (!r300->disable_lowimpact_fallback) { +- FALLBACK_IF(ctx->Polygon.OffsetPoint); +- FALLBACK_IF(ctx->Polygon.OffsetLine); + FALLBACK_IF(ctx->Polygon.StippleFlag); + FALLBACK_IF(ctx->Multisample.Enabled); + FALLBACK_IF(ctx->Line.StippleFlag); +@@ -478,12 +371,17 @@ static int r300Fallback(GLcontext * ctx) + static GLboolean r300RunNonTCLRender(GLcontext * ctx, + struct tnl_pipeline_stage *stage) + { ++ r300ContextPtr rmesa = R300_CONTEXT(ctx); ++ + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (r300Fallback(ctx) >= R300_FALLBACK_RAST) + return GL_TRUE; + ++ if (!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) ++ return GL_TRUE; ++ + return r300RunRender(ctx, stage); + } + +diff --git a/src/mesa/drivers/dri/r300/r300_shader.c b/src/mesa/drivers/dri/r300/r300_shader.c +index 59fe17b..5f5ac7c 100644 +--- a/src/mesa/drivers/dri/r300/r300_shader.c ++++ b/src/mesa/drivers/dri/r300/r300_shader.c +@@ -54,6 +54,7 @@ r300ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog) + fp->translated = GL_FALSE; + break; + } ++ + /* need this for tcl fallbacks */ + _tnl_program_string(ctx, target, prog); + } +@@ -61,7 +62,7 @@ r300ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog) + static GLboolean + r300IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog) + { +- return 1; ++ return GL_TRUE; + } + + void r300InitShaderFuncs(struct dd_function_table *functions) +diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c +index e8d67f9..088216c 100644 +--- a/src/mesa/drivers/dri/r300/r300_state.c ++++ b/src/mesa/drivers/dri/r300/r300_state.c +@@ -65,6 +65,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + #include "drirenderbuffer.h" + ++extern int future_hw_tcl_on; ++extern void _tnl_UpdateFixedFunctionProgram(GLcontext * ctx); ++ + static void r300BlendColor(GLcontext * ctx, const GLfloat cf[4]) + { + GLubyte color[4]; +@@ -79,6 +82,8 @@ static void r300BlendColor(GLcontext * ctx, const GLfloat cf[4]) + + rmesa->hw.blend_color.cmd[1] = PACK_COLOR_8888(color[3], color[0], + color[1], color[2]); ++ rmesa->hw.blend_color.cmd[2] = 0; ++ rmesa->hw.blend_color.cmd[3] = 0; + } + + /** +@@ -314,20 +319,34 @@ 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) ++ switch (ctx->Polygon.CullFaceMode) { ++ case GL_FRONT: + val = R300_CULL_FRONT; +- else ++ break; ++ case GL_BACK: + val = R300_CULL_BACK; ++ break; ++ case GL_FRONT_AND_BACK: ++ val = R300_CULL_FRONT | R300_CULL_BACK; ++ break; ++ default: ++ break; ++ } ++ } + +- if (ctx->Polygon.FrontFace == GL_CW) +- val |= R300_FRONT_FACE_CW; +- else +- val |= R300_FRONT_FACE_CCW; ++ switch (ctx->Polygon.FrontFace) { ++ case GL_CW: ++ val |= R300_FRONT_FACE_CW; ++ break; ++ case GL_CCW: ++ val |= R300_FRONT_FACE_CCW; ++ break; ++ default: ++ break; + } ++ ++ R300_STATECHANGE(r300, cul); + r300->hw.cul.cmd[R300_CUL_CULL] = val; + } + +@@ -341,6 +360,20 @@ static void r300SetEarlyZState(GLcontext * ctx) + r300ContextPtr r300 = R300_CONTEXT(ctx); + + R300_STATECHANGE(r300, zstencil_format); ++ switch (ctx->Visual.depthBits) { ++ case 16: ++ r300->hw.zstencil_format.cmd[1] = R300_DEPTH_FORMAT_16BIT_INT_Z; ++ break; ++ case 24: ++ r300->hw.zstencil_format.cmd[1] = R300_DEPTH_FORMAT_24BIT_INT_Z; ++ break; ++ default: ++ fprintf(stderr, "Error: Unsupported depth %d... exiting\n", ctx->Visual.depthBits); ++ _mesa_exit(-1); ++ } ++ ++ // r300->hw.zstencil_format.cmd[1] |= R300_DEPTH_FORMAT_UNK32; ++ + if (ctx->Color.AlphaEnabled && ctx->Color.AlphaFunc != GL_ALWAYS) + /* disable early Z */ + r300->hw.zstencil_format.cmd[2] = R300_EARLY_Z_DISABLE; +@@ -352,6 +385,9 @@ static void r300SetEarlyZState(GLcontext * ctx) + /* disable early Z */ + r300->hw.zstencil_format.cmd[2] = R300_EARLY_Z_DISABLE; + } ++ ++ r300->hw.zstencil_format.cmd[3] = 0x00000003; ++ r300->hw.zstencil_format.cmd[4] = 0x00000000; + } + + static void r300SetAlphaState(GLcontext * ctx) +@@ -400,6 +436,7 @@ static void r300SetAlphaState(GLcontext * ctx) + + R300_STATECHANGE(r300, at); + r300->hw.at.cmd[R300_AT_ALPHA_TEST] = pp_misc; ++ r300->hw.at.cmd[R300_AT_UNKNOWN] = 0; + + r300SetEarlyZState(ctx); + } +@@ -462,97 +499,6 @@ static void r300SetDepthState(GLcontext * ctx) + r300SetEarlyZState(ctx); + } + +-/** +- * 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); +- +- 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_FOG: +- R300_STATECHANGE(r300, fogs); +- if (state) { +- r300->hw.fogs.cmd[R300_FOGS_STATE] |= R300_FOG_ENABLE; +- +- ctx->Driver.Fogfv(ctx, GL_FOG_MODE, NULL); +- ctx->Driver.Fogfv(ctx, GL_FOG_DENSITY, +- &ctx->Fog.Density); +- ctx->Driver.Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start); +- ctx->Driver.Fogfv(ctx, GL_FOG_END, &ctx->Fog.End); +- ctx->Driver.Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color); +- } else { +- r300->hw.fogs.cmd[R300_FOGS_STATE] &= ~R300_FOG_ENABLE; +- } +- +- break; +- +- case GL_ALPHA_TEST: +- r300SetAlphaState(ctx); +- break; +- +- case GL_BLEND: +- case GL_COLOR_LOGIC_OP: +- r300SetBlendState(ctx); +- break; +- +- case GL_DEPTH_TEST: +- r300SetDepthState(ctx); +- break; +- +- case GL_STENCIL_TEST: +- 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 { +-#if R200_MERGED +- FALLBACK(&r300->radeon, RADEON_FALLBACK_STENCIL, state); +-#endif +- } +- break; +- +- case GL_CULL_FACE: +- r300UpdateCulling(ctx); +- break; +- +- case GL_POLYGON_OFFSET_POINT: +- case GL_POLYGON_OFFSET_LINE: +- break; +- +- case GL_POLYGON_OFFSET_FILL: +- R300_STATECHANGE(r300, occlusion_cntl); +- if (state) { +- r300->hw.occlusion_cntl.cmd[1] |= (3 << 0); +- } else { +- r300->hw.occlusion_cntl.cmd[1] &= ~(3 << 0); +- } +- break; +- default: +- radeonEnable(ctx, cap, state); +- return; +- } +-} +- + static void r300UpdatePolygonMode(GLcontext * ctx) + { + r300ContextPtr r300 = R300_CONTEXT(ctx); +@@ -601,6 +547,9 @@ static void r300UpdatePolygonMode(GLcontext * ctx) + R300_STATECHANGE(r300, polygon_mode); + r300->hw.polygon_mode.cmd[1] = hw_mode; + } ++ ++ r300->hw.polygon_mode.cmd[2] = 0x00000001; ++ r300->hw.polygon_mode.cmd[3] = 0x00000000; + } + + /** +@@ -784,8 +733,8 @@ static void r300Fogfv(GLcontext * ctx, GLenum pname, const GLfloat * param) + static void r300PointSize(GLcontext * ctx, GLfloat size) + { + r300ContextPtr r300 = R300_CONTEXT(ctx); +- +- size = ctx->Point._Size; ++ /* same size limits for AA, non-AA points */ ++ size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize); + + R300_STATECHANGE(r300, ps); + r300->hw.ps.cmd[R300_PS_POINTSIZE] = +@@ -800,11 +749,12 @@ static void r300LineWidth(GLcontext * ctx, GLfloat widthf) + { + r300ContextPtr r300 = R300_CONTEXT(ctx); + +- widthf = ctx->Line._Width; +- ++ widthf = CLAMP(widthf, ++ ctx->Const.MinPointSize, ++ ctx->Const.MaxPointSize); + R300_STATECHANGE(r300, lcntl); +- r300->hw.lcntl.cmd[1] = (int)(widthf * 6.0); +- r300->hw.lcntl.cmd[1] |= R300_LINE_CNT_VE; ++ r300->hw.lcntl.cmd[1] = ++ R300_LINE_CNT_HO | R300_LINE_CNT_VE | (int)(widthf * 6.0); + } + + static void r300PolygonMode(GLcontext * ctx, GLenum face, GLenum mode) +@@ -850,6 +800,7 @@ static void r300ShadeModel(GLcontext * ctx, GLenum mode) + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + R300_STATECHANGE(rmesa, shade); ++ rmesa->hw.shade.cmd[1] = 0x00000002; + switch (mode) { + case GL_FLAT: + rmesa->hw.shade.cmd[2] = R300_RE_SHADE_MODEL_FLAT; +@@ -860,6 +811,8 @@ static void r300ShadeModel(GLcontext * ctx, GLenum mode) + default: + return; + } ++ rmesa->hw.shade.cmd[3] = 0x00000000; ++ rmesa->hw.shade.cmd[4] = 0x00000000; + } + + static void r300StencilFuncSeparate(GLcontext * ctx, GLenum face, +@@ -1460,11 +1413,9 @@ static void r300SetupRSUnit(GLcontext * ctx) + int i; + + if (hw_tcl_on) +- OutputsWritten.vp_outputs = +- CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten; ++ OutputsWritten.vp_outputs = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten; + else +- RENDERINPUTS_COPY(OutputsWritten.index_bitset, +- r300->state.render_inputs_bitset); ++ RENDERINPUTS_COPY(OutputsWritten.index_bitset, r300->state.render_inputs_bitset); + + if (ctx->FragmentProgram._Current) + InputsRead = ctx->FragmentProgram._Current->Base.InputsRead; +@@ -1496,9 +1447,7 @@ static void r300SetupRSUnit(GLcontext * ctx) + } + + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { +- r300->hw.ri.cmd[R300_RI_INTERP_0 + i] = 0 +- | R300_RS_INTERP_USED +- | (in_texcoords << R300_RS_INTERP_SRC_SHIFT) ++ r300->hw.ri.cmd[R300_RI_INTERP_0 + i] = 0 | R300_RS_INTERP_USED | (in_texcoords << R300_RS_INTERP_SRC_SHIFT) + | interp_magic[i]; + + r300->hw.rr.cmd[R300_RR_ROUTE_0 + fp_reg] = 0; +@@ -1508,65 +1457,45 @@ static void r300SetupRSUnit(GLcontext * ctx) + | (fp_reg << R300_RS_ROUTE_DEST_SHIFT); + high_rr = fp_reg; + +- if (!R300_OUTPUTS_WRITTEN_TEST +- (OutputsWritten, VERT_RESULT_TEX0 + i, +- _TNL_ATTRIB_TEX(i))) { +- /* Passing invalid data here can lock the GPU. */ +- WARN_ONCE +- ("fragprog wants coords for tex%d, vp doesn't provide them!\n", +- i); +- //_mesa_print_program(&CURRENT_VERTEX_SHADER(ctx)->Base); +- //_mesa_exit(-1); ++ /* Passing invalid data here can lock the GPU. */ ++ if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_TEX0 + i, _TNL_ATTRIB_TEX(i))) { ++ InputsRead &= ~(FRAG_BIT_TEX0 << i); ++ fp_reg++; ++ } else { ++ WARN_ONCE("fragprog wants coords for tex%d, vp doesn't provide them!\n", i); + } +- InputsRead &= ~(FRAG_BIT_TEX0 << i); +- fp_reg++; + } + /* Need to count all coords enabled at vof */ +- if (R300_OUTPUTS_WRITTEN_TEST +- (OutputsWritten, VERT_RESULT_TEX0 + i, _TNL_ATTRIB_TEX(i))) ++ if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_TEX0 + i, _TNL_ATTRIB_TEX(i))) { + in_texcoords++; ++ } + } + + if (InputsRead & FRAG_BIT_COL0) { +- if (!R300_OUTPUTS_WRITTEN_TEST +- (OutputsWritten, VERT_RESULT_COL0, _TNL_ATTRIB_COLOR0)) { +- WARN_ONCE +- ("fragprog wants col0, vp doesn't provide it\n"); +- goto out; /* FIXME */ +- //_mesa_print_program(&CURRENT_VERTEX_SHADER(ctx)->Base); +- //_mesa_exit(-1); ++ if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_COL0, _TNL_ATTRIB_COLOR0)) { ++ r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0 | R300_RS_ROUTE_0_COLOR | (fp_reg++ << R300_RS_ROUTE_0_COLOR_DEST_SHIFT); ++ InputsRead &= ~FRAG_BIT_COL0; ++ col_interp_nr++; ++ } else { ++ WARN_ONCE("fragprog wants col0, vp doesn't provide it\n"); + } +- +- r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0 +- | R300_RS_ROUTE_0_COLOR +- | (fp_reg++ << R300_RS_ROUTE_0_COLOR_DEST_SHIFT); +- InputsRead &= ~FRAG_BIT_COL0; +- col_interp_nr++; + } +- out: + + if (InputsRead & FRAG_BIT_COL1) { +- if (!R300_OUTPUTS_WRITTEN_TEST +- (OutputsWritten, VERT_RESULT_COL1, _TNL_ATTRIB_COLOR1)) { +- WARN_ONCE +- ("fragprog wants col1, vp doesn't provide it\n"); +- //_mesa_exit(-1); ++ if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_COL1, _TNL_ATTRIB_COLOR1)) { ++ r300->hw.rr.cmd[R300_RR_ROUTE_1] |= R300_RS_ROUTE_1_UNKNOWN11 | R300_RS_ROUTE_1_COLOR1 | (fp_reg++ << R300_RS_ROUTE_1_COLOR1_DEST_SHIFT); ++ InputsRead &= ~FRAG_BIT_COL1; ++ if (high_rr < 1) ++ high_rr = 1; ++ col_interp_nr++; ++ } else { ++ WARN_ONCE("fragprog wants col1, vp doesn't provide it\n"); + } +- +- r300->hw.rr.cmd[R300_RR_ROUTE_1] |= +- R300_RS_ROUTE_1_UNKNOWN11 | R300_RS_ROUTE_1_COLOR1 | +- (fp_reg++ << R300_RS_ROUTE_1_COLOR1_DEST_SHIFT); +- InputsRead &= ~FRAG_BIT_COL1; +- if (high_rr < 1) +- high_rr = 1; +- col_interp_nr++; + } + + /* Need at least one. This might still lock as the values are undefined... */ + if (in_texcoords == 0 && col_interp_nr == 0) { +- r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0 +- | R300_RS_ROUTE_0_COLOR +- | (fp_reg++ << R300_RS_ROUTE_0_COLOR_DEST_SHIFT); ++ r300->hw.rr.cmd[R300_RR_ROUTE_0] |= 0 | R300_RS_ROUTE_0_COLOR | (fp_reg++ << R300_RS_ROUTE_0_COLOR_DEST_SHIFT); + col_interp_nr++; + } + +@@ -1575,17 +1504,13 @@ static void r300SetupRSUnit(GLcontext * ctx) + | R300_RS_CNTL_0_UNKNOWN_18; + + assert(high_rr >= 0); +- r300->hw.rr.cmd[R300_RR_CMD_0] = +- cmdpacket0(R300_RS_ROUTE_0, high_rr + 1); ++ r300->hw.rr.cmd[R300_RR_CMD_0] = cmdpacket0(R300_RS_ROUTE_0, high_rr + 1); + r300->hw.rc.cmd[2] = 0xC0 | high_rr; + + if (InputsRead) +- WARN_ONCE("Don't know how to satisfy InputsRead=0x%08x\n", +- InputsRead); ++ WARN_ONCE("Don't know how to satisfy InputsRead=0x%08x\n", InputsRead); + } + +-#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; \ +@@ -1593,9 +1518,7 @@ static void r300SetupRSUnit(GLcontext * ctx) + 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) ++static inline void r300SetupVertexProgramFragment(r300ContextPtr r300, int dest, struct r300_vertex_shader_fragment *vsf) + { + int i; + +@@ -1603,8 +1526,7 @@ void static inline setup_vertex_shader_fragment(r300ContextPtr r300, int dest, s + return; + + if (vsf->length & 0x3) { +- fprintf(stderr, +- "VERTEX_SHADER_FRAGMENT must have length divisible by 4\n"); ++ fprintf(stderr, "VERTEX_SHADER_FRAGMENT must have length divisible by 4\n"); + _mesa_exit(-1); + } + +@@ -1612,147 +1534,101 @@ void static inline setup_vertex_shader_fragment(r300ContextPtr r300, int dest, s + case 0: + R300_STATECHANGE(r300, vpi); + for (i = 0; i < vsf->length; 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)); ++ 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; i < vsf->length; 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)); ++ 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; i < vsf->length; 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)); ++ 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); ++ fprintf(stderr, "%s:%s don't know how to handle dest %04x\n", __FILE__, __FUNCTION__, dest); + _mesa_exit(-1); + } + } + +-/* 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 */ +-static void r300GenerateSimpleVertexShader(r300ContextPtr r300) ++static void r300SetupDefaultVertexProgram(r300ContextPtr rmesa) + { +- int i; ++ struct r300_vertex_shader_state *prog = &(rmesa->state.vertex_shader); + GLuint o_reg = 0; +- +- /* 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 */ +- +- 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].src[0]=(source1); \ +- r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].src[1]=(source2); \ +- r300->state.vertex_shader.program.body.i[r300->state.vertex_shader.program_end].src[2]=(source3); \ +- r300->state.vertex_shader.program_end++; \ +- } +- +- for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_MAX; i++) +- if (r300->state.sw_tcl_inputs[i] != -1) { +- WRITE_OP(EASY_VSF_OP(MUL, o_reg++, ALL, RESULT), +- VSF_REG(r300->state.sw_tcl_inputs[i]), +- VSF_ATTR_UNITY(r300->state. +- sw_tcl_inputs[i]), +- VSF_UNITY(r300->state.sw_tcl_inputs[i]) +- ) +- ++ int i; ++ int inst_count = 0; ++ int param_count = 0; ++ int program_end = 0; ++ ++ for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_MAX; i++) { ++ if (rmesa->state.sw_tcl_inputs[i] != -1) { ++ prog->program.body.i[program_end + 0] = EASY_VSF_OP(MUL, o_reg++, ALL, RESULT); ++ prog->program.body.i[program_end + 1] = VSF_REG(rmesa->state.sw_tcl_inputs[i]); ++ prog->program.body.i[program_end + 2] = VSF_ATTR_UNITY(rmesa->state.sw_tcl_inputs[i]); ++ prog->program.body.i[program_end + 3] = VSF_UNITY(rmesa->state.sw_tcl_inputs[i]); ++ program_end += 4; + } ++ } + +- 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; ++ prog->program.length = program_end; + +- 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 ? */ ++ r300SetupVertexProgramFragment(rmesa, R300_PVS_UPLOAD_PROGRAM, ++ &(prog->program)); ++ inst_count = (prog->program.length / 4) - 1; + ++ R300_STATECHANGE(rmesa, pvs); ++ rmesa->hw.pvs.cmd[R300_PVS_CNTL_1] = ++ (0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) | ++ (inst_count << R300_PVS_CNTL_1_POS_END_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] = ++ (inst_count << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT) | ++ (inst_count << R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT); + } + +-static void r300SetupVertexProgram(r300ContextPtr rmesa) ++static void r300SetupRealVertexProgram(r300ContextPtr rmesa) + { + GLcontext *ctx = rmesa->radeon.glCtx; +- int inst_count; +- int param_count; +- struct r300_vertex_program *prog = +- (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); ++ struct r300_vertex_program *prog = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); ++ int inst_count = 0; ++ int param_count = 0; + +- ((drm_r300_cmd_header_t *) rmesa->hw.vpp.cmd)->vpu.count = 0; ++ /* FIXME: r300SetupVertexProgramFragment */ + R300_STATECHANGE(rmesa, vpp); + param_count = +- r300VertexProgUpdateParams(ctx, (struct r300_vertex_program_cont *) +- ctx->VertexProgram._Current /*prog */ , ++ r300VertexProgUpdateParams(ctx, ++ (struct r300_vertex_program_cont *) ++ ctx->VertexProgram._Current, + (float *)&rmesa->hw.vpp. + cmd[R300_VPP_PARAM_0]); + bump_vpu_count(rmesa->hw.vpp.cmd, param_count); + param_count /= 4; + +- /* Reset state, in case we don't use something */ +- ((drm_r300_cmd_header_t *) rmesa->hw.vpi.cmd)->vpu.count = 0; +- ((drm_r300_cmd_header_t *) rmesa->hw.vps.cmd)->vpu.count = 0; +- +- setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(prog->program)); +- +-#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 = prog->program.length / 4 - 1; ++ r300SetupVertexProgramFragment(rmesa, R300_PVS_UPLOAD_PROGRAM, &(prog->program)); ++ inst_count = (prog->program.length / 4) - 1; + + R300_STATECHANGE(rmesa, pvs); + rmesa->hw.pvs.cmd[R300_PVS_CNTL_1] = +- (0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) +- | (inst_count /*pos_end */ << R300_PVS_CNTL_1_POS_END_SHIFT) +- | (inst_count << R300_PVS_CNTL_1_PROGRAM_END_SHIFT); ++ (0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) | ++ (inst_count << R300_PVS_CNTL_1_POS_END_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); ++ (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->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 ++ (inst_count << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT) | ++ (inst_count << R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT); + } + +-static void r300SetupVertexShader(r300ContextPtr rmesa) ++static void r300SetupVertexProgram(r300ContextPtr rmesa) + { + GLcontext *ctx = rmesa->radeon.glCtx; + +@@ -1765,50 +1641,108 @@ static void r300SetupVertexShader(r300ContextPtr rmesa) + 0x400 area might have something to do with pixel shaders as it appears right after pfs programming. + 0x406 is set to { 0.0, 0.0, 1.0, 0.0 } most of the time but should change with smooth points and in other rare cases. */ + //setup_vertex_shader_fragment(rmesa, 0x406, &unk4); +- if (hw_tcl_on +- && ((struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx))-> +- translated) { +- r300SetupVertexProgram(rmesa); +- return; ++ if (hw_tcl_on && ((struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx))->translated) { ++ r300SetupRealVertexProgram(rmesa); ++ } else { ++ /* FIXME: This needs to be replaced by vertex shader generation code. */ ++ r300SetupDefaultVertexProgram(rmesa); + } + +- /* This needs to be replaced by vertex shader generation code */ +- r300GenerateSimpleVertexShader(rmesa); +- +- setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, +- &(rmesa->state.vertex_shader.program)); + ++ /* FIXME: 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 +- 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)); ++ reg_start(R300_VAP_PVS_WAITIDLE, 0); ++ e32(0x00000000); + #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_POS_END_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); ++/** ++ * Enable/Disable states. ++ * ++ * \note Mesa already filters redundant calls to this function. ++ */ ++static void r300Enable(GLcontext * ctx, GLenum cap, GLboolean state) ++{ ++ r300ContextPtr r300 = R300_CONTEXT(ctx); + +- /* 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); ++ 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_FOG: ++ R300_STATECHANGE(r300, fogs); ++ if (state) { ++ r300->hw.fogs.cmd[R300_FOGS_STATE] |= R300_FOG_ENABLE; ++ ++ r300Fogfv(ctx, GL_FOG_MODE, NULL); ++ r300Fogfv(ctx, GL_FOG_DENSITY, &ctx->Fog.Density); ++ r300Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start); ++ r300Fogfv(ctx, GL_FOG_END, &ctx->Fog.End); ++ r300Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color); ++ } else { ++ r300->hw.fogs.cmd[R300_FOGS_STATE] &= ~R300_FOG_ENABLE; ++ } ++ ++ break; ++ ++ case GL_ALPHA_TEST: ++ r300SetAlphaState(ctx); ++ break; ++ ++ case GL_BLEND: ++ case GL_COLOR_LOGIC_OP: ++ r300SetBlendState(ctx); ++ break; ++ ++ case GL_DEPTH_TEST: ++ r300SetDepthState(ctx); ++ break; ++ ++ case GL_STENCIL_TEST: ++ 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 { ++#if R200_MERGED ++ FALLBACK(&r300->radeon, RADEON_FALLBACK_STENCIL, state); + #endif ++ } ++ break; ++ ++ case GL_CULL_FACE: ++ r300UpdateCulling(ctx); ++ break; ++ ++ case GL_POLYGON_OFFSET_POINT: ++ case GL_POLYGON_OFFSET_LINE: ++ case GL_POLYGON_OFFSET_FILL: ++ R300_STATECHANGE(r300, occlusion_cntl); ++ if (state) { ++ r300->hw.occlusion_cntl.cmd[1] |= (3 << 0); ++ } else { ++ r300->hw.occlusion_cntl.cmd[1] &= ~(3 << 0); ++ } ++ break; ++ default: ++ radeonEnable(ctx, cap, state); ++ return; ++ } + } + + /** +@@ -1825,12 +1759,6 @@ static void r300ResetHwState(r300ContextPtr r300) + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "%s\n", __FUNCTION__); + +- /* This is a place to initialize registers which +- have bitfields accessed by different functions +- and not all bits are used */ +- +- /* go and compute register values from GL state */ +- + r300UpdateWindow(ctx); + + r300ColorMask(ctx, +@@ -1860,13 +1788,11 @@ static void r300ResetHwState(r300ContextPtr r300) + 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 */ + if (!has_tcl) + r300->hw.vap_cntl.cmd[1] = 0x0014045a; + else + r300->hw.vap_cntl.cmd[1] = 0x0030045A; //0x0030065a /* Dangerous */ ++ + r300->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA + | R300_VPORT_X_OFFSET_ENA + | R300_VPORT_Y_SCALE_ENA +@@ -1877,10 +1803,12 @@ static void r300ResetHwState(r300ContextPtr r300) + + r300->hw.unk2134.cmd[1] = 0x00FFFFFF; + r300->hw.unk2134.cmd[2] = 0x00000000; +- if (_mesa_little_endian()) +- r300->hw.vap_cntl_status.cmd[1] = R300_VC_NO_SWAP; +- else +- r300->hw.vap_cntl_status.cmd[1] = R300_VC_32BIT_SWAP; ++ ++#ifdef MESA_LITTLE_ENDIAN ++ r300->hw.vap_cntl_status.cmd[1] = R300_VC_NO_SWAP; ++#else ++ r300->hw.vap_cntl_status.cmd[1] = R300_VC_32BIT_SWAP; ++#endif + + /* disable VAP/TCL on non-TCL capable chips */ + if (!has_tcl) +@@ -1890,16 +1818,22 @@ static void r300ResetHwState(r300ContextPtr r300) + + r300->hw.unk221C.cmd[1] = R300_221C_NORMAL; + +- r300->hw.unk2220.cmd[1] = r300PackFloat32(1.0); +- r300->hw.unk2220.cmd[2] = r300PackFloat32(1.0); +- r300->hw.unk2220.cmd[3] = r300PackFloat32(1.0); +- r300->hw.unk2220.cmd[4] = r300PackFloat32(1.0); ++ r300->hw.vap_clip.cmd[1] = r300PackFloat32(1.0); /* X */ ++ r300->hw.vap_clip.cmd[2] = r300PackFloat32(1.0); /* X */ ++ r300->hw.vap_clip.cmd[3] = r300PackFloat32(1.0); /* Y */ ++ r300->hw.vap_clip.cmd[4] = r300PackFloat32(1.0); /* Y */ + +- /* what about other chips than r300 or rv350??? */ +- if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R300) +- r300->hw.unk2288.cmd[1] = R300_2288_R300; +- else +- r300->hw.unk2288.cmd[1] = R300_2288_RV350; ++ /* XXX: Other families? */ ++ if (has_tcl) { ++ switch (r300->radeon.radeonScreen->chip_family) { ++ case CHIP_FAMILY_R300: ++ r300->hw.unk2288.cmd[1] = R300_2288_R300; ++ break; ++ default: ++ r300->hw.unk2288.cmd[1] = R300_2288_RV350; ++ break; ++ } ++ } + + r300->hw.gb_enable.cmd[1] = R300_GB_POINT_STUFF_ENABLE + | R300_GB_LINE_STUFF_ENABLE +@@ -1907,26 +1841,35 @@ static void r300ResetHwState(r300ContextPtr r300) + + r300->hw.gb_misc.cmd[R300_GB_MISC_MSPOS_0] = 0x66666666; + r300->hw.gb_misc.cmd[R300_GB_MISC_MSPOS_1] = 0x06666666; +- if ((r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R300) || +- (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_R350)) +- 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 (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV410) +- r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = +- R300_GB_TILE_ENABLE | R300_GB_TILE_PIPE_COUNT_RV410 | +- R300_GB_TILE_SIZE_16; +- else if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_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.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = +- R300_GB_TILE_ENABLE | R300_GB_TILE_PIPE_COUNT_RV300 | +- R300_GB_TILE_SIZE_16; +- /* set to 0 when fog is disabled? */ ++ ++ /* XXX: Other families? */ ++ r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = ++ R300_GB_TILE_ENABLE | R300_GB_TILE_SIZE_16; ++ switch (r300->radeon.radeonScreen->chip_family) { ++ case CHIP_FAMILY_R300: ++ case CHIP_FAMILY_R350: ++ r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] |= ++ R300_GB_TILE_PIPE_COUNT_R300; ++ break; ++ case CHIP_FAMILY_RV410: ++ r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] |= ++ R300_GB_TILE_PIPE_COUNT_RV410; ++ break; ++ case CHIP_FAMILY_R420: ++ r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] |= ++ R300_GB_TILE_PIPE_COUNT_R420; ++ break; ++ default: ++ r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] |= ++ R300_GB_TILE_PIPE_COUNT_RV300; ++ break; ++ } ++ ++ /* XXX: set to 0 when fog is disabled? */ + r300->hw.gb_misc.cmd[R300_GB_MISC_SELECT] = R300_GB_FOG_SELECT_1_1_W; +- r300->hw.gb_misc.cmd[R300_GB_MISC_AA_CONFIG] = R300_AA_DISABLE; /* No antialiasing */ ++ ++ /* XXX: Enable anti-aliasing? */ ++ r300->hw.gb_misc.cmd[R300_GB_MISC_AA_CONFIG] = R300_AA_DISABLE; + + r300->hw.unk4200.cmd[1] = r300PackFloat32(0.0); + r300->hw.unk4200.cmd[2] = r300PackFloat32(0.0); +@@ -1935,31 +1878,28 @@ static void r300ResetHwState(r300ContextPtr r300) + + r300->hw.unk4214.cmd[1] = 0x00050005; + +- r300PointSize(ctx, 0.0); ++ r300PointSize(ctx, 1.0); + + r300->hw.unk4230.cmd[1] = 0x18000006; + r300->hw.unk4230.cmd[2] = 0x00020006; + r300->hw.unk4230.cmd[3] = r300PackFloat32(1.0 / 192.0); + +- r300LineWidth(ctx, 0.0); ++ r300LineWidth(ctx, 1.0); + + r300->hw.unk4260.cmd[1] = 0; + r300->hw.unk4260.cmd[2] = r300PackFloat32(0.0); + r300->hw.unk4260.cmd[3] = r300PackFloat32(1.0); + +- r300->hw.shade.cmd[1] = 0x00000002; + r300ShadeModel(ctx, ctx->Light.ShadeModel); +- r300->hw.shade.cmd[3] = 0x00000000; +- r300->hw.shade.cmd[4] = 0x00000000; + + r300PolygonMode(ctx, GL_FRONT, ctx->Polygon.FrontMode); + r300PolygonMode(ctx, GL_BACK, ctx->Polygon.BackMode); +- r300->hw.polygon_mode.cmd[2] = 0x00000001; +- r300->hw.polygon_mode.cmd[3] = 0x00000000; + r300->hw.zbias_cntl.cmd[1] = 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; +@@ -1977,21 +1917,18 @@ static void r300ResetHwState(r300ContextPtr r300) + r300->hw.unk46A4.cmd[5] = 0x00000001; + + r300Enable(ctx, GL_FOG, ctx->Fog.Enabled); +- ctx->Driver.Fogfv(ctx, GL_FOG_MODE, NULL); +- ctx->Driver.Fogfv(ctx, GL_FOG_DENSITY, &ctx->Fog.Density); +- ctx->Driver.Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start); +- ctx->Driver.Fogfv(ctx, GL_FOG_END, &ctx->Fog.End); +- ctx->Driver.Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color); +- ctx->Driver.Fogfv(ctx, GL_FOG_COORDINATE_SOURCE_EXT, NULL); ++ r300Fogfv(ctx, GL_FOG_MODE, NULL); ++ r300Fogfv(ctx, GL_FOG_DENSITY, &ctx->Fog.Density); ++ r300Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start); ++ r300Fogfv(ctx, GL_FOG_END, &ctx->Fog.End); ++ r300Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color); ++ r300Fogfv(ctx, GL_FOG_COORDINATE_SOURCE_EXT, NULL); + +- r300->hw.at.cmd[R300_AT_UNKNOWN] = 0; + r300->hw.unk4BD8.cmd[1] = 0; + + r300->hw.unk4E00.cmd[1] = 0; + + r300BlendColor(ctx, ctx->Color.BlendColor); +- r300->hw.blend_color.cmd[2] = 0; +- r300->hw.blend_color.cmd[3] = 0; + + /* Again, r300ClearBuffer uses this */ + r300->hw.cb.cmd[R300_CB_OFFSET] = +@@ -2022,32 +1959,13 @@ static void r300ResetHwState(r300ContextPtr r300) + r300->hw.unk4EA0.cmd[1] = 0x00000000; + r300->hw.unk4EA0.cmd[2] = 0xffffffff; + +- switch (ctx->Visual.depthBits) { +- case 16: +- r300->hw.zstencil_format.cmd[1] = R300_DEPTH_FORMAT_16BIT_INT_Z; +- break; +- case 24: +- r300->hw.zstencil_format.cmd[1] = R300_DEPTH_FORMAT_24BIT_INT_Z; +- break; +- default: +- fprintf(stderr, "Error: Unsupported depth %d... exiting\n", +- ctx->Visual.depthBits); +- _mesa_exit(-1); +- +- } +- /* z compress? */ +- //r300->hw.zstencil_format.cmd[1] |= R300_DEPTH_FORMAT_UNK32; +- +- r300->hw.zstencil_format.cmd[3] = 0x00000003; +- r300->hw.zstencil_format.cmd[4] = 0x00000000; +- + r300->hw.zb.cmd[R300_ZB_OFFSET] = + r300->radeon.radeonScreen->depthOffset + + r300->radeon.radeonScreen->fbLocation; + r300->hw.zb.cmd[R300_ZB_PITCH] = r300->radeon.radeonScreen->depthPitch; + + if (r300->radeon.sarea->tiling_enabled) { +- /* Turn off when clearing buffers ? */ ++ /* XXX: Turn off when clearing buffers ? */ + r300->hw.zb.cmd[R300_ZB_PITCH] |= R300_DEPTH_TILE_ENABLE; + + if (ctx->Visual.depthBits == 24) +@@ -2070,14 +1988,10 @@ static void r300ResetHwState(r300ContextPtr r300) + r300->hw.vps.cmd[R300_VPS_POINTSIZE] = r300PackFloat32(1.0); + r300->hw.vps.cmd[R300_VPS_ZERO_3] = 0; + } +-//END: TODO ++ + r300->hw.all_dirty = GL_TRUE; + } + +- +-extern void _tnl_UpdateFixedFunctionProgram(GLcontext * ctx); +- +-extern int future_hw_tcl_on; + void r300UpdateShaders(r300ContextPtr rmesa) + { + GLcontext *ctx; +@@ -2117,7 +2031,6 @@ void r300UpdateShaders(r300ContextPtr rmesa) + } + r300UpdateStateParameters(ctx, _NEW_PROGRAM); + } +- + } + + static void r300SetupPixelShader(r300ContextPtr rmesa) +@@ -2136,62 +2049,61 @@ static void r300SetupPixelShader(r300ContextPtr rmesa) + __FUNCTION__); + return; + } +-#define OUTPUT_FIELD(st, reg, field) \ +- R300_STATECHANGE(rmesa, st); \ +- for(i=0;i<=fp->alu_end;i++) \ +- rmesa->hw.st.cmd[R300_FPI_INSTR_0+i]=fp->alu.inst[i].field;\ +- rmesa->hw.st.cmd[R300_FPI_CMD_0]=cmdpacket0(reg, fp->alu_end+1); + +- 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, fpi[0]); ++ rmesa->hw.fpi[0].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR0_0, fp->alu_end + 1); ++ for (i = 0; i <= fp->alu_end; i++) { ++ rmesa->hw.fpi[0].cmd[R300_FPI_INSTR_0 + i] = fp->alu.inst[i].inst0; ++ } ++ ++ R300_STATECHANGE(rmesa, fpi[1]); ++ rmesa->hw.fpi[1].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR1_0, fp->alu_end + 1); ++ for (i = 0; i <= fp->alu_end; i++) { ++ rmesa->hw.fpi[1].cmd[R300_FPI_INSTR_0 + i] = fp->alu.inst[i].inst1; ++ } ++ ++ R300_STATECHANGE(rmesa, fpi[2]); ++ rmesa->hw.fpi[2].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR2_0, fp->alu_end + 1); ++ for (i = 0; i <= fp->alu_end; i++) { ++ rmesa->hw.fpi[2].cmd[R300_FPI_INSTR_0 + i] = fp->alu.inst[i].inst2; ++ } ++ ++ R300_STATECHANGE(rmesa, fpi[3]); ++ rmesa->hw.fpi[3].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR3_0, fp->alu_end + 1); ++ for (i = 0; i <= fp->alu_end; i++) { ++ rmesa->hw.fpi[3].cmd[R300_FPI_INSTR_0 + i] = fp->alu.inst[i].inst3; ++ } + + R300_STATECHANGE(rmesa, fp); ++ rmesa->hw.fp.cmd[R300_FP_CNTL0] = fp->cur_node | (fp->first_node_has_tex << 3); ++ rmesa->hw.fp.cmd[R300_FP_CNTL1] = fp->max_temp_idx; ++ rmesa->hw.fp.cmd[R300_FP_CNTL2] = ++ (fp->alu_offset << R300_PFS_CNTL_ALU_OFFSET_SHIFT) | ++ (fp->alu_end << R300_PFS_CNTL_ALU_END_SHIFT) | ++ (fp->tex_offset << R300_PFS_CNTL_TEX_OFFSET_SHIFT) | ++ (fp->tex_end << R300_PFS_CNTL_TEX_END_SHIFT); + /* I just want to say, the way these nodes are stored.. weird.. */ + for (i = 0, k = (4 - (fp->cur_node + 1)); i < 4; i++, k++) { + if (i < (fp->cur_node + 1)) { + rmesa->hw.fp.cmd[R300_FP_NODE0 + k] = +- (fp->node[i]. +- alu_offset << R300_PFS_NODE_ALU_OFFSET_SHIFT) +- | (fp->node[i]. +- alu_end << R300_PFS_NODE_ALU_END_SHIFT) +- | (fp->node[i]. +- tex_offset << R300_PFS_NODE_TEX_OFFSET_SHIFT) +- | (fp->node[i]. +- tex_end << R300_PFS_NODE_TEX_END_SHIFT) +- | fp->node[i].flags; /* ( (k==3) ? R300_PFS_NODE_LAST_NODE : 0); */ ++ (fp->node[i].alu_offset << R300_PFS_NODE_ALU_OFFSET_SHIFT) | ++ (fp->node[i].alu_end << R300_PFS_NODE_ALU_END_SHIFT) | ++ (fp->node[i].tex_offset << R300_PFS_NODE_TEX_OFFSET_SHIFT) | ++ (fp->node[i].tex_end << R300_PFS_NODE_TEX_END_SHIFT) | ++ fp->node[i].flags; + } else { + rmesa->hw.fp.cmd[R300_FP_NODE0 + (3 - i)] = 0; + } + } + +- /* PFS_CNTL_0 */ +- rmesa->hw.fp.cmd[R300_FP_CNTL0] = +- fp->cur_node | (fp->first_node_has_tex << 3); +- /* PFS_CNTL_1 */ +- rmesa->hw.fp.cmd[R300_FP_CNTL1] = fp->max_temp_idx; +- /* PFS_CNTL_2 */ +- rmesa->hw.fp.cmd[R300_FP_CNTL2] = +- (fp->alu_offset << R300_PFS_CNTL_ALU_OFFSET_SHIFT) +- | (fp->alu_end << R300_PFS_CNTL_ALU_END_SHIFT) +- | (fp->tex_offset << R300_PFS_CNTL_TEX_OFFSET_SHIFT) +- | (fp->tex_end << R300_PFS_CNTL_TEX_END_SHIFT); +- + R300_STATECHANGE(rmesa, fpp); ++ rmesa->hw.fpp.cmd[R300_FPP_CMD_0] = cmdpacket0(R300_PFS_PARAM_0_X, fp->const_nr * 4); + for (i = 0; i < fp->const_nr; i++) { +- rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 0] = +- r300PackFloat24(fp->constant[i][0]); +- rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 1] = +- r300PackFloat24(fp->constant[i][1]); +- rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 2] = +- r300PackFloat24(fp->constant[i][2]); +- rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 3] = +- r300PackFloat24(fp->constant[i][3]); +- } +- rmesa->hw.fpp.cmd[R300_FPP_CMD_0] = +- cmdpacket0(R300_PFS_PARAM_0_X, fp->const_nr * 4); ++ rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 0] = r300PackFloat24(fp->constant[i][0]); ++ rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 1] = r300PackFloat24(fp->constant[i][1]); ++ rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 2] = r300PackFloat24(fp->constant[i][2]); ++ rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 3] = r300PackFloat24(fp->constant[i][3]); ++ } + } + + void r300UpdateShaderStates(r300ContextPtr rmesa) +@@ -2205,7 +2117,7 @@ void r300UpdateShaderStates(r300ContextPtr rmesa) + r300SetupTextures(ctx); + + if ((rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) +- r300SetupVertexShader(rmesa); ++ r300SetupVertexProgram(rmesa); + r300SetupRSUnit(ctx); + } + +diff --git a/src/mesa/drivers/dri/r300/r300_state.h b/src/mesa/drivers/dri/r300/r300_state.h +index 21a49b7..365f7ec 100644 +--- a/src/mesa/drivers/dri/r300/r300_state.h ++++ b/src/mesa/drivers/dri/r300/r300_state.h +@@ -37,8 +37,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + #include "r300_context.h" + ++#define R300_NEWPRIM( rmesa ) \ ++ do { \ ++ if ( rmesa->dma.flush ) \ ++ rmesa->dma.flush( rmesa ); \ ++ } while (0) ++ + #define R300_STATECHANGE(r300, atom) \ + do { \ ++ R300_NEWPRIM(r300); \ + r300->hw.atom.dirty = GL_TRUE; \ + r300->hw.is_dirty = GL_TRUE; \ + } while(0) +diff --git a/src/mesa/drivers/dri/r300/r300_swtcl.c b/src/mesa/drivers/dri/r300/r300_swtcl.c +new file mode 100644 +index 0000000..c949f33 +--- /dev/null ++++ b/src/mesa/drivers/dri/r300/r300_swtcl.c +@@ -0,0 +1,711 @@ ++/************************************************************************** ++ ++Copyright (C) 2007 Dave Airlie ++ ++All Rights Reserved. ++ ++Permission is hereby granted, free of charge, to any person obtaining a ++copy of this software and associated documentation files (the "Software"), ++to deal in the Software without restriction, including without limitation ++on the rights to use, copy, modify, merge, publish, distribute, sub ++license, and/or sell copies of the Software, and to permit persons to whom ++the Software is furnished to do so, subject to the following conditions: ++ ++The above copyright notice and this permission notice (including the next ++paragraph) shall be included in all copies or substantial portions of the ++Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL ++THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, ++DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ++OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE ++USE OR OTHER DEALINGS IN THE SOFTWARE. ++ ++**************************************************************************/ ++ ++/* ++ * Authors: ++ * Dave Airlie ++ */ ++ ++/* derived from r200 swtcl path */ ++ ++ ++ ++#include "glheader.h" ++#include "mtypes.h" ++#include "colormac.h" ++#include "enums.h" ++#include "image.h" ++#include "imports.h" ++#include "macros.h" ++ ++#include "swrast/s_context.h" ++#include "swrast/s_fog.h" ++#include "swrast_setup/swrast_setup.h" ++#include "math/m_translate.h" ++#include "tnl/tnl.h" ++#include "tnl/t_context.h" ++#include "tnl/t_pipeline.h" ++ ++#include "r300_context.h" ++#include "r300_swtcl.h" ++#include "r300_state.h" ++#include "r300_ioctl.h" ++#include "r300_emit.h" ++#include "r300_mem.h" ++ ++static void flush_last_swtcl_prim( r300ContextPtr rmesa ); ++ ++ ++void r300EmitVertexAOS(r300ContextPtr rmesa, GLuint vertex_size, GLuint offset); ++void r300EmitVbufPrim(r300ContextPtr rmesa, GLuint primitive, GLuint vertex_nr); ++#define EMIT_ATTR( ATTR, STYLE ) \ ++do { \ ++ rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = (ATTR); \ ++ rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = (STYLE); \ ++ rmesa->swtcl.vertex_attr_count++; \ ++} while (0) ++ ++#define EMIT_PAD( N ) \ ++do { \ ++ rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = 0; \ ++ rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = EMIT_PAD; \ ++ rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].offset = (N); \ ++ rmesa->swtcl.vertex_attr_count++; \ ++} while (0) ++ ++/* this differs from the VIR0 in emit.c - TODO merge them using another option */ ++static GLuint r300VAPInputRoute0(uint32_t * dst, GLvector4f ** attribptr, ++ int *inputs, GLint * tab, GLuint nr) ++{ ++ GLuint i, dw; ++ ++ /* type, inputs, stop bit, size */ ++ for (i = 0; i + 1 < nr; i += 2) { ++ dw = (inputs[tab[i]] << 8) | 0x3; ++ dw |= ((inputs[tab[i + 1]] << 8) | 0x3) << 16; ++ if (i + 2 == nr) { ++ dw |= (R300_VAP_INPUT_ROUTE_END << 16); ++ } ++ dst[i >> 1] = dw; ++ } ++ ++ if (nr & 1) { ++ dw = (inputs[tab[nr - 1]] << 8) | 0x3; ++ dw |= R300_VAP_INPUT_ROUTE_END; ++ dst[nr >> 1] = dw; ++ } ++ ++ return (nr + 1) >> 1; ++} ++ ++static void r300SetVertexFormat( GLcontext *ctx ) ++{ ++ r300ContextPtr rmesa = R300_CONTEXT( ctx ); ++ TNLcontext *tnl = TNL_CONTEXT(ctx); ++ struct vertex_buffer *VB = &tnl->vb; ++ DECLARE_RENDERINPUTS(index_bitset); ++ GLuint InputsRead = 0, OutputsWritten = 0; ++ int vap_fmt_0 = 0; ++ int vap_vte_cntl = 0; ++ int offset = 0; ++ int vte = 0; ++ GLint inputs[VERT_ATTRIB_MAX]; ++ GLint tab[VERT_ATTRIB_MAX]; ++ int swizzle[VERT_ATTRIB_MAX][4]; ++ GLuint i, nr; ++ ++ DECLARE_RENDERINPUTS(render_inputs_bitset); ++ RENDERINPUTS_COPY(render_inputs_bitset, tnl->render_inputs_bitset); ++ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); ++ RENDERINPUTS_COPY(rmesa->state.render_inputs_bitset, render_inputs_bitset); ++ ++ /* Important: ++ */ ++ if ( VB->NdcPtr != NULL ) { ++ VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; ++ } ++ else { ++ VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr; ++ } ++ ++ assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL ); ++ rmesa->swtcl.vertex_attr_count = 0; ++ ++ /* EMIT_ATTR's must be in order as they tell t_vertex.c how to ++ * build up a hardware vertex. ++ */ ++ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POS)) { ++ vap_vte_cntl |= R300_VTX_W0_FMT; ++ InputsRead |= 1 << VERT_ATTRIB_POS; ++ OutputsWritten |= 1 << VERT_RESULT_HPOS; ++ EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F ); ++ } else ++ EMIT_PAD(4 * sizeof(float)); ++ ++ offset = 4; ++ ++ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) { ++ EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F ); ++ vap_fmt_0 |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; ++ offset += 1; ++ } ++ ++ if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_COLOR0)) { ++ rmesa->swtcl.coloroffset = offset; ++ InputsRead |= 1 << VERT_ATTRIB_COLOR0; ++ OutputsWritten |= 1 << VERT_RESULT_COL0; ++ EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4F ); ++ } ++ ++ offset += 4; ++ ++ rmesa->swtcl.specoffset = 0; ++ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { ++ rmesa->swtcl.specoffset = offset; ++ EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_4F ); ++ InputsRead |= 1 << VERT_ATTRIB_COLOR1; ++ OutputsWritten |= 1 << VERT_RESULT_COL1; ++ } ++ ++ if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { ++ int i; ++ ++ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { ++ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) { ++ InputsRead |= 1 << (VERT_ATTRIB_TEX0 + i); ++ OutputsWritten |= 1 << (VERT_RESULT_TEX0 + i); ++ EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_4F ); ++ } ++ } ++ } ++ ++ for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) { ++ if (InputsRead & (1 << i)) { ++ inputs[i] = nr++; ++ } else { ++ inputs[i] = -1; ++ } ++ } ++ ++ /* Fixed, apply to vir0 only */ ++ if (InputsRead & (1 << VERT_ATTRIB_POS)) ++ inputs[VERT_ATTRIB_POS] = 0; ++ if (InputsRead & (1 << VERT_ATTRIB_COLOR0)) ++ inputs[VERT_ATTRIB_COLOR0] = 2; ++ if (InputsRead & (1 << VERT_ATTRIB_COLOR1)) ++ inputs[VERT_ATTRIB_COLOR1] = 3; ++ for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) ++ if (InputsRead & (1 << i)) ++ inputs[i] = 6 + (i - VERT_ATTRIB_TEX0); ++ ++ for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) { ++ if (InputsRead & (1 << i)) { ++ tab[nr++] = i; ++ } ++ } ++ ++ for (i = 0; i < nr; i++) { ++ int ci; ++ ++ swizzle[i][0] = SWIZZLE_ZERO; ++ swizzle[i][1] = SWIZZLE_ZERO; ++ swizzle[i][2] = SWIZZLE_ZERO; ++ swizzle[i][3] = SWIZZLE_ONE; ++ ++ for (ci = 0; ci < VB->AttribPtr[tab[i]]->size; ci++) { ++ swizzle[i][ci] = ci; ++ } ++ } ++ ++ R300_NEWPRIM(rmesa); ++ R300_STATECHANGE(rmesa, vir[0]); ++ ((drm_r300_cmd_header_t *) rmesa->hw.vir[0].cmd)->packet0.count = ++ r300VAPInputRoute0(&rmesa->hw.vir[0].cmd[R300_VIR_CNTL_0], ++ VB->AttribPtr, inputs, tab, nr); ++ R300_STATECHANGE(rmesa, vir[1]); ++ ((drm_r300_cmd_header_t *) rmesa->hw.vir[1].cmd)->packet0.count = ++ r300VAPInputRoute1(&rmesa->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle, ++ nr); ++ ++ R300_STATECHANGE(rmesa, vic); ++ rmesa->hw.vic.cmd[R300_VIC_CNTL_0] = r300VAPInputCntl0(ctx, InputsRead); ++ rmesa->hw.vic.cmd[R300_VIC_CNTL_1] = r300VAPInputCntl1(ctx, InputsRead); ++ ++ R300_STATECHANGE(rmesa, vof); ++ rmesa->hw.vof.cmd[R300_VOF_CNTL_0] = r300VAPOutputCntl0(ctx, OutputsWritten); ++ rmesa->hw.vof.cmd[R300_VOF_CNTL_1] = r300VAPOutputCntl1(ctx, OutputsWritten); ++ ++ rmesa->swtcl.vertex_size = ++ _tnl_install_attrs( ctx, ++ rmesa->swtcl.vertex_attrs, ++ rmesa->swtcl.vertex_attr_count, ++ NULL, 0 ); ++ ++ rmesa->swtcl.vertex_size /= 4; ++ ++ RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset ); ++ ++ vte = rmesa->hw.vte.cmd[1]; ++ R300_STATECHANGE(rmesa, vte); ++ rmesa->hw.vte.cmd[1] = vte; ++ rmesa->hw.vte.cmd[2] = rmesa->swtcl.vertex_size; ++} ++ ++ ++/* Flush vertices in the current dma region. ++ */ ++static void flush_last_swtcl_prim( r300ContextPtr rmesa ) ++{ ++ if (RADEON_DEBUG & DEBUG_IOCTL) ++ fprintf(stderr, "%s\n", __FUNCTION__); ++ ++ rmesa->dma.flush = NULL; ++ ++ if (rmesa->dma.current.buf) { ++ struct r300_dma_region *current = &rmesa->dma.current; ++ GLuint current_offset = GET_START(current); ++ ++ assert (current->start + ++ rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 == ++ current->ptr); ++ ++ if (rmesa->dma.current.start != rmesa->dma.current.ptr) { ++ ++ r300EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size + (12*sizeof(int)), __FUNCTION__); ++ ++ r300EmitState(rmesa); ++ ++ r300EmitVertexAOS( rmesa, ++ rmesa->swtcl.vertex_size, ++ current_offset); ++ ++ r300EmitVbufPrim( rmesa, ++ rmesa->swtcl.hw_primitive, ++ rmesa->swtcl.numverts); ++ ++ r300EmitCacheFlush(rmesa); ++ } ++ ++ rmesa->swtcl.numverts = 0; ++ current->start = current->ptr; ++ } ++} ++ ++/* Alloc space in the current dma region. ++ */ ++static void * ++r300AllocDmaLowVerts( r300ContextPtr rmesa, int nverts, int vsize ) ++{ ++ GLuint bytes = vsize * nverts; ++ ++ if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end ) ++ r300RefillCurrentDmaRegion( rmesa, bytes); ++ ++ if (!rmesa->dma.flush) { ++ rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; ++ rmesa->dma.flush = flush_last_swtcl_prim; ++ } ++ ++ ASSERT( vsize == rmesa->swtcl.vertex_size * 4 ); ++ ASSERT( rmesa->dma.flush == flush_last_swtcl_prim ); ++ ASSERT( rmesa->dma.current.start + ++ rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 == ++ rmesa->dma.current.ptr ); ++ ++ { ++ GLubyte *head = (GLubyte *) (rmesa->dma.current.address + rmesa->dma.current.ptr); ++ rmesa->dma.current.ptr += bytes; ++ rmesa->swtcl.numverts += nverts; ++ return head; ++ } ++} ++ ++static GLuint reduced_prim[] = { ++ GL_POINTS, ++ GL_LINES, ++ GL_LINES, ++ GL_LINES, ++ GL_TRIANGLES, ++ GL_TRIANGLES, ++ GL_TRIANGLES, ++ GL_TRIANGLES, ++ GL_TRIANGLES, ++ GL_TRIANGLES, ++}; ++ ++static void r300RasterPrimitive( GLcontext *ctx, GLuint prim ); ++static void r300RenderPrimitive( GLcontext *ctx, GLenum prim ); ++//static void r300ResetLineStipple( GLcontext *ctx ); ++ ++/*********************************************************************** ++ * Emit primitives as inline vertices * ++ ***********************************************************************/ ++ ++ ++#define HAVE_POINTS 1 ++#define HAVE_LINES 1 ++#define HAVE_LINE_STRIPS 1 ++#define HAVE_TRIANGLES 1 ++#define HAVE_TRI_STRIPS 1 ++#define HAVE_TRI_STRIP_1 0 ++#define HAVE_TRI_FANS 1 ++#define HAVE_QUADS 0 ++#define HAVE_QUAD_STRIPS 0 ++#define HAVE_POLYGONS 1 ++#define HAVE_ELTS 1 ++ ++#undef LOCAL_VARS ++#undef ALLOC_VERTS ++#define CTX_ARG r300ContextPtr rmesa ++#define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size ++#define ALLOC_VERTS( n, size ) r300AllocDmaLowVerts( rmesa, n, size * 4 ) ++#define LOCAL_VARS \ ++ r300ContextPtr rmesa = R300_CONTEXT(ctx); \ ++ const char *r300verts = (char *)rmesa->swtcl.verts; ++#define VERT(x) (r300Vertex *)(r300verts + ((x) * vertsize * sizeof(int))) ++#define VERTEX r300Vertex ++#define DO_DEBUG_VERTS (1 && (RADEON_DEBUG & DEBUG_VERTS)) ++#define PRINT_VERTEX(x) ++#undef TAG ++#define TAG(x) r300_##x ++#include "tnl_dd/t_dd_triemit.h" ++ ++ ++ ++/*********************************************************************** ++ * Macros for t_dd_tritmp.h to draw basic primitives * ++ ***********************************************************************/ ++ ++#define QUAD( a, b, c, d ) r300_quad( rmesa, a, b, c, d ) ++#define TRI( a, b, c ) r300_triangle( rmesa, a, b, c ) ++#define LINE( a, b ) r300_line( rmesa, a, b ) ++#define POINT( a ) r300_point( rmesa, a ) ++ ++/*********************************************************************** ++ * Build render functions from dd templates * ++ ***********************************************************************/ ++ ++#define R300_TWOSIDE_BIT 0x01 ++#define R300_UNFILLED_BIT 0x02 ++#define R300_MAX_TRIFUNC 0x04 ++ ++static struct { ++ tnl_points_func points; ++ tnl_line_func line; ++ tnl_triangle_func triangle; ++ tnl_quad_func quad; ++} rast_tab[R300_MAX_TRIFUNC]; ++ ++#define DO_FALLBACK 0 ++#define DO_UNFILLED (IND & R300_UNFILLED_BIT) ++#define DO_TWOSIDE (IND & R300_TWOSIDE_BIT) ++#define DO_FLAT 0 ++#define DO_OFFSET 0 ++#define DO_TRI 1 ++#define DO_QUAD 1 ++#define DO_LINE 1 ++#define DO_POINTS 1 ++#define DO_FULL_QUAD 1 ++ ++#define HAVE_RGBA 1 ++#define HAVE_SPEC 1 ++#define HAVE_BACK_COLORS 0 ++#define HAVE_HW_FLATSHADE 1 ++#define TAB rast_tab ++ ++#define DEPTH_SCALE 1.0 ++#define UNFILLED_TRI unfilled_tri ++#define UNFILLED_QUAD unfilled_quad ++#define VERT_X(_v) _v->v.x ++#define VERT_Y(_v) _v->v.y ++#define VERT_Z(_v) _v->v.z ++#define AREA_IS_CCW( a ) (a < 0) ++#define GET_VERTEX(e) (rmesa->swtcl.verts + (e*rmesa->swtcl.vertex_size*sizeof(int))) ++ ++/* Only used to pull back colors into vertices (ie, we know color is ++ * floating point). ++ */ ++#define R300_COLOR( dst, src ) \ ++do { \ ++ UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \ ++ UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \ ++ UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \ ++ UNCLAMPED_FLOAT_TO_UBYTE((dst)[3], (src)[3]); \ ++} while (0) ++ ++#define VERT_SET_RGBA( v, c ) if (coloroffset) R300_COLOR( v->ub4[coloroffset], c ) ++#define VERT_COPY_RGBA( v0, v1 ) if (coloroffset) v0->ui[coloroffset] = v1->ui[coloroffset] ++#define VERT_SAVE_RGBA( idx ) if (coloroffset) color[idx] = v[idx]->ui[coloroffset] ++#define VERT_RESTORE_RGBA( idx ) if (coloroffset) v[idx]->ui[coloroffset] = color[idx] ++ ++#define R300_SPEC( dst, src ) \ ++do { \ ++ UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \ ++ UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \ ++ UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \ ++} while (0) ++ ++#define VERT_SET_SPEC( v, c ) if (specoffset) R300_SPEC( v->ub4[specoffset], c ) ++#define VERT_COPY_SPEC( v0, v1 ) if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset]) ++#define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset] ++#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] ++ ++#undef LOCAL_VARS ++#undef TAG ++#undef INIT ++ ++#define LOCAL_VARS(n) \ ++ r300ContextPtr rmesa = R300_CONTEXT(ctx); \ ++ GLuint color[n], spec[n]; \ ++ GLuint coloroffset = rmesa->swtcl.coloroffset; \ ++ GLuint specoffset = rmesa->swtcl.specoffset; \ ++ (void) color; (void) spec; (void) coloroffset; (void) specoffset; ++ ++/*********************************************************************** ++ * Helpers for rendering unfilled primitives * ++ ***********************************************************************/ ++ ++#define RASTERIZE(x) r300RasterPrimitive( ctx, reduced_prim[x] ) ++#define RENDER_PRIMITIVE rmesa->swtcl.render_primitive ++#undef TAG ++#define TAG(x) x ++#include "tnl_dd/t_dd_unfilled.h" ++#undef IND ++ ++ ++/*********************************************************************** ++ * Generate GL render functions * ++ ***********************************************************************/ ++ ++ ++#define IND (0) ++#define TAG(x) x ++#include "tnl_dd/t_dd_tritmp.h" ++ ++#define IND (R300_TWOSIDE_BIT) ++#define TAG(x) x##_twoside ++#include "tnl_dd/t_dd_tritmp.h" ++ ++#define IND (R300_UNFILLED_BIT) ++#define TAG(x) x##_unfilled ++#include "tnl_dd/t_dd_tritmp.h" ++ ++#define IND (R300_TWOSIDE_BIT|R300_UNFILLED_BIT) ++#define TAG(x) x##_twoside_unfilled ++#include "tnl_dd/t_dd_tritmp.h" ++ ++ ++ ++static void init_rast_tab( void ) ++{ ++ init(); ++ init_twoside(); ++ init_unfilled(); ++ init_twoside_unfilled(); ++} ++ ++/**********************************************************************/ ++/* Render unclipped begin/end objects */ ++/**********************************************************************/ ++ ++#define RENDER_POINTS( start, count ) \ ++ for ( ; start < count ; start++) \ ++ r300_point( rmesa, VERT(start) ) ++#define RENDER_LINE( v0, v1 ) \ ++ r300_line( rmesa, VERT(v0), VERT(v1) ) ++#define RENDER_TRI( v0, v1, v2 ) \ ++ r300_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) ) ++#define RENDER_QUAD( v0, v1, v2, v3 ) \ ++ r300_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) ) ++#define INIT(x) do { \ ++ r300RenderPrimitive( ctx, x ); \ ++} while (0) ++#undef LOCAL_VARS ++#define LOCAL_VARS \ ++ r300ContextPtr rmesa = R300_CONTEXT(ctx); \ ++ const GLuint vertsize = rmesa->swtcl.vertex_size; \ ++ const char *r300verts = (char *)rmesa->swtcl.verts; \ ++ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ ++ const GLboolean stipple = ctx->Line.StippleFlag; \ ++ (void) elt; (void) stipple; ++#define RESET_STIPPLE //if ( stipple ) r200ResetLineStipple( ctx ); ++#define RESET_OCCLUSION ++#define PRESERVE_VB_DEFS ++#define ELT(x) (x) ++#define TAG(x) r300_##x##_verts ++#include "tnl/t_vb_rendertmp.h" ++#undef ELT ++#undef TAG ++#define TAG(x) r300_##x##_elts ++#define ELT(x) elt[x] ++#include "tnl/t_vb_rendertmp.h" ++ ++ ++ ++ ++/**********************************************************************/ ++/* Choose render functions */ ++/**********************************************************************/ ++static void r300ChooseRenderState( GLcontext *ctx ) ++{ ++ TNLcontext *tnl = TNL_CONTEXT(ctx); ++ r300ContextPtr rmesa = R300_CONTEXT(ctx); ++ GLuint index = 0; ++ GLuint flags = ctx->_TriangleCaps; ++ ++ if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R300_TWOSIDE_BIT; ++ if (flags & DD_TRI_UNFILLED) index |= R300_UNFILLED_BIT; ++ ++ if (index != rmesa->swtcl.RenderIndex) { ++ tnl->Driver.Render.Points = rast_tab[index].points; ++ tnl->Driver.Render.Line = rast_tab[index].line; ++ tnl->Driver.Render.ClippedLine = rast_tab[index].line; ++ tnl->Driver.Render.Triangle = rast_tab[index].triangle; ++ tnl->Driver.Render.Quad = rast_tab[index].quad; ++ ++ if (index == 0) { ++ tnl->Driver.Render.PrimTabVerts = r300_render_tab_verts; ++ tnl->Driver.Render.PrimTabElts = r300_render_tab_elts; ++ tnl->Driver.Render.ClippedPolygon = r300_fast_clipped_poly; ++ } else { ++ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; ++ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; ++ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; ++ } ++ ++ rmesa->swtcl.RenderIndex = index; ++ } ++} ++ ++ ++static void r300RenderStart(GLcontext *ctx) ++{ ++ r300ContextPtr rmesa = R300_CONTEXT( ctx ); ++ // fprintf(stderr, "%s\n", __FUNCTION__); ++ ++ r300ChooseRenderState(ctx); ++ r300SetVertexFormat(ctx); ++ ++ r300UpdateShaderStates(rmesa); ++ ++ r300EmitCacheFlush(rmesa); ++ ++ if (rmesa->dma.flush != 0 && ++ rmesa->dma.flush != flush_last_swtcl_prim) ++ rmesa->dma.flush( rmesa ); ++ ++} ++ ++static void r300RenderFinish(GLcontext *ctx) ++{ ++} ++ ++static void r300RasterPrimitive( GLcontext *ctx, GLuint hwprim ) ++{ ++ r300ContextPtr rmesa = R300_CONTEXT(ctx); ++ ++ if (rmesa->swtcl.hw_primitive != hwprim) { ++ R300_NEWPRIM( rmesa ); ++ rmesa->swtcl.hw_primitive = hwprim; ++ } ++} ++ ++static void r300RenderPrimitive(GLcontext *ctx, GLenum prim) ++{ ++ ++ r300ContextPtr rmesa = R300_CONTEXT(ctx); ++ rmesa->swtcl.render_primitive = prim; ++ ++ if ((prim == GL_TRIANGLES) && (ctx->_TriangleCaps & DD_TRI_UNFILLED)) ++ return; ++ ++ r300RasterPrimitive( ctx, reduced_prim[prim] ); ++ // fprintf(stderr, "%s\n", __FUNCTION__); ++ ++} ++ ++static void r300ResetLineStipple(GLcontext *ctx) ++{ ++ ++ ++} ++ ++void r300InitSwtcl(GLcontext *ctx) ++{ ++ TNLcontext *tnl = TNL_CONTEXT(ctx); ++ r300ContextPtr rmesa = R300_CONTEXT(ctx); ++ static int firsttime = 1; ++ ++ if (firsttime) { ++ init_rast_tab(); ++ firsttime = 0; ++ } ++ ++ tnl->Driver.Render.Start = r300RenderStart; ++ tnl->Driver.Render.Finish = r300RenderFinish; ++ tnl->Driver.Render.PrimitiveNotify = r300RenderPrimitive; ++ tnl->Driver.Render.ResetLineStipple = r300ResetLineStipple; ++ tnl->Driver.Render.BuildVertices = _tnl_build_vertices; ++ tnl->Driver.Render.CopyPV = _tnl_copy_pv; ++ tnl->Driver.Render.Interp = _tnl_interp; ++ ++ /* FIXME: what are these numbers? */ ++ _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, ++ 48 * sizeof(GLfloat) ); ++ ++ rmesa->swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf; ++ rmesa->swtcl.RenderIndex = ~0; ++ rmesa->swtcl.render_primitive = GL_TRIANGLES; ++ rmesa->swtcl.hw_primitive = 0; ++ ++ _tnl_invalidate_vertex_state( ctx, ~0 ); ++ _tnl_invalidate_vertices( ctx, ~0 ); ++ RENDERINPUTS_ZERO( rmesa->tnl_index_bitset ); ++ ++ _tnl_need_projected_coords( ctx, GL_FALSE ); ++ r300ChooseRenderState(ctx); ++ ++ _mesa_validate_all_lighting_tables( ctx ); ++ ++ tnl->Driver.NotifyMaterialChange = ++ _mesa_validate_all_lighting_tables; ++} ++ ++void r300DestroySwtcl(GLcontext *ctx) ++{ ++} ++ ++void r300EmitVertexAOS(r300ContextPtr rmesa, GLuint vertex_size, GLuint offset) ++{ ++ int cmd_reserved = 0; ++ int cmd_written = 0; ++ ++ drm_radeon_cmd_header_t *cmd = NULL; ++ if (RADEON_DEBUG & DEBUG_VERTS) ++ fprintf(stderr, "%s: vertex_size %d, offset 0x%x \n", ++ __FUNCTION__, vertex_size, offset); ++ ++ start_packet3(CP_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, 2), 2); ++ e32(1); ++ e32(vertex_size | (vertex_size << 8)); ++ e32(offset); ++} ++ ++void r300EmitVbufPrim(r300ContextPtr rmesa, GLuint primitive, GLuint vertex_nr) ++{ ++ ++ int cmd_reserved = 0; ++ int cmd_written = 0; ++ int type, num_verts; ++ drm_radeon_cmd_header_t *cmd = NULL; ++ ++ type = r300PrimitiveType(rmesa, primitive); ++ num_verts = r300NumVerts(rmesa, vertex_nr, primitive); ++ ++ start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0), 0); ++ e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (num_verts << 16) | type); ++} +diff --git a/src/mesa/drivers/dri/r300/r300_swtcl.h b/src/mesa/drivers/dri/r300/r300_swtcl.h +new file mode 100644 +index 0000000..2ea6ced +--- /dev/null ++++ b/src/mesa/drivers/dri/r300/r300_swtcl.h +@@ -0,0 +1,45 @@ ++/* ++Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. ++ ++The Weather Channel (TM) funded Tungsten Graphics to develop the ++initial release of the Radeon 8500 driver under the XFree86 license. ++This notice must be preserved. ++ ++Permission is hereby granted, free of charge, to any person obtaining ++a copy of this software and associated documentation files (the ++"Software"), to deal in the Software without restriction, including ++without limitation the rights to use, copy, modify, merge, publish, ++distribute, sublicense, and/or sell copies of the Software, and to ++permit persons to whom the Software is furnished to do so, subject to ++the following conditions: ++ ++The above copyright notice and this permission notice (including the ++next paragraph) shall be included in all copies or substantial ++portions of the Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE ++LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++*/ ++ ++/* ++ * Authors: ++ * Keith Whitwell - original r200 code ++ * Dave Airlie ++ */ ++ ++#ifndef __R300_SWTCL_H__ ++#define __R300_SWTCL_H__ ++ ++#include "mtypes.h" ++#include "swrast/swrast.h" ++#include "r300_context.h" ++ ++extern void r300InitSwtcl( GLcontext *ctx ); ++extern void r300DestroySwtcl( GLcontext *ctx ); ++ ++#endif +diff --git a/src/mesa/drivers/dri/r300/r300_tex.c b/src/mesa/drivers/dri/r300/r300_tex.c +index 2a21c61..1805cec 100644 +--- a/src/mesa/drivers/dri/r300/r300_tex.c ++++ b/src/mesa/drivers/dri/r300/r300_tex.c +@@ -294,27 +294,20 @@ static const struct gl_texture_format *r300Choose8888TexFormat(GLenum srcFormat, + const GLubyte littleEndian = *((const GLubyte *)&ui); + + if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) || +- (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE +- && !littleEndian) || (srcFormat == GL_ABGR_EXT +- && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) +- || (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE +- && littleEndian)) { ++ (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) || ++ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || ++ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian)) { + return &_mesa_texformat_rgba8888; +- } else +- if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) +- || (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE +- && littleEndian) || (srcFormat == GL_ABGR_EXT +- && srcType == GL_UNSIGNED_INT_8_8_8_8) +- || (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE +- && !littleEndian)) { ++ } else if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || ++ (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) || ++ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) || ++ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian)) { + return &_mesa_texformat_rgba8888_rev; +- } else if (srcFormat == GL_BGRA && +- ((srcType == GL_UNSIGNED_BYTE && !littleEndian) || +- srcType == GL_UNSIGNED_INT_8_8_8_8)) { ++ } else if (srcFormat == GL_BGRA && ((srcType == GL_UNSIGNED_BYTE && !littleEndian) || ++ srcType == GL_UNSIGNED_INT_8_8_8_8)) { + return &_mesa_texformat_argb8888_rev; +- } else if (srcFormat == GL_BGRA && +- ((srcType == GL_UNSIGNED_BYTE && littleEndian) || +- srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) { ++ } else if (srcFormat == GL_BGRA && ((srcType == GL_UNSIGNED_BYTE && littleEndian) || ++ srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) { + return &_mesa_texformat_argb8888; + } else + return _dri_texformat_argb8888; +@@ -563,34 +556,31 @@ r300ValidateClientStorage(GLcontext * ctx, GLenum target, + return 0; + } + +- { +- GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth, +- format, type); ++ GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth, ++ format, type); + +- if (RADEON_DEBUG & DEBUG_TEXTURE) +- fprintf(stderr, "%s: srcRowStride %d/%x\n", +- __FUNCTION__, srcRowStride, srcRowStride); ++ if (RADEON_DEBUG & DEBUG_TEXTURE) ++ fprintf(stderr, "%s: srcRowStride %d/%x\n", ++ __FUNCTION__, srcRowStride, srcRowStride); + +- /* Could check this later in upload, pitch restrictions could be +- * relaxed, but would need to store the image pitch somewhere, +- * as packing details might change before image is uploaded: +- */ +- if (!r300IsGartMemory(rmesa, pixels, srcHeight * srcRowStride) +- || (srcRowStride & 63)) +- return 0; ++ /* Could check this later in upload, pitch restrictions could be ++ * relaxed, but would need to store the image pitch somewhere, ++ * as packing details might change before image is uploaded: ++ */ ++ if (!r300IsGartMemory(rmesa, pixels, srcHeight * srcRowStride) ++ || (srcRowStride & 63)) ++ return 0; + +- /* Have validated that _mesa_transfer_teximage would be a straight +- * memcpy at this point. NOTE: future calls to TexSubImage will +- * overwrite the client data. This is explicitly mentioned in the +- * extension spec. +- */ +- texImage->Data = (void *)pixels; +- texImage->IsClientData = GL_TRUE; +- texImage->RowStride = +- srcRowStride / texImage->TexFormat->TexelBytes; ++ /* Have validated that _mesa_transfer_teximage would be a straight ++ * memcpy at this point. NOTE: future calls to TexSubImage will ++ * overwrite the client data. This is explicitly mentioned in the ++ * extension spec. ++ */ ++ texImage->Data = (void *)pixels; ++ texImage->IsClientData = GL_TRUE; ++ texImage->RowStride = srcRowStride / texImage->TexFormat->TexelBytes; + +- return 1; +- } ++ return 1; + } + + static void r300TexImage1D(GLcontext * ctx, GLenum target, GLint level, +diff --git a/src/mesa/drivers/dri/r300/r300_texmem.c b/src/mesa/drivers/dri/r300/r300_texmem.c +index e2e8355..723601a 100644 +--- a/src/mesa/drivers/dri/r300/r300_texmem.c ++++ b/src/mesa/drivers/dri/r300/r300_texmem.c +@@ -63,29 +63,16 @@ SOFTWARE. + */ + void r300DestroyTexObj(r300ContextPtr rmesa, r300TexObjPtr t) + { ++ int i; ++ + if (RADEON_DEBUG & DEBUG_TEXTURE) { + fprintf(stderr, "%s( %p, %p )\n", __FUNCTION__, + (void *)t, (void *)t->base.tObj); + } + +- if (rmesa != NULL) { +- unsigned i; +- +- for (i = 0; i < rmesa->radeon.glCtx->Const.MaxTextureUnits; i++) { +- if (t == rmesa->state.texture.unit[i].texobj) { +- rmesa->state.texture.unit[i].texobj = NULL; +- /* This code below is meant to shorten state +- pushed to the hardware by not programming +- unneeded units. +- +- This does not appear to be worthwhile on R300 */ +-#if 0 +- remove_from_list(&rmesa->hw.tex[i]); +- make_empty_list(&rmesa->hw.tex[i]); +- remove_from_list(&rmesa->hw.cube[i]); +- make_empty_list(&rmesa->hw.cube[i]); +-#endif +- } ++ for (i = 0; i < rmesa->radeon.glCtx->Const.MaxTextureUnits; i++) { ++ if (rmesa->state.texture.unit[i].texobj == t) { ++ rmesa->state.texture.unit[i].texobj = NULL; + } + } + } +@@ -518,7 +505,7 @@ int r300UploadTexImages(r300ContextPtr rmesa, r300TexObjPtr t, GLuint face) + t->base.lastLevel); + } + +- if (!t || t->base.totalSize == 0) ++ if (t->base.totalSize == 0) + return 0; + + if (RADEON_DEBUG & DEBUG_SYNC) { +diff --git a/src/mesa/drivers/dri/r300/r300_texstate.c b/src/mesa/drivers/dri/r300/r300_texstate.c +index 8203189..1d2909f 100644 +--- a/src/mesa/drivers/dri/r300/r300_texstate.c ++++ b/src/mesa/drivers/dri/r300/r300_texstate.c +@@ -54,7 +54,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5 \ + || ((f) >= MESA_FORMAT_RGBA_FLOAT32 && \ + (f) <= MESA_FORMAT_INTENSITY_FLOAT16)) \ +- && tx_table_le[f].flag ) ++ && tx_table[f].flag ) + + #define _ASSIGN(entry, format) \ + [ MESA_FORMAT_ ## entry ] = { format, 0, 1} +@@ -70,53 +70,19 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + static const struct tx_table { + GLuint format, filter, flag; +-} tx_table_be[] = { +- /* *INDENT-OFF* */ +- _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)), +- _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)), +- _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)), +- _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)), +- _ASSIGN(RGB888, 0xffffffff), +- _ASSIGN(RGB565, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)), +- _ASSIGN(RGB565_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)), +- _ASSIGN(ARGB4444, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)), +- _ASSIGN(ARGB4444_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)), +- _ASSIGN(ARGB1555, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)), +- _ASSIGN(ARGB1555_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)), +- _ASSIGN(AL88, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)), +- _ASSIGN(AL88_REV, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)), +- _ASSIGN(RGB332, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z3Y3X2)), +- _ASSIGN(A8, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X8)), +- _ASSIGN(L8, R300_EASY_TX_FORMAT(X, X, X, ONE, X8)), +- _ASSIGN(I8, R300_EASY_TX_FORMAT(X, X, X, X, X8)), +- _ASSIGN(CI8, R300_EASY_TX_FORMAT(X, X, X, X, X8)), +- _ASSIGN(YCBCR, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE ), +- _ASSIGN(YCBCR_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE), +- _ASSIGN(RGB_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, ONE, DXT1)), +- _ASSIGN(RGBA_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT1)), +- _ASSIGN(RGBA_DXT3, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT3)), +- _ASSIGN(RGBA_DXT5, R300_EASY_TX_FORMAT(Y, Z, W, X, DXT5)), +- _ASSIGN(RGBA_FLOAT32, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R32G32B32A32)), +- _ASSIGN(RGBA_FLOAT16, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R16G16B16A16)), +- _ASSIGN(RGB_FLOAT32, 0xffffffff), +- _ASSIGN(RGB_FLOAT16, 0xffffffff), +- _ASSIGN(ALPHA_FLOAT32, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I32)), +- _ASSIGN(ALPHA_FLOAT16, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I16)), +- _ASSIGN(LUMINANCE_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I32)), +- _ASSIGN(LUMINANCE_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I16)), +- _ASSIGN(LUMINANCE_ALPHA_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I32A32)), +- _ASSIGN(LUMINANCE_ALPHA_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I16A16)), +- _ASSIGN(INTENSITY_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, X, FL_I32)), +- _ASSIGN(INTENSITY_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, X, FL_I16)), +- /* *INDENT-ON* */ +-}; +- +-static const struct tx_table tx_table_le[] = { ++} tx_table[] = { + /* *INDENT-OFF* */ ++#ifdef MESA_LITTLE_ENDIAN + _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)), + _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)), + _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)), + _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)), ++#else ++ _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)), ++ _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)), ++ _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)), ++ _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)), ++#endif + _ASSIGN(RGB888, R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8)), + _ASSIGN(RGB565, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)), + _ASSIGN(RGB565_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)), +@@ -131,8 +97,8 @@ static const struct tx_table tx_table_le[] = { + _ASSIGN(L8, R300_EASY_TX_FORMAT(X, X, X, ONE, X8)), + _ASSIGN(I8, R300_EASY_TX_FORMAT(X, X, X, X, X8)), + _ASSIGN(CI8, R300_EASY_TX_FORMAT(X, X, X, X, X8)), +- _ASSIGN(YCBCR, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE ), +- _ASSIGN(YCBCR_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE), ++ _ASSIGN(YCBCR, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8) | R300_TX_FORMAT_YUV_MODE), ++ _ASSIGN(YCBCR_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8) | R300_TX_FORMAT_YUV_MODE), + _ASSIGN(RGB_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, ONE, DXT1)), + _ASSIGN(RGBA_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT1)), + _ASSIGN(RGBA_DXT3, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT3)), +@@ -178,22 +144,10 @@ static void r300SetTexImages(r300ContextPtr rmesa, + + /* Set the hardware texture format + */ +- if (!t->image_override && VALID_FORMAT(baseImage->TexFormat->MesaFormat)) { +- if (_mesa_little_endian()) { +- t->format = +- tx_table_le[baseImage->TexFormat->MesaFormat]. +- format; +- t->filter |= +- tx_table_le[baseImage->TexFormat->MesaFormat]. +- filter; +- } else { +- t->format = +- tx_table_be[baseImage->TexFormat->MesaFormat]. +- format; +- t->filter |= +- tx_table_be[baseImage->TexFormat->MesaFormat]. +- filter; +- } ++ if (!t->image_override ++ && VALID_FORMAT(baseImage->TexFormat->MesaFormat)) { ++ t->format = tx_table[baseImage->TexFormat->MesaFormat].format; ++ t->filter |= tx_table[baseImage->TexFormat->MesaFormat].filter; + } else if (!t->image_override) { + _mesa_problem(NULL, "unexpected texture format in %s", + __FUNCTION__); +@@ -526,11 +480,11 @@ static GLboolean r300UpdateTexture(GLcontext * ctx, int unit) + */ + + rmesa->state.texture.unit[unit].texobj->base.bound &= +- ~(1UL << unit); ++ ~(1 << unit); + } + + rmesa->state.texture.unit[unit].texobj = t; +- t->base.bound |= (1UL << unit); ++ t->base.bound |= (1 << unit); + t->dirty_state |= 1 << unit; + driUpdateTextureLRU((driTextureObject *) t); /* XXX: should be locked! */ + } +@@ -538,15 +492,15 @@ static GLboolean r300UpdateTexture(GLcontext * ctx, int unit) + return !t->border_fallback; + } + +-void r300SetTexOffset(__DRIcontext *pDRICtx, GLint texname, ++void r300SetTexOffset(__DRIcontext * pDRICtx, GLint texname, + unsigned long long offset, GLint depth, GLuint pitch) + { + r300ContextPtr rmesa = +- (r300ContextPtr)((__DRIcontextPrivate*)pDRICtx->private)->driverPrivate; ++ (r300ContextPtr) ((__DRIcontextPrivate *) pDRICtx->private)-> ++ driverPrivate; + struct gl_texture_object *tObj = +- _mesa_lookup_texture(rmesa->radeon.glCtx, texname); ++ _mesa_lookup_texture(rmesa->radeon.glCtx, texname); + r300TexObjPtr t; +- int idx; + + if (!tObj) + return; +@@ -563,24 +517,24 @@ void r300SetTexOffset(__DRIcontext *pDRICtx, GLint texname, + + switch (depth) { + case 32: +- idx = 2; ++ t->format = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8); ++ t->filter |= tx_table[2].filter; + t->pitch_reg /= 4; + break; + case 24: + default: +- idx = 4; ++ t->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8); ++ t->filter |= tx_table[4].filter; + t->pitch_reg /= 4; + break; + case 16: +- idx = 5; ++ t->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5); ++ t->filter |= tx_table[5].filter; + t->pitch_reg /= 2; + break; + } + + t->pitch_reg--; +- +- t->format = tx_table_le[idx].format; +- t->filter |= tx_table_le[idx].filter; + } + + static GLboolean r300UpdateTextureUnit(GLcontext * ctx, int unit) +diff --git a/src/mesa/drivers/dri/r300/r300_vertprog.c b/src/mesa/drivers/dri/r300/r300_vertprog.c +index 1d90ade..7d4e8c9 100644 +--- a/src/mesa/drivers/dri/r300/r300_vertprog.c ++++ b/src/mesa/drivers/dri/r300/r300_vertprog.c +@@ -29,6 +29,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. + * \file + * + * \author Aapo Tahkola ++ * ++ * \author Oliver McFadden ++ * ++ * For a description of the vertex program instruction set see r300_reg.h. + */ + + #include "glheader.h" +@@ -55,54 +59,58 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. + #error Cannot change these! + #endif + +-#define SCALAR_FLAG (1<<31) +-#define FLAG_MASK (1<<31) +-#define OP_MASK (0xf) /* we are unlikely to have more than 15 */ +-#define OPN(operator, ip) {#operator, OPCODE_##operator, ip} +- +-static struct { +- char *name; +- int opcode; +- unsigned long ip; /* number of input operands and flags */ +-} op_names[] = { +- /* *INDENT-OFF* */ +- OPN(ABS, 1), +- OPN(ADD, 2), +- OPN(ARL, 1 | SCALAR_FLAG), +- OPN(DP3, 2), +- OPN(DP4, 2), +- OPN(DPH, 2), +- OPN(DST, 2), +- OPN(EX2, 1 | SCALAR_FLAG), +- OPN(EXP, 1 | SCALAR_FLAG), +- OPN(FLR, 1), +- OPN(FRC, 1), +- OPN(LG2, 1 | SCALAR_FLAG), +- OPN(LIT, 1), +- OPN(LOG, 1 | SCALAR_FLAG), +- OPN(MAD, 3), +- OPN(MAX, 2), +- OPN(MIN, 2), +- OPN(MOV, 1), +- OPN(MUL, 2), +- OPN(POW, 2 | SCALAR_FLAG), +- OPN(RCP, 1 | SCALAR_FLAG), +- OPN(RSQ, 1 | SCALAR_FLAG), +- OPN(SGE, 2), +- OPN(SLT, 2), +- OPN(SUB, 2), +- OPN(SWZ, 1), +- OPN(XPD, 2), +- OPN(RCC, 0), //extra +- OPN(PRINT, 0), +- OPN(END, 0) +- /* *INDENT-ON* */ +-}; +- +-#undef OPN ++/* TODO: Get rid of t_src_class call */ ++#define CMP_SRCS(a, b) ((a.RelAddr != b.RelAddr) || (a.Index != b.Index && \ ++ ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \ ++ t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \ ++ (t_src_class(a.File) == VSF_IN_CLASS_ATTR && \ ++ t_src_class(b.File) == VSF_IN_CLASS_ATTR)))) \ ++ ++#define ZERO_SRC_0 (MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \ ++ SWIZZLE_ZERO, SWIZZLE_ZERO, \ ++ SWIZZLE_ZERO, SWIZZLE_ZERO, \ ++ t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4)) ++ ++#define ZERO_SRC_1 (MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \ ++ SWIZZLE_ZERO, SWIZZLE_ZERO, \ ++ SWIZZLE_ZERO, SWIZZLE_ZERO, \ ++ t_src_class(src[1].File), VSF_FLAG_NONE) | (src[1].RelAddr << 4)) ++ ++#define ZERO_SRC_2 (MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \ ++ SWIZZLE_ZERO, SWIZZLE_ZERO, \ ++ SWIZZLE_ZERO, SWIZZLE_ZERO, \ ++ t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4)) ++ ++#define ONE_SRC_0 (MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \ ++ SWIZZLE_ONE, SWIZZLE_ONE, \ ++ SWIZZLE_ONE, SWIZZLE_ONE, \ ++ t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4)) ++ ++#define ONE_SRC_1 (MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \ ++ SWIZZLE_ONE, SWIZZLE_ONE, \ ++ SWIZZLE_ONE, SWIZZLE_ONE, \ ++ t_src_class(src[1].File), VSF_FLAG_NONE) | (src[1].RelAddr << 4)) ++ ++#define ONE_SRC_2 (MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \ ++ SWIZZLE_ONE, SWIZZLE_ONE, \ ++ SWIZZLE_ONE, SWIZZLE_ONE, \ ++ t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4)) ++ ++/* DP4 version seems to trigger some hw peculiarity */ ++//#define PREFER_DP4 ++ ++#define FREE_TEMPS() \ ++ do { \ ++ if(u_temp_i < vp->num_temporaries) { \ ++ WARN_ONCE("Ran out of temps, num temps %d, us %d\n", vp->num_temporaries, u_temp_i); \ ++ vp->native = GL_FALSE; \ ++ } \ ++ u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; \ ++ } while (0) + + int r300VertexProgUpdateParams(GLcontext * ctx, +- struct r300_vertex_program_cont *vp, float *dst) ++ struct r300_vertex_program_cont *vp, ++ float *dst) + { + int pi; + struct gl_vertex_program *mesa_vp = &vp->mesa_program; +@@ -222,7 +230,7 @@ static unsigned long t_src_class(enum register_file file) + } + } + +-static __inline unsigned long t_swizzle(GLubyte swizzle) ++static inline unsigned long t_swizzle(GLubyte swizzle) + { + /* this is in fact a NOP as the Mesa SWIZZLE_* are all identical to VSF_IN_COMPONENT_* */ + return swizzle; +@@ -234,8 +242,8 @@ static void vp_dump_inputs(struct r300_vertex_program *vp, char *caller) + int i; + + if (vp == NULL) { +- fprintf(stderr, "vp null in call to %s from %s\n", __FUNCTION__, +- caller); ++ fprintf(stderr, "vp null in call to %s from %s\n", ++ __FUNCTION__, caller); + return; + } + +@@ -276,6 +284,8 @@ static unsigned long t_src_index(struct r300_vertex_program *vp, + } + } + ++/* these two functions should probably be merged... */ ++ + static unsigned long t_src(struct r300_vertex_program *vp, + struct prog_src_register *src) + { +@@ -294,7 +304,9 @@ static unsigned long t_src(struct r300_vertex_program *vp, + static unsigned long t_src_scalar(struct r300_vertex_program *vp, + struct prog_src_register *src) + { +- ++ /* src->NegateBase uses the NEGATE_ flags from program_instruction.h, ++ * which equal our VSF_FLAGS_ values, so it's safe to just pass it here. ++ */ + return MAKE_VSF_SOURCE(t_src_index(vp, src), + t_swizzle(GET_SWZ(src->Swizzle, 0)), + t_swizzle(GET_SWZ(src->Swizzle, 0)), +@@ -306,128 +318,741 @@ static unsigned long t_src_scalar(struct r300_vertex_program *vp, + (src->RelAddr << 4); + } + +-static unsigned long t_opcode(enum prog_opcode opcode) ++static GLboolean valid_dst(struct r300_vertex_program *vp, ++ struct prog_dst_register *dst) + { ++ if (dst->File == PROGRAM_OUTPUT && vp->outputs[dst->Index] == -1) { ++ return GL_FALSE; ++ } else if (dst->File == PROGRAM_ADDRESS) { ++ assert(dst->Index == 0); ++ } + +- switch (opcode) { +- /* *INDENT-OFF* */ +- case OPCODE_ARL: return R300_VPI_OUT_OP_ARL; +- case OPCODE_DST: return R300_VPI_OUT_OP_DST; +- case OPCODE_EX2: return R300_VPI_OUT_OP_EX2; +- case OPCODE_EXP: return R300_VPI_OUT_OP_EXP; +- case OPCODE_FRC: return R300_VPI_OUT_OP_FRC; +- case OPCODE_LG2: return R300_VPI_OUT_OP_LG2; +- case OPCODE_LOG: return R300_VPI_OUT_OP_LOG; +- case OPCODE_MAX: return R300_VPI_OUT_OP_MAX; +- case OPCODE_MIN: return R300_VPI_OUT_OP_MIN; +- case OPCODE_MUL: return R300_VPI_OUT_OP_MUL; +- case OPCODE_RCP: return R300_VPI_OUT_OP_RCP; +- case OPCODE_RSQ: return R300_VPI_OUT_OP_RSQ; +- case OPCODE_SGE: return R300_VPI_OUT_OP_SGE; +- case OPCODE_SLT: return R300_VPI_OUT_OP_SLT; +- case OPCODE_DP4: return R300_VPI_OUT_OP_DOT; +- /* *INDENT-ON* */ ++ return GL_TRUE; ++} + +- default: +- fprintf(stderr, "%s: Should not be called with opcode %d!", +- __FUNCTION__, opcode); +- } +- _mesa_exit(-1); +- return 0; ++/* ++ * Instruction Inputs Output Description ++ * ----------- ------ ------ -------------------------------- ++ * ABS v v absolute value ++ * ADD v,v v add ++ * ARL s a address register load ++ * DP3 v,v ssss 3-component dot product ++ * DP4 v,v ssss 4-component dot product ++ * DPH v,v ssss homogeneous dot product ++ * DST v,v v distance vector ++ * EX2 s ssss exponential base 2 ++ * EXP s v exponential base 2 (approximate) ++ * FLR v v floor ++ * FRC v v fraction ++ * LG2 s ssss logarithm base 2 ++ * LIT v v compute light coefficients ++ * LOG s v logarithm base 2 (approximate) ++ * MAD v,v,v v multiply and add ++ * MAX v,v v maximum ++ * MIN v,v v minimum ++ * MOV v v move ++ * MUL v,v v multiply ++ * POW s,s ssss exponentiate ++ * RCP s ssss reciprocal ++ * RSQ s ssss reciprocal square root ++ * SGE v,v v set on greater than or equal ++ * SLT v,v v set on less than ++ * SUB v,v v subtract ++ * SWZ v v extended swizzle ++ * XPD v,v v cross product ++ * ++ * Table X.5: Summary of vertex program instructions. "v" indicates a ++ * floating-point vector input or output, "s" indicates a floating-point ++ * scalar input, "ssss" indicates a scalar output replicated across a ++ * 4-component result vector, and "a" indicates a single address register ++ * component. ++ */ ++ ++static GLuint *t_opcode_abs(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ //MAX RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W ++ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_MAX, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = ++ MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 0)), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 1)), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 2)), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 3)), ++ t_src_class(src[0].File), ++ (!src[0]. ++ NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | ++ (src[0].RelAddr << 4); ++ inst[3] = 0; ++ ++ return inst; + } + +-static unsigned long op_operands(enum prog_opcode opcode) ++static GLuint *t_opcode_add(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) + { +- int i; ++ unsigned long hw_op; + +- /* Can we trust mesas opcodes to be in order ? */ +- for (i = 0; i < sizeof(op_names) / sizeof(*op_names); i++) +- if (op_names[i].opcode == opcode) +- return op_names[i].ip; ++#if 1 ++ hw_op = (src[0].File == PROGRAM_TEMPORARY ++ && src[1].File == ++ PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : ++ R300_VPI_OUT_OP_MAD; ++ ++ inst[0] = ++ MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ inst[1] = ONE_SRC_0; ++ inst[2] = t_src(vp, &src[0]); ++ inst[3] = t_src(vp, &src[1]); ++#else ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = t_src(vp, &src[1]); ++ inst[3] = ZERO_SRC_1; + +- fprintf(stderr, "op %d not found in op_names\n", opcode); +- _mesa_exit(-1); +- return 0; ++#endif ++ ++ return inst; + } + +-static GLboolean valid_dst(struct r300_vertex_program *vp, +- struct prog_dst_register *dst) ++static GLuint *t_opcode_arl(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) + { +- if (dst->File == PROGRAM_OUTPUT && vp->outputs[dst->Index] == -1) { +- return GL_FALSE; +- } else if (dst->File == PROGRAM_ADDRESS) { +- assert(dst->Index == 0); +- } ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_ARL, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); + +- return GL_TRUE; ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++ ++ return inst; + } + +-/* TODO: Get rid of t_src_class call */ +-#define CMP_SRCS(a, b) ((a.RelAddr != b.RelAddr) || (a.Index != b.Index && \ +- ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \ +- t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \ +- (t_src_class(a.File) == VSF_IN_CLASS_ATTR && \ +- t_src_class(b.File) == VSF_IN_CLASS_ATTR)))) \ ++static GLuint *t_opcode_dp3(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ //DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO} ++ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = ++ MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 0)), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 1)), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 2)), ++ SWIZZLE_ZERO, t_src_class(src[0].File), ++ src[0]. ++ NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE) | ++ (src[0].RelAddr << 4); ++ ++ inst[2] = ++ MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), ++ t_swizzle(GET_SWZ(src[1].Swizzle, 0)), ++ t_swizzle(GET_SWZ(src[1].Swizzle, 1)), ++ t_swizzle(GET_SWZ(src[1].Swizzle, 2)), ++ SWIZZLE_ZERO, t_src_class(src[1].File), ++ src[1]. ++ NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE) | ++ (src[1].RelAddr << 4); ++ ++ inst[3] = ZERO_SRC_1; ++ ++ return inst; ++} + +-#define ZERO_SRC_0 (MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \ +- SWIZZLE_ZERO, SWIZZLE_ZERO, \ +- SWIZZLE_ZERO, SWIZZLE_ZERO, \ +- t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4)) ++static GLuint *t_opcode_dp4(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); + +-#define ZERO_SRC_1 (MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \ +- SWIZZLE_ZERO, SWIZZLE_ZERO, \ +- SWIZZLE_ZERO, SWIZZLE_ZERO, \ +- t_src_class(src[1].File), VSF_FLAG_NONE) | (src[1].RelAddr << 4)) ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = t_src(vp, &src[1]); ++ inst[3] = ZERO_SRC_1; + +-#define ZERO_SRC_2 (MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \ +- SWIZZLE_ZERO, SWIZZLE_ZERO, \ +- SWIZZLE_ZERO, SWIZZLE_ZERO, \ +- t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4)) ++ return inst; ++} + +-#define ONE_SRC_0 (MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \ +- SWIZZLE_ONE, SWIZZLE_ONE, \ +- SWIZZLE_ONE, SWIZZLE_ONE, \ +- t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4)) ++static GLuint *t_opcode_dph(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ //DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W} ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = ++ MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 0)), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 1)), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 2)), ++ VSF_IN_COMPONENT_ONE, t_src_class(src[0].File), ++ src[0]. ++ NegateBase ? VSF_FLAG_XYZ : VSF_FLAG_NONE) | ++ (src[0].RelAddr << 4); ++ inst[2] = t_src(vp, &src[1]); ++ inst[3] = ZERO_SRC_1; ++ ++ return inst; ++} + +-#define ONE_SRC_1 (MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \ +- SWIZZLE_ONE, SWIZZLE_ONE, \ +- SWIZZLE_ONE, SWIZZLE_ONE, \ +- t_src_class(src[1].File), VSF_FLAG_NONE) | (src[1].RelAddr << 4)) ++static GLuint *t_opcode_dst(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_DST, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); + +-#define ONE_SRC_2 (MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \ +- SWIZZLE_ONE, SWIZZLE_ONE, \ +- SWIZZLE_ONE, SWIZZLE_ONE, \ +- t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4)) ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = t_src(vp, &src[1]); ++ inst[3] = ZERO_SRC_1; + +-/* DP4 version seems to trigger some hw peculiarity */ +-//#define PREFER_DP4 ++ return inst; ++} + +-#define FREE_TEMPS() \ +- do { \ +- if(u_temp_i < vp->num_temporaries) { \ +- WARN_ONCE("Ran out of temps, num temps %d, us %d\n", vp->num_temporaries, u_temp_i); \ +- vp->native = GL_FALSE; \ +- } \ +- u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; \ +- } while (0) ++static GLuint *t_opcode_ex2(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_EX2, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); + +-static void r300TranslateVertexShader(struct r300_vertex_program *vp, +- struct prog_instruction *vpi) ++ inst[1] = t_src_scalar(vp, &src[0]); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_exp(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_EXP, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src_scalar(vp, &src[0]); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_flr(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3], int *u_temp_i) ++{ ++ /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W} ++ ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} TMP 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W */ ++ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_FRC, *u_temp_i, ++ t_dst_mask(vpi->DstReg.WriteMask), ++ VSF_OUT_CLASS_TMP); ++ ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++ inst += 4; ++ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = ++ MAKE_VSF_SOURCE(*u_temp_i, VSF_IN_COMPONENT_X, ++ VSF_IN_COMPONENT_Y, VSF_IN_COMPONENT_Z, ++ VSF_IN_COMPONENT_W, VSF_IN_CLASS_TMP, ++ /* Not 100% sure about this */ ++ (!src[0]. ++ NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE ++ /*VSF_FLAG_ALL */ ); ++ ++ inst[3] = ZERO_SRC_0; ++ (*u_temp_i)--; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_frc(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_FRC, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_lg2(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ // LG2 RESULT 1.X Y Z W PARAM 0{} {X X X X} ++ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_LG2, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = ++ MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 0)), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 0)), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 0)), ++ t_swizzle(GET_SWZ(src[0].Swizzle, 0)), ++ t_src_class(src[0].File), ++ src[0]. ++ NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | ++ (src[0].RelAddr << 4); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_lit(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ //LIT TMP 1.Y Z TMP 1{} {X W Z Y} TMP 1{} {Y W Z X} TMP 1{} {Y X Z W} ++ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_LIT, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ /* NOTE: Users swizzling might not work. */ ++ inst[1] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x ++ t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w ++ VSF_IN_COMPONENT_ZERO, // z ++ t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y ++ t_src_class(src[0].File), ++ src[0]. ++ NegateBase ? VSF_FLAG_ALL : ++ VSF_FLAG_NONE) | (src[0].RelAddr << 4); ++ inst[2] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y ++ t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w ++ VSF_IN_COMPONENT_ZERO, // z ++ t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x ++ t_src_class(src[0].File), ++ src[0]. ++ NegateBase ? VSF_FLAG_ALL : ++ VSF_FLAG_NONE) | (src[0].RelAddr << 4); ++ inst[3] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y ++ t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x ++ VSF_IN_COMPONENT_ZERO, // z ++ t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w ++ t_src_class(src[0].File), ++ src[0]. ++ NegateBase ? VSF_FLAG_ALL : ++ VSF_FLAG_NONE) | (src[0].RelAddr << 4); ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_log(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_LOG, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src_scalar(vp, &src[0]); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_mad(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) + { +- int i, cur_reg = 0; +- VERTEX_SHADER_INSTRUCTION *o_inst; +- unsigned long operands; +- int are_srcs_scalar; + unsigned long hw_op; +- /* Initial value should be last tmp reg that hw supports. +- Strangely enough r300 doesnt mind even though these would be out of range. +- Smart enough to realize that it doesnt need it? */ +- int u_temp_i = VSF_MAX_FRAGMENT_TEMPS - 1; +- struct prog_src_register src[3]; + +- vp->pos_end = 0; /* Not supported yet */ +- vp->program.length = 0; +- /*vp->num_temporaries=mesa_vp->Base.NumTemporaries; */ ++ hw_op = (src[0].File == PROGRAM_TEMPORARY ++ && src[1].File == PROGRAM_TEMPORARY ++ && src[2].File == ++ PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : ++ R300_VPI_OUT_OP_MAD; ++ ++ inst[0] = ++ MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = t_src(vp, &src[1]); ++ inst[3] = t_src(vp, &src[2]); ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_max(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_MAX, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = t_src(vp, &src[1]); ++ inst[3] = ZERO_SRC_1; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_min(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_MIN, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = t_src(vp, &src[1]); ++ inst[3] = ZERO_SRC_1; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_mov(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ //ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO} ++ ++#if 1 ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++#else ++ hw_op = ++ (src[0].File == ++ PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : ++ R300_VPI_OUT_OP_MAD; ++ ++ inst[0] = ++ MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = ONE_SRC_0; ++ inst[3] = ZERO_SRC_0; ++#endif ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_mul(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ unsigned long hw_op; ++ ++ // HW mul can take third arg but appears to have some other limitations. ++ ++ hw_op = (src[0].File == PROGRAM_TEMPORARY ++ && src[1].File == ++ PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : ++ R300_VPI_OUT_OP_MAD; ++ ++ inst[0] = ++ MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = t_src(vp, &src[1]); ++ ++ inst[3] = ZERO_SRC_1; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_pow(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_POW, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ inst[1] = t_src_scalar(vp, &src[0]); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = t_src_scalar(vp, &src[1]); ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_rcp(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_RCP, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src_scalar(vp, &src[0]); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_rsq(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_RSQ, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src_scalar(vp, &src[0]); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_sge(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_SGE, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = t_src(vp, &src[1]); ++ inst[3] = ZERO_SRC_1; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_slt(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_SLT, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = t_src(vp, &src[1]); ++ inst[3] = ZERO_SRC_1; ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_sub(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ unsigned long hw_op; ++ ++ //ADD RESULT 1.X Y Z W TMP 0{} {X Y Z W} PARAM 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W ++ ++#if 1 ++ hw_op = (src[0].File == PROGRAM_TEMPORARY ++ && src[1].File == ++ PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : ++ R300_VPI_OUT_OP_MAD; ++ ++ inst[0] = ++ MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = ONE_SRC_0; ++ inst[3] = ++ MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), ++ t_swizzle(GET_SWZ(src[1].Swizzle, 0)), ++ t_swizzle(GET_SWZ(src[1].Swizzle, 1)), ++ t_swizzle(GET_SWZ(src[1].Swizzle, 2)), ++ t_swizzle(GET_SWZ(src[1].Swizzle, 3)), ++ t_src_class(src[1].File), ++ (!src[1]. ++ NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | ++ (src[1].RelAddr << 4); ++#else ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = ++ MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), ++ t_swizzle(GET_SWZ(src[1].Swizzle, 0)), ++ t_swizzle(GET_SWZ(src[1].Swizzle, 1)), ++ t_swizzle(GET_SWZ(src[1].Swizzle, 2)), ++ t_swizzle(GET_SWZ(src[1].Swizzle, 3)), ++ t_src_class(src[1].File), ++ (!src[1]. ++ NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | ++ (src[1].RelAddr << 4); ++ inst[3] = 0; ++#endif ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_swz(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3]) ++{ ++ //ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO} ++ ++#if 1 ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++#else ++ hw_op = ++ (src[0].File == ++ PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : ++ R300_VPI_OUT_OP_MAD; ++ ++ inst[0] = ++ MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ inst[1] = t_src(vp, &src[0]); ++ inst[2] = ONE_SRC_0; ++ inst[3] = ZERO_SRC_0; ++#endif ++ ++ return inst; ++} ++ ++static GLuint *t_opcode_xpd(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi, GLuint * inst, ++ struct prog_src_register src[3], int *u_temp_i) ++{ ++ /* mul r0, r1.yzxw, r2.zxyw ++ mad r0, -r2.yzxw, r1.zxyw, r0 ++ NOTE: might need MAD_2 ++ */ ++ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, *u_temp_i, ++ t_dst_mask(vpi->DstReg.WriteMask), ++ VSF_OUT_CLASS_TMP); ++ ++ inst[1] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y ++ t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z ++ t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x ++ t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w ++ t_src_class(src[0].File), ++ src[0]. ++ NegateBase ? VSF_FLAG_ALL : ++ VSF_FLAG_NONE) | (src[0].RelAddr << 4); ++ ++ inst[2] = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z ++ t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x ++ t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y ++ t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w ++ t_src_class(src[1].File), ++ src[1]. ++ NegateBase ? VSF_FLAG_ALL : ++ VSF_FLAG_NONE) | (src[1].RelAddr << 4); ++ ++ inst[3] = ZERO_SRC_1; ++ inst += 4; ++ (*u_temp_i)--; ++ ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, t_dst_index(vp, &vpi->DstReg), ++ t_dst_mask(vpi->DstReg.WriteMask), ++ t_dst_class(vpi->DstReg.File)); ++ ++ inst[1] = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y ++ t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z ++ t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x ++ t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w ++ t_src_class(src[1].File), ++ (!src[1]. ++ NegateBase) ? VSF_FLAG_ALL : ++ VSF_FLAG_NONE) | (src[1].RelAddr << 4); ++ ++ inst[2] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z ++ t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x ++ t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y ++ t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w ++ t_src_class(src[0].File), ++ src[0]. ++ NegateBase ? VSF_FLAG_ALL : ++ VSF_FLAG_NONE) | (src[0].RelAddr << 4); ++ ++ inst[3] = ++ MAKE_VSF_SOURCE(*u_temp_i + 1, VSF_IN_COMPONENT_X, ++ VSF_IN_COMPONENT_Y, VSF_IN_COMPONENT_Z, ++ VSF_IN_COMPONENT_W, VSF_IN_CLASS_TMP, ++ VSF_FLAG_NONE); ++ ++ return inst; ++} ++ ++static void t_inputs_outputs(struct r300_vertex_program *vp) ++{ ++ int i; ++ int cur_reg = 0; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + vp->inputs[i] = -1; +@@ -437,39 +1062,71 @@ static void r300TranslateVertexShader(struct r300_vertex_program *vp, + + assert(vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS)); + +- /* Assign outputs */ +- if (vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS)) ++ if (vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS)) { + vp->outputs[VERT_RESULT_HPOS] = cur_reg++; ++ } + +- if (vp->key.OutputsWritten & (1 << VERT_RESULT_PSIZ)) ++ if (vp->key.OutputsWritten & (1 << VERT_RESULT_PSIZ)) { + vp->outputs[VERT_RESULT_PSIZ] = cur_reg++; ++ } + +- if (vp->key.OutputsWritten & (1 << VERT_RESULT_COL0)) ++ if (vp->key.OutputsWritten & (1 << VERT_RESULT_COL0)) { + vp->outputs[VERT_RESULT_COL0] = cur_reg++; ++ } + +- if (vp->key.OutputsWritten & (1 << VERT_RESULT_COL1)) +- vp->outputs[VERT_RESULT_COL1] = cur_reg++; +- +-#if 0 /* Not supported yet */ +- if (vp->key.OutputsWritten & (1 << VERT_RESULT_BFC0)) +- vp->outputs[VERT_RESULT_BFC0] = cur_reg++; ++ if (vp->key.OutputsWritten & (1 << VERT_RESULT_COL1)) { ++ vp->outputs[VERT_RESULT_COL1] = ++ vp->outputs[VERT_RESULT_COL0] + 1; ++ cur_reg = vp->outputs[VERT_RESULT_COL1] + 1; ++ } + +- if (vp->key.OutputsWritten & (1 << VERT_RESULT_BFC1)) +- vp->outputs[VERT_RESULT_BFC1] = cur_reg++; ++ if (vp->key.OutputsWritten & (1 << VERT_RESULT_BFC0)) { ++ vp->outputs[VERT_RESULT_BFC0] = ++ vp->outputs[VERT_RESULT_COL0] + 2; ++ cur_reg = vp->outputs[VERT_RESULT_BFC0] + 2; ++ } + +- if (vp->key.OutputsWritten & (1 << VERT_RESULT_FOGC)) ++ if (vp->key.OutputsWritten & (1 << VERT_RESULT_BFC1)) { ++ vp->outputs[VERT_RESULT_BFC1] = ++ vp->outputs[VERT_RESULT_COL0] + 3; ++ cur_reg = vp->outputs[VERT_RESULT_BFC1] + 1; ++ } ++#if 0 ++ if (vp->key.OutputsWritten & (1 << VERT_RESULT_FOGC)) { + vp->outputs[VERT_RESULT_FOGC] = cur_reg++; ++ } + #endif + +- for (i = VERT_RESULT_TEX0; i <= VERT_RESULT_TEX7; i++) +- if (vp->key.OutputsWritten & (1 << i)) ++ for (i = VERT_RESULT_TEX0; i <= VERT_RESULT_TEX7; i++) { ++ if (vp->key.OutputsWritten & (1 << i)) { + vp->outputs[i] = cur_reg++; ++ } ++ } ++} ++ ++static void r300TranslateVertexShader(struct r300_vertex_program *vp, ++ struct prog_instruction *vpi) ++{ ++ int i; ++ GLuint *inst; ++ unsigned long num_operands; ++ /* Initial value should be last tmp reg that hw supports. ++ Strangely enough r300 doesnt mind even though these would be out of range. ++ Smart enough to realize that it doesnt need it? */ ++ int u_temp_i = VSF_MAX_FRAGMENT_TEMPS - 1; ++ struct prog_src_register src[3]; + ++ vp->pos_end = 0; /* Not supported yet */ ++ vp->program.length = 0; ++ /*vp->num_temporaries=mesa_vp->Base.NumTemporaries; */ + vp->translated = GL_TRUE; + vp->native = GL_TRUE; + +- o_inst = vp->program.body.i; +- for (; vpi->Opcode != OPCODE_END; vpi++, o_inst++) { ++ t_inputs_outputs(vp); ++ ++ for (inst = vp->program.body.i; vpi->Opcode != OPCODE_END; ++ vpi++, inst += 4) { ++ + FREE_TEMPS(); + + if (!valid_dst(vp, &vpi->DstReg)) { +@@ -478,61 +1135,62 @@ static void r300TranslateVertexShader(struct r300_vertex_program *vp, + vpi->DstReg.Index = u_temp_i; + } + +- operands = op_operands(vpi->Opcode); +- are_srcs_scalar = operands & SCALAR_FLAG; +- operands &= OP_MASK; ++ num_operands = _mesa_num_inst_src_regs(vpi->Opcode); + +- for (i = 0; i < operands; i++) ++ /* copy the sources (src) from mesa into a local variable... is this needed? */ ++ for (i = 0; i < num_operands; i++) { + src[i] = vpi->SrcReg[i]; ++ } + +- if (operands == 3) { /* TODO: scalars */ ++ if (num_operands == 3) { /* TODO: scalars */ + if (CMP_SRCS(src[1], src[2]) + || CMP_SRCS(src[0], src[2])) { +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i, +- VSF_FLAG_ALL, ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, ++ u_temp_i, VSF_FLAG_ALL, + VSF_OUT_CLASS_TMP); + +- o_inst->src[0] = +- MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), ++ inst[1] = ++ MAKE_VSF_SOURCE(t_src_index ++ (vp, &src[2]), + SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_Z, SWIZZLE_W, +- t_src_class(src[2].File), +- VSF_FLAG_NONE) | (src[2]. +- RelAddr << +- 4); ++ t_src_class(src[2]. ++ File), ++ VSF_FLAG_NONE) | ++ (src[2].RelAddr << 4); + +- o_inst->src[1] = ZERO_SRC_2; +- o_inst->src[2] = ZERO_SRC_2; +- o_inst++; ++ inst[2] = ZERO_SRC_2; ++ inst[3] = ZERO_SRC_2; ++ inst += 4; + + src[2].File = PROGRAM_TEMPORARY; + src[2].Index = u_temp_i; + src[2].RelAddr = 0; + u_temp_i--; + } +- + } + +- if (operands >= 2) { ++ if (num_operands >= 2) { + if (CMP_SRCS(src[1], src[0])) { +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i, +- VSF_FLAG_ALL, ++ inst[0] = ++ MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, ++ u_temp_i, VSF_FLAG_ALL, + VSF_OUT_CLASS_TMP); + +- o_inst->src[0] = +- MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), ++ inst[1] = ++ MAKE_VSF_SOURCE(t_src_index ++ (vp, &src[0]), + SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_Z, SWIZZLE_W, +- t_src_class(src[0].File), +- VSF_FLAG_NONE) | (src[0]. +- RelAddr << +- 4); ++ t_src_class(src[0]. ++ File), ++ VSF_FLAG_NONE) | ++ (src[0].RelAddr << 4); + +- o_inst->src[1] = ZERO_SRC_0; +- o_inst->src[2] = ZERO_SRC_0; +- o_inst++; ++ inst[2] = ZERO_SRC_0; ++ inst[3] = ZERO_SRC_0; ++ inst += 4; + + src[0].File = PROGRAM_TEMPORARY; + src[0].Index = u_temp_i; +@@ -541,517 +1199,103 @@ static void r300TranslateVertexShader(struct r300_vertex_program *vp, + } + } + +- /* These ops need special handling. */ + switch (vpi->Opcode) { +- case OPCODE_POW: +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_POW, +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- o_inst->src[0] = t_src_scalar(vp, &src[0]); +- o_inst->src[1] = ZERO_SRC_0; +- o_inst->src[2] = t_src_scalar(vp, &src[1]); +- goto next; +- +- case OPCODE_MOV: //ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO} +- case OPCODE_SWZ: +-#if 1 +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = ZERO_SRC_0; +- o_inst->src[2] = ZERO_SRC_0; +-#else +- hw_op = +- (src[0].File == +- PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : +- R300_VPI_OUT_OP_MAD; +- +- o_inst->op = +- MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = ONE_SRC_0; +- o_inst->src[2] = ZERO_SRC_0; +-#endif +- +- goto next; +- ++ case OPCODE_ABS: ++ inst = t_opcode_abs(vp, vpi, inst, src); ++ break; + case OPCODE_ADD: +-#if 1 +- hw_op = (src[0].File == PROGRAM_TEMPORARY && +- src[1].File == +- PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : +- R300_VPI_OUT_OP_MAD; +- +- o_inst->op = +- MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- o_inst->src[0] = ONE_SRC_0; +- o_inst->src[1] = t_src(vp, &src[0]); +- o_inst->src[2] = t_src(vp, &src[1]); +-#else +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = t_src(vp, &src[1]); +- o_inst->src[2] = ZERO_SRC_1; +- +-#endif +- goto next; +- +- case OPCODE_MAD: +- hw_op = (src[0].File == PROGRAM_TEMPORARY && +- src[1].File == PROGRAM_TEMPORARY && +- src[2].File == +- PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : +- R300_VPI_OUT_OP_MAD; +- +- o_inst->op = +- MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = t_src(vp, &src[1]); +- o_inst->src[2] = t_src(vp, &src[2]); +- goto next; +- +- case OPCODE_MUL: /* HW mul can take third arg but appears to have some other limitations. */ +- hw_op = (src[0].File == PROGRAM_TEMPORARY && +- src[1].File == +- PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : +- R300_VPI_OUT_OP_MAD; +- +- o_inst->op = +- MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = t_src(vp, &src[1]); +- +- o_inst->src[2] = ZERO_SRC_1; +- goto next; +- +- case OPCODE_DP3: //DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO} +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- +- o_inst->src[0] = +- MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 0)), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 1)), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 2)), +- SWIZZLE_ZERO, +- t_src_class(src[0].File), +- src[0]. +- NegateBase ? VSF_FLAG_XYZ : +- VSF_FLAG_NONE) | (src[0]. +- RelAddr << 4); +- +- o_inst->src[1] = +- MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), +- t_swizzle(GET_SWZ +- (src[1].Swizzle, 0)), +- t_swizzle(GET_SWZ +- (src[1].Swizzle, 1)), +- t_swizzle(GET_SWZ +- (src[1].Swizzle, 2)), +- SWIZZLE_ZERO, +- t_src_class(src[1].File), +- src[1]. +- NegateBase ? VSF_FLAG_XYZ : +- VSF_FLAG_NONE) | (src[1]. +- RelAddr << 4); +- +- o_inst->src[2] = ZERO_SRC_1; +- goto next; +- +- case OPCODE_SUB: //ADD RESULT 1.X Y Z W TMP 0{} {X Y Z W} PARAM 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W +-#if 1 +- hw_op = (src[0].File == PROGRAM_TEMPORARY && +- src[1].File == +- PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : +- R300_VPI_OUT_OP_MAD; +- +- o_inst->op = +- MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = ONE_SRC_0; +- o_inst->src[2] = +- MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), +- t_swizzle(GET_SWZ +- (src[1].Swizzle, 0)), +- t_swizzle(GET_SWZ +- (src[1].Swizzle, 1)), +- t_swizzle(GET_SWZ +- (src[1].Swizzle, 2)), +- t_swizzle(GET_SWZ +- (src[1].Swizzle, 3)), +- t_src_class(src[1].File), +- (!src[1]. +- NegateBase) ? VSF_FLAG_ALL : +- VSF_FLAG_NONE) | (src[1]. +- RelAddr << 4); +-#else +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = +- MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), +- t_swizzle(GET_SWZ +- (src[1].Swizzle, 0)), +- t_swizzle(GET_SWZ +- (src[1].Swizzle, 1)), +- t_swizzle(GET_SWZ +- (src[1].Swizzle, 2)), +- t_swizzle(GET_SWZ +- (src[1].Swizzle, 3)), +- t_src_class(src[1].File), +- (!src[1]. +- NegateBase) ? VSF_FLAG_ALL : +- VSF_FLAG_NONE) | (src[1]. +- RelAddr << 4); +- o_inst->src[2] = 0; +-#endif +- goto next; +- +- case OPCODE_ABS: //MAX RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_MAX, +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = +- MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 0)), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 1)), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 2)), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 3)), +- t_src_class(src[0].File), +- (!src[0]. +- NegateBase) ? VSF_FLAG_ALL : +- VSF_FLAG_NONE) | (src[0]. +- RelAddr << 4); +- o_inst->src[2] = 0; +- goto next; +- ++ inst = t_opcode_add(vp, vpi, inst, src); ++ break; ++ case OPCODE_ARL: ++ inst = t_opcode_arl(vp, vpi, inst, src); ++ break; ++ case OPCODE_DP3: ++ inst = t_opcode_dp3(vp, vpi, inst, src); ++ break; ++ case OPCODE_DP4: ++ inst = t_opcode_dp4(vp, vpi, inst, src); ++ break; ++ case OPCODE_DPH: ++ inst = t_opcode_dph(vp, vpi, inst, src); ++ break; ++ case OPCODE_DST: ++ inst = t_opcode_dst(vp, vpi, inst, src); ++ break; ++ case OPCODE_EX2: ++ inst = t_opcode_ex2(vp, vpi, inst, src); ++ break; ++ case OPCODE_EXP: ++ inst = t_opcode_exp(vp, vpi, inst, src); ++ break; + case OPCODE_FLR: +- /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W} +- ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} TMP 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W */ +- +- o_inst->op = MAKE_VSF_OP(R300_VPI_OUT_OP_FRC, u_temp_i, +- t_dst_mask(vpi->DstReg. +- WriteMask), +- VSF_OUT_CLASS_TMP); +- +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = ZERO_SRC_0; +- o_inst->src[2] = ZERO_SRC_0; +- o_inst++; +- +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = MAKE_VSF_SOURCE(u_temp_i, +- VSF_IN_COMPONENT_X, +- VSF_IN_COMPONENT_Y, +- VSF_IN_COMPONENT_Z, +- VSF_IN_COMPONENT_W, +- VSF_IN_CLASS_TMP, +- /* Not 100% sure about this */ +- (!src[0]. +- NegateBase) ? +- VSF_FLAG_ALL : +- VSF_FLAG_NONE +- /*VSF_FLAG_ALL */ ); +- +- o_inst->src[2] = ZERO_SRC_0; +- u_temp_i--; +- goto next; +- +- case OPCODE_LG2: // LG2 RESULT 1.X Y Z W PARAM 0{} {X X X X} +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_LG2, +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- +- o_inst->src[0] = +- MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 0)), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 0)), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 0)), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 0)), +- t_src_class(src[0].File), +- src[0]. +- NegateBase ? VSF_FLAG_ALL : +- VSF_FLAG_NONE) | (src[0]. +- RelAddr << 4); +- o_inst->src[1] = ZERO_SRC_0; +- o_inst->src[2] = ZERO_SRC_0; +- goto next; +- +- case OPCODE_LIT: //LIT TMP 1.Y Z TMP 1{} {X W Z Y} TMP 1{} {Y W Z X} TMP 1{} {Y X Z W} +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_LIT, +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- /* NOTE: Users swizzling might not work. */ +- o_inst->src[0] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x +- t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w +- VSF_IN_COMPONENT_ZERO, // z +- t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y +- t_src_class(src[0]. +- File), +- src[0]. +- NegateBase ? +- VSF_FLAG_ALL : +- VSF_FLAG_NONE) | +- (src[0].RelAddr << 4); +- o_inst->src[1] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y +- t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w +- VSF_IN_COMPONENT_ZERO, // z +- t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x +- t_src_class(src[0]. +- File), +- src[0]. +- NegateBase ? +- VSF_FLAG_ALL : +- VSF_FLAG_NONE) | +- (src[0].RelAddr << 4); +- o_inst->src[2] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y +- t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x +- VSF_IN_COMPONENT_ZERO, // z +- t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w +- t_src_class(src[0]. +- File), +- src[0]. +- NegateBase ? +- VSF_FLAG_ALL : +- VSF_FLAG_NONE) | +- (src[0].RelAddr << 4); +- goto next; +- +- case OPCODE_DPH: //DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W} +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- +- o_inst->src[0] = +- MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 0)), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 1)), +- t_swizzle(GET_SWZ +- (src[0].Swizzle, 2)), +- VSF_IN_COMPONENT_ONE, +- t_src_class(src[0].File), +- src[0]. +- NegateBase ? VSF_FLAG_XYZ : +- VSF_FLAG_NONE) | (src[0]. +- RelAddr << 4); +- o_inst->src[1] = t_src(vp, &src[1]); +- o_inst->src[2] = ZERO_SRC_1; +- goto next; +- +- case OPCODE_XPD: +- /* mul r0, r1.yzxw, r2.zxyw +- mad r0, -r2.yzxw, r1.zxyw, r0 +- NOTE: might need MAD_2 +- */ +- +- o_inst->op = MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, u_temp_i, +- t_dst_mask(vpi->DstReg. +- WriteMask), +- VSF_OUT_CLASS_TMP); +- +- o_inst->src[0] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y +- t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z +- t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x +- t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w +- t_src_class(src[0]. +- File), +- src[0]. +- NegateBase ? +- VSF_FLAG_ALL : +- VSF_FLAG_NONE) | +- (src[0].RelAddr << 4); +- +- o_inst->src[1] = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z +- t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x +- t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y +- t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w +- t_src_class(src[1]. +- File), +- src[1]. +- NegateBase ? +- VSF_FLAG_ALL : +- VSF_FLAG_NONE) | +- (src[1].RelAddr << 4); +- +- o_inst->src[2] = ZERO_SRC_1; +- o_inst++; +- u_temp_i--; +- +- o_inst->op = +- MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- +- o_inst->src[0] = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y +- t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z +- t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x +- t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w +- t_src_class(src[1]. +- File), +- (!src[1]. +- NegateBase) ? +- VSF_FLAG_ALL : +- VSF_FLAG_NONE) | +- (src[1].RelAddr << 4); +- +- o_inst->src[1] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z +- t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x +- t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y +- t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w +- t_src_class(src[0]. +- File), +- src[0]. +- NegateBase ? +- VSF_FLAG_ALL : +- VSF_FLAG_NONE) | +- (src[0].RelAddr << 4); +- +- o_inst->src[2] = MAKE_VSF_SOURCE(u_temp_i + 1, +- VSF_IN_COMPONENT_X, +- VSF_IN_COMPONENT_Y, +- VSF_IN_COMPONENT_Z, +- VSF_IN_COMPONENT_W, +- VSF_IN_CLASS_TMP, +- VSF_FLAG_NONE); +- +- goto next; +- +- case OPCODE_RCC: +- fprintf(stderr, "Dont know how to handle op %d yet\n", +- vpi->Opcode); +- _mesa_exit(-1); ++ inst = ++ t_opcode_flr(vp, vpi, inst, src, /* FIXME */ ++ &u_temp_i); ++ break; ++ case OPCODE_FRC: ++ inst = t_opcode_frc(vp, vpi, inst, src); ++ break; ++ case OPCODE_LG2: ++ inst = t_opcode_lg2(vp, vpi, inst, src); ++ break; ++ case OPCODE_LIT: ++ inst = t_opcode_lit(vp, vpi, inst, src); ++ break; ++ case OPCODE_LOG: ++ inst = t_opcode_log(vp, vpi, inst, src); ++ break; ++ case OPCODE_MAD: ++ inst = t_opcode_mad(vp, vpi, inst, src); ++ break; ++ case OPCODE_MAX: ++ inst = t_opcode_max(vp, vpi, inst, src); ++ break; ++ case OPCODE_MIN: ++ inst = t_opcode_min(vp, vpi, inst, src); ++ break; ++ case OPCODE_MOV: ++ inst = t_opcode_mov(vp, vpi, inst, src); + break; +- case OPCODE_END: ++ case OPCODE_MUL: ++ inst = t_opcode_mul(vp, vpi, inst, src); ++ break; ++ case OPCODE_POW: ++ inst = t_opcode_pow(vp, vpi, inst, src); ++ break; ++ case OPCODE_RCP: ++ inst = t_opcode_rcp(vp, vpi, inst, src); ++ break; ++ case OPCODE_RSQ: ++ inst = t_opcode_rsq(vp, vpi, inst, src); ++ break; ++ case OPCODE_SGE: ++ inst = t_opcode_sge(vp, vpi, inst, src); ++ break; ++ case OPCODE_SLT: ++ inst = t_opcode_slt(vp, vpi, inst, src); ++ break; ++ case OPCODE_SUB: ++ inst = t_opcode_sub(vp, vpi, inst, src); ++ break; ++ case OPCODE_SWZ: ++ inst = t_opcode_swz(vp, vpi, inst, src); ++ break; ++ case OPCODE_XPD: ++ inst = ++ t_opcode_xpd(vp, vpi, inst, src, /* FIXME */ ++ &u_temp_i); + break; + default: ++ assert(0); + break; + } +- +- o_inst->op = +- MAKE_VSF_OP(t_opcode(vpi->Opcode), +- t_dst_index(vp, &vpi->DstReg), +- t_dst_mask(vpi->DstReg.WriteMask), +- t_dst_class(vpi->DstReg.File)); +- +- if (are_srcs_scalar) { +- switch (operands) { +- case 1: +- o_inst->src[0] = t_src_scalar(vp, &src[0]); +- o_inst->src[1] = ZERO_SRC_0; +- o_inst->src[2] = ZERO_SRC_0; +- break; +- +- case 2: +- o_inst->src[0] = t_src_scalar(vp, &src[0]); +- o_inst->src[1] = t_src_scalar(vp, &src[1]); +- o_inst->src[2] = ZERO_SRC_1; +- break; +- +- case 3: +- o_inst->src[0] = t_src_scalar(vp, &src[0]); +- o_inst->src[1] = t_src_scalar(vp, &src[1]); +- o_inst->src[2] = t_src_scalar(vp, &src[2]); +- break; +- +- default: +- fprintf(stderr, +- "scalars and op RCC not handled yet"); +- _mesa_exit(-1); +- break; +- } +- } else { +- switch (operands) { +- case 1: +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = ZERO_SRC_0; +- o_inst->src[2] = ZERO_SRC_0; +- break; +- +- case 2: +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = t_src(vp, &src[1]); +- o_inst->src[2] = ZERO_SRC_1; +- break; +- +- case 3: +- o_inst->src[0] = t_src(vp, &src[0]); +- o_inst->src[1] = t_src(vp, &src[1]); +- o_inst->src[2] = t_src(vp, &src[2]); +- break; +- +- default: +- fprintf(stderr, +- "scalars and op RCC not handled yet"); +- _mesa_exit(-1); +- break; +- } +- } +- next:; + } + +- /* Will most likely segfault before we get here... fix later. */ +- if (o_inst - vp->program.body.i >= VSF_MAX_FRAGMENT_LENGTH / 4) { ++ vp->program.length = (inst - vp->program.body.i); ++ if (vp->program.length >= VSF_MAX_FRAGMENT_LENGTH) { + vp->program.length = 0; + vp->native = GL_FALSE; +- return; + } +- vp->program.length = (o_inst - vp->program.body.i) * 4; + #if 0 + fprintf(stderr, "hw program:\n"); + for (i = 0; i < vp->program.length; i++) +@@ -1065,7 +1309,8 @@ static void position_invariant(struct gl_program *prog) + struct gl_program_parameter_list *paramList; + int i; + +- gl_state_index tokens[STATE_LENGTH] = { STATE_MVP_MATRIX, 0, 0, 0, 0 }; ++ gl_state_index tokens[STATE_LENGTH] = ++ { STATE_MVP_MATRIX, 0, 0, 0, 0 }; + + /* tokens[4] = matrix modifier */ + #ifdef PREFER_DP4 +@@ -1159,8 +1404,8 @@ static void insert_wpos(struct r300_vertex_program *vp, + prog->NumInstructions - 1); + /* END */ + _mesa_copy_instructions(&vpi[prog->NumInstructions + 1], +- &prog->Instructions[prog->NumInstructions - 1], +- 1); ++ &prog->Instructions[prog->NumInstructions - ++ 1], 1); + vpi_insert = &vpi[prog->NumInstructions - 1]; + + vpi_insert[i].Opcode = OPCODE_MOV; +@@ -1206,8 +1451,8 @@ static void pos_as_texcoord(struct r300_vertex_program *vp, + prog->NumTemporaries++; + + for (vpi = prog->Instructions; vpi->Opcode != OPCODE_END; vpi++) { +- if (vpi->DstReg.File == PROGRAM_OUTPUT && +- vpi->DstReg.Index == VERT_RESULT_HPOS) { ++ if (vpi->DstReg.File == PROGRAM_OUTPUT ++ && vpi->DstReg.Index == VERT_RESULT_HPOS) { + vpi->DstReg.File = PROGRAM_TEMPORARY; + vpi->DstReg.Index = tempregi; + } +@@ -1223,20 +1468,18 @@ static struct r300_vertex_program *build_program(struct r300_vertex_program_key + + vp = _mesa_calloc(sizeof(*vp)); + _mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key)); +- + vp->wpos_idx = wpos_idx; + + if (mesa_vp->IsPositionInvariant) { + position_invariant(&mesa_vp->Base); + } + +- if (wpos_idx > -1) ++ if (wpos_idx > -1) { + pos_as_texcoord(vp, &mesa_vp->Base); ++ } + + assert(mesa_vp->Base.NumInstructions); +- + vp->num_temporaries = mesa_vp->Base.NumTemporaries; +- + r300TranslateVertexShader(vp, mesa_vp->Base.Instructions); + + return vp; +@@ -1252,11 +1495,10 @@ void r300SelectVertexShader(r300ContextPtr r300) + struct r300_vertex_program *vp; + GLint wpos_idx; + +- vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current; ++ vpc = ++ (struct r300_vertex_program_cont *)ctx->VertexProgram._Current; + InputsRead = ctx->FragmentProgram._Current->Base.InputsRead; + +- wanted_key.OutputsWritten |= 1 << VERT_RESULT_HPOS; +- + wpos_idx = -1; + if (InputsRead & FRAG_BIT_WPOS) { + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) +@@ -1271,28 +1513,35 @@ void r300SelectVertexShader(r300ContextPtr r300) + InputsRead |= (FRAG_BIT_TEX0 << i); + wpos_idx = i; + } ++ wanted_key.InputsRead = vpc->mesa_program.Base.InputsRead; ++ wanted_key.OutputsWritten = vpc->mesa_program.Base.OutputsWritten; ++ ++ wanted_key.OutputsWritten |= 1 << VERT_RESULT_HPOS; + +- if (InputsRead & FRAG_BIT_COL0) ++ if (InputsRead & FRAG_BIT_COL0) { + wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL0; ++ } + +- if ((InputsRead & FRAG_BIT_COL1) /*|| +- (InputsRead & FRAG_BIT_FOGC) */ ) ++ if ((InputsRead & FRAG_BIT_COL1)) { + wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL1; ++ } + +- for (i = 0; i < ctx->Const.MaxTextureUnits; i++) +- if (InputsRead & (FRAG_BIT_TEX0 << i)) ++ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { ++ if (InputsRead & (FRAG_BIT_TEX0 << i)) { + wanted_key.OutputsWritten |= + 1 << (VERT_RESULT_TEX0 + i); ++ } ++ } + +- wanted_key.InputsRead = vpc->mesa_program.Base.InputsRead; + if (vpc->mesa_program.IsPositionInvariant) { + /* we wan't position don't we ? */ + wanted_key.InputsRead |= (1 << VERT_ATTRIB_POS); ++ wanted_key.OutputsWritten |= (1 << VERT_RESULT_HPOS); + } + + for (vp = vpc->progs; vp; vp = vp->next) +- if (_mesa_memcmp(&vp->key, &wanted_key, sizeof(wanted_key)) == +- 0) { ++ if (_mesa_memcmp(&vp->key, &wanted_key, sizeof(wanted_key)) ++ == 0) { + r300->selected_vp = vp; + return; + } +diff --git a/src/mesa/drivers/dri/r300/r300_vertprog.h b/src/mesa/drivers/dri/r300/r300_vertprog.h +index 252d5a9..3df0eee 100644 +--- a/src/mesa/drivers/dri/r300/r300_vertprog.h ++++ b/src/mesa/drivers/dri/r300/r300_vertprog.h +@@ -3,11 +3,6 @@ + + #include "r300_reg.h" + +-typedef struct { +- GLuint op; +- GLuint src[3]; +-} VERTEX_SHADER_INSTRUCTION; +- + #define VSF_FLAG_X 1 + #define VSF_FLAG_Y 2 + #define VSF_FLAG_Z 4 +diff --git a/src/mesa/drivers/dri/r300/radeon_lock.h b/src/mesa/drivers/dri/r300/radeon_lock.h +index c47adc9..a344837 100644 +--- a/src/mesa/drivers/dri/r300/radeon_lock.h ++++ b/src/mesa/drivers/dri/r300/radeon_lock.h +@@ -42,9 +42,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + #ifndef __RADEON_LOCK_H__ + #define __RADEON_LOCK_H__ + +-#if 0 +-#include "r200_ioctl.h" +-#endif + #include "radeon_context.h" + + extern void radeonGetLock(radeonContextPtr rmesa, GLuint flags); diff --git a/mesa-7.0.1-stable-branch.patch b/mesa-7.0.1-stable-branch.patch new file mode 100644 index 0000000..d419048 --- /dev/null +++ b/mesa-7.0.1-stable-branch.patch @@ -0,0 +1,1447 @@ +Brian (21): + added md5 sums + fix even-sized point positioning (bug 11874) + Merge branch 'mesa_7_0_branch' of git+ssh://brianp@git.freedesktop.org/git/mesa/mesa into mesa_7_0_branch + fix bug 9962 (vbo splitting) as in trunk + initial 7.0.2 notes + fix swizzle error test (bug 11881) + fix potential NULL dereference (bug 11880) + remove SHELL line, replace -e test with new logic (Daniel Stone) + fix potential NULL dereference (bug 11879) + move free() after dereference (bug 11878) + fix byte swap bug for GLuint stencil indexes (bug 11909) + fix link to 7.0.1 relnotes + Implement mutex/locking around texture object reference counting. + free any render/framebuffers left in hash tables when freeing shared state + Add PCI IDs for the G33, Q33, and Q35 chipsets. + added more i915/945 chipsets + fix blending/banding bug + Fix a few more problems with freeing FBOs/textures during context destruction. + added some temporary texobj ref counting debug output + more tex obj ref count debugging (temporary) + Added _mesa_free_attrib_data() to free anything left in the attribute stack upon context destruction. + +Dan Torop (1): + fix spantmp2 READ_RGBA inline asm (#11931) + +Michel Dänzer (1): + i915tex: Make sure pitch is aligned properly for render-to-texture. + +Wang Zhenyu (1): + i915tex: Add support for 945GME + +diff --git a/Makefile b/Makefile +index 3cab262..56efa83 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,5 @@ + # Top-level Mesa makefile + +-SHELL = /bin/bash +- + TOP = . + + SUBDIRS = src progs +@@ -156,7 +154,7 @@ sunos5-v9 \ + sunos5-v9-static \ + sunos5-v9-cc-g++ \ + ultrix-gcc: +- @ if [ -e configs/current ] ; then \ ++ @ if test -f configs/current || test -L configs/current ; then \ + echo "Please run 'make realclean' before changing configs" ; \ + exit 1 ; \ + fi +diff --git a/docs/news.html b/docs/news.html +index 1f66d4e..e5f2adb 100644 +--- a/docs/news.html ++++ b/docs/news.html +@@ -13,7 +13,7 @@ + +

August 3, 2007

+

+-Mesa 7.0.1 is released. ++Mesa 7.0.1 is released. + This is a bug-fix release. +

+ +diff --git a/docs/relnotes-7.0.1.html b/docs/relnotes-7.0.1.html +index 47ee162..02713ad 100644 +--- a/docs/relnotes-7.0.1.html ++++ b/docs/relnotes-7.0.1.html +@@ -17,6 +17,15 @@ Mesa 7.0.1 is a stable release with bug fixes since version 7.0. + +

MD5 checksums

+
++db55141a44b902fcc61d9265b7862c06  MesaLib-7.0.1.tar.gz
++c056abd763e899114bf745c9eedbf9ad  MesaLib-7.0.1.tar.bz2
++ecc2637547fae2b38271ae362d013afa  MesaLib-7.0.1.zip
++b85a4a5be4e829f4a1165e4514b13183  MesaDemos-7.0.1.tar.gz
++3b66b3268df12ca8a6c4e0c4c457912c  MesaDemos-7.0.1.tar.bz2
++b1c18006f16e44e80fea66774c59b391  MesaDemos-7.0.1.zip
++b87a69986839ae43ce12fc8e3dc1ebb4  MesaGLUT-7.0.1.tar.gz
++25f30d0c1651997b4412366ba0572f7f  MesaGLUT-7.0.1.tar.bz2
++676ee6682a6ce78a5540554fd975c03e  MesaGLUT-7.0.1.zip
+ 
+ + +diff --git a/docs/relnotes-7.0.2.html b/docs/relnotes-7.0.2.html +new file mode 100644 +index 0000000..f1fd3d2 +--- /dev/null ++++ b/docs/relnotes-7.0.2.html +@@ -0,0 +1,70 @@ ++ ++ ++Mesa Release Notes ++ ++ ++ ++ ++ ++ ++ ++

Mesa 7.0.2 Release Notes / (TBD) 2007

++ ++

++Mesa 7.0.2 is a stable release with bug fixes since version 7.0. ++

++ ++ ++

MD5 checksums

++
++
++ ++ ++

New features

++
    ++
++ ++

Bug fixes

++
    ++
  • Fixed a vertex buffer wrapping issue (bug 9962) ++
  • Added mutex protection around texture object reference counters ++
  • Added checking/support for additional chips in the i915/i945 family ++(see 11978) ++
  • Fixed a blending/banding issue (bug 11931) ++
++ ++ ++

Changes

++
    ++
++ ++ ++

To Do (someday) items

++
    ++
  • Switch to freeglut ++
  • Fix linux-glide target/driver. ++
  • Improved lambda and derivative calculation for frag progs. ++
++ ++ ++

Driver Status

++ ++
++Driver			Status
++----------------------	----------------------
++DRI drivers		varies with the driver
++XMesa/GLX (on Xlib)	implements OpenGL 2.1
++OSMesa (off-screen)	implements OpenGL 2.1
++Windows/Win32		implements OpenGL 2.1
++Glide (3dfx Voodoo1/2)	implements OpenGL 1.3
++SVGA			unsupported
++Wind River UGL		unsupported
++DJGPP			unsupported
++GGI			unsupported
++BeOS			unsupported
++Allegro			unsupported
++D3D			unsupported
++
++ ++ ++ +diff --git a/docs/relnotes.html b/docs/relnotes.html +index 9a978d9..7464f5c 100644 +--- a/docs/relnotes.html ++++ b/docs/relnotes.html +@@ -20,6 +20,7 @@ The release notes summarize what's new or changed in each Mesa release. +

+ +
    ++
  • 7.0.2 release notes +
  • 7.0.1 release notes +
  • 7.0 release notes +
  • 6.5.3 release notes +diff --git a/src/mesa/drivers/dri/common/spantmp2.h b/src/mesa/drivers/dri/common/spantmp2.h +index 50f3cf5..53f5f84 100644 +--- a/src/mesa/drivers/dri/common/spantmp2.h ++++ b/src/mesa/drivers/dri/common/spantmp2.h +@@ -114,7 +114,7 @@ + do { \ + GLuint p = *(volatile GLuint *) GET_PTR(_x, _y); \ + __asm__ __volatile__( "bswap %0; rorl $8, %0" \ +- : "=r" (p) : "r" (p) ); \ ++ : "=r" (p) : "0" (p) ); \ + ((GLuint *)rgba)[0] = p; \ + } while (0) + # elif defined( MESA_BIG_ENDIAN ) +diff --git a/src/mesa/drivers/dri/i810/i810screen.c b/src/mesa/drivers/dri/i810/i810screen.c +index f64c10a..f8cf050 100644 +--- a/src/mesa/drivers/dri/i810/i810screen.c ++++ b/src/mesa/drivers/dri/i810/i810screen.c +@@ -288,8 +288,8 @@ i810InitDriver(__DRIscreenPrivate *sPriv) + i810Screen->depth.handle, + i810Screen->depth.size, + (drmAddress *)&i810Screen->depth.map) != 0) { +- FREE(i810Screen); + drmUnmap(i810Screen->back.map, i810Screen->back.size); ++ FREE(i810Screen); + sPriv->private = NULL; + __driUtilMessage("i810InitDriver: drmMap (2) failed"); + return GL_FALSE; +diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c +index 9f0c949..a19d4b6 100644 +--- a/src/mesa/drivers/dri/i915/i915_texstate.c ++++ b/src/mesa/drivers/dri/i915/i915_texstate.c +@@ -491,12 +491,19 @@ static void i915SetTexImages( i915ContextPtr i915, + abort(); + } + +- +- if (i915->intel.intelScreen->deviceID == PCI_CHIP_I945_G || +- i915->intel.intelScreen->deviceID == PCI_CHIP_I945_GM) +- i945LayoutTextureImages( i915, tObj ); +- else +- i915LayoutTextureImages( i915, tObj ); ++ switch (i915->intel.intelScreen->deviceID) { ++ case PCI_CHIP_I945_G: ++ case PCI_CHIP_I945_GM: ++ case PCI_CHIP_I945_GME: ++ case PCI_CHIP_G33_G: ++ case PCI_CHIP_Q33_G: ++ case PCI_CHIP_Q35_G: ++ i945LayoutTextureImages( i915, tObj ); ++ break; ++ default: ++ i915LayoutTextureImages( i915, tObj ); ++ break; ++ } + + t->Setup[I915_TEXREG_MS3] = + (((tObj->Image[0][t->intel.base.firstLevel]->Height - 1) << MS3_HEIGHT_SHIFT) | +diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c +index e1e7cdb..bb5ce64 100644 +--- a/src/mesa/drivers/dri/i915/intel_context.c ++++ b/src/mesa/drivers/dri/i915/intel_context.c +@@ -123,6 +123,14 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) + chipset = "Intel(R) 945G"; break; + case PCI_CHIP_I945_GM: + chipset = "Intel(R) 945GM"; break; ++ case PCI_CHIP_I945_GME: ++ chipset = "Intel(R) 945GME"; break; ++ case PCI_CHIP_G33_G: ++ chipset = "Intel(R) G33"; break; ++ case PCI_CHIP_Q35_G: ++ chipset = "Intel(R) Q35"; break; ++ case PCI_CHIP_Q33_G: ++ chipset = "Intel(R) Q33"; break; + default: + chipset = "Unknown Intel Chipset"; break; + } +diff --git a/src/mesa/drivers/dri/i915/intel_context.h b/src/mesa/drivers/dri/i915/intel_context.h +index 05195e7..50e6178 100644 +--- a/src/mesa/drivers/dri/i915/intel_context.h ++++ b/src/mesa/drivers/dri/i915/intel_context.h +@@ -454,6 +454,10 @@ extern int INTEL_DEBUG; + #define PCI_CHIP_I915_GM 0x2592 + #define PCI_CHIP_I945_G 0x2772 + #define PCI_CHIP_I945_GM 0x27A2 ++#define PCI_CHIP_I945_GME 0x27AE ++#define PCI_CHIP_G33_G 0x29C2 ++#define PCI_CHIP_Q35_G 0x29B2 ++#define PCI_CHIP_Q33_G 0x29D2 + + + /* ================================================================ +diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c +index 67e176a..ca8610b 100644 +--- a/src/mesa/drivers/dri/i915/intel_screen.c ++++ b/src/mesa/drivers/dri/i915/intel_screen.c +@@ -514,6 +514,10 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis, + case PCI_CHIP_I915_GM: + case PCI_CHIP_I945_G: + case PCI_CHIP_I945_GM: ++ case PCI_CHIP_I945_GME: ++ case PCI_CHIP_G33_G: ++ case PCI_CHIP_Q35_G: ++ case PCI_CHIP_Q33_G: + return i915CreateContext( mesaVis, driContextPriv, + sharedContextPrivate ); + +diff --git a/src/mesa/drivers/dri/i915/intel_tex.c b/src/mesa/drivers/dri/i915/intel_tex.c +index 98ddc79..5bd2806 100644 +--- a/src/mesa/drivers/dri/i915/intel_tex.c ++++ b/src/mesa/drivers/dri/i915/intel_tex.c +@@ -677,7 +677,11 @@ static void intelUploadTexImage( intelContextPtr intel, + /* Time for another vtbl entry: + */ + else if (intel->intelScreen->deviceID == PCI_CHIP_I945_G || +- intel->intelScreen->deviceID == PCI_CHIP_I945_GM) { ++ intel->intelScreen->deviceID == PCI_CHIP_I945_GM || ++ intel->intelScreen->deviceID == PCI_CHIP_I945_GME || ++ intel->intelScreen->deviceID == PCI_CHIP_G33_G || ++ intel->intelScreen->deviceID == PCI_CHIP_Q33_G || ++ intel->intelScreen->deviceID == PCI_CHIP_Q35_G) { + GLuint row_len = image->Width * image->TexFormat->TexelBytes; + GLubyte *dst = (GLubyte *)(t->BufAddr + offset); + GLubyte *src = (GLubyte *)image->Data; +diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c +index 093b3b4..40ea756 100644 +--- a/src/mesa/drivers/dri/i915tex/intel_context.c ++++ b/src/mesa/drivers/dri/i915tex/intel_context.c +@@ -130,6 +130,18 @@ intelGetString(GLcontext * ctx, GLenum name) + case PCI_CHIP_I945_GM: + chipset = "Intel(R) 945GM"; + break; ++ case PCI_CHIP_I945_GME: ++ chipset = "Intel(R) 945GME"; ++ break; ++ case PCI_CHIP_G33_G: ++ chipset = "Intel(R) G33"; ++ break; ++ case PCI_CHIP_Q35_G: ++ chipset = "Intel(R) Q35"; ++ break; ++ case PCI_CHIP_Q33_G: ++ chipset = "Intel(R) Q33"; ++ break; + default: + chipset = "Unknown Intel Chipset"; + break; +diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h +index bcbbb12..5fc8eb3 100644 +--- a/src/mesa/drivers/dri/i915tex/intel_context.h ++++ b/src/mesa/drivers/dri/i915tex/intel_context.h +@@ -385,6 +385,10 @@ extern int INTEL_DEBUG; + #define PCI_CHIP_I915_GM 0x2592 + #define PCI_CHIP_I945_G 0x2772 + #define PCI_CHIP_I945_GM 0x27A2 ++#define PCI_CHIP_I945_GME 0x27AE ++#define PCI_CHIP_G33_G 0x29C2 ++#define PCI_CHIP_Q35_G 0x29B2 ++#define PCI_CHIP_Q33_G 0x29D2 + + + /* ================================================================ +diff --git a/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c b/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c +index 8e83028..6c28543 100644 +--- a/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c ++++ b/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c +@@ -79,6 +79,10 @@ intel_miptree_create(struct intel_context *intel, + switch (intel->intelScreen->deviceID) { + case PCI_CHIP_I945_G: + case PCI_CHIP_I945_GM: ++ case PCI_CHIP_I945_GME: ++ case PCI_CHIP_G33_G: ++ case PCI_CHIP_Q33_G: ++ case PCI_CHIP_Q35_G: + ok = i945_miptree_layout(mt); + break; + case PCI_CHIP_I915_G: +@@ -93,9 +97,19 @@ intel_miptree_create(struct intel_context *intel, + break; + } + +- if (ok) ++ if (ok) { ++ if (!mt->compressed) { ++ /* XXX: Align pitch to multiple of 64 bytes for now to allow ++ * render-to-texture to work in all cases. This should probably be ++ * replaced at some point by some scheme to only do this when really ++ * necessary. ++ */ ++ mt->pitch = ((mt->pitch * cpp + 63) & ~63) / cpp; ++ } ++ + mt->region = intel_region_alloc(intel->intelScreen, + mt->cpp, mt->pitch, mt->total_height); ++ } + + if (!mt->region) { + free(mt); +diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.c b/src/mesa/drivers/dri/i915tex/intel_screen.c +index 5e6df81..2acdead 100644 +--- a/src/mesa/drivers/dri/i915tex/intel_screen.c ++++ b/src/mesa/drivers/dri/i915tex/intel_screen.c +@@ -752,6 +752,10 @@ intelCreateContext(const __GLcontextModes * mesaVis, + case PCI_CHIP_I915_GM: + case PCI_CHIP_I945_G: + case PCI_CHIP_I945_GM: ++ case PCI_CHIP_I945_GME: ++ case PCI_CHIP_G33_G: ++ case PCI_CHIP_Q35_G: ++ case PCI_CHIP_Q33_G: + return i915CreateContext(mesaVis, driContextPriv, sharedContextPrivate); + + default: +diff --git a/src/mesa/drivers/dri/unichrome/via_context.c b/src/mesa/drivers/dri/unichrome/via_context.c +index 4d25d32..7c73877 100644 +--- a/src/mesa/drivers/dri/unichrome/via_context.c ++++ b/src/mesa/drivers/dri/unichrome/via_context.c +@@ -733,14 +733,15 @@ void viaXMesaWindowMoved(struct via_context *vmesa) + { + __DRIdrawablePrivate *const drawable = vmesa->driDrawable; + __DRIdrawablePrivate *const readable = vmesa->driReadable; +- struct via_renderbuffer *const draw_buffer = +- (struct via_renderbuffer *) drawable->driverPrivate; +- struct via_renderbuffer *const read_buffer = +- (struct via_renderbuffer *) readable->driverPrivate; ++ struct via_renderbuffer * draw_buffer; ++ struct via_renderbuffer * read_buffer; + GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3; + + if (!drawable) + return; ++ ++ draw_buffer = (struct via_renderbuffer *) drawable->driverPrivate; ++ read_buffer = (struct via_renderbuffer *) readable->driverPrivate; + + switch (vmesa->glCtx->DrawBuffer->_ColorDrawBufferMask[0]) { + case BUFFER_BIT_BACK_LEFT: +diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c +index 0b821cf..df40b88 100644 +--- a/src/mesa/main/attrib.c ++++ b/src/mesa/main/attrib.c +@@ -342,6 +342,12 @@ _mesa_PushAttrib(GLbitfield mask) + /* Bump the texture object reference counts so that they don't + * inadvertantly get deleted. + */ ++#ifdef DEBUG ++ printf("%lu: MESA PUSH TEX ATTRIB, INCR REF COUNT BY %d\n", ++ _glthread_GetID(), ++ ctx->Const.MaxTextureUnits); ++#endif ++ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + ctx->Texture.Unit[u].Current1D->RefCount++; + ctx->Texture.Unit[u].Current2D->RefCount++; +@@ -349,6 +355,7 @@ _mesa_PushAttrib(GLbitfield mask) + ctx->Texture.Unit[u].CurrentCubeMap->RefCount++; + ctx->Texture.Unit[u].CurrentRect->RefCount++; + } ++ + attr = MALLOC_STRUCT( gl_texture_attrib ); + MEMCPY( attr, &ctx->Texture, sizeof(struct gl_texture_attrib) ); + /* copy state of the currently bound texture objects */ +@@ -792,6 +799,11 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib) + * wouldn't inadvertantly get deleted while they were still referenced + * inside the attribute state stack. + */ ++#ifdef DEBUG ++ printf("%lu: MESA POP TEX ATTRIB, DECR REF COUNT BY %d\n", ++ _glthread_GetID(), ++ ctx->Const.MaxTextureUnits); ++#endif + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + ctx->Texture.Unit[u].Current1D->RefCount--; + ctx->Texture.Unit[u].Current2D->RefCount--; +@@ -1401,6 +1413,84 @@ _mesa_PopClientAttrib(void) + } + + ++static struct gl_texture_object * ++get_texobj(GLcontext *ctx, GLenum target, GLuint name) ++{ ++ struct gl_texture_object *texObj; ++ if (name) { ++ texObj = _mesa_lookup_texture(ctx, name); ++ } ++ else { ++ switch (target) { ++ case GL_TEXTURE_1D: ++ texObj = ctx->Shared->Default1D; ++ break; ++ case GL_TEXTURE_2D: ++ texObj = ctx->Shared->Default2D; ++ break; ++ case GL_TEXTURE_3D: ++ texObj = ctx->Shared->Default3D; ++ break; ++ case GL_TEXTURE_CUBE_MAP_ARB: ++ texObj = ctx->Shared->DefaultCubeMap; ++ break; ++ case GL_TEXTURE_RECTANGLE_NV: ++ texObj = ctx->Shared->DefaultRect; ++ break; ++ default: ++ abort(); ++ } ++ } ++ return texObj; ++} ++ ++ ++void ++_mesa_free_attrib_data(GLcontext *ctx) ++{ ++#ifdef DEBUG ++ printf("%lu: MESA FREEING ATTRIB STACK DATA\n", ++ _glthread_GetID()); ++#endif ++ while (ctx->AttribStackDepth > 0) { ++ struct gl_attrib_node *attr, *next; ++ ++ ctx->AttribStackDepth--; ++ attr = ctx->AttribStack[ctx->AttribStackDepth]; ++ ++ while (attr) { ++ struct gl_texture_attrib *texAttrib ++ = (struct gl_texture_attrib *) attr->data; ++ GLuint u; ++ ++ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { ++ struct gl_texture_unit *unit = &texAttrib->Unit[u]; ++ struct gl_texture_object *texObj; ++ texObj = get_texobj(ctx, GL_TEXTURE_1D, unit->Saved1D.Name); ++ MESA_REF_TEXOBJ(&texObj, NULL); ++ texObj = get_texobj(ctx, GL_TEXTURE_2D, unit->Saved2D.Name); ++ MESA_REF_TEXOBJ(&texObj, NULL); ++ texObj = get_texobj(ctx, GL_TEXTURE_3D, unit->Saved3D.Name); ++ MESA_REF_TEXOBJ(&texObj, NULL); ++ texObj = get_texobj(ctx, GL_TEXTURE_CUBE_MAP, unit->SavedCubeMap.Name); ++ MESA_REF_TEXOBJ(&texObj, NULL); ++ texObj = get_texobj(ctx, GL_TEXTURE_RECTANGLE_NV, unit->SavedRect.Name); ++ MESA_REF_TEXOBJ(&texObj, NULL); ++ } ++ ++ next = attr->next; ++ _mesa_free(attr->data); ++ _mesa_free(attr); ++ attr = next; ++ } ++ } ++#ifdef DEBUG ++ printf("%lu: MESA DONE FREEING ATTRIB STACK DATA\n", ++ _glthread_GetID()); ++#endif ++} ++ ++ + void _mesa_init_attrib( GLcontext *ctx ) + { + /* Renderer and client attribute stacks */ +diff --git a/src/mesa/main/attrib.h b/src/mesa/main/attrib.h +index 09d7519..ea28859 100644 +--- a/src/mesa/main/attrib.h ++++ b/src/mesa/main/attrib.h +@@ -58,10 +58,14 @@ _mesa_PopClientAttrib( void ); + extern void + _mesa_init_attrib( GLcontext *ctx ); + ++extern void ++_mesa_free_attrib_data( GLcontext *ctx ); ++ + #else + + /** No-op */ + #define _mesa_init_attrib( c ) ((void)0) ++#define _mesa_free_attrib_data( c ) ((void)0) + + #endif + +diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c +index e067840..64f3a7f 100644 +--- a/src/mesa/main/context.c ++++ b/src/mesa/main/context.c +@@ -467,17 +467,12 @@ alloc_shared_state( GLcontext *ctx ) + if (!ss->DefaultRect) + goto cleanup; + +- /* Effectively bind the default textures to all texture units */ +- ss->Default1D->RefCount += MAX_TEXTURE_IMAGE_UNITS; +- ss->Default2D->RefCount += MAX_TEXTURE_IMAGE_UNITS; +- ss->Default3D->RefCount += MAX_TEXTURE_IMAGE_UNITS; +- ss->DefaultCubeMap->RefCount += MAX_TEXTURE_IMAGE_UNITS; +- ss->DefaultRect->RefCount += MAX_TEXTURE_IMAGE_UNITS; ++ /* sanity check */ ++ assert(ss->Default1D->RefCount == 1); + + _glthread_INIT_MUTEX(ss->TexMutex); + ss->TextureStateStamp = 0; + +- + #if FEATURE_EXT_framebuffer_object + ss->FrameBuffers = _mesa_NewHashTable(); + if (!ss->FrameBuffers) +@@ -487,10 +482,9 @@ alloc_shared_state( GLcontext *ctx ) + goto cleanup; + #endif + +- + return GL_TRUE; + +- cleanup: ++cleanup: + /* Ran out of memory at some point. Free everything and return NULL */ + if (ss->DisplayList) + _mesa_DeleteHashTable(ss->DisplayList); +@@ -567,6 +561,10 @@ delete_texture_cb(GLuint id, void *data, void *userData) + { + struct gl_texture_object *texObj = (struct gl_texture_object *) data; + GLcontext *ctx = (GLcontext *) userData; ++#ifdef DEBUG ++ printf("MESA TEX DELETE %p (%u) from DestroyContext\n", ++ (void *) texObj, texObj->Name); ++#endif + ctx->Driver.DeleteTexture(ctx, texObj); + } + +@@ -634,6 +632,33 @@ delete_shader_cb(GLuint id, void *data, void *userData) + } + } + ++/** ++ * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll() ++ */ ++static void ++delete_framebuffer_cb(GLuint id, void *data, void *userData) ++{ ++ struct gl_framebuffer *fb = (struct gl_framebuffer *) data; ++ /* The fact that the framebuffer is in the hashtable means its refcount ++ * is one, but we're removing from the hashtable now. So clear refcount. ++ */ ++ /*assert(fb->RefCount == 1);*/ ++ fb->RefCount = 0; ++ fb->Delete(fb); ++} ++ ++/** ++ * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll() ++ */ ++static void ++delete_renderbuffer_cb(GLuint id, void *data, void *userData) ++{ ++ struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data; ++ rb->RefCount = 0; /* see comment for FBOs above */ ++ rb->Delete(rb); ++} ++ ++ + + /** + * Deallocate a shared state object and all children structures. +@@ -656,20 +681,6 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) + _mesa_HashDeleteAll(ss->DisplayList, delete_displaylist_cb, ctx); + _mesa_DeleteHashTable(ss->DisplayList); + +- /* +- * Free texture objects +- */ +- ASSERT(ctx->Driver.DeleteTexture); +- /* the default textures */ +- ctx->Driver.DeleteTexture(ctx, ss->Default1D); +- ctx->Driver.DeleteTexture(ctx, ss->Default2D); +- ctx->Driver.DeleteTexture(ctx, ss->Default3D); +- ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap); +- ctx->Driver.DeleteTexture(ctx, ss->DefaultRect); +- /* all other textures */ +- _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx); +- _mesa_DeleteHashTable(ss->TexObjects); +- + #if defined(FEATURE_NV_vertex_program) || defined(FEATURE_NV_fragment_program) + _mesa_HashDeleteAll(ss->Programs, delete_program_cb, ctx); + _mesa_DeleteHashTable(ss->Programs); +@@ -701,10 +712,27 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) + #endif + + #if FEATURE_EXT_framebuffer_object ++ _mesa_HashDeleteAll(ss->FrameBuffers, delete_framebuffer_cb, ctx); + _mesa_DeleteHashTable(ss->FrameBuffers); ++ _mesa_HashDeleteAll(ss->RenderBuffers, delete_renderbuffer_cb, ctx); + _mesa_DeleteHashTable(ss->RenderBuffers); + #endif + ++ /* ++ * Free texture objects (after FBOs since some textures might have ++ * been bound to FBOs). ++ */ ++ ASSERT(ctx->Driver.DeleteTexture); ++ /* the default textures */ ++ ctx->Driver.DeleteTexture(ctx, ss->Default1D); ++ ctx->Driver.DeleteTexture(ctx, ss->Default2D); ++ ctx->Driver.DeleteTexture(ctx, ss->Default3D); ++ ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap); ++ ctx->Driver.DeleteTexture(ctx, ss->DefaultRect); ++ /* all other textures */ ++ _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx); ++ _mesa_DeleteHashTable(ss->TexObjects); ++ + _glthread_DESTROY_MUTEX(ss->Mutex); + + _mesa_free(ss); +@@ -1157,18 +1185,27 @@ _mesa_create_context(const GLvisual *visual, + void + _mesa_free_context_data( GLcontext *ctx ) + { +- /* if we're destroying the current context, unbind it first */ +- if (ctx == _mesa_get_current_context()) { +- _mesa_make_current(NULL, NULL, NULL); ++ if (!_mesa_get_current_context()){ ++ /* No current context, but we may need one in order to delete ++ * texture objs, etc. So temporarily bind the context now. ++ */ ++ _mesa_make_current(ctx, NULL, NULL); + } +- else { +- /* unreference WinSysDraw/Read buffers */ +- _mesa_unreference_framebuffer(&ctx->WinSysDrawBuffer); +- _mesa_unreference_framebuffer(&ctx->WinSysReadBuffer); +- _mesa_unreference_framebuffer(&ctx->DrawBuffer); +- _mesa_unreference_framebuffer(&ctx->ReadBuffer); ++ ++ if (ctx->AttribStackDepth > 0) { ++#ifdef DEBUG ++ printf("%lu: MESA: DESTROY CONTEXT WITH NON-EMPTRY ATTRIB STACK!\n", ++ _glthread_GetID()); ++#endif + } + ++ /* unreference WinSysDraw/Read buffers */ ++ _mesa_unreference_framebuffer(&ctx->WinSysDrawBuffer); ++ _mesa_unreference_framebuffer(&ctx->WinSysReadBuffer); ++ _mesa_unreference_framebuffer(&ctx->DrawBuffer); ++ _mesa_unreference_framebuffer(&ctx->ReadBuffer); ++ ++ _mesa_free_attrib_data(ctx); + _mesa_free_lighting_data( ctx ); + _mesa_free_eval_data( ctx ); + _mesa_free_texture_data( ctx ); +@@ -1200,6 +1237,11 @@ _mesa_free_context_data( GLcontext *ctx ) + + if (ctx->Extensions.String) + _mesa_free((void *) ctx->Extensions.String); ++ ++ /* unbind the context if it's currently bound */ ++ if (ctx == _mesa_get_current_context()) { ++ _mesa_make_current(NULL, NULL, NULL); ++ } + } + + +diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c +index eac2f78..f0e413b 100644 +--- a/src/mesa/main/fbobject.c ++++ b/src/mesa/main/fbobject.c +@@ -150,22 +150,18 @@ _mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att) + { + if (att->Type == GL_TEXTURE) { + ASSERT(att->Texture); +- att->Texture->RefCount--; +- if (att->Texture->RefCount == 0) { +- ctx->Driver.DeleteTexture(ctx, att->Texture); ++ if (ctx->Driver.FinishRenderTexture) { ++ /* tell driver we're done rendering to this texobj */ ++ ctx->Driver.FinishRenderTexture(ctx, att); + } +- else { +- /* tell driver that we're done rendering to this texture. */ +- if (ctx->Driver.FinishRenderTexture) { +- ctx->Driver.FinishRenderTexture(ctx, att); +- } +- } +- att->Texture = NULL; ++ MESA_REF_TEXOBJ(&att->Texture, NULL); /* unbind */ ++ ASSERT(!att->Texture); + } + if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) { + ASSERT(att->Renderbuffer); + ASSERT(!att->Texture); +- _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); ++ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */ ++ ASSERT(!att->Renderbuffer); + } + att->Type = GL_NONE; + att->Complete = GL_TRUE; +@@ -191,8 +187,8 @@ _mesa_set_texture_attachment(GLcontext *ctx, + /* new attachment */ + _mesa_remove_attachment(ctx, att); + att->Type = GL_TEXTURE; +- att->Texture = texObj; +- texObj->RefCount++; ++ assert(!att->Texture); ++ MESA_REF_TEXOBJ(&att->Texture, texObj); + } + + /* always update these fields */ +diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c +index 1fd31a5..09f0994 100644 +--- a/src/mesa/main/framebuffer.c ++++ b/src/mesa/main/framebuffer.c +@@ -38,6 +38,7 @@ + #include "fbobject.h" + #include "framebuffer.h" + #include "renderbuffer.h" ++#include "texobj.h" + + + +@@ -190,17 +191,11 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb) + _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); + } + if (att->Texture) { +- /* render to texture */ +- att->Texture->RefCount--; +- if (att->Texture->RefCount == 0) { +- GET_CURRENT_CONTEXT(ctx); +- if (ctx) { +- ctx->Driver.DeleteTexture(ctx, att->Texture); +- } +- } ++ MESA_REF_TEXOBJ(&att->Texture, NULL); + } ++ ASSERT(!att->Renderbuffer); ++ ASSERT(!att->Texture); + att->Type = GL_NONE; +- att->Texture = NULL; + } + + /* unbind _Depth/_StencilBuffer to decr ref counts */ +diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c +index 803f478..d7a96f7 100644 +--- a/src/mesa/main/image.c ++++ b/src/mesa/main/image.c +@@ -3794,7 +3794,7 @@ _mesa_pack_stencil_span( const GLcontext *ctx, GLuint n, + GLint *dst = (GLint *) dest; + GLuint i; + for (i=0;iSwapBytes) { + _mesa_swap4( (GLuint *) dst, n ); +diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c +index 56d816e..fa14d91 100644 +--- a/src/mesa/main/texobj.c ++++ b/src/mesa/main/texobj.c +@@ -154,8 +154,18 @@ _mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj ) + { + GLuint i, face; + ++#ifdef DEBUG ++ printf("%lu: MESA TEX DELETE %p (%u) REF COUNT = %d\n", ++ _glthread_GetID(), ++ (void*) texObj, texObj->Name, texObj->RefCount); ++#endif + (void) ctx; + ++ /* Set Target to an invalid value. With some assertions elsewhere ++ * we can try to detect possible use of deleted textures. ++ */ ++ texObj->Target = 0x99; ++ + _mesa_free_colortable_data(&texObj->Palette); + + /* free the texture images */ +@@ -220,6 +230,106 @@ _mesa_copy_texture_object( struct gl_texture_object *dest, + + + /** ++ * Check if the given texture object is valid by examining its Target field. ++ * For debugging only. ++ */ ++static GLboolean ++valid_texture_object(const struct gl_texture_object *tex) ++{ ++ switch (tex->Target) { ++ case 0: ++ case GL_TEXTURE_1D: ++ case GL_TEXTURE_2D: ++ case GL_TEXTURE_3D: ++ case GL_TEXTURE_CUBE_MAP_ARB: ++ case GL_TEXTURE_RECTANGLE_NV: ++ return GL_TRUE; ++ case 0x99: ++ _mesa_problem(NULL, "invalid reference to a deleted texture object"); ++ return GL_FALSE; ++ default: ++ _mesa_problem(NULL, "invalid texture object Target value"); ++ return GL_FALSE; ++ } ++} ++ ++ ++/** ++ * Reference (or unreference) a texture object. ++ * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero). ++ * If 'tex' is non-null, increment its refcount. ++ */ ++void ++_mesa_reference_texobj(struct gl_texture_object **ptr, ++ struct gl_texture_object *tex, ++ const char *where) ++{ ++ assert(ptr); ++ if (*ptr == tex) { ++ /* no change */ ++ return; ++ } ++ ++ if (*ptr) { ++ /* Unreference the old texture */ ++ GLboolean deleteFlag = GL_FALSE; ++ struct gl_texture_object *oldTex = *ptr; ++ ++ assert(valid_texture_object(oldTex)); ++ ++ _glthread_LOCK_MUTEX(oldTex->Mutex); ++ ASSERT(oldTex->RefCount > 0); ++ oldTex->RefCount--; ++ ++#ifdef DEBUG ++ printf("%lu: MESA TEX REF DECR %p (%u) to %d from %s\n", ++ _glthread_GetID(), ++ (void*) oldTex, oldTex->Name, oldTex->RefCount, where); ++#endif ++ ++ deleteFlag = (oldTex->RefCount == 0); ++ _glthread_UNLOCK_MUTEX(oldTex->Mutex); ++ ++ if (deleteFlag) { ++ GET_CURRENT_CONTEXT(ctx); ++ if (ctx) ++ ctx->Driver.DeleteTexture(ctx, oldTex); ++ else ++ _mesa_problem(NULL, "Unable to delete texture, no context"); ++ } ++ ++ *ptr = NULL; ++ } ++ assert(!*ptr); ++ ++ if (tex) { ++ /* reference new texture */ ++ assert(valid_texture_object(tex)); ++ _glthread_LOCK_MUTEX(tex->Mutex); ++ if (tex->RefCount == 0) { ++ /* this texture's being deleted (look just above) */ ++ /* Not sure this can every really happen. Warn if it does. */ ++ _mesa_problem(NULL, "referencing deleted texture object"); ++ *ptr = NULL; ++ } ++ else { ++ tex->RefCount++; ++ ++#ifdef DEBUG ++ printf("%lu: MESA TEX REF INCR %p (%u) to %d from %s\n", ++ _glthread_GetID(), ++ (void*) tex, tex->Name, tex->RefCount, where); ++#endif ++ ++ *ptr = tex; ++ } ++ _glthread_UNLOCK_MUTEX(tex->Mutex); ++ } ++} ++ ++ ++ ++/** + * Report why a texture object is incomplete. + * + * \param t texture object. +@@ -620,8 +730,7 @@ unbind_texobj_from_fbo(GLcontext *ctx, struct gl_texture_object *texObj) + + /** + * Check if the given texture object is bound to any texture image units and +- * unbind it if so. +- * XXX all RefCount accesses should be protected by a mutex. ++ * unbind it if so (revert to default textures). + */ + static void + unbind_texobj_from_texunits(GLcontext *ctx, struct gl_texture_object *texObj) +@@ -630,34 +739,20 @@ unbind_texobj_from_texunits(GLcontext *ctx, struct gl_texture_object *texObj) + + for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) { + struct gl_texture_unit *unit = &ctx->Texture.Unit[u]; +- struct gl_texture_object **curr = NULL; +- + if (texObj == unit->Current1D) { +- curr = &unit->Current1D; +- unit->Current1D = ctx->Shared->Default1D; ++ MESA_REF_TEXOBJ(&unit->Current1D, ctx->Shared->Default1D); + } + else if (texObj == unit->Current2D) { +- curr = &unit->Current2D; +- unit->Current2D = ctx->Shared->Default2D; ++ MESA_REF_TEXOBJ(&unit->Current2D, ctx->Shared->Default2D); + } + else if (texObj == unit->Current3D) { +- curr = &unit->Current3D; +- unit->Current3D = ctx->Shared->Default3D; ++ MESA_REF_TEXOBJ(&unit->Current3D, ctx->Shared->Default3D); + } + else if (texObj == unit->CurrentCubeMap) { +- curr = &unit->CurrentCubeMap; +- unit->CurrentCubeMap = ctx->Shared->DefaultCubeMap; ++ MESA_REF_TEXOBJ(&unit->CurrentCubeMap, ctx->Shared->DefaultCubeMap); + } + else if (texObj == unit->CurrentRect) { +- curr = &unit->CurrentRect; +- unit->CurrentRect = ctx->Shared->DefaultRect; +- } +- +- if (curr) { +- (*curr)->RefCount++; +- texObj->RefCount--; +- if (texObj == unit->_Current) +- unit->_Current = *curr; ++ MESA_REF_TEXOBJ(&unit->CurrentRect, ctx->Shared->DefaultRect); + } + } + } +@@ -693,8 +788,6 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures) + = _mesa_lookup_texture(ctx, textures[i]); + + if (delObj) { +- GLboolean deleted; +- + _mesa_lock_texture(ctx, delObj); + + /* Check if texture is bound to any framebuffer objects. +@@ -704,10 +797,12 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures) + unbind_texobj_from_fbo(ctx, delObj); + + /* Check if this texture is currently bound to any texture units. +- * If so, unbind it and decrement the reference count. ++ * If so, unbind it. + */ + unbind_texobj_from_texunits(ctx, delObj); + ++ _mesa_unlock_texture(ctx, delObj); ++ + ctx->NewState |= _NEW_TEXTURE; + + /* The texture _name_ is now free for re-use. +@@ -717,23 +812,10 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures) + _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + +- /* The actual texture object will not be freed until it's no +- * longer bound in any context. +- * XXX all RefCount accesses should be protected by a mutex. ++ /* Unreference the texobj. If refcount hits zero, the texture ++ * will be deleted. + */ +- delObj->RefCount--; +- deleted = (delObj->RefCount == 0); +- _mesa_unlock_texture(ctx, delObj); +- +- /* We know that refcount went to zero above, so this is +- * the only pointer left to delObj, so we don't have to +- * worry about locking any more: +- */ +- if (deleted) { +- ASSERT(delObj->Name != 0); /* Never delete default tex objs */ +- ASSERT(ctx->Driver.DeleteTexture); +- (*ctx->Driver.DeleteTexture)(ctx, delObj); +- } ++ MESA_REF_TEXOBJ(&delObj, NULL); + } + } + } +@@ -761,7 +843,6 @@ _mesa_BindTexture( GLenum target, GLuint texName ) + GET_CURRENT_CONTEXT(ctx); + const GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; +- struct gl_texture_object *oldTexObj; + struct gl_texture_object *newTexObj = NULL; + ASSERT_OUTSIDE_BEGIN_END(ctx); + +@@ -770,48 +851,6 @@ _mesa_BindTexture( GLenum target, GLuint texName ) + _mesa_lookup_enum_by_nr(target), (GLint) texName); + + /* +- * Get pointer to currently bound texture object (oldTexObj) +- */ +- switch (target) { +- case GL_TEXTURE_1D: +- oldTexObj = texUnit->Current1D; +- break; +- case GL_TEXTURE_2D: +- oldTexObj = texUnit->Current2D; +- break; +- case GL_TEXTURE_3D: +- oldTexObj = texUnit->Current3D; +- break; +- case GL_TEXTURE_CUBE_MAP_ARB: +- if (!ctx->Extensions.ARB_texture_cube_map) { +- _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" ); +- return; +- } +- oldTexObj = texUnit->CurrentCubeMap; +- break; +- case GL_TEXTURE_RECTANGLE_NV: +- if (!ctx->Extensions.NV_texture_rectangle) { +- _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" ); +- return; +- } +- oldTexObj = texUnit->CurrentRect; +- break; +- default: +- _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" ); +- return; +- } +- +- if (oldTexObj->Name == texName) { +- /* XXX this might be wrong. If the texobj is in use by another +- * context and a texobj parameter was changed, this might be our +- * only chance to update this context's hardware state. +- * Note that some applications re-bind the same texture a lot so we +- * want to handle that case quickly. +- */ +- return; /* rebinding the same texture- no change */ +- } +- +- /* + * Get pointer to new texture object (newTexObj) + */ + if (texName == 0) { +@@ -879,28 +918,30 @@ _mesa_BindTexture( GLenum target, GLuint texName ) + newTexObj->Target = target; + } + +- /* XXX all RefCount accesses should be protected by a mutex. */ +- newTexObj->RefCount++; ++ assert(valid_texture_object(newTexObj)); + +- /* do the actual binding, but first flush outstanding vertices: +- */ ++ /* flush before changing binding */ + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + ++ /* Do the actual binding. The refcount on the previously bound ++ * texture object will be decremented. It'll be deleted if the ++ * count hits zero. ++ */ + switch (target) { + case GL_TEXTURE_1D: +- texUnit->Current1D = newTexObj; ++ MESA_REF_TEXOBJ(&texUnit->Current1D, newTexObj); + break; + case GL_TEXTURE_2D: +- texUnit->Current2D = newTexObj; ++ MESA_REF_TEXOBJ(&texUnit->Current2D, newTexObj); + break; + case GL_TEXTURE_3D: +- texUnit->Current3D = newTexObj; ++ MESA_REF_TEXOBJ(&texUnit->Current3D, newTexObj); + break; + case GL_TEXTURE_CUBE_MAP_ARB: +- texUnit->CurrentCubeMap = newTexObj; ++ MESA_REF_TEXOBJ(&texUnit->CurrentCubeMap, newTexObj); + break; + case GL_TEXTURE_RECTANGLE_NV: +- texUnit->CurrentRect = newTexObj; ++ MESA_REF_TEXOBJ(&texUnit->CurrentRect, newTexObj); + break; + default: + _mesa_problem(ctx, "bad target in BindTexture"); +@@ -910,18 +951,6 @@ _mesa_BindTexture( GLenum target, GLuint texName ) + /* Pass BindTexture call to device driver */ + if (ctx->Driver.BindTexture) + (*ctx->Driver.BindTexture)( ctx, target, newTexObj ); +- +- /* Decrement the reference count on the old texture and check if it's +- * time to delete it. +- */ +- /* XXX all RefCount accesses should be protected by a mutex. */ +- oldTexObj->RefCount--; +- ASSERT(oldTexObj->RefCount >= 0); +- if (oldTexObj->RefCount == 0) { +- ASSERT(oldTexObj->Name != 0); +- ASSERT(ctx->Driver.DeleteTexture); +- (*ctx->Driver.DeleteTexture)( ctx, oldTexObj ); +- } + } + + +diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h +index ec7cf8c..78e7933 100644 +--- a/src/mesa/main/texobj.h ++++ b/src/mesa/main/texobj.h +@@ -57,6 +57,14 @@ extern void + _mesa_copy_texture_object( struct gl_texture_object *dest, + const struct gl_texture_object *src ); + ++#define MESA_REF_TEXOBJ(PTR, TEX) \ ++ _mesa_reference_texobj(PTR, TEX, __FUNCTION__) ++ ++extern void ++_mesa_reference_texobj(struct gl_texture_object **ptr, ++ struct gl_texture_object *tex, ++ const char *where); ++ + extern void + _mesa_test_texobj_completeness( const GLcontext *ctx, + struct gl_texture_object *obj ); +diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c +index 1b45eae..c4b678b 100644 +--- a/src/mesa/main/texstate.c ++++ b/src/mesa/main/texstate.c +@@ -63,31 +63,6 @@ static const struct gl_tex_env_combine_state default_combine_state = { + }; + + +-/** +- * Copy a texture binding. Helper used by _mesa_copy_texture_state(). +- */ +-static void +-copy_texture_binding(const GLcontext *ctx, +- struct gl_texture_object **dst, +- struct gl_texture_object *src) +-{ +- /* only copy if names differ (per OpenGL SI) */ +- if ((*dst)->Name != src->Name) { +- /* unbind/delete dest binding which we're changing */ +- (*dst)->RefCount--; +- if ((*dst)->RefCount == 0) { +- /* time to delete this texture object */ +- ASSERT((*dst)->Name != 0); +- ASSERT(ctx->Driver.DeleteTexture); +- /* XXX cast-away const, unfortunately */ +- (*ctx->Driver.DeleteTexture)((GLcontext *) ctx, *dst); +- } +- /* make new binding, incrementing ref count */ +- *dst = src; +- src->RefCount++; +- } +-} +- + + /** + * Used by glXCopyContext to copy texture state from one context to another. +@@ -144,16 +119,16 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst ) + /* copy texture object bindings, not contents of texture objects */ + _mesa_lock_context_textures(dst); + +- copy_texture_binding(src, &dst->Texture.Unit[i].Current1D, +- src->Texture.Unit[i].Current1D); +- copy_texture_binding(src, &dst->Texture.Unit[i].Current2D, +- src->Texture.Unit[i].Current2D); +- copy_texture_binding(src, &dst->Texture.Unit[i].Current3D, +- src->Texture.Unit[i].Current3D); +- copy_texture_binding(src, &dst->Texture.Unit[i].CurrentCubeMap, +- src->Texture.Unit[i].CurrentCubeMap); +- copy_texture_binding(src, &dst->Texture.Unit[i].CurrentRect, +- src->Texture.Unit[i].CurrentRect); ++ MESA_REF_TEXOBJ(&dst->Texture.Unit[i].Current1D, ++ src->Texture.Unit[i].Current1D); ++ MESA_REF_TEXOBJ(&dst->Texture.Unit[i].Current2D, ++ src->Texture.Unit[i].Current2D); ++ MESA_REF_TEXOBJ(&dst->Texture.Unit[i].Current3D, ++ src->Texture.Unit[i].Current3D); ++ MESA_REF_TEXOBJ(&dst->Texture.Unit[i].CurrentCubeMap, ++ src->Texture.Unit[i].CurrentCubeMap); ++ MESA_REF_TEXOBJ(&dst->Texture.Unit[i].CurrentRect, ++ src->Texture.Unit[i].CurrentRect); + + _mesa_unlock_context_textures(dst); + } +@@ -3032,6 +3007,8 @@ alloc_proxy_textures( GLcontext *ctx ) + if (!ctx->Texture.ProxyRect) + goto cleanup; + ++ assert(ctx->Texture.Proxy1D->RefCount == 1); ++ + return GL_TRUE; + + cleanup: +@@ -3087,11 +3064,12 @@ init_texture_unit( GLcontext *ctx, GLuint unit ) + ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 ); + +- texUnit->Current1D = ctx->Shared->Default1D; +- texUnit->Current2D = ctx->Shared->Default2D; +- texUnit->Current3D = ctx->Shared->Default3D; +- texUnit->CurrentCubeMap = ctx->Shared->DefaultCubeMap; +- texUnit->CurrentRect = ctx->Shared->DefaultRect; ++ /* initialize current texture object ptrs to the shared default objects */ ++ MESA_REF_TEXOBJ(&texUnit->Current1D, ctx->Shared->Default1D); ++ MESA_REF_TEXOBJ(&texUnit->Current2D, ctx->Shared->Default2D); ++ MESA_REF_TEXOBJ(&texUnit->Current3D, ctx->Shared->Default3D); ++ MESA_REF_TEXOBJ(&texUnit->CurrentCubeMap, ctx->Shared->DefaultCubeMap); ++ MESA_REF_TEXOBJ(&texUnit->CurrentRect, ctx->Shared->DefaultRect); + } + + +@@ -3106,21 +3084,20 @@ _mesa_init_texture(GLcontext *ctx) + assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS); + assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS); + +- /* Effectively bind the default textures to all texture units */ +- ctx->Shared->Default1D->RefCount += MAX_TEXTURE_UNITS; +- ctx->Shared->Default2D->RefCount += MAX_TEXTURE_UNITS; +- ctx->Shared->Default3D->RefCount += MAX_TEXTURE_UNITS; +- ctx->Shared->DefaultCubeMap->RefCount += MAX_TEXTURE_UNITS; +- ctx->Shared->DefaultRect->RefCount += MAX_TEXTURE_UNITS; +- + /* Texture group */ + ctx->Texture.CurrentUnit = 0; /* multitexture */ + ctx->Texture._EnabledUnits = 0; +- for (i=0; iTexture.SharedPalette = GL_FALSE; + _mesa_init_colortable(&ctx->Texture.Palette); + ++ for (i = 0; i < MAX_TEXTURE_UNITS; i++) ++ init_texture_unit( ctx, i ); ++ ++ /* After we're done initializing the context's texture state the default ++ * texture objects' refcounts should be at least MAX_TEXTURE_UNITS + 1. ++ */ ++ assert(ctx->Shared->Default1D->RefCount >= MAX_TEXTURE_UNITS + 1); ++ + _mesa_TexEnvProgramCacheInit( ctx ); + + /* Allocate proxy textures */ +@@ -3132,12 +3109,22 @@ _mesa_init_texture(GLcontext *ctx) + + + /** +- * Free dynamically-allocted texture data attached to the given context. ++ * Free dynamically-allocated texture data attached to the given context. + */ + void + _mesa_free_texture_data(GLcontext *ctx) + { +- GLuint i; ++ GLuint u; ++ ++ /* unreference current textures */ ++ for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) { ++ struct gl_texture_unit *unit = ctx->Texture.Unit + u; ++ MESA_REF_TEXOBJ(&unit->Current1D, NULL); ++ MESA_REF_TEXOBJ(&unit->Current2D, NULL); ++ MESA_REF_TEXOBJ(&unit->Current3D, NULL); ++ MESA_REF_TEXOBJ(&unit->CurrentCubeMap, NULL); ++ MESA_REF_TEXOBJ(&unit->CurrentRect, NULL); ++ } + + /* Free proxy texture objects */ + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D ); +@@ -3146,8 +3133,8 @@ _mesa_free_texture_data(GLcontext *ctx) + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap ); + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect ); + +- for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) +- _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable ); ++ for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) ++ _mesa_free_colortable_data( &ctx->Texture.Unit[u].ColorTable ); + + _mesa_TexEnvProgramCacheDestroy( ctx ); + } +diff --git a/src/mesa/shader/atifragshader.c b/src/mesa/shader/atifragshader.c +index 4727c1a..854c911 100644 +--- a/src/mesa/shader/atifragshader.c ++++ b/src/mesa/shader/atifragshader.c +@@ -440,7 +440,7 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) + _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)"); + return; + } +- if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) { ++ if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)"); + return; + } +@@ -513,7 +513,7 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) + _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)"); + return; + } +- if ((swizzle < GL_SWIZZLE_STR_ATI) && (swizzle > GL_SWIZZLE_STQ_DQ_ATI)) { ++ if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)"); + return; + } +diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c +index b794e30..06d24b4 100644 +--- a/src/mesa/shader/shader_api.c ++++ b/src/mesa/shader/shader_api.c +@@ -378,7 +378,7 @@ _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader) + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); +- const GLuint n = shProg->NumShaders; ++ GLuint n; + GLuint i; + + if (!shProg || !sh) { +@@ -387,6 +387,8 @@ _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader) + return; + } + ++ n = shProg->NumShaders; ++ + for (i = 0; i < n; i++) { + if (shProg->Shaders[i] == sh) { + /* already attached */ +@@ -548,7 +550,7 @@ _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader) + { + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); +- const GLuint n = shProg->NumShaders; ++ GLuint n; + GLuint i, j; + + if (!shProg) { +@@ -557,6 +559,8 @@ _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader) + return; + } + ++ n = shProg->NumShaders; ++ + for (i = 0; i < n; i++) { + if (shProg->Shaders[i]->Name == shader) { + /* found it */ +diff --git a/src/mesa/swrast/s_pointtemp.h b/src/mesa/swrast/s_pointtemp.h +index dddc2f7..9436464 100644 +--- a/src/mesa/swrast/s_pointtemp.h ++++ b/src/mesa/swrast/s_pointtemp.h +@@ -217,9 +217,9 @@ NAME ( GLcontext *ctx, const SWvertex *vert ) + } + else { + /* even size */ +- xmin = (GLint) vert->win[0] - iRadius + 1; ++ xmin = (GLint) vert->win[0] - iRadius; + xmax = xmin + iSize - 1; +- ymin = (GLint) vert->win[1] - iRadius + 1; ++ ymin = (GLint) vert->win[1] - iRadius; + ymax = ymin + iSize - 1; + } + #endif /*SMOOTH*/ +diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c +index e142dde..b71a935 100644 +--- a/src/mesa/vbo/vbo_split_copy.c ++++ b/src/mesa/vbo/vbo_split_copy.c +@@ -129,6 +129,13 @@ static GLuint attr_size( const struct gl_client_array *array ) + */ + static GLboolean check_flush( struct copy_context *copy ) + { ++ GLenum mode = copy->dstprim[copy->dstprim_nr].mode; ++ ++ if (GL_TRIANGLE_STRIP == mode && ++ copy->dstelt_nr & 1) { /* see bug9962 */ ++ return GL_FALSE; ++ } ++ + if (copy->dstbuf_nr + 4 > copy->dstbuf_size) + return GL_TRUE; + +@@ -458,7 +465,7 @@ static void replay_init( struct copy_context *copy ) + dst->StrideB = copy->vertex_size; + dst->Ptr = copy->dstbuf + offset; + dst->Enabled = GL_TRUE; +- dst->Normalized = GL_TRUE; ++ dst->Normalized = src->Normalized; + dst->BufferObj = ctx->Array.NullBufferObj; + dst->_MaxElement = copy->dstbuf_size; /* may be less! */ + diff --git a/mesa.spec b/mesa.spec index d437d6c..e6cf58f 100644 --- a/mesa.spec +++ b/mesa.spec @@ -32,7 +32,7 @@ Summary: Mesa graphics libraries Name: mesa Version: 7.0.1 -Release: 2%{?dist} +Release: 3%{?dist} License: MIT Group: System Environment/Libraries URL: http://www.mesa3d.org @@ -50,6 +50,8 @@ Patch22: mesa-6.5.2-hush-synthetic-visual-warning.patch Patch23: mesa-6.5.2-bindcontext-paranoia.patch Patch24: mesa-7.0-i-already-defined-glapi-you-twit.patch Patch25: mesa-7.0-symlinks-before-depend.patch +Patch26: mesa-7.0.1-stable-branch.patch +Patch27: mesa-7.0-use_master-r300.patch BuildRequires: pkgconfig %if %{with_dri} @@ -179,6 +181,8 @@ chmod a-x progs/demos/glslnoise.c %patch23 -p1 -b .bindcontext %patch24 -p1 -b .glapi %patch25 -p1 -b .makej +%patch26 -p1 -b .stable +%patch27 -p1 -b .r300 # WARNING: The following files are copyright "Mark J. Kilgard" under the GLUT # license and are not open source/free software, so we remove them. @@ -408,6 +412,11 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/mesa-demos-data %changelog +* Wed Aug 15 2007 Dave Airlie - 7.0.1-3 +- mesa-7.0.1-stable-branch.patch - Add patches from stable branch + includes support for some Intel chipsets +- mesa-7.0-use_master-r300.patch - Add r300 driver from master + * Tue Aug 14 2007 Dave Airlie - 7.0.1-2 - missing build requires for Xfixes-devel and Xdamage-devel