Merge branch 'r345-cleanup' of git://people.freedesktop.org/~agd5f/mesa into r500test
[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 "glheader.h"
54 #include "state.h"
55 #include "imports.h"
56 #include "enums.h"
57 #include "macros.h"
58 #include "context.h"
59 #include "dd.h"
60 #include "simple_list.h"
61 #include "api_arrayelt.h"
62 #include "swrast/swrast.h"
63 #include "swrast_setup/swrast_setup.h"
64 #include "vbo/vbo.h"
65 #include "tnl/tnl.h"
66 #include "tnl/t_vp_build.h"
67 #include "radeon_reg.h"
68 #include "radeon_macros.h"
69 #include "radeon_ioctl.h"
70 #include "radeon_state.h"
71 #include "r300_context.h"
72 #include "r300_ioctl.h"
73 #include "r300_state.h"
74 #include "r300_reg.h"
75 #include "r300_tex.h"
76 #include "r300_emit.h"
77 extern int future_hw_tcl_on;
78
79 /**
80 * \brief Convert a OpenGL primitive type into a R300 primitive type.
81 */
82 int r300PrimitiveType(r300ContextPtr rmesa, int prim)
83 {
84 switch (prim & PRIM_MODE_MASK) {
85 case GL_POINTS:
86 return R300_VAP_VF_CNTL__PRIM_POINTS;
87 break;
88 case GL_LINES:
89 return R300_VAP_VF_CNTL__PRIM_LINES;
90 break;
91 case GL_LINE_STRIP:
92 return R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
93 break;
94 case GL_LINE_LOOP:
95 return R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
96 break;
97 case GL_TRIANGLES:
98 return R300_VAP_VF_CNTL__PRIM_TRIANGLES;
99 break;
100 case GL_TRIANGLE_STRIP:
101 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
102 break;
103 case GL_TRIANGLE_FAN:
104 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
105 break;
106 case GL_QUADS:
107 return R300_VAP_VF_CNTL__PRIM_QUADS;
108 break;
109 case GL_QUAD_STRIP:
110 return R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
111 break;
112 case GL_POLYGON:
113 return R300_VAP_VF_CNTL__PRIM_POLYGON;
114 break;
115 default:
116 assert(0);
117 return -1;
118 break;
119 }
120 }
121
122 int r300NumVerts(r300ContextPtr rmesa, int num_verts, int prim)
123 {
124 int verts_off = 0;
125
126 switch (prim & PRIM_MODE_MASK) {
127 case GL_POINTS:
128 verts_off = 0;
129 break;
130 case GL_LINES:
131 verts_off = num_verts % 2;
132 break;
133 case GL_LINE_STRIP:
134 if (num_verts < 2)
135 verts_off = num_verts;
136 break;
137 case GL_LINE_LOOP:
138 if (num_verts < 2)
139 verts_off = num_verts;
140 break;
141 case GL_TRIANGLES:
142 verts_off = num_verts % 3;
143 break;
144 case GL_TRIANGLE_STRIP:
145 if (num_verts < 3)
146 verts_off = num_verts;
147 break;
148 case GL_TRIANGLE_FAN:
149 if (num_verts < 3)
150 verts_off = num_verts;
151 break;
152 case GL_QUADS:
153 verts_off = num_verts % 4;
154 break;
155 case GL_QUAD_STRIP:
156 if (num_verts < 4)
157 verts_off = num_verts;
158 else
159 verts_off = num_verts % 2;
160 break;
161 case GL_POLYGON:
162 if (num_verts < 3)
163 verts_off = num_verts;
164 break;
165 default:
166 assert(0);
167 return -1;
168 break;
169 }
170
171 return num_verts - verts_off;
172 }
173
174 static void r300EmitElts(GLcontext * ctx, void *elts, unsigned long n_elts)
175 {
176 r300ContextPtr rmesa = R300_CONTEXT(ctx);
177 struct r300_dma_region *rvb = &rmesa->state.elt_dma;
178 void *out;
179
180 if (r300IsGartMemory(rmesa, elts, n_elts * 4)) {
181 rvb->address = rmesa->radeon.radeonScreen->gartTextures.map;
182 rvb->start = ((char *)elts) - rvb->address;
183 rvb->aos_offset =
184 rmesa->radeon.radeonScreen->gart_texture_offset +
185 rvb->start;
186 return;
187 } else if (r300IsGartMemory(rmesa, elts, 1)) {
188 WARN_ONCE("Pointer not within GART memory!\n");
189 _mesa_exit(-1);
190 }
191
192 r300AllocDmaRegion(rmesa, rvb, n_elts * 4, 4);
193 rvb->aos_offset = GET_START(rvb);
194
195 out = rvb->address + rvb->start;
196 memcpy(out, elts, n_elts * 4);
197 }
198
199 static void r300FireEB(r300ContextPtr rmesa, unsigned long addr,
200 int vertex_count, int type)
201 {
202 int cmd_reserved = 0;
203 int cmd_written = 0;
204 drm_radeon_cmd_header_t *cmd = NULL;
205
206 start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_INDX_2, 0), 0);
207 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (vertex_count << 16) | type | R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
208
209 start_packet3(CP_PACKET3(R300_PACKET3_INDX_BUFFER, 2), 2);
210 e32(R300_EB_UNK1 | (0 << 16) | R300_EB_UNK2);
211 e32(addr);
212 e32(vertex_count);
213 }
214
215 static void r300EmitAOS(r300ContextPtr rmesa, GLuint nr, GLuint offset)
216 {
217 int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
218 int i;
219 int cmd_reserved = 0;
220 int cmd_written = 0;
221 drm_radeon_cmd_header_t *cmd = NULL;
222
223 if (RADEON_DEBUG & DEBUG_VERTS)
224 fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__, nr,
225 offset);
226
227 start_packet3(CP_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1), sz - 1);
228 e32(nr);
229
230 for (i = 0; i + 1 < nr; i += 2) {
231 e32((rmesa->state.aos[i].aos_size << 0) |
232 (rmesa->state.aos[i].aos_stride << 8) |
233 (rmesa->state.aos[i + 1].aos_size << 16) |
234 (rmesa->state.aos[i + 1].aos_stride << 24));
235
236 e32(rmesa->state.aos[i].aos_offset + offset * 4 * rmesa->state.aos[i].aos_stride);
237 e32(rmesa->state.aos[i + 1].aos_offset + offset * 4 * rmesa->state.aos[i + 1].aos_stride);
238 }
239
240 if (nr & 1) {
241 e32((rmesa->state.aos[nr - 1].aos_size << 0) |
242 (rmesa->state.aos[nr - 1].aos_stride << 8));
243 e32(rmesa->state.aos[nr - 1].aos_offset + offset * 4 * rmesa->state.aos[nr - 1].aos_stride);
244 }
245 }
246
247 static void r300FireAOS(r300ContextPtr rmesa, int vertex_count, int type)
248 {
249 int cmd_reserved = 0;
250 int cmd_written = 0;
251 drm_radeon_cmd_header_t *cmd = NULL;
252
253 start_packet3(CP_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2, 0), 0);
254 e32(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (vertex_count << 16) | type);
255 }
256
257 static void r300RunRenderPrimitive(r300ContextPtr rmesa, GLcontext * ctx,
258 int start, int end, int prim)
259 {
260 int type, num_verts;
261 TNLcontext *tnl = TNL_CONTEXT(ctx);
262 struct vertex_buffer *vb = &tnl->vb;
263
264 type = r300PrimitiveType(rmesa, prim);
265 num_verts = r300NumVerts(rmesa, end - start, prim);
266
267 if (type < 0 || num_verts <= 0)
268 return;
269
270 if (vb->Elts) {
271 r300EmitAOS(rmesa, rmesa->state.aos_count, start);
272 if (num_verts > 65535) {
273 /* not implemented yet */
274 WARN_ONCE("Too many elts\n");
275 return;
276 }
277 r300EmitElts(ctx, vb->Elts, num_verts);
278 r300FireEB(rmesa, rmesa->state.elt_dma.aos_offset, num_verts, type);
279 } else {
280 r300EmitAOS(rmesa, rmesa->state.aos_count, start);
281 r300FireAOS(rmesa, num_verts, type);
282 }
283 }
284
285 static GLboolean r300RunRender(GLcontext * ctx,
286 struct tnl_pipeline_stage *stage)
287 {
288 r300ContextPtr rmesa = R300_CONTEXT(ctx);
289 int i;
290 TNLcontext *tnl = TNL_CONTEXT(ctx);
291 struct vertex_buffer *vb = &tnl->vb;
292
293
294 if (RADEON_DEBUG & DEBUG_PRIMS)
295 fprintf(stderr, "%s\n", __FUNCTION__);
296
297 r300UpdateShaders(rmesa);
298 if (r300EmitArrays(ctx))
299 return GL_TRUE;
300
301 r300UpdateShaderStates(rmesa);
302
303 r300EmitCacheFlush(rmesa);
304 r300EmitState(rmesa);
305
306 for (i = 0; i < vb->PrimitiveCount; i++) {
307 GLuint prim = _tnl_translate_prim(&vb->Primitive[i]);
308 GLuint start = vb->Primitive[i].start;
309 GLuint end = vb->Primitive[i].start + vb->Primitive[i].count;
310 r300RunRenderPrimitive(rmesa, ctx, start, end, prim);
311 }
312
313 r300EmitCacheFlush(rmesa);
314
315 #ifdef USER_BUFFERS
316 r300UseArrays(ctx);
317 #endif
318
319 r300ReleaseArrays(ctx);
320
321 return GL_FALSE;
322 }
323
324 #define FALLBACK_IF(expr) \
325 do { \
326 if (expr) { \
327 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
328 WARN_ONCE("Software fallback:%s\n", \
329 #expr); \
330 return R300_FALLBACK_RAST; \
331 } \
332 } while(0)
333
334 static int r300Fallback(GLcontext * ctx)
335 {
336 r300ContextPtr r300 = R300_CONTEXT(ctx);
337 /* Do we need to use new-style shaders?
338 * Also is there a better way to do this? */
339 if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
340 struct r500_fragment_program *fp = (struct r500_fragment_program *)
341 (char *)ctx->FragmentProgram._Current;
342 if (fp) {
343 if (!fp->translated) {
344 r500TranslateFragmentShader(r300, fp);
345 FALLBACK_IF(!fp->translated);
346 }
347 }
348 } else {
349 struct r300_fragment_program *fp = (struct r300_fragment_program *)
350 (char *)ctx->FragmentProgram._Current;
351 if (fp) {
352 if (!fp->translated) {
353 r300TranslateFragmentShader(r300, fp);
354 FALLBACK_IF(!fp->translated);
355 }
356 }
357 }
358
359 FALLBACK_IF(ctx->RenderMode != GL_RENDER);
360
361 FALLBACK_IF(ctx->Stencil._TestTwoSide
362 && (ctx->Stencil.Ref[0] != ctx->Stencil.Ref[1]
363 || ctx->Stencil.ValueMask[0] !=
364 ctx->Stencil.ValueMask[1]
365 || ctx->Stencil.WriteMask[0] !=
366 ctx->Stencil.WriteMask[1]));
367
368 FALLBACK_IF(ctx->Color.ColorLogicOpEnabled);
369
370 if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
371 FALLBACK_IF(ctx->Point.PointSprite);
372
373 if (!r300->disable_lowimpact_fallback) {
374 FALLBACK_IF(ctx->Polygon.StippleFlag);
375 FALLBACK_IF(ctx->Multisample.Enabled);
376 FALLBACK_IF(ctx->Line.StippleFlag);
377 FALLBACK_IF(ctx->Line.SmoothFlag);
378 FALLBACK_IF(ctx->Point.SmoothFlag);
379 }
380
381 return R300_FALLBACK_NONE;
382 }
383
384 static GLboolean r300RunNonTCLRender(GLcontext * ctx,
385 struct tnl_pipeline_stage *stage)
386 {
387 r300ContextPtr rmesa = R300_CONTEXT(ctx);
388
389 if (RADEON_DEBUG & DEBUG_PRIMS)
390 fprintf(stderr, "%s\n", __FUNCTION__);
391
392 if (r300Fallback(ctx) >= R300_FALLBACK_RAST)
393 return GL_TRUE;
394
395 if (!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
396 return GL_TRUE;
397
398 return r300RunRender(ctx, stage);
399 }
400
401 static GLboolean r300RunTCLRender(GLcontext * ctx,
402 struct tnl_pipeline_stage *stage)
403 {
404 r300ContextPtr rmesa = R300_CONTEXT(ctx);
405 struct r300_vertex_program *vp;
406
407 hw_tcl_on = future_hw_tcl_on;
408
409 if (RADEON_DEBUG & DEBUG_PRIMS)
410 fprintf(stderr, "%s\n", __FUNCTION__);
411
412 if (hw_tcl_on == GL_FALSE)
413 return GL_TRUE;
414
415 if (r300Fallback(ctx) >= R300_FALLBACK_TCL) {
416 hw_tcl_on = GL_FALSE;
417 return GL_TRUE;
418 }
419
420 r300UpdateShaders(rmesa);
421
422 vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
423 if (vp->native == GL_FALSE) {
424 hw_tcl_on = GL_FALSE;
425 return GL_TRUE;
426 }
427
428 return r300RunRender(ctx, stage);
429 }
430
431 const struct tnl_pipeline_stage _r300_render_stage = {
432 "r300 Hardware Rasterization",
433 NULL,
434 NULL,
435 NULL,
436 NULL,
437 r300RunNonTCLRender
438 };
439
440 const struct tnl_pipeline_stage _r300_tcl_stage = {
441 "r300 Hardware Transform, Clipping and Lighting",
442 NULL,
443 NULL,
444 NULL,
445 NULL,
446 r300RunTCLRender
447 };