Rev 4315 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4315 | Serge | 1 | /* -*- c-basic-offset: 4 -*- */ |
2 | /* |
||
3 | * Copyright © 2006 Intel Corporation |
||
4 | * |
||
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
6 | * copy of this software and associated documentation files (the "Software"), |
||
7 | * to deal in the Software without restriction, including without limitation |
||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
9 | * and/or sell copies of the Software, and to permit persons to whom the |
||
10 | * Software is furnished to do so, subject to the following conditions: |
||
11 | * |
||
12 | * The above copyright notice and this permission notice (including the next |
||
13 | * paragraph) shall be included in all copies or substantial portions of the |
||
14 | * Software. |
||
15 | * |
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||
22 | * SOFTWARE. |
||
23 | * |
||
24 | * Authors: |
||
25 | * Eric Anholt |
||
26 | * |
||
27 | */ |
||
28 | |||
29 | #ifdef HAVE_CONFIG_H |
||
30 | #include "config.h" |
||
31 | #endif |
||
32 | |||
33 | #include |
||
34 | #include |
||
35 | #include |
||
36 | #include |
||
37 | |||
38 | //#include "xf86.h" |
||
39 | #include "intel.h" |
||
40 | #include "i830_reg.h" |
||
41 | #include "i915_drm.h" |
||
42 | #include "i965_reg.h" |
||
43 | |||
44 | //#include "uxa.h" |
||
45 | |||
46 | #define DUMP_BATCHBUFFERS NULL // "/tmp/i915-batchbuffers.dump" |
||
47 | |||
4348 | Serge | 48 | #define DBG printf |
49 | |||
4315 | Serge | 50 | static void intel_end_vertex(intel_screen_private *intel) |
51 | { |
||
52 | if (intel->vertex_bo) { |
||
53 | if (intel->vertex_used) { |
||
54 | dri_bo_subdata(intel->vertex_bo, 0, intel->vertex_used*4, intel->vertex_ptr); |
||
55 | intel->vertex_used = 0; |
||
56 | } |
||
57 | |||
58 | dri_bo_unreference(intel->vertex_bo); |
||
59 | intel->vertex_bo = NULL; |
||
60 | } |
||
61 | |||
62 | intel->vertex_id = 0; |
||
63 | } |
||
64 | |||
65 | void intel_next_vertex(intel_screen_private *intel) |
||
66 | { |
||
67 | intel_end_vertex(intel); |
||
68 | |||
69 | intel->vertex_bo = |
||
70 | dri_bo_alloc(intel->bufmgr, "vertex", sizeof (intel->vertex_ptr), 4096); |
||
71 | } |
||
72 | |||
73 | static dri_bo *bo_alloc() |
||
74 | { |
||
75 | intel_screen_private *intel = intel_get_screen_private(); |
||
76 | int size = 4 * 4096; |
||
77 | /* The 865 has issues with larger-than-page-sized batch buffers. */ |
||
78 | if (IS_I865G(intel)) |
||
79 | size = 4096; |
||
80 | return dri_bo_alloc(intel->bufmgr, "batch", size, 4096); |
||
81 | } |
||
82 | |||
83 | static void intel_next_batch(int mode) |
||
84 | { |
||
85 | intel_screen_private *intel = intel_get_screen_private(); |
||
86 | dri_bo *tmp; |
||
87 | |||
88 | drm_intel_gem_bo_clear_relocs(intel->batch_bo, 0); |
||
89 | |||
90 | tmp = intel->last_batch_bo[mode]; |
||
91 | intel->last_batch_bo[mode] = intel->batch_bo; |
||
92 | intel->batch_bo = tmp; |
||
93 | |||
94 | intel->batch_used = 0; |
||
95 | |||
96 | /* We don't know when another client has executed, so we have |
||
97 | * to reinitialize our 3D state per batch. |
||
98 | */ |
||
99 | intel->last_3d = LAST_3D_OTHER; |
||
100 | } |
||
101 | |||
102 | void intel_batch_init() |
||
103 | { |
||
104 | intel_screen_private *intel = intel_get_screen_private(); |
||
105 | |||
106 | ENTER(); |
||
107 | |||
108 | intel->batch_emit_start = 0; |
||
109 | intel->batch_emitting = 0; |
||
110 | intel->vertex_id = 0; |
||
111 | |||
112 | intel->last_batch_bo[0] = bo_alloc(); |
||
113 | intel->last_batch_bo[1] = bo_alloc(); |
||
114 | |||
115 | intel->batch_bo = bo_alloc(); |
||
116 | intel->batch_used = 0; |
||
117 | intel->last_3d = LAST_3D_OTHER; |
||
118 | |||
119 | LEAVE(); |
||
120 | } |
||
121 | |||
122 | void intel_batch_teardown() |
||
123 | { |
||
124 | intel_screen_private *intel = intel_get_screen_private(); |
||
125 | int i; |
||
126 | |||
127 | for (i = 0; i < ARRAY_SIZE(intel->last_batch_bo); i++) { |
||
128 | if (intel->last_batch_bo[i] != NULL) { |
||
129 | dri_bo_unreference(intel->last_batch_bo[i]); |
||
130 | intel->last_batch_bo[i] = NULL; |
||
131 | } |
||
132 | } |
||
133 | |||
134 | if (intel->batch_bo != NULL) { |
||
135 | dri_bo_unreference(intel->batch_bo); |
||
136 | intel->batch_bo = NULL; |
||
137 | } |
||
138 | |||
139 | if (intel->vertex_bo) { |
||
140 | dri_bo_unreference(intel->vertex_bo); |
||
141 | intel->vertex_bo = NULL; |
||
142 | } |
||
143 | |||
144 | while (!list_is_empty(&intel->batch_pixmaps)) |
||
145 | list_del(intel->batch_pixmaps.next); |
||
146 | } |
||
147 | |||
148 | static void intel_batch_do_flush() |
||
149 | { |
||
150 | intel_screen_private *intel = intel_get_screen_private(); |
||
151 | struct intel_pixmap *priv; |
||
152 | |||
153 | list_for_each_entry(priv, &intel->batch_pixmaps, batch) |
||
154 | priv->dirty = 0; |
||
155 | } |
||
156 | |||
157 | static void intel_emit_post_sync_nonzero_flush() |
||
158 | { |
||
159 | intel_screen_private *intel = intel_get_screen_private(); |
||
160 | |||
161 | /* keep this entire sequence of 3 PIPE_CONTROL cmds in one batch to |
||
162 | * avoid upsetting the gpu. */ |
||
163 | BEGIN_BATCH(3*4); |
||
164 | OUT_BATCH(BRW_PIPE_CONTROL | (4 - 2)); |
||
165 | OUT_BATCH(BRW_PIPE_CONTROL_CS_STALL | |
||
166 | BRW_PIPE_CONTROL_STALL_AT_SCOREBOARD); |
||
167 | OUT_BATCH(0); /* address */ |
||
168 | OUT_BATCH(0); /* write data */ |
||
169 | |||
170 | OUT_BATCH(BRW_PIPE_CONTROL | (4 - 2)); |
||
171 | OUT_BATCH(BRW_PIPE_CONTROL_WRITE_QWORD); |
||
172 | OUT_RELOC(intel->wa_scratch_bo, |
||
173 | I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0); |
||
174 | OUT_BATCH(0); /* write data */ |
||
175 | |||
176 | /* now finally the _real flush */ |
||
177 | OUT_BATCH(BRW_PIPE_CONTROL | (4 - 2)); |
||
178 | OUT_BATCH(BRW_PIPE_CONTROL_WC_FLUSH | |
||
179 | BRW_PIPE_CONTROL_TC_FLUSH | |
||
180 | BRW_PIPE_CONTROL_NOWRITE); |
||
181 | OUT_BATCH(0); /* write address */ |
||
182 | OUT_BATCH(0); /* write data */ |
||
183 | ADVANCE_BATCH(); |
||
184 | } |
||
185 | |||
186 | void intel_batch_emit_flush() |
||
187 | { |
||
188 | intel_screen_private *intel = intel_get_screen_private(); |
||
189 | int flags; |
||
190 | |||
191 | assert (!intel->in_batch_atomic); |
||
192 | |||
193 | /* Big hammer, look to the pipelined flushes in future. */ |
||
194 | if ((INTEL_INFO(intel)->gen >= 060)) { |
||
195 | if (intel->current_batch == BLT_BATCH) { |
||
196 | BEGIN_BATCH_BLT(4); |
||
197 | OUT_BATCH(MI_FLUSH_DW | 2); |
||
198 | OUT_BATCH(0); |
||
199 | OUT_BATCH(0); |
||
200 | OUT_BATCH(0); |
||
201 | ADVANCE_BATCH(); |
||
202 | } else { |
||
203 | if ((INTEL_INFO(intel)->gen == 060)) { |
||
204 | /* HW-Workaround for Sandybdrige */ |
||
205 | intel_emit_post_sync_nonzero_flush(); |
||
206 | } else { |
||
207 | BEGIN_BATCH(4); |
||
208 | OUT_BATCH(BRW_PIPE_CONTROL | (4 - 2)); |
||
209 | OUT_BATCH(BRW_PIPE_CONTROL_WC_FLUSH | |
||
210 | BRW_PIPE_CONTROL_TC_FLUSH | |
||
211 | BRW_PIPE_CONTROL_NOWRITE); |
||
212 | OUT_BATCH(0); /* write address */ |
||
213 | OUT_BATCH(0); /* write data */ |
||
214 | ADVANCE_BATCH(); |
||
215 | } |
||
216 | } |
||
217 | } else { |
||
218 | flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE; |
||
219 | if (INTEL_INFO(intel)->gen >= 040) |
||
220 | flags = 0; |
||
221 | |||
222 | BEGIN_BATCH(1); |
||
223 | OUT_BATCH(MI_FLUSH | flags); |
||
224 | ADVANCE_BATCH(); |
||
225 | } |
||
226 | intel_batch_do_flush(); |
||
227 | } |
||
228 | |||
229 | void intel_batch_submit() |
||
230 | { |
||
231 | intel_screen_private *intel = intel_get_screen_private(); |
||
232 | int ret; |
||
233 | |||
234 | assert (!intel->in_batch_atomic); |
||
235 | |||
236 | if (intel->vertex_flush) |
||
237 | intel->vertex_flush(intel); |
||
238 | intel_end_vertex(intel); |
||
239 | |||
240 | if (intel->batch_flush) |
||
241 | intel->batch_flush(intel); |
||
242 | |||
243 | if (intel->batch_used == 0) |
||
244 | return; |
||
245 | |||
246 | /* Mark the end of the batchbuffer. */ |
||
247 | OUT_BATCH(MI_BATCH_BUFFER_END); |
||
248 | /* Emit a padding dword if we aren't going to be quad-word aligned. */ |
||
249 | if (intel->batch_used & 1) |
||
250 | OUT_BATCH(MI_NOOP); |
||
251 | |||
252 | if (DUMP_BATCHBUFFERS) { |
||
253 | FILE *file = fopen(DUMP_BATCHBUFFERS, "a"); |
||
254 | if (file) { |
||
255 | fwrite (intel->batch_ptr, intel->batch_used*4, 1, file); |
||
256 | fclose(file); |
||
257 | } |
||
258 | } |
||
259 | |||
260 | ret = dri_bo_subdata(intel->batch_bo, 0, intel->batch_used*4, intel->batch_ptr); |
||
261 | if (ret == 0) { |
||
262 | ret = drm_intel_bo_mrb_exec(intel->batch_bo, |
||
263 | intel->batch_used*4, |
||
264 | NULL, 0, 0xffffffff, |
||
265 | (HAS_BLT(intel) ? |
||
266 | intel->current_batch: |
||
267 | I915_EXEC_DEFAULT)); |
||
268 | } |
||
269 | |||
270 | if (ret != 0) { |
||
271 | static int once; |
||
272 | if (!once) { |
||
273 | if (ret == -EIO) { |
||
274 | /* The GPU has hung and unlikely to recover by this point. */ |
||
275 | printf("Detected a hung GPU, disabling acceleration.\n"); |
||
276 | printf("When reporting this, please include i915_error_state from debugfs and the full dmesg.\n"); |
||
277 | } else { |
||
278 | /* The driver is broken. */ |
||
279 | printf("Failed to submit batch buffer, expect rendering corruption\n "); |
||
280 | } |
||
281 | // uxa_set_force_fallback(xf86ScrnToScreen(scrn), TRUE); |
||
282 | intel->force_fallback = TRUE; |
||
283 | once = 1; |
||
284 | } |
||
285 | } |
||
286 | |||
287 | while (!list_is_empty(&intel->batch_pixmaps)) { |
||
288 | struct intel_pixmap *entry; |
||
289 | |||
290 | entry = list_first_entry(&intel->batch_pixmaps, |
||
291 | struct intel_pixmap, |
||
292 | batch); |
||
293 | |||
4348 | Serge | 294 | entry->busy = -1; |
4315 | Serge | 295 | entry->dirty = 0; |
296 | list_del(&entry->batch); |
||
297 | } |
||
298 | |||
299 | if (intel->debug_flush & DEBUG_FLUSH_WAIT) |
||
300 | drm_intel_bo_wait_rendering(intel->batch_bo); |
||
301 | |||
302 | intel_next_batch(intel->current_batch == I915_EXEC_BLT); |
||
303 | |||
304 | if (intel->batch_commit_notify) |
||
305 | intel->batch_commit_notify(intel); |
||
306 | |||
307 | intel->current_batch = 0; |
||
308 | } |
||
309 | |||
310 | void intel_debug_flush() |
||
311 | { |
||
312 | intel_screen_private *intel = intel_get_screen_private(); |
||
313 | |||
314 | if (intel->debug_flush & DEBUG_FLUSH_CACHES) |
||
315 | intel_batch_emit_flush(); |
||
316 | |||
317 | if (intel->debug_flush & DEBUG_FLUSH_BATCHES) |
||
318 | intel_batch_submit(); |
||
319 | }> |