• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <keithw@vmware.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 "util/simple_list.h"
46 
47 #include "radeon_context.h"
48 #include "radeon_common.h"
49 #include "radeon_ioctl.h"
50 
51 #define RADEON_TIMEOUT             512
52 #define RADEON_IDLE_RETRY           16
53 
54 
55 /* =============================================================
56  * Kernel command buffer handling
57  */
58 
59 /* The state atoms will be emitted in the order they appear in the atom list,
60  * so this step is important.
61  */
radeonSetUpAtomList(r100ContextPtr rmesa)62 void radeonSetUpAtomList( r100ContextPtr rmesa )
63 {
64    int i, mtu = rmesa->radeon.glCtx.Const.MaxTextureUnits;
65 
66    make_empty_list(&rmesa->radeon.hw.atomlist);
67    rmesa->radeon.hw.atomlist.name = "atom-list";
68 
69    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.ctx);
70    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.set);
71    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.lin);
72    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.msk);
73    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.vpt);
74    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.tcl);
75    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.msc);
76    for (i = 0; i < mtu; ++i) {
77        insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.tex[i]);
78        insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.txr[i]);
79        insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.cube[i]);
80    }
81    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.zbs);
82    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.mtl);
83    for (i = 0; i < 3 + mtu; ++i)
84       insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.mat[i]);
85    for (i = 0; i < 8; ++i)
86       insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i]);
87    for (i = 0; i < 6; ++i)
88       insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i]);
89    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.stp);
90    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.eye);
91    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.grd);
92    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.fog);
93    insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.glt);
94 }
95 
radeonEmitScissor(r100ContextPtr rmesa)96 static void radeonEmitScissor(r100ContextPtr rmesa)
97 {
98     BATCH_LOCALS(&rmesa->radeon);
99     if (rmesa->radeon.state.scissor.enabled) {
100         BEGIN_BATCH(6);
101         OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 0));
102         OUT_BATCH(rmesa->hw.ctx.cmd[CTX_PP_CNTL] | RADEON_SCISSOR_ENABLE);
103         OUT_BATCH(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
104         OUT_BATCH((rmesa->radeon.state.scissor.rect.y1 << 16) |
105                   rmesa->radeon.state.scissor.rect.x1);
106         OUT_BATCH(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
107         OUT_BATCH(((rmesa->radeon.state.scissor.rect.y2) << 16) |
108                   (rmesa->radeon.state.scissor.rect.x2));
109         END_BATCH();
110     } else {
111         BEGIN_BATCH(2);
112         OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 0));
113         OUT_BATCH(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ~RADEON_SCISSOR_ENABLE);
114         END_BATCH();
115     }
116 }
117 
118 /* Fire a section of the retained (indexed_verts) buffer as a regular
119  * primtive.
120  */
radeonEmitVbufPrim(r100ContextPtr rmesa,GLuint vertex_format,GLuint primitive,GLuint vertex_nr)121 extern void radeonEmitVbufPrim( r100ContextPtr rmesa,
122 				GLuint vertex_format,
123 				GLuint primitive,
124 				GLuint vertex_nr )
125 {
126    BATCH_LOCALS(&rmesa->radeon);
127 
128    assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
129 
130    radeonEmitState(&rmesa->radeon);
131    radeonEmitScissor(rmesa);
132 
133 #if RADEON_OLD_PACKETS
134    BEGIN_BATCH(8);
135    OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 3);
136    OUT_BATCH(rmesa->ioctl.vertex_offset);
137 
138    OUT_BATCH(vertex_nr);
139    OUT_BATCH(vertex_format);
140    OUT_BATCH(primitive |  RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
141 	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
142 	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
143 	     (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
144 
145    radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
146 			 rmesa->ioctl.bo,
147 			 RADEON_GEM_DOMAIN_GTT,
148 			 0, 0);
149 
150    END_BATCH();
151 
152 #else
153    BEGIN_BATCH(4);
154    OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_DRAW_VBUF, 1);
155    OUT_BATCH(vertex_format);
156    OUT_BATCH(primitive |
157 	     RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
158 	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
159 	     RADEON_CP_VC_CNTL_MAOS_ENABLE |
160 	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
161 	     (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
162    END_BATCH();
163 #endif
164 }
165 
radeonFlushElts(struct gl_context * ctx)166 void radeonFlushElts( struct gl_context *ctx )
167 {
168    r100ContextPtr rmesa = R100_CONTEXT(ctx);
169    BATCH_LOCALS(&rmesa->radeon);
170    int nr;
171    uint32_t *cmd = (uint32_t *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_start);
172    int dwords = (rmesa->radeon.cmdbuf.cs->section_ndw - rmesa->radeon.cmdbuf.cs->section_cdw);
173 
174    if (RADEON_DEBUG & RADEON_IOCTL)
175       fprintf(stderr, "%s\n", __func__);
176 
177    assert( rmesa->radeon.dma.flush == radeonFlushElts );
178    rmesa->radeon.dma.flush = NULL;
179 
180    nr = rmesa->tcl.elt_used;
181 
182 #if RADEON_OLD_PACKETS
183    dwords -= 2;
184 #endif
185 
186 #if RADEON_OLD_PACKETS
187    cmd[1] |= (dwords + 3) << 16;
188    cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
189 #else
190    cmd[1] |= (dwords + 2) << 16;
191    cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
192 #endif
193 
194    rmesa->radeon.cmdbuf.cs->cdw += dwords;
195    rmesa->radeon.cmdbuf.cs->section_cdw += dwords;
196 
197 #if RADEON_OLD_PACKETS
198    radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
199 			 rmesa->ioctl.bo,
200 			 RADEON_GEM_DOMAIN_GTT,
201 			 0, 0);
202 #endif
203 
204    END_BATCH();
205 
206    if (RADEON_DEBUG & RADEON_SYNC) {
207       fprintf(stderr, "%s: Syncing\n", __func__);
208       radeonFinish( &rmesa->radeon.glCtx );
209    }
210 
211 }
212 
radeonAllocEltsOpenEnded(r100ContextPtr rmesa,GLuint vertex_format,GLuint primitive,GLuint min_nr)213 GLushort *radeonAllocEltsOpenEnded( r100ContextPtr rmesa,
214 				    GLuint vertex_format,
215 				    GLuint primitive,
216 				    GLuint min_nr )
217 {
218    GLushort *retval;
219    int align_min_nr;
220    BATCH_LOCALS(&rmesa->radeon);
221 
222    if (RADEON_DEBUG & RADEON_IOCTL)
223       fprintf(stderr, "%s %d prim %x\n", __func__, min_nr, primitive);
224 
225    assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
226 
227    radeonEmitState(&rmesa->radeon);
228    radeonEmitScissor(rmesa);
229 
230    rmesa->tcl.elt_cmd_start = rmesa->radeon.cmdbuf.cs->cdw;
231 
232    /* round up min_nr to align the state */
233    align_min_nr = (min_nr + 1) & ~1;
234 
235 #if RADEON_OLD_PACKETS
236    BEGIN_BATCH(2+ELTS_BUFSZ(align_min_nr)/4);
237    OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 0);
238    OUT_BATCH(rmesa->ioctl.vertex_offset);
239    OUT_BATCH(rmesa->ioctl.vertex_max);
240    OUT_BATCH(vertex_format);
241    OUT_BATCH(primitive |
242 	     RADEON_CP_VC_CNTL_PRIM_WALK_IND |
243 	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
244 	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
245 #else
246    BEGIN_BATCH(ELTS_BUFSZ(align_min_nr)/4);
247    OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_DRAW_INDX, 0);
248    OUT_BATCH(vertex_format);
249    OUT_BATCH(primitive |
250 	     RADEON_CP_VC_CNTL_PRIM_WALK_IND |
251 	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
252 	     RADEON_CP_VC_CNTL_MAOS_ENABLE |
253 	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
254 #endif
255 
256 
257    rmesa->tcl.elt_cmd_offset = rmesa->radeon.cmdbuf.cs->cdw;
258    rmesa->tcl.elt_used = min_nr;
259 
260    retval = (GLushort *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_offset);
261 
262    if (RADEON_DEBUG & RADEON_RENDER)
263       fprintf(stderr, "%s: header prim %x \n",
264 	      __func__, primitive);
265 
266    assert(!rmesa->radeon.dma.flush);
267    rmesa->radeon.glCtx.Driver.NeedFlush |= FLUSH_STORED_VERTICES;
268    rmesa->radeon.dma.flush = radeonFlushElts;
269 
270    return retval;
271 }
272 
radeonEmitVertexAOS(r100ContextPtr rmesa,GLuint vertex_size,struct radeon_bo * bo,GLuint offset)273 void radeonEmitVertexAOS( r100ContextPtr rmesa,
274 			  GLuint vertex_size,
275 			  struct radeon_bo *bo,
276 			  GLuint offset )
277 {
278 #if RADEON_OLD_PACKETS
279    rmesa->ioctl.vertex_offset = offset;
280    rmesa->ioctl.bo = bo;
281 #else
282    BATCH_LOCALS(&rmesa->radeon);
283 
284    if (RADEON_DEBUG & (RADEON_PRIMS|RADEON_IOCTL))
285       fprintf(stderr, "%s:  vertex_size 0x%x offset 0x%x \n",
286 	      __func__, vertex_size, offset);
287 
288    BEGIN_BATCH(7);
289    OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, 2);
290    OUT_BATCH(1);
291    OUT_BATCH(vertex_size | (vertex_size << 8));
292    OUT_BATCH_RELOC(bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
293    END_BATCH();
294 
295 #endif
296 }
297 
298 
radeonEmitAOS(r100ContextPtr rmesa,GLuint nr,GLuint offset)299 void radeonEmitAOS( r100ContextPtr rmesa,
300 		    GLuint nr,
301 		    GLuint offset )
302 {
303 #if RADEON_OLD_PACKETS
304    assert( nr == 1 );
305    rmesa->ioctl.bo = rmesa->radeon.tcl.aos[0].bo;
306    rmesa->ioctl.vertex_offset =
307      (rmesa->radeon.tcl.aos[0].offset + offset * rmesa->radeon.tcl.aos[0].stride * 4);
308    rmesa->ioctl.vertex_max = rmesa->radeon.tcl.aos[0].count;
309 #else
310    BATCH_LOCALS(&rmesa->radeon);
311    uint32_t voffset;
312    //   int sz = AOS_BUFSZ(nr);
313    int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
314    int i;
315 
316    if (RADEON_DEBUG & RADEON_IOCTL)
317       fprintf(stderr, "%s\n", __func__);
318 
319    BEGIN_BATCH(sz+2+(nr * 2));
320    OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, sz - 1);
321    OUT_BATCH(nr);
322 
323    {
324       for (i = 0; i + 1 < nr; i += 2) {
325 	 OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
326 		   (rmesa->radeon.tcl.aos[i].stride << 8) |
327 		   (rmesa->radeon.tcl.aos[i + 1].components << 16) |
328 		   (rmesa->radeon.tcl.aos[i + 1].stride << 24));
329 
330 	 voffset =  rmesa->radeon.tcl.aos[i + 0].offset +
331 	    offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
332 	 OUT_BATCH(voffset);
333 	 voffset =  rmesa->radeon.tcl.aos[i + 1].offset +
334 	    offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
335 	 OUT_BATCH(voffset);
336       }
337 
338       if (nr & 1) {
339 	 OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
340 		   (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
341 	 voffset =  rmesa->radeon.tcl.aos[nr - 1].offset +
342 	    offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
343 	 OUT_BATCH(voffset);
344       }
345       for (i = 0; i + 1 < nr; i += 2) {
346 	 voffset =  rmesa->radeon.tcl.aos[i + 0].offset +
347 	    offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
348 	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
349 			       rmesa->radeon.tcl.aos[i+0].bo,
350 			       RADEON_GEM_DOMAIN_GTT,
351 			       0, 0);
352 	 voffset =  rmesa->radeon.tcl.aos[i + 1].offset +
353 	    offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
354 	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
355 			       rmesa->radeon.tcl.aos[i+1].bo,
356 			       RADEON_GEM_DOMAIN_GTT,
357 			       0, 0);
358       }
359       if (nr & 1) {
360 	 voffset =  rmesa->radeon.tcl.aos[nr - 1].offset +
361 	    offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
362 	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
363 			       rmesa->radeon.tcl.aos[nr-1].bo,
364 			       RADEON_GEM_DOMAIN_GTT,
365 			       0, 0);
366       }
367    }
368    END_BATCH();
369 
370 #endif
371 }
372 
373 /* ================================================================
374  * Buffer clear
375  */
376 #define RADEON_MAX_CLEARS	256
377 
radeonClear(struct gl_context * ctx,GLbitfield mask)378 static void radeonClear( struct gl_context *ctx, GLbitfield mask )
379 {
380    r100ContextPtr rmesa = R100_CONTEXT(ctx);
381    GLuint hwmask, swmask;
382    GLuint hwbits = BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT |
383                    BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL |
384                    BUFFER_BIT_COLOR0;
385 
386    if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT)) {
387       rmesa->radeon.front_buffer_dirty = GL_TRUE;
388    }
389 
390    if ( RADEON_DEBUG & RADEON_IOCTL ) {
391       fprintf( stderr, "radeonClear\n");
392    }
393 
394    radeon_firevertices(&rmesa->radeon);
395 
396    hwmask = mask & hwbits;
397    swmask = mask & ~hwbits;
398 
399    if ( swmask ) {
400       if (RADEON_DEBUG & RADEON_FALLBACKS)
401 	 fprintf(stderr, "%s: swrast clear, mask: %x\n", __func__, swmask);
402       _swrast_Clear( ctx, swmask );
403    }
404 
405    if ( !hwmask )
406       return;
407 
408    radeonUserClear(ctx, hwmask);
409 }
410 
radeonInitIoctlFuncs(struct gl_context * ctx)411 void radeonInitIoctlFuncs( struct gl_context *ctx )
412 {
413     ctx->Driver.Clear = radeonClear;
414     ctx->Driver.Finish = radeonFinish;
415     ctx->Driver.Flush = radeonFlush;
416 }
417 
418