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