1 /**************************************************************************
3 Copyright (C) 2004 Nicolai Haehnle.
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:
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
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.
26 **************************************************************************/
31 * \brief R300 Render (Vertex Buffer Implementation)
33 * The immediate implementation has been removed from CVS in favor of the vertex
34 * buffer implementation.
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.
41 * When falling back to software TCL still attempt to use hardware
44 * I am not sure that the cache related registers are setup correctly, but
45 * obviously this does work... Further investigation is needed.
47 * \author Nicolai Haehnle <prefect_@gmx.net>
49 * \todo Add immediate implementation back? Perhaps this is useful if there are
53 #include "r300_render.h"
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"
62 #include "main/simple_list.h"
63 #include "main/api_arrayelt.h"
64 #include "swrast/swrast.h"
65 #include "swrast_setup/swrast_setup.h"
67 #include "vbo/vbo_split.h"
69 #include "tnl/t_vp_build.h"
70 #include "radeon_reg.h"
71 #include "radeon_macros.h"
72 #include "r300_context.h"
73 #include "r300_ioctl.h"
74 #include "r300_state.h"
77 #include "r300_emit.h"
78 #include "r300_fragprog_common.h"
79 #include "r300_swtcl.h"
82 * \brief Convert a OpenGL primitive type into a R300 primitive type.
84 int r300PrimitiveType(r300ContextPtr rmesa
, int prim
)
86 switch (prim
& PRIM_MODE_MASK
) {
88 return R300_VAP_VF_CNTL__PRIM_POINTS
;
91 return R300_VAP_VF_CNTL__PRIM_LINES
;
94 return R300_VAP_VF_CNTL__PRIM_LINE_STRIP
;
97 return R300_VAP_VF_CNTL__PRIM_LINE_LOOP
;
100 return R300_VAP_VF_CNTL__PRIM_TRIANGLES
;
102 case GL_TRIANGLE_STRIP
:
103 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP
;
105 case GL_TRIANGLE_FAN
:
106 return R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN
;
109 return R300_VAP_VF_CNTL__PRIM_QUADS
;
112 return R300_VAP_VF_CNTL__PRIM_QUAD_STRIP
;
115 return R300_VAP_VF_CNTL__PRIM_POLYGON
;
124 int r300NumVerts(r300ContextPtr rmesa
, int num_verts
, int prim
)
128 switch (prim
& PRIM_MODE_MASK
) {
133 verts_off
= num_verts
% 2;
137 verts_off
= num_verts
;
141 verts_off
= num_verts
;
144 verts_off
= num_verts
% 3;
146 case GL_TRIANGLE_STRIP
:
148 verts_off
= num_verts
;
150 case GL_TRIANGLE_FAN
:
152 verts_off
= num_verts
;
155 verts_off
= num_verts
% 4;
159 verts_off
= num_verts
;
161 verts_off
= num_verts
% 2;
165 verts_off
= num_verts
;
173 return num_verts
- verts_off
;
176 static void r300FireEB(r300ContextPtr rmesa
, int vertex_count
, int type
, int offset
)
178 BATCH_LOCALS(&rmesa
->radeon
);
181 /* offset is in indices */
183 OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_INDX_2
, 0);
184 if (rmesa
->ind_buf
.is_32bit
) {
185 /* convert to bytes */
188 OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_INDICES
|
189 (vertex_count
<< 16) | type
|
190 R300_VAP_VF_CNTL__INDEX_SIZE_32bit
);
192 /* convert to bytes */
194 size
= (vertex_count
+ 1) >> 1;
195 OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_INDICES
|
196 (vertex_count
<< 16) | type
);
199 if (!rmesa
->radeon
.radeonScreen
->kernel_mm
) {
200 OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER
, 2);
201 OUT_BATCH(R300_INDX_BUFFER_ONE_REG_WR
| (0 << R300_INDX_BUFFER_SKIP_SHIFT
) |
202 (R300_VAP_PORT_IDX0
>> 2));
203 OUT_BATCH_RELOC(0, rmesa
->ind_buf
.bo
, rmesa
->ind_buf
.bo_offset
+ offset
, RADEON_GEM_DOMAIN_GTT
, 0, 0);
206 OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER
, 2);
207 OUT_BATCH(R300_INDX_BUFFER_ONE_REG_WR
| (0 << R300_INDX_BUFFER_SKIP_SHIFT
) |
208 (R300_VAP_PORT_IDX0
>> 2));
209 OUT_BATCH(rmesa
->ind_buf
.bo_offset
+ offset
);
211 radeon_cs_write_reloc(rmesa
->radeon
.cmdbuf
.cs
,
212 rmesa
->ind_buf
.bo
, RADEON_GEM_DOMAIN_GTT
, 0, 0);
217 static void r300EmitAOS(r300ContextPtr rmesa
, GLuint nr
, GLuint offset
)
219 BATCH_LOCALS(&rmesa
->radeon
);
221 int sz
= 1 + (nr
>> 1) * 3 + (nr
& 1) * 2;
224 if (RADEON_DEBUG
& DEBUG_VERTS
)
225 fprintf(stderr
, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__
, nr
,
228 if (!rmesa
->radeon
.radeonScreen
->kernel_mm
) {
229 BEGIN_BATCH(sz
+2+(nr
* 2));
230 OUT_BATCH_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR
, sz
- 1);
233 for (i
= 0; i
+ 1 < nr
; i
+= 2) {
234 OUT_BATCH((rmesa
->radeon
.tcl
.aos
[i
].components
<< 0) |
235 (rmesa
->radeon
.tcl
.aos
[i
].stride
<< 8) |
236 (rmesa
->radeon
.tcl
.aos
[i
+ 1].components
<< 16) |
237 (rmesa
->radeon
.tcl
.aos
[i
+ 1].stride
<< 24));
239 voffset
= rmesa
->radeon
.tcl
.aos
[i
+ 0].offset
+
240 offset
* 4 * rmesa
->radeon
.tcl
.aos
[i
+ 0].stride
;
241 OUT_BATCH_RELOC(voffset
,
242 rmesa
->radeon
.tcl
.aos
[i
].bo
,
244 RADEON_GEM_DOMAIN_GTT
,
246 voffset
= rmesa
->radeon
.tcl
.aos
[i
+ 1].offset
+
247 offset
* 4 * rmesa
->radeon
.tcl
.aos
[i
+ 1].stride
;
248 OUT_BATCH_RELOC(voffset
,
249 rmesa
->radeon
.tcl
.aos
[i
+1].bo
,
251 RADEON_GEM_DOMAIN_GTT
,
256 OUT_BATCH((rmesa
->radeon
.tcl
.aos
[nr
- 1].components
<< 0) |
257 (rmesa
->radeon
.tcl
.aos
[nr
- 1].stride
<< 8));
258 voffset
= rmesa
->radeon
.tcl
.aos
[nr
- 1].offset
+
259 offset
* 4 * rmesa
->radeon
.tcl
.aos
[nr
- 1].stride
;
260 OUT_BATCH_RELOC(voffset
,
261 rmesa
->radeon
.tcl
.aos
[nr
- 1].bo
,
263 RADEON_GEM_DOMAIN_GTT
,
269 BEGIN_BATCH(sz
+2+(nr
* 2));
270 OUT_BATCH_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR
, sz
- 1);
273 for (i
= 0; i
+ 1 < nr
; i
+= 2) {
274 OUT_BATCH((rmesa
->radeon
.tcl
.aos
[i
].components
<< 0) |
275 (rmesa
->radeon
.tcl
.aos
[i
].stride
<< 8) |
276 (rmesa
->radeon
.tcl
.aos
[i
+ 1].components
<< 16) |
277 (rmesa
->radeon
.tcl
.aos
[i
+ 1].stride
<< 24));
279 voffset
= rmesa
->radeon
.tcl
.aos
[i
+ 0].offset
+
280 offset
* 4 * rmesa
->radeon
.tcl
.aos
[i
+ 0].stride
;
282 voffset
= rmesa
->radeon
.tcl
.aos
[i
+ 1].offset
+
283 offset
* 4 * rmesa
->radeon
.tcl
.aos
[i
+ 1].stride
;
288 OUT_BATCH((rmesa
->radeon
.tcl
.aos
[nr
- 1].components
<< 0) |
289 (rmesa
->radeon
.tcl
.aos
[nr
- 1].stride
<< 8));
290 voffset
= rmesa
->radeon
.tcl
.aos
[nr
- 1].offset
+
291 offset
* 4 * rmesa
->radeon
.tcl
.aos
[nr
- 1].stride
;
294 for (i
= 0; i
+ 1 < nr
; i
+= 2) {
295 voffset
= rmesa
->radeon
.tcl
.aos
[i
+ 0].offset
+
296 offset
* 4 * rmesa
->radeon
.tcl
.aos
[i
+ 0].stride
;
297 radeon_cs_write_reloc(rmesa
->radeon
.cmdbuf
.cs
,
298 rmesa
->radeon
.tcl
.aos
[i
+0].bo
,
299 RADEON_GEM_DOMAIN_GTT
,
301 voffset
= rmesa
->radeon
.tcl
.aos
[i
+ 1].offset
+
302 offset
* 4 * rmesa
->radeon
.tcl
.aos
[i
+ 1].stride
;
303 radeon_cs_write_reloc(rmesa
->radeon
.cmdbuf
.cs
,
304 rmesa
->radeon
.tcl
.aos
[i
+1].bo
,
305 RADEON_GEM_DOMAIN_GTT
,
309 voffset
= rmesa
->radeon
.tcl
.aos
[nr
- 1].offset
+
310 offset
* 4 * rmesa
->radeon
.tcl
.aos
[nr
- 1].stride
;
311 radeon_cs_write_reloc(rmesa
->radeon
.cmdbuf
.cs
,
312 rmesa
->radeon
.tcl
.aos
[nr
-1].bo
,
313 RADEON_GEM_DOMAIN_GTT
,
321 static void r300FireAOS(r300ContextPtr rmesa
, int vertex_count
, int type
)
323 BATCH_LOCALS(&rmesa
->radeon
);
325 r300_emit_scissor(rmesa
->radeon
.glCtx
);
327 OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_VBUF_2
, 0);
328 OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST
| (vertex_count
<< 16) | type
);
332 void r300RunRenderPrimitive(GLcontext
* ctx
, int start
, int end
, int prim
)
334 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
335 BATCH_LOCALS(&rmesa
->radeon
);
338 type
= r300PrimitiveType(rmesa
, prim
);
339 num_verts
= r300NumVerts(rmesa
, end
- start
, prim
);
341 if (type
< 0 || num_verts
<= 0)
344 /* Make space for at least 128 dwords.
345 * This is supposed to ensure that we can get all rendering
346 * commands into a single command buffer.
348 rcommonEnsureCmdBufSpace(&rmesa
->radeon
, 128, __FUNCTION__
);
350 if (rmesa
->ind_buf
.bo
) {
351 GLuint first
, incr
, offset
= 0;
353 if (!split_prim_inplace(prim
& PRIM_MODE_MASK
, &first
, &incr
) &&
355 WARN_ONCE("Fixme: can't handle spliting prim %d\n", prim
);
360 r300EmitAOS(rmesa
, rmesa
->radeon
.tcl
.aos_count
, 0);
361 if (rmesa
->radeon
.radeonScreen
->kernel_mm
) {
362 BEGIN_BATCH_NO_AUTOSTATE(2);
363 OUT_BATCH_REGSEQ(R300_VAP_VF_MAX_VTX_INDX
, 1);
364 OUT_BATCH(rmesa
->radeon
.tcl
.aos
[0].count
);
368 r300_emit_scissor(rmesa
->radeon
.glCtx
);
369 while (num_verts
> 0) {
373 nr
= MIN2(num_verts
, 65535);
374 nr
-= (nr
- first
) % incr
;
376 /* get alignment for IB correct */
377 if (nr
!= num_verts
) {
379 align
= nr
* (rmesa
->ind_buf
.is_32bit
? 4 : 2);
384 WARN_ONCE("did the impossible happen? we never aligned nr to dword\n");
389 r300FireEB(rmesa
, nr
, type
, offset
);
396 if (num_verts
> 65535) {
397 WARN_ONCE("Fixme: can't handle more then 65535 vertices");
400 r300EmitAOS(rmesa
, rmesa
->radeon
.tcl
.aos_count
, start
);
401 r300FireAOS(rmesa
, num_verts
, type
);
406 static const char *getFallbackString(uint32_t bit
)
409 case R300_FALLBACK_VERTEX_PROGRAM
:
410 return "vertex program";
411 case R300_FALLBACK_LINE_SMOOTH
:
412 return "smooth lines";
413 case R300_FALLBACK_POINT_SMOOTH
:
414 return "smooth points";
415 case R300_FALLBACK_POLYGON_SMOOTH
:
416 return "smooth polygons";
417 case R300_FALLBACK_LINE_STIPPLE
:
418 return "line stipple";
419 case R300_FALLBACK_POLYGON_STIPPLE
:
420 return "polygon stipple";
421 case R300_FALLBACK_STENCIL_TWOSIDE
:
422 return "two-sided stencil";
423 case R300_FALLBACK_RENDER_MODE
:
424 return "render mode != GL_RENDER";
425 case R300_FALLBACK_FRAGMENT_PROGRAM
:
426 return "fragment program";
427 case R300_FALLBACK_AOS_LIMIT
:
429 case R300_FALLBACK_INVALID_BUFFERS
:
430 return "invalid buffers";
436 void r300SwitchFallback(GLcontext
*ctx
, uint32_t bit
, GLboolean mode
)
438 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
439 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
440 uint32_t old_fallback
= rmesa
->fallback
;
441 static uint32_t fallback_warn
= 0;
444 if ((fallback_warn
& bit
) == 0) {
445 if (RADEON_DEBUG
& DEBUG_FALLBACKS
)
446 _mesa_fprintf(stderr
, "WARNING! Falling back to software for %s\n", getFallbackString(bit
));
447 fallback_warn
|= bit
;
449 rmesa
->fallback
|= bit
;
451 /* update only if we change from no tcl fallbacks to some tcl fallbacks */
452 if (rmesa
->options
.hw_tcl_enabled
) {
453 if (((old_fallback
& R300_TCL_FALLBACK_MASK
) == 0) &&
454 ((bit
& R300_TCL_FALLBACK_MASK
) > 0)) {
455 R300_STATECHANGE(rmesa
, vap_cntl_status
);
456 rmesa
->hw
.vap_cntl_status
.cmd
[1] |= R300_VAP_TCL_BYPASS
;
460 /* update only if we change from no raster fallbacks to some raster fallbacks */
461 if (((old_fallback
& R300_RASTER_FALLBACK_MASK
) == 0) &&
462 ((bit
& R300_RASTER_FALLBACK_MASK
) > 0)) {
464 radeon_firevertices(&rmesa
->radeon
);
465 rmesa
->radeon
.swtcl
.RenderIndex
= ~0;
466 _swsetup_Wakeup( ctx
);
469 rmesa
->fallback
&= ~bit
;
471 /* update only if we have disabled all tcl fallbacks */
472 if (rmesa
->options
.hw_tcl_enabled
) {
473 if ((old_fallback
& R300_RASTER_FALLBACK_MASK
) == bit
) {
474 R300_STATECHANGE(rmesa
, vap_cntl_status
);
475 rmesa
->hw
.vap_cntl_status
.cmd
[1] &= ~R300_VAP_TCL_BYPASS
;
479 /* update only if we have disabled all raster fallbacks */
480 if ((old_fallback
& R300_RASTER_FALLBACK_MASK
) == bit
) {
481 _swrast_flush( ctx
);
483 tnl
->Driver
.Render
.Start
= r300RenderStart
;
484 tnl
->Driver
.Render
.Finish
= r300RenderFinish
;
485 tnl
->Driver
.Render
.PrimitiveNotify
= r300RenderPrimitive
;
486 tnl
->Driver
.Render
.ResetLineStipple
= r300ResetLineStipple
;
487 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
488 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
489 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
491 _tnl_invalidate_vertex_state( ctx
, ~0 );
492 _tnl_invalidate_vertices( ctx
, ~0 );