#include "swrast_setup/swrast_setup.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
+#include "tnl/t_vp_build.h"
+#include "radeon_reg.h"
+#include "radeon_macros.h"
#include "radeon_ioctl.h"
#include "radeon_state.h"
#include "r300_context.h"
#include "r300_state.h"
#include "r300_reg.h"
#include "r300_program.h"
+#include "r300_tex.h"
+#include "r300_maos.h"
+#include "r300_emit.h"
-#include "r300_lib.h"
-
+extern int future_hw_tcl_on;
/**********************************************************************
* Hardware rasterization
* rasterization hardware for rendering.
**********************************************************************/
-static int r300_get_primitive_type(r300ContextPtr rmesa,
- GLcontext *ctx,
- int start,
- int end,
- int prim)
+static int r300_get_primitive_type(r300ContextPtr rmesa, GLcontext *ctx, int prim)
{
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- GLuint i;
- int type=-1;
-
- if(end<=start)return -1; /* do we need to watch for this ? */
-
- fprintf(stderr, "[%d-%d]", start, end);
+ int type=-1;
+
switch (prim & PRIM_MODE_MASK) {
- case GL_LINES:
- fprintf(stderr, "L ");
+ case GL_POINTS:
+ type=R300_VAP_VF_CNTL__PRIM_POINTS;
+ break;
+ case GL_LINES:
type=R300_VAP_VF_CNTL__PRIM_LINES;
- if(end<start+2){
- fprintf(stderr, "Not enough vertices\n");
- return -1; /* need enough vertices for Q */
- }
break;
- case GL_LINE_STRIP:
- fprintf(stderr, "LS ");
+ case GL_LINE_STRIP:
type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
- if(end<start+2){
- fprintf(stderr, "Not enough vertices\n");
- return -1; /* need enough vertices for Q */
- }
break;
- case GL_LINE_LOOP:
- fprintf(stderr, "LL ");
- return -1;
- if(end<start+2){
- fprintf(stderr, "Not enough vertices\n");
- return -1; /* need enough vertices for Q */
- }
+ case GL_LINE_LOOP:
+ type=R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
break;
- case GL_TRIANGLES:
- fprintf(stderr, "T ");
+ case GL_TRIANGLES:
type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
- if(end<start+3){
- fprintf(stderr, "Not enough vertices\n");
- return -1; /* need enough vertices for Q */
- }
break;
- case GL_TRIANGLE_STRIP:
- fprintf(stderr, "TS ");
+ case GL_TRIANGLE_STRIP:
type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
- if(end<start+3){
- fprintf(stderr, "Not enough vertices\n");
- return -1; /* need enough vertices for Q */
- }
break;
- case GL_TRIANGLE_FAN:
- fprintf(stderr, "TF ");
+ case GL_TRIANGLE_FAN:
type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
- if(end<start+3){
- fprintf(stderr, "Not enough vertices\n");
- return -1; /* need enough vertices for Q */
- }
break;
- case GL_QUADS:
- fprintf(stderr, "Q ");
+ case GL_QUADS:
type=R300_VAP_VF_CNTL__PRIM_QUADS;
- if(end<start+4){
- fprintf(stderr, "Not enough vertices\n");
- return -1; /* need enough vertices for Q */
- }
break;
- case GL_QUAD_STRIP:
- fprintf(stderr, "QS ");
+ case GL_QUAD_STRIP:
type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
- if(end<start+4){
- fprintf(stderr, "Not enough vertices\n");
- return -1; /* need enough vertices for Q */
- }
break;
- default:
- fprintf(stderr, "Cannot handle primitive %02x ", prim & PRIM_MODE_MASK);
+ case GL_POLYGON:
+ type=R300_VAP_VF_CNTL__PRIM_POLYGON;
+ break;
+ default:
+ fprintf(stderr, "%s:%s Do not know how to handle primitive %02x - help me !\n",
+ __FILE__, __FUNCTION__,
+ prim & PRIM_MODE_MASK);
return -1;
break;
- }
+ }
return type;
}
+static int r300_get_num_verts(r300ContextPtr rmesa,
+ GLcontext *ctx,
+ int num_verts,
+ int prim)
+{
+ int verts_off=0;
+ char *name="UNKNOWN";
+ switch (prim & PRIM_MODE_MASK) {
+ case GL_POINTS:
+ name="P";
+ verts_off = 0;
+ break;
+ case GL_LINES:
+ name="L";
+ verts_off = num_verts % 2;
+ break;
+ case GL_LINE_STRIP:
+ name="LS";
+ if(num_verts < 2)
+ verts_off = num_verts;
+ break;
+ case GL_LINE_LOOP:
+ name="LL";
+ if(num_verts < 2)
+ verts_off = num_verts;
+ break;
+ case GL_TRIANGLES:
+ name="T";
+ verts_off = num_verts % 3;
+ break;
+ case GL_TRIANGLE_STRIP:
+ name="TS";
+ if(num_verts < 3)
+ verts_off = num_verts;
+ break;
+ case GL_TRIANGLE_FAN:
+ name="TF";
+ if(num_verts < 3)
+ verts_off = num_verts;
+ break;
+ case GL_QUADS:
+ name="Q";
+ verts_off = num_verts % 4;
+ break;
+ case GL_QUAD_STRIP:
+ name="QS";
+ if(num_verts < 4)
+ verts_off = num_verts;
+ else
+ verts_off = num_verts % 2;
+ break;
+ case GL_POLYGON:
+ name="P";
+ if(num_verts < 3)
+ verts_off = num_verts;
+ break;
+ default:
+ fprintf(stderr, "%s:%s Do not know how to handle primitive %02x - help me !\n",
+ __FILE__, __FUNCTION__,
+ prim & PRIM_MODE_MASK);
+ return -1;
+ break;
+ }
-/* Immediate implementation - vertex data is sent via command stream */
+ if (RADEON_DEBUG & DEBUG_VERTS) {
+ if (num_verts - verts_off == 0) {
+ WARN_ONCE("user error: Need more than %d vertices to draw primitive %s !\n", num_verts, name);
+ return 0;
+ }
-static GLfloat default_vector[4]={0.0, 0.0, 0.0, 1.0};
+ if (verts_off > 0) {
+ WARN_ONCE("user error: %d is not a valid number of vertices for primitive %s !\n", num_verts, name);
+ }
+ }
-#define output_vector(v, i) \
- { \
- int _i; \
- for(_i=0;_i<v->size;_i++){ \
- efloat(VEC_ELT(v, GLfloat, i)[_i]); \
- } \
- for(_i=v->size;_i<4;_i++){ \
- efloat(default_vector[_i]); \
- } \
+ return num_verts - verts_off;
+}
+
+/* Immediate implementation has been removed from CVS. */
+
+/* vertex buffer implementation */
+
+static void inline fire_EB(PREFIX unsigned long addr, int vertex_count, int type, int elt_size)
+{
+ LOCAL_VARS
+ unsigned long addr_a;
+ unsigned long t_addr;
+ unsigned long magic_1, magic_2;
+ GLcontext *ctx;
+ ctx = rmesa->radeon.glCtx;
+
+ assert(elt_size == 2 || elt_size == 4);
+
+ if(addr & (elt_size-1)){
+ WARN_ONCE("Badly aligned buffer\n");
+ return ;
+ }
+#ifdef OPTIMIZE_ELTS
+ addr_a = 0;
+
+ magic_1 = (addr % 32) / 4;
+ t_addr = addr & (~0x1d);
+ magic_2 = (vertex_count + 1 + (t_addr & 0x2)) / 2 + magic_1;
+
+ check_space(6);
+
+ 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);
}
-static void r300_render_flat_primitive(r300ContextPtr rmesa,
+ start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2);
+ if(elt_size == 4){
+ e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
+ e32(addr /*& 0xffffffe3*/);
+ } else {
+ e32(R300_EB_UNK1 | (magic_1 << 16) | R300_EB_UNK2);
+ e32(t_addr);
+ }
+
+ if(elt_size == 4){
+ e32(vertex_count /*+ addr_a/4*/); /* Total number of dwords needed? */
+ } else {
+ e32(magic_2); /* Total number of dwords needed? */
+ }
+ //cp_delay(PASS_PREFIX 1);
+#if 0
+ fprintf(stderr, "magic_1 %d\n", magic_1);
+ fprintf(stderr, "t_addr %x\n", t_addr);
+ fprintf(stderr, "magic_2 %d\n", magic_2);
+ exit(1);
+#endif
+#else
+ (void)magic_2, (void)magic_1, (void)t_addr;
+
+ addr_a = 0;
+
+ check_space(6);
+
+ 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);
+ e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
+ e32(addr /*& 0xffffffe3*/);
+
+ if(elt_size == 4){
+ e32(vertex_count /*+ addr_a/4*/); /* Total number of dwords needed? */
+ } else {
+ e32((vertex_count+1)/2 /*+ addr_a/4*/); /* Total number of dwords needed? */
+ }
+ //cp_delay(PASS_PREFIX 1);
+#endif
+}
+
+static void r300_render_vb_primitive(r300ContextPtr rmesa,
GLcontext *ctx,
int start,
int end,
int prim)
{
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- GLuint i;
- int k, type;
- LOCAL_VARS
-
- type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
- if(type<0)return;
-
-
- start_immediate_packet(end-start, type, 8);
-
- for(i=start;i<end;i++){
- #if 0
- fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n",
- VEC_ELT(VB->ObjPtr, GLfloat, i)[0],
- VEC_ELT(VB->ObjPtr, GLfloat, i)[1],
- VEC_ELT(VB->ObjPtr, GLfloat, i)[2],
- VEC_ELT(VB->ObjPtr, GLfloat, i)[3],
-
- VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0],
- VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1],
- VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2],
- VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]
- );
- #endif
-
-
- /* coordinates */
- #if 1
- output_vector(VB->ObjPtr, i);
- #else
- efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[0]);
- efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[1]);
- efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[2]);
- #if 0
- efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[3]);
- #else
- efloat(2.0);
- #endif
- #endif
-
- /* color components */
- #if 1
- output_vector(VB->ColorPtr[0], i);
- #else
- efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0]);
- efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1]);
- efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2]);
- #if 0
- efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]);
- #else
- efloat(0.0);
- #endif
- #endif
- }
+ int type, num_verts;
+ type=r300_get_primitive_type(rmesa, ctx, prim);
+ num_verts=r300_get_num_verts(rmesa, ctx, end-start, prim);
+
+ if(type<0 || num_verts <= 0)return;
+
+ if(rmesa->state.VB.Elts){
+ r300EmitAOS(rmesa, rmesa->state.aos_count, /*0*/start);
+#if 0
+ LOCAL_VARS
+ int i;
+ start_index32_packet(num_verts, type);
+ for(i=0; i < num_verts; i++)
+ e32(((unsigned long *)rmesa->state.VB.Elts)[i]/*rmesa->state.Elts[start+i]*/); /* start ? */
+#else
+ if(num_verts == 1){
+ //start_index32_packet(num_verts, type);
+ //e32(rmesa->state.Elts[start]);
+ return;
+ }
+
+ 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);
+ fire_EB(PASS_PREFIX rmesa->state.elt_dma.aos_offset, num_verts, type, rmesa->state.VB.elt_size);
+#endif
+ }else{
+ r300EmitAOS(rmesa, rmesa->state.aos_count, start);
+ fire_AOS(PASS_PREFIX num_verts, type);
+ }
}
-static GLboolean r300_run_flat_render(GLcontext *ctx,
- struct tnl_pipeline_stage *stage)
+#if 0
+void dump_array(struct r300_dma_region *rvb, int count)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- GLuint i;
- AOS_DATA vb_arrays[2];
- LOCAL_VARS
+ int *out = (int *)(rvb->address + rvb->start);
+ int i, ci;
- if (RADEON_DEBUG == DEBUG_PRIMS)
- fprintf(stderr, "%s\n", __FUNCTION__);
+ fprintf(stderr, "stride %d:", rvb->aos_stride);
+ for (i=0; i < count; i++) {
+ fprintf(stderr, "{");
+ if (rvb->aos_format == AOS_FORMAT_FLOAT)
+ for (ci=0; ci < rvb->aos_size; ci++)
+ fprintf(stderr, "%f ", ((float *)out)[ci]);
+ else
+ for (ci=0; ci < rvb->aos_size; ci++)
+ fprintf(stderr, "%d ", ((unsigned char *)out)[ci]);
+ fprintf(stderr, "}");
+
+ out += rvb->aos_stride;
+ }
- /* setup array of structures data */
-
- /* Note: immediate vertex data includes all coordinates.
- To save bandwidth use either VBUF or state-based vertex generation */
- /* xyz */
- vb_arrays[0].element_size=4;
- vb_arrays[0].stride=4;
- vb_arrays[0].offset=0; /* Not used */
- vb_arrays[0].format=AOS_FORMAT_FLOAT;
- vb_arrays[0].ncomponents=4;
- vb_arrays[0].reg=REG_COORDS;
-
- /* color */
- vb_arrays[1].element_size=4;
- vb_arrays[1].stride=4;
- vb_arrays[1].offset=0; /* Not used */
- vb_arrays[1].format=AOS_FORMAT_FLOAT_COLOR;
- vb_arrays[1].ncomponents=4;
- vb_arrays[1].reg=REG_COLOR0;
-
- r300EmitState(rmesa);
-
- /* needed before starting 3d operation .. */
- reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
- e32(0x0000000a);
-
- reg_start(0x4f18,0);
- e32(0x00000003);
+ fprintf(stderr, "\n");
+}
+
+void dump_dt(struct dt *dt, int count)
+{
+ int *out = dt->data;
+ int i, ci;
+ fprintf(stderr, "stride %d", dt->stride);
- reg_start(0x20b0,0);
- e32(0x0000043f);
-
- memcpy(FLAT_COLOR_PIPELINE.vertex_shader.parameters.body.f, ctx->_ModelProjectMatrix.m, 16*4);
-
- program_pipeline(PASS_PREFIX &FLAT_COLOR_PIPELINE);
-
- #if 0 /* Turn on for smooth color on teeth.. why ??.. */
- set_cull_cntl(PASS_PREFIX 0);
- #endif
- reg_start(R300_RE_OCCLUSION_CNTL, 0);
- e32(R300_OCCLUSION_ON);
-
-// set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0);
- set_init21(PASS_PREFIX 0.0,1.0);
-
- /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
- setup_AOS(PASS_PREFIX vb_arrays, 2);
-
- for(i=0; i < VB->PrimitiveCount; i++){
- GLuint prim = VB->Primitive[i].mode;
- GLuint start = VB->Primitive[i].start;
- GLuint length = VB->Primitive[i].count;
- r300_render_flat_primitive(rmesa, ctx, start, start + length, prim);
- }
+ for (i=0; i < count; i++){
+ fprintf(stderr, "{");
+ if (dt->type == GL_FLOAT)
+ for (ci=0; ci < dt->size; ci++)
+ fprintf(stderr, "%f ", ((float *)out)[ci]);
+ else
+ for (ci=0; ci < dt->size; ci++)
+ fprintf(stderr, "%d ", ((unsigned char *)out)[ci]);
+ fprintf(stderr, "}");
+
+ out = (int *)((char *)out + dt->stride);
+ }
- end_3d(PASS_PREFIX_VOID);
-
- fprintf(stderr, "\n");
- return GL_FALSE;
+ fprintf(stderr, "\n");
}
+#endif
-/* vertex buffer implementation */
-
-/* We use the start part of GART texture buffer for vertices */
-
-#define R300_MAX_AOS_ARRAYS 16
-
-static void upload_vertex_buffer(r300ContextPtr rmesa,
- GLcontext *ctx, AOS_DATA *array, int *n_arrays)
+GLboolean r300_run_vb_render(GLcontext *ctx,
+ struct tnl_pipeline_stage *stage)
{
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- int offset=0, idx=0;
- int i,j;
- radeonScreenPtr rsp=rmesa->radeon.radeonScreen;
- /* Not the most efficient implementation, but, for now, I just want something that
- works */
- /* to do - make single memcpy per column (is it possible ?) */
- /* to do - use dirty flags to avoid redundant copies */
-#define UPLOAD_VECTOR(v, r, f)\
- { \
- /* Is the data dirty ? */ \
- if (v->flags & ((1<<v->size)-1)) { \
- fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); \
- if(v->size*4==v->stride){\
- /* fast path */ \
- memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
- } else { \
- for(i=0;i<VB->Count;i++){ \
- /* copy one vertex at a time*/ \
- memcpy(rsp->gartTextures.map+offset, VEC_ELT(v, GLfloat, i), v->size*4); \
- } \
- } \
- /* v->flags &= ~((1<<v->size)-1);*/ \
- } \
- array[idx].element_size=v->size; \
- array[idx].stride=v->size; \
- array[idx].format=(f); \
- array[idx].ncomponents=v->size; \
- array[idx].offset=rsp->gartTextures.handle+offset; \
- array[idx].reg=r; \
- offset+=v->size*4*VB->Count; \
- idx++; \
- /* Fill in the rest with the components of default_vector */\
- /* \
- if(v->size<4){ \
- array[idx].element_size=4-v->size; \
- array[idx].stride=0; \
- array[idx].format=(f); \
- array[idx].ncomponents=4-v->size; \
- array[idx].offset=rsp->gartTextures.handle+v->size*4;\
- array[idx].reg=r; \
- idx++; \
- } \
- */\
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct radeon_vertex_buffer *VB = &rmesa->state.VB;
+ int i;
+ LOCAL_VARS
+
+ 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);
}
-/* Put a copy of default vector */
-memcpy(rsp->gartTextures.map, default_vector, 16);
-offset+=16;
+ r300UpdateShaders(rmesa);
+ if (rmesa->state.VB.LockCount == 0 || 1) {
+ r300EmitArrays(ctx, GL_FALSE);
+
+ r300UpdateShaderStates(rmesa);
+ } else {
+ /* TODO: Figure out why do we need these. */
+ R300_STATECHANGE(rmesa, vir[0]);
+ R300_STATECHANGE(rmesa, vir[1]);
+ R300_STATECHANGE(rmesa, vic);
+ R300_STATECHANGE(rmesa, vof);
-UPLOAD_VECTOR(VB->ObjPtr, REG_COORDS, AOS_FORMAT_FLOAT);
-UPLOAD_VECTOR(VB->ColorPtr[0], REG_COLOR0, AOS_FORMAT_FLOAT_COLOR);
+#if 0
+ fprintf(stderr, "dt:\n");
+ for(i=0; i < VERT_ATTRIB_MAX; i++){
+ fprintf(stderr, "dt %d:", i);
+ dump_dt(&rmesa->state.VB.AttribPtr[i], VB->Count);
+ }
+
+ fprintf(stderr, "before:\n");
+ for(i=0; i < rmesa->state.aos_count; i++){
+ fprintf(stderr, "aos %d:", i);
+ dump_array(&rmesa->state.aos[i], VB->Count);
+ }
+#endif
+#if 0
+ r300ReleaseArrays(ctx);
+ r300EmitArrays(ctx, GL_FALSE);
+
+ fprintf(stderr, "after:\n");
+ for(i=0; i < rmesa->state.aos_count; i++){
+ fprintf(stderr, "aos %d:", i);
+ dump_array(&rmesa->state.aos[i], VB->Count);
+ }
+#endif
+ }
+
+ reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
+ e32(0x0000000a);
-*n_arrays=idx;
-if(idx>=R300_MAX_AOS_ARRAYS){
- fprintf(stderr, "Aieee ! Maximum AOS arrays count exceeded.. \n");
- exit(-1);
+ reg_start(0x4f18,0);
+ e32(0x00000003);
+#if 0
+ reg_start(R300_VAP_PVS_WAITIDLE,0);
+ e32(0x00000000);
+#endif
+ r300EmitState(rmesa);
+
+ for(i=0; i < VB->PrimitiveCount; i++){
+ GLuint prim = VB->Primitive[i].mode;
+ GLuint start = VB->Primitive[i].start;
+ GLuint length = VB->Primitive[i].count;
+
+ r300_render_vb_primitive(rmesa, ctx, start, start + length, prim);
}
-}
-static void r300_render_vb_flat_primitive(r300ContextPtr rmesa,
- GLcontext *ctx,
- int start,
- int end,
- int prim)
-{
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- GLuint i;
- int k, type, n_arrays;
- LOCAL_VARS
-
- if(end<=start)return; /* do we need to watch for this ? */
-
- type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
- if(type<0)return;
+ reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
+ e32(0x0000000a/*0x2*/);
+
+ reg_start(0x4f18,0);
+ e32(0x00000003/*0x1*/);
- fire_AOS(PASS_PREFIX end-start, type);
+#ifdef USER_BUFFERS
+ r300UseArrays(ctx);
+#endif
+ r300ReleaseArrays(ctx);
+ return GL_FALSE;
}
-static VERTEX_SHADER_FRAGMENT default_vector_vsf={
- length: 4,
- body: {
- f: {0.0, 0.0, 0.0, 1.0}
- }
- };
+#define FALLBACK_IF(expr) \
+do { \
+ if (expr) { \
+ if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
+ WARN_ONCE("Software fallback:%s\n", #expr); \
+ return R300_FALLBACK_RAST; \
+ } \
+} while(0)
-static GLboolean r300_run_vb_flat_render(GLcontext *ctx,
- struct tnl_pipeline_stage *stage)
+int r300Fallback(GLcontext *ctx)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- int i, j, n_arrays;
- AOS_DATA vb_arrays[R300_MAX_AOS_ARRAYS];
- AOS_DATA vb_arrays2[R300_MAX_AOS_ARRAYS];
- LOCAL_VARS
-
- if (RADEON_DEBUG == DEBUG_PRIMS)
- fprintf(stderr, "%s\n", __FUNCTION__);
+ int i;
- /* setup array of structures data */
+ //FALLBACK_IF(ctx->RenderMode != GL_RENDER); // We do not do SELECT or FEEDBACK (yet ?)
+
+#if 0 /* These should work now.. */
+ FALLBACK_IF(ctx->Color.DitherFlag);
+ FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST
+ FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
+ FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
+#endif
+ FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT
+ FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE
+ //FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
+
+ //FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG disable as swtcl doesnt seem to support this
+ //FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH disabling to get blender going
+ FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE
+ FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB
+
+
+ FALLBACK_IF(ctx->Line.StippleFlag);
+
+ /* HW doesnt appear to directly support these */
+ FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH
+ FALLBACK_IF(ctx->Point.SmoothFlag); // GL_POINT_SMOOTH
+ /* Rest could be done with vertex fragments */
+ if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
+ FALLBACK_IF(ctx->Point.PointSprite); // GL_POINT_SPRITE_NV
- upload_vertex_buffer(rmesa, ctx, vb_arrays, &n_arrays);
- fprintf(stderr, "Using %d AOS arrays\n", n_arrays);
-
- r300EmitState(rmesa);
-
- reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
- e32(0x0000000a);
-
- reg_start(0x4f18,0);
- e32(0x00000003);
-
- reg_start(0x20b0,0);
- e32(0x0000043f);
-
- program_pipeline(PASS_PREFIX &FLAT_COLOR_PIPELINE);
-
- //upload_vertex_shader_fragment(PASS_PREFIX VSF_DEST_UNKNOWN1, &default_vector_vsf);
-
- reg_start(R300_RE_OCCLUSION_CNTL, 0);
- e32(R300_OCCLUSION_ON);
-
- set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0);
- set_init21(PASS_PREFIX 0.0,1.0);
-
- for(i=0; i < VB->PrimitiveCount; i++){
- GLuint prim = VB->Primitive[i].mode;
- GLuint start = VB->Primitive[i].start;
- GLuint length = VB->Primitive[i].count;
-
- /* copy arrays */
- memcpy(vb_arrays2, vb_arrays, sizeof(AOS_DATA)*n_arrays);
- for(j=0;j<n_arrays;j++){
- vb_arrays2[j].offset+=vb_arrays2[j].stride*start;
- }
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
+ if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_RECT_BIT)
+ return R300_FALLBACK_TCL;
- setup_AOS(PASS_PREFIX vb_arrays2, n_arrays);
-
- r300_render_vb_flat_primitive(rmesa, ctx, start, start + length, prim);
- }
-
- end_3d(PASS_PREFIX_VOID);
-
- /* Flush state - we are done drawing.. */
- r300Flush(ctx);
- fprintf(stderr, "\n");
- return GL_FALSE;
+ return R300_FALLBACK_NONE;
}
/**
static GLboolean r300_run_render(GLcontext *ctx,
struct tnl_pipeline_stage *stage)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- GLuint i;
-
- if (RADEON_DEBUG == DEBUG_PRIMS)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- return r300_run_flat_render(ctx, stage);
- #if 0
- return GL_TRUE;
- #else
- return GL_FALSE;
- #endif
-
-#if 0
- mgaContextPtr mmesa = MGA_CONTEXT(ctx);
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- GLuint i;
- /* Don't handle clipping or indexed vertices or vertex manipulations.
- */
- if (mmesa->RenderIndex != 0 ||
- !mga_validate_render( ctx, VB )) {
- return GL_TRUE;
- }
+ if (RADEON_DEBUG & DEBUG_PRIMS)
+ fprintf(stderr, "%s\n", __FUNCTION__);
- tnl->Driver.Render.Start( ctx );
- mmesa->SetupNewInputs = ~0;
+ if (r300Fallback(ctx) >= R300_FALLBACK_RAST)
+ return GL_TRUE;
- for (i = 0 ; i < VB->PrimitiveCount ; i++)
- {
- GLuint prim = VB->Primitive[i].mode;
- GLuint start = VB->Primitive[i].start;
- GLuint length = VB->Primitive[i].count;
+ return r300_run_vb_render(ctx, stage);
+}
- if (!length)
- continue;
+const struct tnl_pipeline_stage _r300_render_stage = {
+ "r300 hw rasterize",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ r300_run_render /* run */
+};
- mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length,
- prim);
- }
+static GLboolean r300_run_tcl_render(GLcontext *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct r300_vertex_program *vp;
+
+ hw_tcl_on=future_hw_tcl_on;
+
+ if (RADEON_DEBUG & DEBUG_PRIMS)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+ if(hw_tcl_on == GL_FALSE)
+ return GL_TRUE;
+
+ if (r300Fallback(ctx) >= R300_FALLBACK_TCL) {
+ hw_tcl_on = GL_FALSE;
+ return GL_TRUE;
+ }
+
+ r300UpdateShaders(rmesa);
- tnl->Driver.Render.Finish( ctx );
+ vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
+#if 0 /* Draw every second request with software arb vp */
+ vp->native++;
+ vp->native &= 1;
+ //vp->native = GL_FALSE;
+#endif
- return GL_FALSE; /* finished the pipe */
+#if 0 /* You dont want to know what this does... */
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct tnl_cache *cache;
+ struct tnl_cache_item *c;
+
+ cache = tnl->vp_cache;
+ c = cache->items[0xc000cc0e % cache->size];
+
+ if(c && c->data == vp)
+ vp->native = GL_FALSE;
+
#endif
+#if 0
+ vp->native = GL_FALSE;
+#endif
+ if (vp->native == GL_FALSE) {
+ hw_tcl_on = GL_FALSE;
+ return GL_TRUE;
+ }
+ //r300UpdateShaderStates(rmesa);
+
+ return r300_run_vb_render(ctx, stage);
}
+const struct tnl_pipeline_stage _r300_tcl_stage = {
+ "r300 tcl",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ r300_run_tcl_render /* run */
+};
-/**
- * Called by the pipeline manager once before rendering.
- * We check the GL state here to
- * a) decide whether we can do the current state in hardware and
- * b) update hardware registers
+/* R300 texture rectangle expects coords in 0..1 range, not 0..dimension
+ * as in the extension spec. Need to translate here.
+ *
+ * Note that swrast expects 0..dimension, so if a fallback is active,
+ * don't do anything. (Maybe need to configure swrast to match hw)
*/
-#define FALLBACK_IF(expr) \
-do { \
- if (expr) { \
- if (RADEON_DEBUG & DEBUG_FALLBACKS) \
- fprintf(stderr, "%s: fallback:%s\n", \
- __FUNCTION__, #expr); \
- stage->active = GL_FALSE; \
- return; \
- } \
-} while(0)
+struct texrect_stage_data {
+ GLvector4f texcoord[MAX_TEXTURE_UNITS];
+};
+
+#define TEXRECT_STAGE_DATA(stage) ((struct texrect_stage_data *)stage->privatePtr)
-static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+
+static GLboolean run_texrect_stage( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
- int i;
+ struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage);
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint i;
- if (RADEON_DEBUG & DEBUG_STATE)
- fprintf(stderr, "%s\n", __FUNCTION__);
+ if (rmesa->radeon.Fallback)
+ return GL_TRUE;
- /* We only support rendering in hardware for now */
- if (ctx->RenderMode != GL_RENDER) {
- stage->active = GL_FALSE;
- return;
- }
+ for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_RECT_BIT) {
+ struct gl_texture_object *texObj = ctx->Texture.Unit[i].CurrentRect;
+ struct gl_texture_image *texImage = texObj->Image[0][texObj->BaseLevel];
+ const GLfloat iw = 1.0/texImage->Width;
+ const GLfloat ih = 1.0/texImage->Height;
+ GLfloat *in = (GLfloat *)VB->TexCoordPtr[i]->data;
+ GLint instride = VB->TexCoordPtr[i]->stride;
+ GLfloat (*out)[4] = store->texcoord[i].data;
+ GLint j;
+
+ store->texcoord[i].size = VB->TexCoordPtr[i]->size;
+ for (j = 0 ; j < VB->Count ; j++) {
+ switch (VB->TexCoordPtr[i]->size) {
+ case 4:
+ out[j][3] = in[3];
+ /* fallthrough */
+ case 3:
+ out[j][2] = in[2];
+ /* fallthrough */
+ default:
+ out[j][0] = in[0] * iw;
+ out[j][1] = in[1] * ih;
+ }
+ in = (GLfloat *)((GLubyte *)in + instride);
+ }
+
+ VB->AttribPtr[VERT_ATTRIB_TEX0+i] = VB->TexCoordPtr[i] = &store->texcoord[i];
+ }
+ }
- // I failed to figure out how dither works in hardware,
- // let's just ignore it for now
- //FALLBACK_IF(ctx->Color.DitherFlag);
+ return GL_TRUE;
+}
- /* I'm almost certain I forgot something here */
- FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST
- FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
- FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG
- FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH
- FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE
- FALLBACK_IF(ctx->Point.SmoothFlag); // GL_POINT_SMOOTH
- if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
- FALLBACK_IF(ctx->Point.PointSprite); // GL_POINT_SPRITE_NV
- FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT
- FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE
- FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
- FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH
- FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE
- FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
- FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
- FALLBACK_IF(ctx->Texture.Unit[i].Enabled);
+/* Called the first time stage->run() is invoked.
+ */
+static GLboolean alloc_texrect_data( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct texrect_stage_data *store;
+ GLuint i;
+ stage->privatePtr = CALLOC(sizeof(*store));
+ store = TEXRECT_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
- /* let r300_run_render do its job */
- #if 0
- stage->active = GL_FALSE;
- #endif
-}
+ for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
+ _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
+ return GL_TRUE;
+}
-static void dtr(struct tnl_pipeline_stage *stage)
+static void free_texrect_data( struct tnl_pipeline_stage *stage )
{
- (void)stage;
+ struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage);
+ GLuint i;
+
+ if (store) {
+ for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
+ if (store->texcoord[i].data)
+ _mesa_vector4f_free( &store->texcoord[i] );
+ FREE( store );
+ stage->privatePtr = NULL;
+ }
}
-const struct tnl_pipeline_stage _r300_render_stage = {
- "r300 hw rasterize",
- _NEW_ALL, /* re-check (always re-check for now) */
- 0, /* re-run (always runs) */
- GL_TRUE, /* active */
- 0, 0, /* inputs (set in check_render), outputs */
- 0, 0, /* changed_inputs, private */
- dtr, /* destructor */
- r300_check_render, /* check */
- r300_run_render /* run */
+const struct tnl_pipeline_stage _r300_texrect_stage =
+{
+ "r300 texrect stage", /* name */
+ NULL,
+ alloc_texrect_data,
+ free_texrect_data,
+ NULL,
+ run_texrect_stage
};
+