USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
-
/*
- * Authors:
- * Nicolai Haehnle <prefect_@gmx.net>
+ * \file
+ *
+ * \brief R300 Render (Vertex Buffer Implementation)
+ *
+ * The immediate implementation has been removed from CVS in favor of the vertex
+ * buffer implementation.
+ *
+ * When falling back to software TCL still attempt to use hardware
+ * rasterization.
+ *
+ * I am not sure that the cache related registers are setup correctly, but
+ * obviously this does work... Further investigation is needed.
+ *
+ * \author Nicolai Haehnle <prefect_@gmx.net>
*/
-
#include "glheader.h"
#include "state.h"
#include "imports.h"
#include "context.h"
#include "dd.h"
#include "simple_list.h"
-
#include "api_arrayelt.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
-#include "array_cache/acache.h"
+#include "vbo/vbo.h"
#include "tnl/tnl.h"
-
+#include "tnl/t_vp_build.h"
#include "radeon_reg.h"
#include "radeon_macros.h"
#include "radeon_ioctl.h"
#include "r300_tex.h"
#include "r300_maos.h"
#include "r300_emit.h"
-
extern int future_hw_tcl_on;
-/**********************************************************************
-* Hardware rasterization
-*
-* When we fell back to software TCL, we still try to use the
-* rasterization hardware for rendering.
-**********************************************************************/
-
-static int r300_get_primitive_type(r300ContextPtr rmesa, GLcontext *ctx, int prim)
+static int r300PrimitiveType(r300ContextPtr rmesa, GLcontext * ctx,
+ int prim)
{
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- GLuint i;
- int type=-1;
+ int type = -1;
switch (prim & PRIM_MODE_MASK) {
case GL_POINTS:
- type=R300_VAP_VF_CNTL__PRIM_POINTS;
- break;
+ type = R300_VAP_VF_CNTL__PRIM_POINTS;
+ break;
case GL_LINES:
- type=R300_VAP_VF_CNTL__PRIM_LINES;
- break;
+ type = R300_VAP_VF_CNTL__PRIM_LINES;
+ break;
case GL_LINE_STRIP:
- type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
- break;
+ type = R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
+ break;
case GL_LINE_LOOP:
- type=R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
- break;
- case GL_TRIANGLES:
- type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
- break;
- case GL_TRIANGLE_STRIP:
- type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
- break;
- case GL_TRIANGLE_FAN:
- type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
- break;
+ type = R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
+ break;
+ case GL_TRIANGLES:
+ type = R300_VAP_VF_CNTL__PRIM_TRIANGLES;
+ break;
+ case GL_TRIANGLE_STRIP:
+ type = R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
+ break;
+ case GL_TRIANGLE_FAN:
+ type = R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
+ break;
case GL_QUADS:
- type=R300_VAP_VF_CNTL__PRIM_QUADS;
- break;
+ type = R300_VAP_VF_CNTL__PRIM_QUADS;
+ break;
case GL_QUAD_STRIP:
- type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
- break;
+ type = R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
+ break;
case GL_POLYGON:
- type=R300_VAP_VF_CNTL__PRIM_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);
+ default:
+ fprintf(stderr,
+ "%s:%s Do not know how to handle primitive 0x%04x - help me !\n",
+ __FILE__, __FUNCTION__, prim & PRIM_MODE_MASK);
return -1;
- break;
- }
- return type;
+ break;
+ }
+ return type;
}
-static int r300_get_num_verts(r300ContextPtr rmesa,
- GLcontext *ctx,
- int num_verts,
- int prim)
+static int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim)
{
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- GLuint i;
- int type=-1, verts_off=0;
- char *name="UNKNOWN";
+ int verts_off = 0;
switch (prim & PRIM_MODE_MASK) {
case GL_POINTS:
- name="P";
verts_off = 0;
- break;
+ break;
case GL_LINES:
- name="L";
verts_off = num_verts % 2;
- break;
+ break;
case GL_LINE_STRIP:
- name="LS";
- if(num_verts < 2)
+ if (num_verts < 2)
verts_off = num_verts;
- break;
+ break;
case GL_LINE_LOOP:
- name="LL";
- if(num_verts < 2)
+ if (num_verts < 2)
verts_off = num_verts;
- break;
- case GL_TRIANGLES:
- name="T";
+ break;
+ case GL_TRIANGLES:
verts_off = num_verts % 3;
- break;
- case GL_TRIANGLE_STRIP:
- name="TS";
- if(num_verts < 3)
+ break;
+ case GL_TRIANGLE_STRIP:
+ if (num_verts < 3)
verts_off = num_verts;
- break;
- case GL_TRIANGLE_FAN:
- name="TF";
- if(num_verts < 3)
+ break;
+ case GL_TRIANGLE_FAN:
+ if (num_verts < 3)
verts_off = num_verts;
- break;
+ break;
case GL_QUADS:
- name="Q";
verts_off = num_verts % 4;
- break;
+ break;
case GL_QUAD_STRIP:
- name="QS";
- if(num_verts < 4)
+ if (num_verts < 4)
verts_off = num_verts;
else
verts_off = num_verts % 2;
- break;
+ break;
case GL_POLYGON:
- name="P";
- if(num_verts < 3)
+ 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);
+ default:
+ fprintf(stderr,
+ "%s:%s Do not know how to handle primitive 0x%04x - help me !\n",
+ __FILE__, __FUNCTION__, prim & PRIM_MODE_MASK);
return -1;
- break;
- }
-
- 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;
+ break;
}
- if(verts_off > 0){
- WARN_ONCE("user error: %d is not a valid number of vertices for primitive %s !\n", num_verts, name);
+ if (RADEON_DEBUG & DEBUG_VERTS) {
+ if (num_verts - verts_off == 0) {
+ WARN_ONCE
+ ("user error: Need more than %d vertices to draw primitive 0x%04x !\n",
+ num_verts, prim & PRIM_MODE_MASK);
+ return 0;
+ }
+
+ if (verts_off > 0) {
+ WARN_ONCE
+ ("user error: %d is not a valid number of vertices for primitive 0x%04x !\n",
+ num_verts, prim & PRIM_MODE_MASK);
+ }
}
return num_verts - verts_off;
}
-/* This function compiles GL context into state registers that
- describe data routing inside of R300 pipeline.
-
- In particular, it programs input_route, output_vtx_fmt, texture
- unit configuration and gb_output_vtx_fmt
-
- This function encompasses setup_AOS() from r300_lib.c
-*/
-
-
-
-
-/* Immediate implementation - vertex data is sent via command stream */
-
-static GLfloat default_vector[4]={0.0, 0.0, 0.0, 1.0};
-
-#define output_vector(v, i) { \
- int _i; \
- for(_i=0;_i<v->size;_i++){ \
- if(VB->Elts){ \
- efloat(VEC_ELT(v, GLfloat, VB->Elts[i])[_i]); \
- }else{ \
- efloat(VEC_ELT(v, GLfloat, i)[_i]); \
- } \
- } \
- for(_i=v->size;_i<4;_i++){ \
- efloat(default_vector[_i]); \
- } \
-}
-
-/* Immediate implementation - vertex data is sent via command stream */
-
-static void r300_render_immediate_primitive(r300ContextPtr rmesa,
- GLcontext *ctx,
- int start,
- int end,
- int prim)
+static void inline r300FireEB(r300ContextPtr rmesa, unsigned long addr,
+ int vertex_count, int type, int elt_size)
{
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- GLuint i, render_inputs;
- int k, type, num_verts;
- LOCAL_VARS
-
- type=r300_get_primitive_type(rmesa, ctx, prim);
- num_verts=r300_get_num_verts(rmesa, ctx, end-start, prim);
-
-#if 0
- fprintf(stderr,"ObjPtr: size=%d stride=%d\n",
- VB->ObjPtr->size, VB->ObjPtr->stride);
- fprintf(stderr,"ColorPtr[0]: size=%d stride=%d\n",
- VB->ColorPtr[0]->size, VB->ColorPtr[0]->stride);
- fprintf(stderr,"TexCoordPtr[0]: size=%d stride=%d\n",
- VB->TexCoordPtr[0]->size, VB->TexCoordPtr[0]->stride);
-#endif
+ 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;
+ GLcontext *ctx;
+ ctx = rmesa->radeon.glCtx;
- if(type<0 || num_verts <= 0)return;
+ assert(elt_size == 2 || elt_size == 4);
- if(!VB->ObjPtr){
- WARN_ONCE("FIXME: Don't know how to handle GL_ARB_vertex_buffer_object correctly\n");
- return;
- }
- /* A packet cannot have more than 16383 data words.. */
- if((num_verts*4*rmesa->state.aos_count)>16380){
- WARN_ONCE("Too many vertices to paint. Fix me !\n");
- return;
+ if (addr & (elt_size - 1)) {
+ WARN_ONCE("Badly aligned buffer\n");
+ return;
}
- //fprintf(stderr, "aos_count=%d start=%d end=%d\n", rmesa->state.aos_count, start, end);
-
- if(rmesa->state.aos_count==0){
- WARN_ONCE("Aeiee ! aos_count==0, while it shouldn't. Skipping rendering\n");
- return;
- }
-
- render_inputs = rmesa->state.render_inputs;
+ magic_1 = (addr % 32) / 4;
+ t_addr = addr & (~0x1d);
+ magic_2 = (vertex_count + 1 + (t_addr & 0x2)) / 2 + magic_1;
- if(!render_inputs){
- WARN_ONCE("Aeiee ! render_inputs==0. Skipping rendering.\n");
- return;
- }
-
-
- start_immediate_packet(num_verts, type, 4*rmesa->state.aos_count);
+ check_space(6);
- for(i=start;i<start+num_verts;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],
+ 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);
+ }
- 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]
- );
+ 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
+ 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
+ }
+}
- /* coordinates */
- if(render_inputs & _TNL_BIT_POS)
- output_vector(VB->ObjPtr, i);
- if(render_inputs & _TNL_BIT_NORMAL)
- output_vector(VB->NormalPtr, i);
-
- /* color components */
- if(render_inputs & _TNL_BIT_COLOR0)
- output_vector(VB->ColorPtr[0], i);
- if(render_inputs & _TNL_BIT_COLOR1)
- output_vector(VB->SecondaryColorPtr[0], i);
+static void r300RunRenderPrimitive(r300ContextPtr rmesa, GLcontext * ctx,
+ int start, int end, int prim)
+{
+ int type, num_verts;
-/* if(render_inputs & _TNL_BIT_FOG) // Causes lock ups when immediate mode is on
- output_vector(VB->FogCoordPtr, i);*/
+ type = r300PrimitiveType(rmesa, ctx, prim);
+ num_verts = r300NumVerts(rmesa, end - start, prim);
- /* texture coordinates */
- for(k=0;k < ctx->Const.MaxTextureUnits;k++)
- if(render_inputs & (_TNL_BIT_TEX0<<k))
- output_vector(VB->TexCoordPtr[k], i);
+ if (type < 0 || num_verts <= 0)
+ return;
- if(render_inputs & _TNL_BIT_INDEX)
- output_vector(VB->IndexPtr[0], i);
- if(render_inputs & _TNL_BIT_POINTSIZE)
- output_vector(VB->PointSizePtr, i);
+ if (rmesa->state.VB.Elts) {
+ r300EmitAOS(rmesa, rmesa->state.aos_count, /*0 */ 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);
+ } else {
+ r300EmitAOS(rmesa, rmesa->state.aos_count, start);
+ fire_AOS(rmesa, num_verts, type);
+ }
}
-
-static GLboolean r300_run_immediate_render(GLcontext *ctx,
- struct tnl_pipeline_stage *stage)
+static GLboolean r300RunRender(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;
- /* Only do 2d textures */
- struct gl_texture_object *to=ctx->Texture.Unit[0].Current2D;
- r300TexObjPtr t=to->DriverData;
- LOCAL_VARS
-
-
- /* Update texture state - needs to be done only when actually changed..
- All the time for now.. */
-
+ 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;
- if (RADEON_DEBUG == DEBUG_PRIMS)
+ if (RADEON_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s\n", __FUNCTION__);
-#if 1 /* we need this, somehow */
- /* Flush state - make sure command buffer is nice and large */
- r300Flush(ctx);
- /* Make sure we have enough space */
-#else
- /* Count is very imprecize, but should be good upper bound */
- r300EnsureCmdBufSpace(rmesa, rmesa->hw.max_state_size + 4+2+30
- +VB->PrimitiveCount*(1+8)+VB->Count*4*rmesa->state.texture.tc_count+4, __FUNCTION__);
-#endif
-
- /* needed before starting 3d operation .. */
- reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
- e32(0x0000000a);
-
- reg_start(0x4f18,0);
- e32(0x00000003);
-
-
-#if 0 /* looks like the Z offset issue got fixed */
- rmesa->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA
- | R300_VPORT_X_OFFSET_ENA
- | R300_VPORT_Y_SCALE_ENA
- | R300_VPORT_Y_OFFSET_ENA
- | R300_VTX_W0_FMT;
- R300_STATECHANGE(rmesa, vte);
-#endif
-
-
-
- /* Magic register - note it is right after 20b0 */
-
-
- if(rmesa->state.texture.tc_count>0){
- reg_start(0x20b4,0);
- e32(0x0000000c);
-
+ if (stage) {
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ radeon_vb_to_rvb(rmesa, VB, &tnl->vb);
}
- r300EmitState(rmesa);
-
-/* Setup INPUT_ROUTE and INPUT_CNTL */
- r300EmitArrays(ctx, GL_TRUE);
-
-/* Why do we need this for immediate mode?? Vertex processor needs it to know proper regs */
-// r300EmitLOAD_VBPNTR(rmesa, 0);
-/* Okay, it seems I misunderstood something, EmitAOS does the same thing */
- r300EmitAOS(rmesa, rmesa->state.aos_count, 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;
-
- r300_render_immediate_primitive(rmesa, ctx, start, start + length, prim);
- }
-
- /* This sequence is required after any 3d drawing packet
- I suspect it work arounds a bug (or deficiency) in hardware */
+ r300UpdateShaders(rmesa);
+ if (r300EmitArrays(ctx))
+ return GL_TRUE;
- reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
- e32(0x0000000a);
+ r300UpdateShaderStates(rmesa);
- reg_start(0x4f18,0);
- e32(0x00000003);
+ reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
+ e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);
- return GL_FALSE;
-}
+ reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0);
+ e32(R300_RB3D_ZCACHE_UNKNOWN_03);
+ r300EmitState(rmesa);
-/* vertex buffer implementation */
+ for (i = 0; i < VB->PrimitiveCount; i++) {
+ GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
+ GLuint start = VB->Primitive[i].start;
+ GLuint length = VB->Primitive[i].count;
-static void inline fire_EB(PREFIX unsigned long addr, int vertex_count, int type)
-{
- LOCAL_VARS
- unsigned long addr_a;
-
- if(addr & 1){
- WARN_ONCE("Badly aligned buffer\n");
- return ;
+ r300RunRenderPrimitive(rmesa, ctx, start, start + length,
+ prim);
}
- addr_a = 0; /*addr & 0x1c;*/
-
- check_space(6);
-
- start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, 0);
- /* TODO: R300_VAP_VF_CNTL__INDEX_SIZE_32bit . */
- e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count<<16) | type);
- start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2);
- e32(R300_EB_UNK1 | (addr_a << 16) | R300_EB_UNK2);
- e32(addr /*& 0xffffffe3*/);
- e32((vertex_count+1)/2 /*+ addr_a/4*/); /* Total number of dwords needed? */
-}
+ reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
+ e32(R300_RB3D_DSTCACHE_UNKNOWN_0A
+ /*R300_RB3D_DSTCACHE_UNKNOWN_02 */ );
-static void r300_render_vb_primitive(r300ContextPtr rmesa,
- GLcontext *ctx,
- int start,
- int end,
- int prim)
-{
- int type, num_verts;
- radeonScreenPtr rsp=rmesa->radeon.radeonScreen;
- LOCAL_VARS
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- int i;
-
- 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.Elts){
- r300EmitAOS(rmesa, rmesa->state.aos_count, 0);
-#if 0
- start_index32_packet(num_verts, type);
- for(i=0; i < num_verts; i++)
- e32(rmesa->state.Elts[start+i]); /* start ? */
-#else
- WARN_ONCE("Rendering with elt buffers\n");
- 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.Elts+start, num_verts);
- fire_EB(PASS_PREFIX GET_START(&(rmesa->state.elt_dma)), num_verts, type);
+ reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0);
+ e32(R300_RB3D_ZCACHE_UNKNOWN_03 /*R300_RB3D_ZCACHE_UNKNOWN_01 */ );
+
+#ifdef USER_BUFFERS
+ r300UseArrays(ctx);
#endif
- }else{
- r300EmitAOS(rmesa, rmesa->state.aos_count, start);
- fire_AOS(PASS_PREFIX num_verts, type);
- }
+ r300ReleaseArrays(ctx);
+ return GL_FALSE;
}
-static GLboolean r300_run_vb_render(GLcontext *ctx,
- struct tnl_pipeline_stage *stage)
+#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)
+
+int r300Fallback(GLcontext * ctx)
{
- r300ContextPtr rmesa = R300_CONTEXT(ctx);
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
- int i, j;
- LOCAL_VARS
-
- if (RADEON_DEBUG & DEBUG_PRIMS)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
-
- r300ReleaseArrays(ctx);
- r300EmitArrays(ctx, GL_FALSE);
-
-// LOCK_HARDWARE(&(rmesa->radeon));
-
- reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
- e32(0x0000000a);
-
- reg_start(0x4f18,0);
- e32(0x00000003);
- r300EmitState(rmesa);
-
- rmesa->state.Elts = VB->Elts;
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ struct r300_fragment_program *fp = (struct r300_fragment_program *)
+ (char *)ctx->FragmentProgram._Current;
- 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);
+ if (fp) {
+ if (!fp->translated)
+ r300_translate_fragment_shader(r300, fp);
+ FALLBACK_IF(!fp->translated);
}
- reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
- e32(0x0000000a);
-
- reg_start(0x4f18,0);
- e32(0x00000003);
-
-// end_3d(PASS_PREFIX_VOID);
-
- /* Flush state - we are done drawing.. */
-// r300FlushCmdBufLocked(rmesa, __FUNCTION__);
-// radeonWaitForIdleLocked(&(rmesa->radeon));
+ FALLBACK_IF(ctx->RenderMode != GL_RENDER);
+
+ FALLBACK_IF(ctx->Stencil._TestTwoSide
+ && (ctx->Stencil.Ref[0] != ctx->Stencil.Ref[1]
+ || ctx->Stencil.ValueMask[0] !=
+ ctx->Stencil.ValueMask[1]
+ || ctx->Stencil.WriteMask[0] !=
+ ctx->Stencil.WriteMask[1]));
+
+ /* GL_COLOR_LOGIC_OP */
+ FALLBACK_IF(ctx->Color.ColorLogicOpEnabled);
+
+ /* GL_POINT_SPRITE_ARB, GL_POINT_SPRITE_NV */
+ if (ctx->Extensions.NV_point_sprite
+ || ctx->Extensions.ARB_point_sprite)
+ FALLBACK_IF(ctx->Point.PointSprite);
+
+ if (!r300->disable_lowimpact_fallback) {
+ /* GL_POLYGON_OFFSET_POINT */
+ FALLBACK_IF(ctx->Polygon.OffsetPoint);
+ /* GL_POLYGON_OFFSET_LINE */
+ FALLBACK_IF(ctx->Polygon.OffsetLine);
+ /* GL_POLYGON_STIPPLE */
+ FALLBACK_IF(ctx->Polygon.StippleFlag);
+ /* GL_MULTISAMPLE */
+ FALLBACK_IF(ctx->Multisample.Enabled);
+ /* GL_LINE_STIPPLE */
+ FALLBACK_IF(ctx->Line.StippleFlag);
+ /* GL_LINE_SMOOTH */
+ FALLBACK_IF(ctx->Line.SmoothFlag);
+ /* GL_POINT_SMOOTH */
+ FALLBACK_IF(ctx->Point.SmoothFlag);
+ }
-// UNLOCK_HARDWARE(&(rmesa->radeon));
- return GL_FALSE;
+ return R300_FALLBACK_NONE;
}
/**
* rasterization) or false to indicate that the pipeline has finished
* after we render something.
*/
-static GLboolean r300_run_render(GLcontext *ctx,
- struct tnl_pipeline_stage *stage)
+static GLboolean r300RunNonTNLRender(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__);
+ if (r300Fallback(ctx) >= R300_FALLBACK_RAST)
+ return GL_TRUE;
-#if 1
-
-#if 0
- return r300_run_immediate_render(ctx, stage);
-#else
- return r300_run_vb_render(ctx, stage);
-#endif
-#else
- return GL_TRUE;
-#endif
+ return r300RunRender(ctx, stage);
}
-
-/**
- * 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
- */
-#define FALLBACK_IF(expr) \
-do { \
- if (expr) { \
- if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
- fprintf(stderr, "%s: fallback:%s\n", \
- __FUNCTION__, #expr); \
- /*stage->active = GL_FALSE*/; \
- return; \
- } \
-} while(0)
-
-static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+static GLboolean r300RunTCLRender(GLcontext * ctx,
+ struct tnl_pipeline_stage *stage)
{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
- int i;
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct r300_vertex_program *vp;
+
+ hw_tcl_on = future_hw_tcl_on;
- if (RADEON_DEBUG & DEBUG_STATE)
+ if (RADEON_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s\n", __FUNCTION__);
- /* We only support rendering in hardware for now */
- if (ctx->RenderMode != GL_RENDER) {
- //stage->active = GL_FALSE;
- return;
+ if (hw_tcl_on == GL_FALSE)
+ return GL_TRUE;
+
+ if (r300Fallback(ctx) >= R300_FALLBACK_TCL) {
+ hw_tcl_on = GL_FALSE;
+ return GL_TRUE;
}
-
-
- /* I'm almost certain I forgot something here */
-#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->RenderMode != GL_RENDER); // We do not do SELECT or FEEDBACK (yet ?)
-
-#if 0 /* ut2k3 fails to start if this is on */
- /* One step at a time - let one texture pass.. */
- for (i = 1; i < ctx->Const.MaxTextureUnits; i++)
- FALLBACK_IF(ctx->Texture.Unit[i].Enabled);
-#endif
-
- /* Assumed factor reg is found but pattern is still missing */
- //FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE disabling to get blender going
-
- /* HW doesnt appear to directly support these */
- //FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH disabling to get blender going
- 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
- //GL_POINT_DISTANCE_ATTENUATION_ARB
- //GL_POINT_FADE_THRESHOLD_SIZE_ARB
-
- /* let r300_run_render do its job */
-#if 0
- stage->active = GL_FALSE;
-#endif
-}
+ r300UpdateShaders(rmesa);
-static void dtr(struct tnl_pipeline_stage *stage)
-{
- (void)stage;
-}
+ vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
+ if (vp->native == GL_FALSE) {
+ hw_tcl_on = GL_FALSE;
+ return GL_TRUE;
+ }
-GLboolean r300_create_render(GLcontext *ctx, struct tnl_pipeline_stage *stage){
- return GL_TRUE;
+ return r300RunRender(ctx, stage);
}
-
const struct tnl_pipeline_stage _r300_render_stage = {
- "r300 hw rasterize",
+ "r300 Hardware Rasterization",
+ NULL,
NULL,
- r300_create_render,
- dtr, /* destructor */
- r300_check_render, /* check */
- r300_run_render /* run */
+ NULL,
+ NULL,
+ r300RunNonTNLRender
};
-static GLboolean r300_run_tcl_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;
- 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(ctx->VertexProgram._Enabled == GL_FALSE){
- _tnl_UpdateFixedFunctionProgram(ctx);
- }
- vp = CURRENT_VERTEX_SHADER(ctx);
- if(vp->translated == GL_FALSE)
- translate_vertex_shader(vp);
- if(vp->translated == GL_FALSE){
- fprintf(stderr, "Failing back to sw-tcl\n");
- debug_vp(ctx, vp);
- hw_tcl_on=future_hw_tcl_on=0;
- r300ResetHwState(rmesa);
- return GL_TRUE;
- }
-
- r300_setup_textures(ctx);
- r300_setup_rs_unit(ctx);
-
- r300SetupVertexShader(rmesa);
- r300SetupPixelShader(rmesa);
-
- return r300_run_vb_render(ctx, stage);
-}
-
-static void r300_check_tcl_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
- int i;
-
- if (RADEON_DEBUG & DEBUG_STATE)
- fprintf(stderr, "%s\n", __FUNCTION__);
-
- /* We only support rendering in hardware for now */
- if (ctx->RenderMode != GL_RENDER) {
- //stage->active = GL_FALSE;
- return;
- }
-}
-
const struct tnl_pipeline_stage _r300_tcl_stage = {
- "r300 tcl",
+ "r300 Hardware Transform, Clipping and Lighting",
+ NULL,
+ NULL,
+ NULL,
NULL,
- r300_create_render,
- dtr, /* destructor */
- r300_check_tcl_render, /* check */
- r300_run_tcl_render /* run */
+ r300RunTCLRender
};