b7e6ff25778c0a790da1743a4758035145baa9c9
[mesa.git] / src / mesa / drivers / dri / r300 / r300_render.c
1 /**************************************************************************
2
3 Copyright (C) 2004 Nicolai Haehnle.
4
5 All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
16 Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Nicolai Haehnle <prefect_@gmx.net>
31 */
32
33 #include "glheader.h"
34 #include "state.h"
35 #include "imports.h"
36 #include "enums.h"
37 #include "macros.h"
38 #include "context.h"
39 #include "dd.h"
40 #include "simple_list.h"
41
42 #include "api_arrayelt.h"
43 #include "swrast/swrast.h"
44 #include "swrast_setup/swrast_setup.h"
45 #include "array_cache/acache.h"
46 #include "tnl/tnl.h"
47
48 #include "radeon_ioctl.h"
49 #include "radeon_state.h"
50 #include "r300_context.h"
51 #include "r300_ioctl.h"
52 #include "r300_state.h"
53 #include "r300_reg.h"
54 #include "r300_program.h"
55
56 #include "r300_lib.h"
57
58
59 /**********************************************************************
60 * Hardware rasterization
61 *
62 * When we fell back to software TCL, we still try to use the
63 * rasterization hardware for rendering.
64 **********************************************************************/
65
66 static int r300_get_primitive_type(r300ContextPtr rmesa,
67 GLcontext *ctx,
68 int start,
69 int end,
70 int prim)
71 {
72 TNLcontext *tnl = TNL_CONTEXT(ctx);
73 struct vertex_buffer *VB = &tnl->vb;
74 GLuint i;
75 int type=-1, min_vertices=0;
76 char *name="UNKNOWN";
77
78 if(end<=start)return -1; /* do we need to watch for this ? */
79
80 switch (prim & PRIM_MODE_MASK) {
81 case GL_POINTS:
82 name="P";
83 type=R300_VAP_VF_CNTL__PRIM_POINTS;
84 min_vertices=1;
85 break;
86 case GL_LINES:
87 name="L";
88 type=R300_VAP_VF_CNTL__PRIM_LINES;
89 min_vertices=2;
90 break;
91 case GL_LINE_STRIP:
92 name="LS";
93 type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
94 min_vertices=2;
95 break;
96 case GL_LINE_LOOP:
97 name="LL";
98 min_vertices=2;
99 return -1;
100 break;
101 case GL_TRIANGLES:
102 name="T";
103 type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
104 min_vertices=3;
105 break;
106 case GL_TRIANGLE_STRIP:
107 name="TS";
108 type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
109 min_vertices=3;
110 break;
111 case GL_TRIANGLE_FAN:
112 name="TF";
113 type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
114 min_vertices=3;
115 break;
116 case GL_QUADS:
117 name="Q";
118 type=R300_VAP_VF_CNTL__PRIM_QUADS;
119 min_vertices=4;
120 break;
121 case GL_QUAD_STRIP:
122 name="QS";
123 type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
124 min_vertices=4;
125 break;
126 default:
127 fprintf(stderr, "Cannot handle primitive %02x ", prim & PRIM_MODE_MASK);
128 return -1;
129 break;
130 }
131 #if 0
132 fprintf(stderr, "[%d-%d]%s ", start, end, name);
133 #endif
134 if(start+min_vertices>=end){
135 fprintf(stderr, "Not enough vertices\n");
136 return -1;
137 }
138 return type;
139 }
140
141 /* This function compiles GL context into state registers that
142 describe data routing inside of R300 pipeline.
143
144 In particular, it programs input_route, output_vtx_fmt, texture
145 unit configuration and gb_output_vtx_fmt
146
147 This function encompasses setup_AOS() from r300_lib.c
148 */
149
150
151
152 static void inline r300_setup_routing(r300ContextPtr r300, GLcontext *ctx, GLboolean immediate)
153 {
154 int i, count=0,reg=0;
155 GLuint dw, mask;
156 TNLcontext *tnl = TNL_CONTEXT(ctx);
157 struct vertex_buffer *VB = &tnl->vb;
158
159
160 /* Stage 1 - input to VAP */
161
162 /* Assign register number automatically, retaining it in rmesa->state.reg */
163
164 /* Note: immediate vertex data includes all coordinates.
165 To save bandwidth use either VBUF or state-based vertex generation */
166
167 #define CONFIGURE_AOS(v, o, r, f) \
168 {\
169 if(immediate){ \
170 r300->state.aos[count].element_size=4; \
171 r300->state.aos[count].stride=4; \
172 r300->state.aos[count].ncomponents=4; \
173 } else { \
174 r300->state.aos[count].element_size=v->size; \
175 r300->state.aos[count].stride=v->size; \
176 r300->state.aos[count].ncomponents=v->size; \
177 } \
178 r300->state.aos[count].offset=o; \
179 r300->state.aos[count].reg=reg; \
180 r300->state.aos[count].format=(f); \
181 r300->state.vap_reg.r=reg; \
182 count++; \
183 reg++; \
184 }
185
186 /* All offsets are 0 - for use by immediate mode.
187 Should change later to handle vertex buffers */
188 CONFIGURE_AOS(VB->ObjPtr, 0, i_coords, AOS_FORMAT_FLOAT);
189 CONFIGURE_AOS(VB->ColorPtr[0], 0, i_color[0], AOS_FORMAT_FLOAT_COLOR);
190 for(i=0;i < ctx->Const.MaxTextureUnits;i++)
191 if(ctx->Texture.Unit[i].Enabled)
192 CONFIGURE_AOS(VB->TexCoordPtr[i], 0, i_tex[i], AOS_FORMAT_FLOAT);
193
194 r300->state.aos_count=count;
195
196 if(count>R300_MAX_AOS_ARRAYS){
197 fprintf(stderr, "Aieee ! AOS array count exceeded !\n");
198 exit(-1);
199 }
200
201 /* Implement AOS */
202
203
204 /* setup INPUT_ROUTE */
205
206 R300_STATECHANGE(r300, vir[0]);
207 for(i=0;i+1<count;i+=2){
208 dw=(r300->state.aos[i].ncomponents-1)
209 | ((r300->state.aos[i].reg)<<8)
210 | (r300->state.aos[i].format<<14)
211 | (((r300->state.aos[i+1].ncomponents-1)
212 | ((r300->state.aos[i+1].reg)<<8)
213 | (r300->state.aos[i+1].format<<14))<<16);
214
215 if(i+2==count){
216 dw|=(1<<(13+16));
217 }
218 r300->hw.vir[0].cmd[R300_VIR_CNTL_0+(i>>1)]=dw;
219 }
220 if(count & 1){
221 dw=(r300->state.aos[count-1].ncomponents-1)
222 | (r300->state.aos[count-1].format<<14)
223 | ((r300->state.aos[count-1].reg)<<8)
224 | (1<<13);
225 r300->hw.vir[0].cmd[R300_VIR_CNTL_0+(count>>1)]=dw;
226 }
227 /* Set the rest of INPUT_ROUTE_0 to 0 */
228 for(i=((count+1)>>1); i<8; i++)r300->hw.vir[0].cmd[R300_VIR_CNTL_0+i]=(0x0);
229
230 /* Mesa assumes that all missing components are from (0, 0, 0, 1) */
231 #define ALL_COMPONENTS ((R300_INPUT_ROUTE_SELECT_X<<R300_INPUT_ROUTE_X_SHIFT) \
232 | (R300_INPUT_ROUTE_SELECT_Y<<R300_INPUT_ROUTE_Y_SHIFT) \
233 | (R300_INPUT_ROUTE_SELECT_Z<<R300_INPUT_ROUTE_Z_SHIFT) \
234 | (R300_INPUT_ROUTE_SELECT_W<<R300_INPUT_ROUTE_W_SHIFT))
235
236 #define ALL_DEFAULT ((R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_X_SHIFT) \
237 | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Y_SHIFT) \
238 | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Z_SHIFT) \
239 | (R300_INPUT_ROUTE_SELECT_ONE<<R300_INPUT_ROUTE_W_SHIFT))
240
241 R300_STATECHANGE(r300, vir[1]);
242
243 for(i=0;i+1<count;i+=2){
244 /* do i first.. */
245 mask=(1<<(r300->state.aos[i].ncomponents*3))-1;
246 dw=(ALL_COMPONENTS & mask)
247 | (ALL_DEFAULT & ~mask)
248 | R300_INPUT_ROUTE_ENABLE;
249
250 /* i+1 */
251 mask=(1<<(r300->state.aos[i+1].ncomponents*3))-1;
252 dw|=(
253 (ALL_COMPONENTS & mask)
254 | (ALL_DEFAULT & ~mask)
255 | R300_INPUT_ROUTE_ENABLE
256 )<<16;
257
258 r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(i>>1)]=dw;
259 }
260 if(count & 1){
261 mask=(1<<(r300->state.aos[count-1].ncomponents*3))-1;
262 dw=(ALL_COMPONENTS & mask)
263 | (ALL_DEFAULT & ~mask)
264 | R300_INPUT_ROUTE_ENABLE;
265 r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(count>>1)]=dw;
266 }
267 /* Set the rest of INPUT_ROUTE_1 to 0 */
268 for(i=((count+1)>>1); i<8; i++)r300->hw.vir[1].cmd[R300_VIR_CNTL_0+i]=(0x0);
269
270 /* Set up input_cntl */
271
272 R300_STATECHANGE(r300, vic);
273 r300->hw.vic.cmd[R300_VIC_CNTL_0]=0x5555; /* Hard coded value, no idea what it means */
274
275 r300->hw.vic.cmd[R300_VIC_CNTL_1]=R300_INPUT_CNTL_POS
276 | R300_INPUT_CNTL_COLOR;
277
278 for(i=0;i < ctx->Const.MaxTextureUnits;i++)
279 if(ctx->Texture.Unit[i].Enabled)
280 r300->hw.vic.cmd[R300_VIC_CNTL_1]|=(R300_INPUT_CNTL_TC0<<i);
281
282 /* Stage 3: VAP output */
283 R300_STATECHANGE(r300, vof);
284 r300->hw.vof.cmd[R300_VOF_CNTL_0]=R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT
285 | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT;
286
287 r300->hw.vof.cmd[R300_VOF_CNTL_1]=0;
288 for(i=0;i < ctx->Const.MaxTextureUnits;i++)
289 if(ctx->Texture.Unit[i].Enabled)
290 r300->hw.vof.cmd[R300_VOF_CNTL_1]|=(4<<(3*i));
291 }
292
293 static inline void r300_setup_textures(r300ContextPtr r300, GLcontext *ctx)
294 {
295 int i;
296 struct r300_tex_obj *t;
297
298 R300_STATECHANGE(r300, txe);
299 R300_STATECHANGE(r300, tex.filter);
300 R300_STATECHANGE(r300, tex.unknown1);
301 R300_STATECHANGE(r300, tex.size);
302 R300_STATECHANGE(r300, tex.format);
303 R300_STATECHANGE(r300, tex.offset);
304 R300_STATECHANGE(r300, tex.unknown4);
305 R300_STATECHANGE(r300, tex.unknown5);
306
307 r300->hw.txe.cmd[R300_TXE_ENABLE]=0x0;
308
309 for(i=0;i<R300_MAX_TEXTURE_UNITS;i++){
310 if((t=r300->state.texture.unit[i].texobj)!=NULL){
311 r300->hw.txe.cmd[R300_TXE_ENABLE]|=(1<<i);
312
313 r300->hw.tex.filter.cmd[R300_TEX_CMD_0+i]=t->filter;
314 r300->hw.tex.unknown1.cmd[R300_TEX_CMD_0+i]=t->pitch;
315 r300->hw.tex.size.cmd[R300_TEX_CMD_0+i]=t->size;
316 r300->hw.tex.format.cmd[R300_TEX_CMD_0+i]=t->format;
317 r300->hw.tex.offset.cmd[R300_TEX_CMD_0+i]=r300->radeon.radeonScreen->fbLocation+t->offset;
318 r300->hw.tex.unknown4.cmd[R300_TEX_CMD_0+i]=0x0;
319 r300->hw.tex.unknown5.cmd[R300_TEX_CMD_0+i]=0x0;
320
321 /* We don't know how to set this yet */
322 r300->hw.tex.format.cmd[R300_TEX_CMD_0+i]=0x88a0c;
323 }
324 }
325 }
326
327 /* Immediate implementation - vertex data is sent via command stream */
328
329 static GLfloat default_vector[4]={0.0, 0.0, 0.0, 1.0};
330
331 #define output_vector(v, i) \
332 { \
333 int _i; \
334 for(_i=0;_i<v->size;_i++){ \
335 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
336 } \
337 for(_i=v->size;_i<4;_i++){ \
338 efloat(default_vector[_i]); \
339 } \
340 }
341
342 static void r300_render_flat_primitive(r300ContextPtr rmesa,
343 GLcontext *ctx,
344 int start,
345 int end,
346 int prim)
347 {
348 TNLcontext *tnl = TNL_CONTEXT(ctx);
349 struct vertex_buffer *VB = &tnl->vb;
350 GLuint i;
351 int k, type;
352 LOCAL_VARS
353
354 type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
355
356 if(type<0)return;
357
358
359 start_immediate_packet(end-start, type, 8);
360
361 for(i=start;i<end;i++){
362 #if 0
363 fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n",
364 VEC_ELT(VB->ObjPtr, GLfloat, i)[0],
365 VEC_ELT(VB->ObjPtr, GLfloat, i)[1],
366 VEC_ELT(VB->ObjPtr, GLfloat, i)[2],
367 VEC_ELT(VB->ObjPtr, GLfloat, i)[3],
368
369 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0],
370 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1],
371 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2],
372 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]
373 );
374 #endif
375
376
377 /* coordinates */
378 output_vector(VB->ObjPtr, i);
379
380 /* color components */
381 output_vector(VB->ColorPtr[0], i);
382 }
383
384 }
385
386 static void assign_pipeline(r300ContextPtr rmesa, R300_PIPELINE *p)
387 {
388 /* Watch out ! This is buggy .. but will do for now */
389
390 /* At least one sanity check is in order */
391 if(sizeof(rmesa->state.vertex_shader) != sizeof(p->vertex_shader)){
392 fprintf(stderr, "Aieee ! vertex_shader sizes don't match.\n");
393 exit(-1);
394 }
395 if(sizeof(rmesa->state.pixel_shader) != sizeof(p->pixel_shader)){
396 fprintf(stderr, "Aieee ! vertex_shader sizes don't match.\n");
397 exit(-1);
398 }
399
400 memcpy(&rmesa->state.vertex_shader, &(p->vertex_shader), sizeof(rmesa->state.vertex_shader));
401 memcpy(&rmesa->state.pixel_shader, &(p->pixel_shader), sizeof(rmesa->state.pixel_shader));
402
403 }
404
405 static GLboolean r300_run_flat_render(GLcontext *ctx,
406 struct tnl_pipeline_stage *stage)
407 {
408 r300ContextPtr rmesa = R300_CONTEXT(ctx);
409 TNLcontext *tnl = TNL_CONTEXT(ctx);
410 struct vertex_buffer *VB = &tnl->vb;
411 GLuint i;
412 LOCAL_VARS
413
414 /* Flush state - make sure command buffer is nice and large */
415 r300Flush(ctx);
416
417 if (RADEON_DEBUG == DEBUG_PRIMS)
418 fprintf(stderr, "%s\n", __FUNCTION__);
419
420 /* needed before starting 3d operation .. */
421 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
422 e32(0x0000000a);
423
424 reg_start(0x4f18,0);
425 e32(0x00000003);
426
427 rmesa->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA
428 | R300_VPORT_X_OFFSET_ENA
429 | R300_VPORT_Y_SCALE_ENA
430 | R300_VPORT_Y_OFFSET_ENA
431 | R300_VTX_W0_FMT;
432 R300_STATECHANGE(rmesa, vte);
433
434 r300_setup_routing(rmesa, ctx, GL_TRUE);
435 r300_setup_textures(rmesa, ctx);
436
437 r300EmitState(rmesa);
438
439 assign_pipeline(rmesa, &FLAT_COLOR_PIPELINE);
440
441 rmesa->state.vertex_shader.matrix[0].length=16;
442 memcpy(rmesa->state.vertex_shader.matrix[0].body.f, ctx->_ModelProjectMatrix.m, 16*4);
443
444 rmesa->state.vertex_shader.unknown2.length=4;
445 rmesa->state.vertex_shader.unknown2.body.f[0]=0.0;
446 rmesa->state.vertex_shader.unknown2.body.f[1]=0.0;
447 rmesa->state.vertex_shader.unknown2.body.f[2]=1.0;
448 rmesa->state.vertex_shader.unknown2.body.f[3]=0.0;
449
450 r300EmitVertexShader(rmesa);
451 r300EmitPixelShader(rmesa);
452
453 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
454 r300EmitLOAD_VBPNTR(rmesa, 0);
455
456 for(i=0; i < VB->PrimitiveCount; i++){
457 GLuint prim = VB->Primitive[i].mode;
458 GLuint start = VB->Primitive[i].start;
459 GLuint length = VB->Primitive[i].count;
460 r300_render_flat_primitive(rmesa, ctx, start, start + length, prim);
461 }
462
463 /* This sequence is required after any 3d drawing packet
464 I suspect it work arounds a bug (or deficiency) in hardware */
465 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
466 e32(0x0000000a);
467
468 reg_start(0x4f18,0);
469 e32(0x00000003);
470
471 return GL_FALSE;
472 }
473
474 /* vertex buffer implementation */
475
476 /* We use the start part of GART texture buffer for vertices */
477
478
479 static void upload_vertex_buffer(r300ContextPtr rmesa,
480 GLcontext *ctx, AOS_DATA *array, int *n_arrays)
481 {
482 TNLcontext *tnl = TNL_CONTEXT(ctx);
483 struct vertex_buffer *VB = &tnl->vb;
484 int offset=0, idx=0;
485 int i,j;
486 radeonScreenPtr rsp=rmesa->radeon.radeonScreen;
487 /* Not the most efficient implementation, but, for now, I just want something that
488 works */
489 /* to do - make single memcpy per column (is it possible ?) */
490 /* to do - use dirty flags to avoid redundant copies */
491 #define UPLOAD_VECTOR(v, r, f)\
492 { \
493 /* Is the data dirty ? */ \
494 if (v->flags & ((1<<v->size)-1)) { \
495 fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); \
496 if(v->size*4==v->stride){\
497 /* fast path */ \
498 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
499 } else { \
500 for(i=0;i<VB->Count;i++){ \
501 /* copy one vertex at a time*/ \
502 memcpy(rsp->gartTextures.map+offset+i*v->size*4, VEC_ELT(v, GLfloat, i), v->size*4); \
503 } \
504 } \
505 /* v->flags &= ~((1<<v->size)-1);*/ \
506 } \
507 array[idx].element_size=v->size; \
508 array[idx].stride=v->size; \
509 array[idx].format=(f); \
510 array[idx].ncomponents=v->size; \
511 array[idx].offset=rsp->gartTextures.handle+offset; \
512 array[idx].reg=r; \
513 offset+=v->size*4*VB->Count; \
514 idx++; \
515 }
516
517 UPLOAD_VECTOR(VB->ObjPtr, REG_COORDS, AOS_FORMAT_FLOAT);
518 UPLOAD_VECTOR(VB->ColorPtr[0], REG_COLOR0, AOS_FORMAT_FLOAT_COLOR);
519
520 *n_arrays=idx;
521 if(idx>=R300_MAX_AOS_ARRAYS){
522 fprintf(stderr, "Aieee ! Maximum AOS arrays count exceeded.. \n");
523 exit(-1);
524 }
525 }
526
527 static void r300_render_vb_flat_primitive(r300ContextPtr rmesa,
528 GLcontext *ctx,
529 int start,
530 int end,
531 int prim)
532 {
533 TNLcontext *tnl = TNL_CONTEXT(ctx);
534 struct vertex_buffer *VB = &tnl->vb;
535 GLuint i;
536 int k, type, n_arrays;
537 LOCAL_VARS
538
539 if(end<=start)return; /* do we need to watch for this ? */
540
541 type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
542 if(type<0)return;
543
544 fire_AOS(PASS_PREFIX end-start, type);
545 }
546
547 static VERTEX_SHADER_FRAGMENT default_vector_vsf={
548 length: 4,
549 body: {
550 f: {0.0, 0.0, 0.0, 1.0}
551 }
552 };
553
554 static GLboolean r300_run_vb_flat_render(GLcontext *ctx,
555 struct tnl_pipeline_stage *stage)
556 {
557 r300ContextPtr rmesa = R300_CONTEXT(ctx);
558 TNLcontext *tnl = TNL_CONTEXT(ctx);
559 struct vertex_buffer *VB = &tnl->vb;
560 int i, j, n_arrays;
561 AOS_DATA vb_arrays[R300_MAX_AOS_ARRAYS];
562 AOS_DATA vb_arrays2[R300_MAX_AOS_ARRAYS];
563 LOCAL_VARS
564
565 if (RADEON_DEBUG == DEBUG_PRIMS)
566 fprintf(stderr, "%s\n", __FUNCTION__);
567
568 /* setup array of structures data */
569
570 upload_vertex_buffer(rmesa, ctx, vb_arrays, &n_arrays);
571 fprintf(stderr, "Using %d AOS arrays\n", n_arrays);
572
573 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
574 e32(0x0000000a);
575
576 reg_start(0x4f18,0);
577 e32(0x00000003);
578
579 r300_setup_routing(rmesa, ctx, GL_FALSE);
580
581 r300EmitState(rmesa);
582
583 FLAT_COLOR_PIPELINE.vertex_shader.matrix[0].length=16;
584 memcpy(FLAT_COLOR_PIPELINE.vertex_shader.matrix[0].body.f, ctx->_ModelProjectMatrix.m, 16*4);
585
586 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.length=4;
587 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[0]=0.0;
588 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[1]=0.0;
589 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[2]=1.0;
590 FLAT_COLOR_PIPELINE.vertex_shader.unknown2.body.f[3]=0.0;
591
592 program_pipeline(PASS_PREFIX &FLAT_COLOR_PIPELINE);
593
594 set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0);
595 set_init21(PASS_PREFIX 0.0,1.0);
596
597 for(i=0; i < VB->PrimitiveCount; i++){
598 GLuint prim = VB->Primitive[i].mode;
599 GLuint start = VB->Primitive[i].start;
600 GLuint length = VB->Primitive[i].count;
601
602 /* copy arrays */
603 memcpy(vb_arrays2, vb_arrays, sizeof(AOS_DATA)*n_arrays);
604 for(j=0;j<n_arrays;j++){
605 vb_arrays2[j].offset+=vb_arrays2[j].stride*start*4;
606 }
607
608 setup_AOS(PASS_PREFIX vb_arrays2, n_arrays);
609
610 r300_render_vb_flat_primitive(rmesa, ctx, start, start + length, prim);
611 }
612
613 /* This sequence is required after any 3d drawing packet
614 I suspect it work arounds a bug (or deficiency) in hardware */
615
616 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
617 e32(0x0000000a);
618
619 reg_start(0x4f18,0);
620 e32(0x00000003);
621
622 end_3d(PASS_PREFIX_VOID);
623
624 /* Flush state - we are done drawing.. */
625 r300Flush(ctx);
626 fprintf(stderr, "\n");
627 return GL_FALSE;
628 }
629
630 /* Textures... */
631
632 /* Immediate implementation - vertex data is sent via command stream */
633
634 static void r300_render_tex_primitive(r300ContextPtr rmesa,
635 GLcontext *ctx,
636 int start,
637 int end,
638 int prim)
639 {
640 TNLcontext *tnl = TNL_CONTEXT(ctx);
641 struct vertex_buffer *VB = &tnl->vb;
642 GLuint i;
643 int k, type;
644 LOCAL_VARS
645
646 type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
647
648 #if 1
649 fprintf(stderr,"ObjPtr: size=%d stride=%d\n",
650 VB->ObjPtr->size, VB->ObjPtr->stride);
651 fprintf(stderr,"ColorPtr[0]: size=%d stride=%d\n",
652 VB->ColorPtr[0]->size, VB->ColorPtr[0]->stride);
653 fprintf(stderr,"TexCoordPtr[0]: size=%d stride=%d\n",
654 VB->TexCoordPtr[0]->size, VB->TexCoordPtr[0]->stride);
655 #endif
656
657 if(type<0)return;
658
659
660 start_immediate_packet(end-start, type, 12);
661
662 for(i=start;i<end;i++){
663 #if 0
664 fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n",
665 VEC_ELT(VB->ObjPtr, GLfloat, i)[0],
666 VEC_ELT(VB->ObjPtr, GLfloat, i)[1],
667 VEC_ELT(VB->ObjPtr, GLfloat, i)[2],
668 VEC_ELT(VB->ObjPtr, GLfloat, i)[3],
669
670 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0],
671 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1],
672 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2],
673 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]
674 );
675 #endif
676
677
678 /* coordinates */
679 output_vector(VB->ObjPtr, i);
680
681 /* color components */
682 output_vector(VB->ColorPtr[0], i);
683
684 /* texture coordinates */
685 output_vector(VB->TexCoordPtr[0], i);
686 }
687
688 }
689
690 static GLboolean r300_run_tex_render(GLcontext *ctx,
691 struct tnl_pipeline_stage *stage)
692 {
693 r300ContextPtr rmesa = R300_CONTEXT(ctx);
694 TNLcontext *tnl = TNL_CONTEXT(ctx);
695 struct vertex_buffer *VB = &tnl->vb;
696 GLuint i;
697 /* Only do 2d textures */
698 struct gl_texture_object *to=ctx->Texture.Unit[0].Current2D;
699 r300TexObjPtr t=to->DriverData;
700 LOCAL_VARS
701
702
703 /* Update texture state - needs to be done only when actually changed..
704 All the time for now.. */
705 r300UpdateTextureState(ctx);
706
707 r300_setup_routing(rmesa, ctx, GL_TRUE);
708 r300_setup_textures(rmesa, ctx);
709 exit(-1);
710
711 /* Flush state - make sure command buffer is nice and large */
712 r300Flush(ctx);
713
714 //fprintf(stderr, "You can enable texture drawing in %s:%s \n", __FILE__, __FUNCTION__);
715 //return GL_TRUE;
716
717
718 if (RADEON_DEBUG == DEBUG_PRIMS)
719 fprintf(stderr, "%s\n", __FUNCTION__);
720
721
722 /* needed before starting 3d operation .. */
723 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
724 e32(0x0000000a);
725
726 reg_start(0x4f18,0);
727 e32(0x00000003);
728
729
730 rmesa->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA
731 | R300_VPORT_X_OFFSET_ENA
732 | R300_VPORT_Y_SCALE_ENA
733 | R300_VPORT_Y_OFFSET_ENA
734 | R300_VTX_W0_FMT;
735 R300_STATECHANGE(rmesa, vte);
736
737 r300EmitState(rmesa);
738
739 SINGLE_TEXTURE_PIPELINE.vertex_shader.matrix[0].length=16;
740 memcpy(SINGLE_TEXTURE_PIPELINE.vertex_shader.matrix[0].body.f, ctx->_ModelProjectMatrix.m, 16*4);
741
742 SINGLE_TEXTURE_PIPELINE.vertex_shader.unknown2.length=4;
743 SINGLE_TEXTURE_PIPELINE.vertex_shader.unknown2.body.f[0]=0.0;
744 SINGLE_TEXTURE_PIPELINE.vertex_shader.unknown2.body.f[1]=0.0;
745 SINGLE_TEXTURE_PIPELINE.vertex_shader.unknown2.body.f[2]=1.0;
746 SINGLE_TEXTURE_PIPELINE.vertex_shader.unknown2.body.f[3]=0.0;
747
748 /* Use actual texture offset */
749
750 fprintf(stderr,"pp_border_color=%08x pp_cubic_faces=%08x format=%08x size=%08x format_x=%08x\n",
751 t->pp_border_color, t->pp_cubic_faces, t->format, t->size, t->format_x);
752
753 SINGLE_TEXTURE_PIPELINE.texture_unit[0].offset=rmesa->radeon.radeonScreen->fbLocation+t->offset;
754 #if 0
755 SINGLE_TEXTURE_PIPELINE.texture_unit[0].format=t->format;
756 #endif
757 SINGLE_TEXTURE_PIPELINE.texture_unit[0].size=t->size;
758 SINGLE_TEXTURE_PIPELINE.texture_unit[0].filter=t->filter;
759 SINGLE_TEXTURE_PIPELINE.texture_unit[0].unknown1=t->pitch; /* Unknown 1 is pitch ! */
760 SINGLE_TEXTURE_PIPELINE.texture_unit[0].filter=t->filter;
761
762
763 /* Program RS unit. This needs to be moved into R300 pipeline */
764 reg_start(R300_RS_CNTL_0,1);
765 /* R300_RS_CNTL_0(4300) */
766 e32(0x00040084);
767 /* RS_INST_COUNT(4304) */
768 e32(0x000000c0);
769
770 reg_start(R300_RS_ROUTE_0,0);
771 e32(0x00024008);
772
773 reg_start(R300_RS_INTERP_0,7);
774 /* X_MEM0_0(4310) */
775 e32(0x00d10000);
776 /* X_MEM0_1(4314) */
777 e32(0x00d10044);
778 /* X_MEM0_2(4318) */
779 e32(0x00d10084);
780 /* X_MEM0_3(431c) */
781 e32(0x00d100c4);
782 /* X_MEM0_4(4320) */
783 e32(0x00d10004);
784 /* X_MEM0_5(4324) */
785 e32(0x00d10004);
786 /* X_MEM0_6(4328) */
787 e32(0x00d10004);
788 /* X_MEM0_7(432c) */
789 e32(0x00d10004);
790
791 reg_start(R300_RS_CNTL_0,0);
792 e32(0x00040084);
793
794 /* Magic register - note it is right after 20b0 */
795
796 reg_start(0x20b4,0);
797 e32(0x0000000c);
798
799 program_pipeline(PASS_PREFIX &SINGLE_TEXTURE_PIPELINE);
800
801 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
802 r300EmitLOAD_VBPNTR(rmesa, 0);
803
804 for(i=0; i < VB->PrimitiveCount; i++){
805 GLuint prim = VB->Primitive[i].mode;
806 GLuint start = VB->Primitive[i].start;
807 GLuint length = VB->Primitive[i].count;
808 r300_render_tex_primitive(rmesa, ctx, start, start + length, prim);
809 }
810
811 /* This sequence is required after any 3d drawing packet
812 I suspect it work arounds a bug (or deficiency) in hardware */
813
814 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
815 e32(0x0000000a);
816
817 reg_start(0x4f18,0);
818 e32(0x00000003);
819
820 // exit(-1);
821 fprintf(stderr, "\n");
822 return GL_FALSE;
823 }
824
825
826 /**
827 * Called by the pipeline manager to render a batch of primitives.
828 * We can return true to pass on to the next stage (i.e. software
829 * rasterization) or false to indicate that the pipeline has finished
830 * after we render something.
831 */
832 static GLboolean r300_run_render(GLcontext *ctx,
833 struct tnl_pipeline_stage *stage)
834 {
835 r300ContextPtr rmesa = R300_CONTEXT(ctx);
836 TNLcontext *tnl = TNL_CONTEXT(ctx);
837 struct vertex_buffer *VB = &tnl->vb;
838 GLuint i;
839
840 if (RADEON_DEBUG == DEBUG_PRIMS)
841 fprintf(stderr, "%s\n", __FUNCTION__);
842
843
844 #if 1
845 /* Just switch between pipelines.. We could possibly do better.. (?) */
846 if(ctx->Texture.Unit[0].Enabled)
847 return r300_run_tex_render(ctx, stage);
848 else
849 return r300_run_flat_render(ctx, stage);
850 #else
851 return GL_TRUE;
852 #endif
853
854 #if 0
855 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
856 TNLcontext *tnl = TNL_CONTEXT(ctx);
857 struct vertex_buffer *VB = &tnl->vb;
858 GLuint i;
859
860 /* Don't handle clipping or indexed vertices or vertex manipulations.
861 */
862 if (mmesa->RenderIndex != 0 ||
863 !mga_validate_render( ctx, VB )) {
864 return GL_TRUE;
865 }
866
867 tnl->Driver.Render.Start( ctx );
868 mmesa->SetupNewInputs = ~0;
869
870 for (i = 0 ; i < VB->PrimitiveCount ; i++)
871 {
872 GLuint prim = VB->Primitive[i].mode;
873 GLuint start = VB->Primitive[i].start;
874 GLuint length = VB->Primitive[i].count;
875
876 if (!length)
877 continue;
878
879 mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length,
880 prim);
881 }
882
883 tnl->Driver.Render.Finish( ctx );
884
885 return GL_FALSE; /* finished the pipe */
886 #endif
887 }
888
889
890 /**
891 * Called by the pipeline manager once before rendering.
892 * We check the GL state here to
893 * a) decide whether we can do the current state in hardware and
894 * b) update hardware registers
895 */
896 #define FALLBACK_IF(expr) \
897 do { \
898 if (expr) { \
899 if (RADEON_DEBUG & DEBUG_FALLBACKS) \
900 fprintf(stderr, "%s: fallback:%s\n", \
901 __FUNCTION__, #expr); \
902 stage->active = GL_FALSE; \
903 return; \
904 } \
905 } while(0)
906
907 static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
908 {
909 r300ContextPtr r300 = R300_CONTEXT(ctx);
910 int i;
911
912 if (RADEON_DEBUG & DEBUG_STATE)
913 fprintf(stderr, "%s\n", __FUNCTION__);
914
915 /* We only support rendering in hardware for now */
916 if (ctx->RenderMode != GL_RENDER) {
917 stage->active = GL_FALSE;
918 return;
919 }
920
921 // I failed to figure out how dither works in hardware,
922 // let's just ignore it for now
923 //FALLBACK_IF(ctx->Color.DitherFlag);
924
925 /* I'm almost certain I forgot something here */
926 #if 0 /* This should work now.. */
927 FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST
928 #endif
929 FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
930 FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG
931 FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH
932 FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE
933 FALLBACK_IF(ctx->Point.SmoothFlag); // GL_POINT_SMOOTH
934 if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
935 FALLBACK_IF(ctx->Point.PointSprite); // GL_POINT_SPRITE_NV
936 FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT
937 FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE
938 FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
939 FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH
940 FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE
941 FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
942 FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB
943
944 /* One step at a time - let one texture pass.. */
945 for (i = 1; i < ctx->Const.MaxTextureUnits; i++)
946 FALLBACK_IF(ctx->Texture.Unit[i].Enabled);
947
948
949 /* let r300_run_render do its job */
950 #if 0
951 stage->active = GL_FALSE;
952 #endif
953 }
954
955
956 static void dtr(struct tnl_pipeline_stage *stage)
957 {
958 (void)stage;
959 }
960
961 const struct tnl_pipeline_stage _r300_render_stage = {
962 "r300 hw rasterize",
963 _NEW_ALL, /* re-check (always re-check for now) */
964 0, /* re-run (always runs) */
965 GL_TRUE, /* active */
966 0, 0, /* inputs (set in check_render), outputs */
967 0, 0, /* changed_inputs, private */
968 dtr, /* destructor */
969 r300_check_render, /* check */
970 r300_run_render /* run */
971 };