r300: Removed some checking in r300NumVerts that is not needed.
[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 * \file
30 *
31 * \brief R300 Render (Vertex Buffer Implementation)
32 *
33 * The immediate implementation has been removed from CVS in favor of the vertex
34 * buffer implementation.
35 *
36 * The render functions are called by the pipeline manager to render a batch of
37 * primitives. They return TRUE to pass on to the next stage (i.e. software
38 * rasterization) or FALSE to indicate that the pipeline has finished after
39 * rendering something.
40 *
41 * When falling back to software TCL still attempt to use hardware
42 * rasterization.
43 *
44 * I am not sure that the cache related registers are setup correctly, but
45 * obviously this does work... Further investigation is needed.
46 *
47 * \author Nicolai Haehnle <prefect_@gmx.net>
48 */
49
50 #include "glheader.h"
51 #include "state.h"
52 #include "imports.h"
53 #include "enums.h"
54 #include "macros.h"
55 #include "context.h"
56 #include "dd.h"
57 #include "simple_list.h"
58 #include "api_arrayelt.h"
59 #include "swrast/swrast.h"
60 #include "swrast_setup/swrast_setup.h"
61 #include "vbo/vbo.h"
62 #include "tnl/tnl.h"
63 #include "tnl/t_vp_build.h"
64 #include "radeon_reg.h"
65 #include "radeon_macros.h"
66 #include "radeon_ioctl.h"
67 #include "radeon_state.h"
68 #include "r300_context.h"
69 #include "r300_ioctl.h"
70 #include "r300_state.h"
71 #include "r300_reg.h"
72 #include "r300_tex.h"
73 #include "r300_emit.h"
74 extern int future_hw_tcl_on;
75
76 /**
77 * \brief Convert a OpenGL primitive type into a R300 primitive type.
78 */
79 static int r300PrimitiveType(r300ContextPtr rmesa, GLcontext * ctx, int prim)
80 {
81 int type = -1;
82
83 switch (prim & PRIM_MODE_MASK) {
84 case GL_POINTS:
85 type = R300_VAP_VF_CNTL__PRIM_POINTS;
86 break;
87 case GL_LINES:
88 type = R300_VAP_VF_CNTL__PRIM_LINES;
89 break;
90 case GL_LINE_STRIP:
91 type = R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
92 break;
93 case GL_LINE_LOOP:
94 type = R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
95 break;
96 case GL_TRIANGLES:
97 type = R300_VAP_VF_CNTL__PRIM_TRIANGLES;
98 break;
99 case GL_TRIANGLE_STRIP:
100 type = R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
101 break;
102 case GL_TRIANGLE_FAN:
103 type = R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
104 break;
105 case GL_QUADS:
106 type = R300_VAP_VF_CNTL__PRIM_QUADS;
107 break;
108 case GL_QUAD_STRIP:
109 type = R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
110 break;
111 case GL_POLYGON:
112 type = R300_VAP_VF_CNTL__PRIM_POLYGON;
113 break;
114 default:
115 fprintf(stderr,
116 "%s:%s Do not know how to handle primitive 0x%04x - help me !\n",
117 __FILE__, __FUNCTION__, prim & PRIM_MODE_MASK);
118 return -1;
119 break;
120 }
121 return type;
122 }
123
124 static int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim)
125 {
126 int verts_off = 0;
127
128 switch (prim & PRIM_MODE_MASK) {
129 case GL_POINTS:
130 verts_off = 0;
131 break;
132 case GL_LINES:
133 verts_off = num_verts % 2;
134 break;
135 case GL_LINE_STRIP:
136 if (num_verts < 2)
137 verts_off = num_verts;
138 break;
139 case GL_LINE_LOOP:
140 if (num_verts < 2)
141 verts_off = num_verts;
142 break;
143 case GL_TRIANGLES:
144 verts_off = num_verts % 3;
145 break;
146 case GL_TRIANGLE_STRIP:
147 if (num_verts < 3)
148 verts_off = num_verts;
149 break;
150 case GL_TRIANGLE_FAN:
151 if (num_verts < 3)
152 verts_off = num_verts;
153 break;
154 case GL_QUADS:
155 verts_off = num_verts % 4;
156 break;
157 case GL_QUAD_STRIP:
158 if (num_verts < 4)
159 verts_off = num_verts;
160 else
161 verts_off = num_verts % 2;
162 break;
163 case GL_POLYGON:
164 if (num_verts < 3)
165 verts_off = num_verts;
166 break;
167 default:
168 fprintf(stderr,
169 "%s:%s Do not know how to handle primitive 0x%04x - help me !\n",
170 __FILE__, __FUNCTION__, prim & PRIM_MODE_MASK);
171 return -1;
172 break;
173 }
174
175 return num_verts - verts_off;
176 }
177
178 static void r300FireEB(r300ContextPtr rmesa, unsigned long addr,
179 int vertex_count, int type, int elt_size)
180 {
181 int cmd_reserved = 0;
182 int cmd_written = 0;
183 drm_radeon_cmd_header_t *cmd = NULL;
184 unsigned long t_addr;
185 unsigned long magic_1, magic_2;
186
187 assert(elt_size == 2 || elt_size == 4);
188
189 if (addr & (elt_size - 1)) {
190 WARN_ONCE("Badly aligned buffer\n");
191 return;
192 }
193
194 magic_1 = (addr % 32) / 4;
195 t_addr = addr & ~0x1d;
196 magic_2 = (vertex_count + 1 + (t_addr & 0x2)) / 2 + magic_1;
197
198 start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2, 0);
199 if (elt_size == 4) {
200 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
201 (vertex_count << 16) | type |
202 R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
203 } else {
204 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
205 (vertex_count << 16) | type);
206 }
207
208 start_packet3(RADEON_CP_PACKET3_INDX_BUFFER, 2);
209 #ifdef OPTIMIZE_ELTS
210 if (elt_size == 4) {
211 e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
212 e32(addr);
213 } else {
214 e32(R300_EB_UNK1 | (magic_1 << 16) | R300_EB_UNK2);
215 e32(t_addr);
216 }
217 #else
218 e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
219 e32(addr);
220 #endif
221
222 if (elt_size == 4) {
223 e32(vertex_count);
224 } else {
225 #ifdef OPTIMIZE_ELTS
226 e32(magic_2);
227 #else
228 e32((vertex_count + 1) / 2);
229 #endif
230 }
231 }
232
233 static void r300EmitElts(GLcontext * ctx, void *elts, unsigned long n_elts,
234 int elt_size)
235 {
236 r300ContextPtr rmesa = R300_CONTEXT(ctx);
237 struct r300_dma_region *rvb = &rmesa->state.elt_dma;
238 void *out;
239
240 assert(elt_size == 2 || elt_size == 4);
241
242 if (r300IsGartMemory(rmesa, elts, n_elts * elt_size)) {
243 rvb->address = rmesa->radeon.radeonScreen->gartTextures.map;
244 rvb->start = ((char *)elts) - rvb->address;
245 rvb->aos_offset =
246 rmesa->radeon.radeonScreen->gart_texture_offset +
247 rvb->start;
248 return;
249 } else if (r300IsGartMemory(rmesa, elts, 1)) {
250 WARN_ONCE("Pointer not within GART memory!\n");
251 _mesa_exit(-1);
252 }
253
254 r300AllocDmaRegion(rmesa, rvb, n_elts * elt_size, elt_size);
255 rvb->aos_offset = GET_START(rvb);
256
257 out = rvb->address + rvb->start;
258 memcpy(out, elts, n_elts * elt_size);
259 }
260
261
262 static void r300EmitAOS(r300ContextPtr rmesa, GLuint nr, GLuint offset)
263 {
264 int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
265 int i;
266 int cmd_reserved = 0;
267 int cmd_written = 0;
268 drm_radeon_cmd_header_t *cmd = NULL;
269
270 if (RADEON_DEBUG & DEBUG_VERTS)
271 fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __func__, nr,
272 offset);
273
274 start_packet3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, sz - 1);
275 e32(nr);
276 for (i = 0; i + 1 < nr; i += 2) {
277 e32((rmesa->state.aos[i].aos_size << 0)
278 | (rmesa->state.aos[i].aos_stride << 8)
279 | (rmesa->state.aos[i + 1].aos_size << 16)
280 | (rmesa->state.aos[i + 1].aos_stride << 24)
281 );
282 e32(rmesa->state.aos[i].aos_offset +
283 offset * 4 * rmesa->state.aos[i].aos_stride);
284 e32(rmesa->state.aos[i + 1].aos_offset +
285 offset * 4 * rmesa->state.aos[i + 1].aos_stride);
286 }
287
288 if (nr & 1) {
289 e32((rmesa->state.aos[nr - 1].aos_size << 0)
290 | (rmesa->state.aos[nr - 1].aos_stride << 8)
291 );
292 e32(rmesa->state.aos[nr - 1].aos_offset +
293 offset * 4 * rmesa->state.aos[nr - 1].aos_stride);
294 }
295 }
296
297 static void r300FireAOS(r300ContextPtr rmesa, int vertex_count, int type)
298 {
299 int cmd_reserved = 0;
300 int cmd_written = 0;
301 drm_radeon_cmd_header_t *cmd = NULL;
302
303 start_packet3(RADEON_CP_PACKET3_3D_DRAW_VBUF_2, 0);
304 e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (vertex_count << 16)
305 | type);
306 }
307
308 static void r300RunRenderPrimitive(r300ContextPtr rmesa, GLcontext * ctx,
309 int start, int end, int prim)
310 {
311 int type, num_verts;
312
313 type = r300PrimitiveType(rmesa, ctx, prim);
314 num_verts = r300NumVerts(rmesa, end - start, prim);
315
316 if (type < 0 || num_verts <= 0)
317 return;
318
319 if (rmesa->state.VB.Elts) {
320 r300EmitAOS(rmesa, rmesa->state.aos_count, start);
321 if (num_verts > 65535) {
322 /* not implemented yet */
323 WARN_ONCE("Too many elts\n");
324 return;
325 }
326 r300EmitElts(ctx, rmesa->state.VB.Elts, num_verts,
327 rmesa->state.VB.elt_size);
328 r300FireEB(rmesa, rmesa->state.elt_dma.aos_offset,
329 num_verts, type, rmesa->state.VB.elt_size);
330 } else {
331 r300EmitAOS(rmesa, rmesa->state.aos_count, start);
332 r300FireAOS(rmesa, num_verts, type);
333 }
334 }
335
336 #define CONV_VB(a, b) rvb->AttribPtr[(a)].size = vb->b->size, \
337 rvb->AttribPtr[(a)].type = GL_FLOAT, \
338 rvb->AttribPtr[(a)].stride = vb->b->stride, \
339 rvb->AttribPtr[(a)].data = vb->b->data
340
341 static void radeon_vb_to_rvb(r300ContextPtr rmesa,
342 struct radeon_vertex_buffer *rvb,
343 struct vertex_buffer *vb)
344 {
345 int i;
346 GLcontext *ctx;
347 ctx = rmesa->radeon.glCtx;
348
349 memset(rvb, 0, sizeof(*rvb));
350
351 rvb->Elts = vb->Elts;
352 rvb->elt_size = 4;
353 rvb->elt_min = 0;
354 rvb->elt_max = vb->Count;
355
356 rvb->Count = vb->Count;
357
358 if (hw_tcl_on) {
359 CONV_VB(VERT_ATTRIB_POS, ObjPtr);
360 } else {
361 assert(vb->ClipPtr);
362 CONV_VB(VERT_ATTRIB_POS, ClipPtr);
363 }
364
365 CONV_VB(VERT_ATTRIB_NORMAL, NormalPtr);
366 CONV_VB(VERT_ATTRIB_COLOR0, ColorPtr[0]);
367 CONV_VB(VERT_ATTRIB_COLOR1, SecondaryColorPtr[0]);
368 CONV_VB(VERT_ATTRIB_FOG, FogCoordPtr);
369
370 for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
371 CONV_VB(VERT_ATTRIB_TEX0 + i, TexCoordPtr[i]);
372
373 for (i = 0; i < MAX_VERTEX_PROGRAM_ATTRIBS; i++)
374 CONV_VB(VERT_ATTRIB_GENERIC0 + i,
375 AttribPtr[VERT_ATTRIB_GENERIC0 + i]);
376
377 rvb->Primitive = vb->Primitive;
378 rvb->PrimitiveCount = vb->PrimitiveCount;
379 rvb->LockFirst = rvb->LockCount = 0;
380 rvb->lock_uptodate = GL_FALSE;
381 }
382
383 static GLboolean r300RunRender(GLcontext * ctx,
384 struct tnl_pipeline_stage *stage)
385 {
386 r300ContextPtr rmesa = R300_CONTEXT(ctx);
387 struct radeon_vertex_buffer *VB = &rmesa->state.VB;
388 int i;
389 int cmd_reserved = 0;
390 int cmd_written = 0;
391 drm_radeon_cmd_header_t *cmd = NULL;
392
393 if (RADEON_DEBUG & DEBUG_PRIMS)
394 fprintf(stderr, "%s\n", __FUNCTION__);
395
396 if (stage) {
397 TNLcontext *tnl = TNL_CONTEXT(ctx);
398 radeon_vb_to_rvb(rmesa, VB, &tnl->vb);
399 }
400
401 r300UpdateShaders(rmesa);
402 if (r300EmitArrays(ctx))
403 return GL_TRUE;
404
405 r300UpdateShaderStates(rmesa);
406
407 reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
408 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);
409
410 reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0);
411 e32(R300_RB3D_ZCACHE_UNKNOWN_03);
412
413 r300EmitState(rmesa);
414
415 for (i = 0; i < VB->PrimitiveCount; i++) {
416 GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
417 GLuint start = VB->Primitive[i].start;
418 GLuint end = VB->Primitive[i].start + VB->Primitive[i].count;
419 r300RunRenderPrimitive(rmesa, ctx, start, end, prim);
420 }
421
422 reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
423 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);
424
425 reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0);
426 e32(R300_RB3D_ZCACHE_UNKNOWN_03);
427
428 #ifdef USER_BUFFERS
429 r300UseArrays(ctx);
430 #endif
431
432 r300ReleaseArrays(ctx);
433
434 return GL_FALSE;
435 }
436
437 #define FALLBACK_IF(expr) \
438 do { \
439 if (expr) { \
440 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
441 WARN_ONCE("Software fallback:%s\n", \
442 #expr); \
443 return R300_FALLBACK_RAST; \
444 } \
445 } while(0)
446
447 static int r300Fallback(GLcontext * ctx)
448 {
449 r300ContextPtr r300 = R300_CONTEXT(ctx);
450 struct r300_fragment_program *fp = (struct r300_fragment_program *)
451 (char *)ctx->FragmentProgram._Current;
452
453 if (fp) {
454 if (!fp->translated)
455 r300TranslateFragmentShader(r300, fp);
456 FALLBACK_IF(!fp->translated);
457 }
458
459 FALLBACK_IF(ctx->RenderMode != GL_RENDER);
460
461 FALLBACK_IF(ctx->Stencil._TestTwoSide
462 && (ctx->Stencil.Ref[0] != ctx->Stencil.Ref[1]
463 || ctx->Stencil.ValueMask[0] !=
464 ctx->Stencil.ValueMask[1]
465 || ctx->Stencil.WriteMask[0] !=
466 ctx->Stencil.WriteMask[1]));
467
468 FALLBACK_IF(ctx->Color.ColorLogicOpEnabled);
469
470 if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
471 FALLBACK_IF(ctx->Point.PointSprite);
472
473 if (!r300->disable_lowimpact_fallback) {
474 FALLBACK_IF(ctx->Polygon.OffsetPoint);
475 FALLBACK_IF(ctx->Polygon.OffsetLine);
476 FALLBACK_IF(ctx->Polygon.StippleFlag);
477 FALLBACK_IF(ctx->Multisample.Enabled);
478 FALLBACK_IF(ctx->Line.StippleFlag);
479 FALLBACK_IF(ctx->Line.SmoothFlag);
480 FALLBACK_IF(ctx->Point.SmoothFlag);
481 }
482
483 return R300_FALLBACK_NONE;
484 }
485
486 static GLboolean r300RunNonTCLRender(GLcontext * ctx,
487 struct tnl_pipeline_stage *stage)
488 {
489 if (RADEON_DEBUG & DEBUG_PRIMS)
490 fprintf(stderr, "%s\n", __FUNCTION__);
491
492 if (r300Fallback(ctx) >= R300_FALLBACK_RAST)
493 return GL_TRUE;
494
495 return r300RunRender(ctx, stage);
496 }
497
498 static GLboolean r300RunTCLRender(GLcontext * ctx,
499 struct tnl_pipeline_stage *stage)
500 {
501 r300ContextPtr rmesa = R300_CONTEXT(ctx);
502 struct r300_vertex_program *vp;
503
504 hw_tcl_on = future_hw_tcl_on;
505
506 if (RADEON_DEBUG & DEBUG_PRIMS)
507 fprintf(stderr, "%s\n", __FUNCTION__);
508
509 if (hw_tcl_on == GL_FALSE)
510 return GL_TRUE;
511
512 if (r300Fallback(ctx) >= R300_FALLBACK_TCL) {
513 hw_tcl_on = GL_FALSE;
514 return GL_TRUE;
515 }
516
517 r300UpdateShaders(rmesa);
518
519 vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
520 if (vp->native == GL_FALSE) {
521 hw_tcl_on = GL_FALSE;
522 return GL_TRUE;
523 }
524
525 return r300RunRender(ctx, stage);
526 }
527
528 const struct tnl_pipeline_stage _r300_render_stage = {
529 "r300 Hardware Rasterization",
530 NULL,
531 NULL,
532 NULL,
533 NULL,
534 r300RunNonTCLRender
535 };
536
537 const struct tnl_pipeline_stage _r300_tcl_stage = {
538 "r300 Hardware Transform, Clipping and Lighting",
539 NULL,
540 NULL,
541 NULL,
542 NULL,
543 r300RunTCLRender
544 };