1 /**************************************************************************
2 
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4                      VA Linux Systems Inc., Fremont, California.
5 
6 All Rights Reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15 
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 
28 **************************************************************************/
29 
30 /*
31  * Authors:
32  *   Kevin E. Martin <martin@valinux.com>
33  *   Gareth Hughes <gareth@valinux.com>
34  *   Keith Whitwell <keith@tungstengraphics.com>
35  */
36 
37 #include <sched.h>
38 #include <errno.h>
39 
40 #include "main/attrib.h"
41 #include "main/bufferobj.h"
42 #include "swrast/swrast.h"
43 
44 #include "main/glheader.h"
45 #include "main/imports.h"
46 #include "main/simple_list.h"
47 
48 #include "radeon_context.h"
49 #include "radeon_common.h"
50 #include "radeon_ioctl.h"
51 
52 #define STANDALONE_MMIO
53 
54 #define RADEON_TIMEOUT             512
55 #define RADEON_IDLE_RETRY           16
56 
57 
58 /* =============================================================
59  * Kernel command buffer handling
60  */
61 
62 /* The state atoms will be emitted in the order they appear in the atom list,
63  * so this step is important.
64  */
radeonSetUpAtomList(r100ContextPtr rmesa)65 void radeonSetUpAtomList( r100ContextPtr rmesa )
66 {
67    int i, mtu = rmesa->radeon.glCtx->Const.MaxTextureUnits;
68 
69    make_empty_list(&rmesa->radeon.hw.atomlist);
70    rmesa->radeon.hw.atomlist.name = "atom-list";
71 
72    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.ctx);
73    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.set);
74    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.lin);
75    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.msk);
76    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.vpt);
77    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.tcl);
78    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.msc);
79    for (i = 0; i < mtu; ++i) {
80        insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.tex[i]);
81        insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.txr[i]);
82        insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.cube[i]);
83    }
84    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.zbs);
85    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.mtl);
86    for (i = 0; i < 3 + mtu; ++i)
87       insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.mat[i]);
88    for (i = 0; i < 8; ++i)
89       insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i]);
90    for (i = 0; i < 6; ++i)
91       insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i]);
92    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.stp);
93    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.eye);
94    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.grd);
95    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.fog);
96    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.glt);
97 }
98 
radeonEmitScissor(r100ContextPtr rmesa)99 static void radeonEmitScissor(r100ContextPtr rmesa)
100 {
101     BATCH_LOCALS(&rmesa->radeon);
102     if (rmesa->radeon.state.scissor.enabled) {
103         BEGIN_BATCH(6);
104         OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 0));
105         OUT_BATCH(rmesa->hw.ctx.cmd[CTX_PP_CNTL] | RADEON_SCISSOR_ENABLE);
106         OUT_BATCH(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
107         OUT_BATCH((rmesa->radeon.state.scissor.rect.y1 << 16) |
108                   rmesa->radeon.state.scissor.rect.x1);
109         OUT_BATCH(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
110         OUT_BATCH(((rmesa->radeon.state.scissor.rect.y2) << 16) |
111                   (rmesa->radeon.state.scissor.rect.x2));
112         END_BATCH();
113     } else {
114         BEGIN_BATCH(2);
115         OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 0));
116         OUT_BATCH(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ~RADEON_SCISSOR_ENABLE);
117         END_BATCH();
118     }
119 }
120 
121 /* Fire a section of the retained (indexed_verts) buffer as a regular
122  * primtive.
123  */
radeonEmitVbufPrim(r100ContextPtr rmesa,GLuint vertex_format,GLuint primitive,GLuint vertex_nr)124 extern void radeonEmitVbufPrim( r100ContextPtr rmesa,
125 				GLuint vertex_format,
126 				GLuint primitive,
127 				GLuint vertex_nr )
128 {
129    BATCH_LOCALS(&rmesa->radeon);
130 
131    assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
132 
133    radeonEmitState(&rmesa->radeon);
134    radeonEmitScissor(rmesa);
135 
136 #if RADEON_OLD_PACKETS
137    BEGIN_BATCH(8);
138    OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 3);
139    OUT_BATCH(rmesa->ioctl.vertex_offset);
140 
141    OUT_BATCH(vertex_nr);
142    OUT_BATCH(vertex_format);
143    OUT_BATCH(primitive |  RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
144 	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
145 	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
146 	     (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
147 
148    radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
149 			 rmesa->ioctl.bo,
150 			 RADEON_GEM_DOMAIN_GTT,
151 			 0, 0);
152 
153    END_BATCH();
154 
155 #else
156    BEGIN_BATCH(4);
157    OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_DRAW_VBUF, 1);
158    OUT_BATCH(vertex_format);
159    OUT_BATCH(primitive |
160 	     RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
161 	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
162 	     RADEON_CP_VC_CNTL_MAOS_ENABLE |
163 	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
164 	     (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
165    END_BATCH();
166 #endif
167 }
168 
radeonFlushElts(struct gl_context * ctx)169 void radeonFlushElts( struct gl_context *ctx )
170 {
171    r100ContextPtr rmesa = R100_CONTEXT(ctx);
172    BATCH_LOCALS(&rmesa->radeon);
173    int nr;
174    uint32_t *cmd = (uint32_t *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_start);
175    int dwords = (rmesa->radeon.cmdbuf.cs->section_ndw - rmesa->radeon.cmdbuf.cs->section_cdw);
176 
177    if (RADEON_DEBUG & RADEON_IOCTL)
178       fprintf(stderr, "%s\n", __FUNCTION__);
179 
180    assert( rmesa->radeon.dma.flush == radeonFlushElts );
181    rmesa->radeon.dma.flush = NULL;
182 
183    nr = rmesa->tcl.elt_used;
184 
185 #if RADEON_OLD_PACKETS
186    dwords -= 2;
187 #endif
188 
189 #if RADEON_OLD_PACKETS
190    cmd[1] |= (dwords + 3) << 16;
191    cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
192 #else
193    cmd[1] |= (dwords + 2) << 16;
194    cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
195 #endif
196 
197    rmesa->radeon.cmdbuf.cs->cdw += dwords;
198    rmesa->radeon.cmdbuf.cs->section_cdw += dwords;
199 
200 #if RADEON_OLD_PACKETS
201    radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
202 			 rmesa->ioctl.bo,
203 			 RADEON_GEM_DOMAIN_GTT,
204 			 0, 0);
205 #endif
206 
207    END_BATCH();
208 
209    if (RADEON_DEBUG & RADEON_SYNC) {
210       fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
211       radeonFinish( rmesa->radeon.glCtx );
212    }
213 
214 }
215 
radeonAllocEltsOpenEnded(r100ContextPtr rmesa,GLuint vertex_format,GLuint primitive,GLuint min_nr)216 GLushort *radeonAllocEltsOpenEnded( r100ContextPtr rmesa,
217 				    GLuint vertex_format,
218 				    GLuint primitive,
219 				    GLuint min_nr )
220 {
221    GLushort *retval;
222    int align_min_nr;
223    BATCH_LOCALS(&rmesa->radeon);
224 
225    if (RADEON_DEBUG & RADEON_IOCTL)
226       fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
227 
228    assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
229 
230    radeonEmitState(&rmesa->radeon);
231    radeonEmitScissor(rmesa);
232 
233    rmesa->tcl.elt_cmd_start = rmesa->radeon.cmdbuf.cs->cdw;
234 
235    /* round up min_nr to align the state */
236    align_min_nr = (min_nr + 1) & ~1;
237 
238 #if RADEON_OLD_PACKETS
239    BEGIN_BATCH_NO_AUTOSTATE(2+ELTS_BUFSZ(align_min_nr)/4);
240    OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 0);
241    OUT_BATCH(rmesa->ioctl.vertex_offset);
242    OUT_BATCH(rmesa->ioctl.vertex_max);
243    OUT_BATCH(vertex_format);
244    OUT_BATCH(primitive |
245 	     RADEON_CP_VC_CNTL_PRIM_WALK_IND |
246 	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
247 	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
248 #else
249    BEGIN_BATCH_NO_AUTOSTATE(ELTS_BUFSZ(align_min_nr)/4);
250    OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_DRAW_INDX, 0);
251    OUT_BATCH(vertex_format);
252    OUT_BATCH(primitive |
253 	     RADEON_CP_VC_CNTL_PRIM_WALK_IND |
254 	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
255 	     RADEON_CP_VC_CNTL_MAOS_ENABLE |
256 	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
257 #endif
258 
259 
260    rmesa->tcl.elt_cmd_offset = rmesa->radeon.cmdbuf.cs->cdw;
261    rmesa->tcl.elt_used = min_nr;
262 
263    retval = (GLushort *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_offset);
264 
265    if (RADEON_DEBUG & RADEON_RENDER)
266       fprintf(stderr, "%s: header prim %x \n",
267 	      __FUNCTION__, primitive);
268 
269    assert(!rmesa->radeon.dma.flush);
270    rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
271    rmesa->radeon.dma.flush = radeonFlushElts;
272 
273    return retval;
274 }
275 
radeonEmitVertexAOS(r100ContextPtr rmesa,GLuint vertex_size,struct radeon_bo * bo,GLuint offset)276 void radeonEmitVertexAOS( r100ContextPtr rmesa,
277 			  GLuint vertex_size,
278 			  struct radeon_bo *bo,
279 			  GLuint offset )
280 {
281 #if RADEON_OLD_PACKETS
282    rmesa->ioctl.vertex_offset = offset;
283    rmesa->ioctl.bo = bo;
284 #else
285    BATCH_LOCALS(&rmesa->radeon);
286 
287    if (RADEON_DEBUG & (RADEON_PRIMS|DEBUG_IOCTL))
288       fprintf(stderr, "%s:  vertex_size 0x%x offset 0x%x \n",
289 	      __FUNCTION__, vertex_size, offset);
290 
291    BEGIN_BATCH(7);
292    OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, 2);
293    OUT_BATCH(1);
294    OUT_BATCH(vertex_size | (vertex_size << 8));
295    OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
296    END_BATCH();
297 
298 #endif
299 }
300 
301 
radeonEmitAOS(r100ContextPtr rmesa,GLuint nr,GLuint offset)302 void radeonEmitAOS( r100ContextPtr rmesa,
303 		    GLuint nr,
304 		    GLuint offset )
305 {
306 #if RADEON_OLD_PACKETS
307    assert( nr == 1 );
308    rmesa->ioctl.bo = rmesa->radeon.tcl.aos[0].bo;
309    rmesa->ioctl.vertex_offset =
310      (rmesa->radeon.tcl.aos[0].offset + offset * rmesa->radeon.tcl.aos[0].stride * 4);
311    rmesa->ioctl.vertex_max = rmesa->radeon.tcl.aos[0].count;
312 #else
313    BATCH_LOCALS(&rmesa->radeon);
314    uint32_t voffset;
315    //   int sz = AOS_BUFSZ(nr);
316    int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
317    int i;
318 
319    if (RADEON_DEBUG & RADEON_IOCTL)
320       fprintf(stderr, "%s\n", __FUNCTION__);
321 
322    BEGIN_BATCH(sz+2+(nr * 2));
323    OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, sz - 1);
324    OUT_BATCH(nr);
325 
326    {
327       for (i = 0; i + 1 < nr; i += 2) {
328 	 OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
329 		   (rmesa->radeon.tcl.aos[i].stride << 8) |
330 		   (rmesa->radeon.tcl.aos[i + 1].components << 16) |
331 		   (rmesa->radeon.tcl.aos[i + 1].stride << 24));
332 
333 	 voffset =  rmesa->radeon.tcl.aos[i + 0].offset +
334 	    offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
335 	 OUT_BATCH(voffset);
336 	 voffset =  rmesa->radeon.tcl.aos[i + 1].offset +
337 	    offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
338 	 OUT_BATCH(voffset);
339       }
340 
341       if (nr & 1) {
342 	 OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
343 		   (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
344 	 voffset =  rmesa->radeon.tcl.aos[nr - 1].offset +
345 	    offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
346 	 OUT_BATCH(voffset);
347       }
348       for (i = 0; i + 1 < nr; i += 2) {
349 	 voffset =  rmesa->radeon.tcl.aos[i + 0].offset +
350 	    offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
351 	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
352 			       rmesa->radeon.tcl.aos[i+0].bo,
353 			       RADEON_GEM_DOMAIN_GTT,
354 			       0, 0);
355 	 voffset =  rmesa->radeon.tcl.aos[i + 1].offset +
356 	    offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
357 	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
358 			       rmesa->radeon.tcl.aos[i+1].bo,
359 			       RADEON_GEM_DOMAIN_GTT,
360 			       0, 0);
361       }
362       if (nr & 1) {
363 	 voffset =  rmesa->radeon.tcl.aos[nr - 1].offset +
364 	    offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
365 	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
366 			       rmesa->radeon.tcl.aos[nr-1].bo,
367 			       RADEON_GEM_DOMAIN_GTT,
368 			       0, 0);
369       }
370    }
371    END_BATCH();
372 
373 #endif
374 }
375 
376 /* ================================================================
377  * Buffer clear
378  */
379 #define RADEON_MAX_CLEARS	256
380 
radeonClear(struct gl_context * ctx,GLbitfield mask)381 static void radeonClear( struct gl_context *ctx, GLbitfield mask )
382 {
383    r100ContextPtr rmesa = R100_CONTEXT(ctx);
384    GLuint hwmask, swmask;
385    GLuint hwbits = BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT |
386                    BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL |
387                    BUFFER_BIT_COLOR0;
388 
389    if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT)) {
390       rmesa->radeon.front_buffer_dirty = GL_TRUE;
391    }
392 
393    if ( RADEON_DEBUG & RADEON_IOCTL ) {
394       fprintf( stderr, "radeonClear\n");
395    }
396 
397    radeon_firevertices(&rmesa->radeon);
398 
399    hwmask = mask & hwbits;
400    swmask = mask & ~hwbits;
401 
402    if ( swmask ) {
403       if (RADEON_DEBUG & RADEON_FALLBACKS)
404 	 fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, swmask);
405       _swrast_Clear( ctx, swmask );
406    }
407 
408    if ( !hwmask )
409       return;
410 
411    radeonUserClear(ctx, hwmask);
412 }
413 
radeonInitIoctlFuncs(struct gl_context * ctx)414 void radeonInitIoctlFuncs( struct gl_context *ctx )
415 {
416     ctx->Driver.Clear = radeonClear;
417     ctx->Driver.Finish = radeonFinish;
418     ctx->Driver.Flush = radeonFlush;
419 }
420 
421