Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 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 |
||
33 | * Gareth Hughes |
||
34 | * Keith Whitwell |
||
35 | */ |
||
36 | |||
37 | #include |
||
38 | #include |
||
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 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 | */ |
||
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 | |||
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 | */ |
||
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 | |||
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", __FUNCTION__); |
||
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", __FUNCTION__); |
||
209 | radeonFinish( &rmesa->radeon.glCtx ); |
||
210 | } |
||
211 | |||
212 | } |
||
213 | |||
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", __FUNCTION__, 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_NO_AUTOSTATE(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_NO_AUTOSTATE(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 | __FUNCTION__, 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 | |||
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|DEBUG_IOCTL)) |
||
286 | fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n", |
||
287 | __FUNCTION__, 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 | |||
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", __FUNCTION__); |
||
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 | |||
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", __FUNCTION__, swmask); |
||
403 | _swrast_Clear( ctx, swmask ); |
||
404 | } |
||
405 | |||
406 | if ( !hwmask ) |
||
407 | return; |
||
408 | |||
409 | radeonUserClear(ctx, hwmask); |
||
410 | } |
||
411 | |||
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 |