Merge branch 'mesa_7_7_branch'
[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 * \todo Add immediate implementation back? Perhaps this is useful if there are
50 * no bugs...
51 */
52
53 #include "r300_render.h"
54
55 #include "main/glheader.h"
56 #include "main/state.h"
57 #include "main/imports.h"
58 #include "main/enums.h"
59 #include "main/macros.h"
60 #include "main/context.h"
61 #include "main/dd.h"
62 #include "main/simple_list.h"
63 #include "main/api_arrayelt.h"
64 #include "swrast/swrast.h"
65 #include "swrast_setup/swrast_setup.h"
66 #include "vbo/vbo.h"
67 #include "vbo/vbo_split.h"
68 #include "tnl/tnl.h"
69 #include "tnl/t_vp_build.h"
70 #include "r300_context.h"
71 #include "r300_state.h"
72 #include "r300_reg.h"
73 #include "r300_tex.h"
74 #include "r300_emit.h"
75 #include "r300_fragprog_common.h"
76 #include "r300_swtcl.h"
77
78 /**
79 * \brief Convert a OpenGL primitive type into a R300 primitive type.
80 */
81 int r300PrimitiveType(r300ContextPtr rmesa, int prim)
82 {
83 switch (prim & PRIM_MODE_MASK) {
84 case GL_POINTS:
85 return R300_VAP_VF_CNTL__PRIM_POINTS;
86 break;
87 case GL_LINES:
88 return R300_VAP_VF_CNTL__PRIM_LINES;
89 break;
90 case GL_LINE_STRIP:
91 return R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
92 break;
93 case GL_LINE_LOOP:
94 return R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
95 break;
96 case GL_TRIANGLES:
97 return R300_VAP_VF_CNTL__PRIM_TRIANGLES;
98 break;
99 case GL_TRIANGLE_STRIP:
100 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
101 break;
102 case GL_TRIANGLE_FAN:
103 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
104 break;
105 case GL_QUADS:
106 return R300_VAP_VF_CNTL__PRIM_QUADS;
107 break;
108 case GL_QUAD_STRIP:
109 return R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
110 break;
111 case GL_POLYGON:
112 return R300_VAP_VF_CNTL__PRIM_POLYGON;
113 break;
114 default:
115 assert(0);
116 return -1;
117 break;
118 }
119 }
120
121 int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim)
122 {
123 int verts_off = 0;
124
125 switch (prim & PRIM_MODE_MASK) {
126 case GL_POINTS:
127 verts_off = 0;
128 break;
129 case GL_LINES:
130 verts_off = num_verts % 2;
131 break;
132 case GL_LINE_STRIP:
133 if (num_verts < 2)
134 verts_off = num_verts;
135 break;
136 case GL_LINE_LOOP:
137 if (num_verts < 2)
138 verts_off = num_verts;
139 break;
140 case GL_TRIANGLES:
141 verts_off = num_verts % 3;
142 break;
143 case GL_TRIANGLE_STRIP:
144 if (num_verts < 3)
145 verts_off = num_verts;
146 break;
147 case GL_TRIANGLE_FAN:
148 if (num_verts < 3)
149 verts_off = num_verts;
150 break;
151 case GL_QUADS:
152 verts_off = num_verts % 4;
153 break;
154 case GL_QUAD_STRIP:
155 if (num_verts < 4)
156 verts_off = num_verts;
157 else
158 verts_off = num_verts % 2;
159 break;
160 case GL_POLYGON:
161 if (num_verts < 3)
162 verts_off = num_verts;
163 break;
164 default:
165 assert(0);
166 return -1;
167 break;
168 }
169
170 return num_verts - verts_off;
171 }
172
173 static void r300FireEB(r300ContextPtr rmesa, int vertex_count, int type, int offset)
174 {
175 BATCH_LOCALS(&rmesa->radeon);
176 int size;
177
178 /* offset is in indices */
179 BEGIN_BATCH(10);
180 OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_INDX_2, 0);
181 if (rmesa->ind_buf.is_32bit) {
182 /* convert to bytes */
183 offset *= 4;
184 size = vertex_count;
185 OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
186 (vertex_count << 16) | type |
187 R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
188 } else {
189 /* convert to bytes */
190 offset *= 2;
191 size = (vertex_count + 1) >> 1;
192 OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_INDICES |
193 (vertex_count << 16) | type);
194 }
195
196 if (!rmesa->radeon.radeonScreen->kernel_mm) {
197 OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER, 2);
198 OUT_BATCH(R300_INDX_BUFFER_ONE_REG_WR | (0 << R300_INDX_BUFFER_SKIP_SHIFT) |
199 (R300_VAP_PORT_IDX0 >> 2));
200 OUT_BATCH_RELOC(0, rmesa->ind_buf.bo, rmesa->ind_buf.bo_offset + offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
201 OUT_BATCH(size);
202 } else {
203 OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER, 2);
204 OUT_BATCH(R300_INDX_BUFFER_ONE_REG_WR | (0 << R300_INDX_BUFFER_SKIP_SHIFT) |
205 (R300_VAP_PORT_IDX0 >> 2));
206 OUT_BATCH(rmesa->ind_buf.bo_offset + offset);
207 OUT_BATCH(size);
208 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
209 rmesa->ind_buf.bo, RADEON_GEM_DOMAIN_GTT, 0, 0);
210 }
211 END_BATCH();
212 }
213
214 static void r300EmitAOS(r300ContextPtr rmesa, GLuint nr, GLuint offset)
215 {
216 BATCH_LOCALS(&rmesa->radeon);
217 uint32_t voffset;
218 int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
219 int i;
220
221 if (RADEON_DEBUG & RADEON_VERTS)
222 fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__, nr,
223 offset);
224
225 if (!rmesa->radeon.radeonScreen->kernel_mm) {
226 BEGIN_BATCH(sz+2+(nr * 2));
227 OUT_BATCH_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1);
228 OUT_BATCH(nr);
229
230 for (i = 0; i + 1 < nr; i += 2) {
231 OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
232 (rmesa->radeon.tcl.aos[i].stride << 8) |
233 (rmesa->radeon.tcl.aos[i + 1].components << 16) |
234 (rmesa->radeon.tcl.aos[i + 1].stride << 24));
235
236 voffset = rmesa->radeon.tcl.aos[i + 0].offset +
237 offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
238 OUT_BATCH_RELOC(voffset,
239 rmesa->radeon.tcl.aos[i].bo,
240 voffset,
241 RADEON_GEM_DOMAIN_GTT,
242 0, 0);
243 voffset = rmesa->radeon.tcl.aos[i + 1].offset +
244 offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
245 OUT_BATCH_RELOC(voffset,
246 rmesa->radeon.tcl.aos[i+1].bo,
247 voffset,
248 RADEON_GEM_DOMAIN_GTT,
249 0, 0);
250 }
251
252 if (nr & 1) {
253 OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
254 (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
255 voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
256 offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
257 OUT_BATCH_RELOC(voffset,
258 rmesa->radeon.tcl.aos[nr - 1].bo,
259 voffset,
260 RADEON_GEM_DOMAIN_GTT,
261 0, 0);
262 }
263 END_BATCH();
264 } else {
265
266 BEGIN_BATCH(sz+2+(nr * 2));
267 OUT_BATCH_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1);
268 OUT_BATCH(nr);
269
270 for (i = 0; i + 1 < nr; i += 2) {
271 OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
272 (rmesa->radeon.tcl.aos[i].stride << 8) |
273 (rmesa->radeon.tcl.aos[i + 1].components << 16) |
274 (rmesa->radeon.tcl.aos[i + 1].stride << 24));
275
276 voffset = rmesa->radeon.tcl.aos[i + 0].offset +
277 offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
278 OUT_BATCH(voffset);
279 voffset = rmesa->radeon.tcl.aos[i + 1].offset +
280 offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
281 OUT_BATCH(voffset);
282 }
283
284 if (nr & 1) {
285 OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
286 (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
287 voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
288 offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
289 OUT_BATCH(voffset);
290 }
291 for (i = 0; i + 1 < nr; i += 2) {
292 voffset = rmesa->radeon.tcl.aos[i + 0].offset +
293 offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
294 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
295 rmesa->radeon.tcl.aos[i+0].bo,
296 RADEON_GEM_DOMAIN_GTT,
297 0, 0);
298 voffset = rmesa->radeon.tcl.aos[i + 1].offset +
299 offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
300 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
301 rmesa->radeon.tcl.aos[i+1].bo,
302 RADEON_GEM_DOMAIN_GTT,
303 0, 0);
304 }
305 if (nr & 1) {
306 voffset = rmesa->radeon.tcl.aos[nr - 1].offset +
307 offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
308 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
309 rmesa->radeon.tcl.aos[nr-1].bo,
310 RADEON_GEM_DOMAIN_GTT,
311 0, 0);
312 }
313 END_BATCH();
314 }
315
316 }
317
318 static void r300FireAOS(r300ContextPtr rmesa, int vertex_count, int type)
319 {
320 BATCH_LOCALS(&rmesa->radeon);
321
322 r300_emit_scissor(rmesa->radeon.glCtx);
323 BEGIN_BATCH(3);
324 OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
325 OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (vertex_count << 16) | type);
326 END_BATCH();
327 }
328
329 void r300RunRenderPrimitive(GLcontext * ctx, int start, int end, int prim)
330 {
331 r300ContextPtr rmesa = R300_CONTEXT(ctx);
332 BATCH_LOCALS(&rmesa->radeon);
333 int type, num_verts;
334
335 type = r300PrimitiveType(rmesa, prim);
336 num_verts = r300NumVerts(rmesa, end - start, prim);
337
338 if (type < 0 || num_verts <= 0)
339 return;
340
341 if (rmesa->ind_buf.bo) {
342 GLuint first, incr, offset = 0;
343
344 if (!split_prim_inplace(prim & PRIM_MODE_MASK, &first, &incr) &&
345 num_verts > 65500) {
346 WARN_ONCE("Fixme: can't handle spliting prim %d\n", prim);
347 return;
348 }
349
350
351 r300EmitAOS(rmesa, rmesa->radeon.tcl.aos_count, 0);
352 if (rmesa->radeon.radeonScreen->kernel_mm) {
353 BEGIN_BATCH_NO_AUTOSTATE(2);
354 OUT_BATCH_REGSEQ(R300_VAP_VF_MAX_VTX_INDX, 1);
355 OUT_BATCH(rmesa->radeon.tcl.aos[0].count);
356 END_BATCH();
357 }
358
359 r300_emit_scissor(rmesa->radeon.glCtx);
360 while (num_verts > 0) {
361 int nr;
362 int align;
363
364 nr = MIN2(num_verts, 65535);
365 nr -= (nr - first) % incr;
366
367 /* get alignment for IB correct */
368 if (nr != num_verts) {
369 do {
370 align = nr * (rmesa->ind_buf.is_32bit ? 4 : 2);
371 if (align % 4)
372 nr -= incr;
373 } while(align % 4);
374 if (nr <= 0) {
375 WARN_ONCE("did the impossible happen? we never aligned nr to dword\n");
376 return;
377 }
378
379 }
380 r300FireEB(rmesa, nr, type, offset);
381
382 num_verts -= nr;
383 offset += nr;
384 }
385
386 } else {
387 GLuint first, incr, offset = 0;
388
389 if (!split_prim_inplace(prim & PRIM_MODE_MASK, &first, &incr) &&
390 num_verts > 65535) {
391 WARN_ONCE("Fixme: can't handle spliting prim %d\n", prim);
392 return;
393 }
394 r300_emit_scissor(rmesa->radeon.glCtx);
395 while (num_verts > 0) {
396 int nr;
397 nr = MIN2(num_verts, 65535);
398 nr -= (nr - first) % incr;
399 r300EmitAOS(rmesa, rmesa->radeon.tcl.aos_count, start + offset);
400 r300FireAOS(rmesa, nr, type);
401 num_verts -= nr;
402 offset += nr;
403 }
404 }
405 COMMIT_BATCH();
406 }
407
408 static const char *getFallbackString(uint32_t bit)
409 {
410 switch (bit) {
411 case R300_FALLBACK_VERTEX_PROGRAM :
412 return "vertex program";
413 case R300_FALLBACK_LINE_SMOOTH:
414 return "smooth lines";
415 case R300_FALLBACK_POINT_SMOOTH:
416 return "smooth points";
417 case R300_FALLBACK_POLYGON_SMOOTH:
418 return "smooth polygons";
419 case R300_FALLBACK_LINE_STIPPLE:
420 return "line stipple";
421 case R300_FALLBACK_POLYGON_STIPPLE:
422 return "polygon stipple";
423 case R300_FALLBACK_STENCIL_TWOSIDE:
424 return "two-sided stencil";
425 case R300_FALLBACK_RENDER_MODE:
426 return "render mode != GL_RENDER";
427 case R300_FALLBACK_FRAGMENT_PROGRAM:
428 return "fragment program";
429 case R300_FALLBACK_AOS_LIMIT:
430 return "aos limit";
431 case R300_FALLBACK_INVALID_BUFFERS:
432 return "invalid buffers";
433 default:
434 return "unknown";
435 }
436 }
437
438 void r300SwitchFallback(GLcontext *ctx, uint32_t bit, GLboolean mode)
439 {
440 TNLcontext *tnl = TNL_CONTEXT(ctx);
441 r300ContextPtr rmesa = R300_CONTEXT(ctx);
442 uint32_t old_fallback = rmesa->fallback;
443 static uint32_t fallback_warn = 0;
444
445 if (mode) {
446 if ((fallback_warn & bit) == 0) {
447 if (RADEON_DEBUG & RADEON_FALLBACKS)
448 _mesa_fprintf(stderr, "WARNING! Falling back to software for %s\n", getFallbackString(bit));
449 fallback_warn |= bit;
450 }
451 rmesa->fallback |= bit;
452
453 /* update only if we change from no tcl fallbacks to some tcl fallbacks */
454 if (rmesa->options.hw_tcl_enabled) {
455 if (((old_fallback & R300_TCL_FALLBACK_MASK) == 0) &&
456 ((bit & R300_TCL_FALLBACK_MASK) > 0)) {
457 R300_STATECHANGE(rmesa, vap_cntl_status);
458 rmesa->hw.vap_cntl_status.cmd[1] |= R300_VAP_TCL_BYPASS;
459 }
460 }
461
462 /* update only if we change from no raster fallbacks to some raster fallbacks */
463 if (((old_fallback & R300_RASTER_FALLBACK_MASK) == 0) &&
464 ((bit & R300_RASTER_FALLBACK_MASK) > 0)) {
465
466 radeon_firevertices(&rmesa->radeon);
467 rmesa->radeon.swtcl.RenderIndex = ~0;
468 _swsetup_Wakeup( ctx );
469 }
470 } else {
471 rmesa->fallback &= ~bit;
472
473 /* update only if we have disabled all tcl fallbacks */
474 if (rmesa->options.hw_tcl_enabled) {
475 if ((old_fallback & R300_TCL_FALLBACK_MASK) == bit) {
476 R300_STATECHANGE(rmesa, vap_cntl_status);
477 rmesa->hw.vap_cntl_status.cmd[1] &= ~R300_VAP_TCL_BYPASS;
478 }
479 }
480
481 /* update only if we have disabled all raster fallbacks */
482 if ((old_fallback & R300_RASTER_FALLBACK_MASK) == bit) {
483 _swrast_flush( ctx );
484
485 tnl->Driver.Render.Start = r300RenderStart;
486 tnl->Driver.Render.Finish = r300RenderFinish;
487 tnl->Driver.Render.PrimitiveNotify = r300RenderPrimitive;
488 tnl->Driver.Render.ResetLineStipple = r300ResetLineStipple;
489 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
490 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
491 tnl->Driver.Render.Interp = _tnl_interp;
492
493 _tnl_invalidate_vertex_state( ctx, ~0 );
494 _tnl_invalidate_vertices( ctx, ~0 );
495 }
496 }
497
498 }