Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /************************************************************************** |
2 | * |
||
3 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. |
||
4 | * All Rights Reserved. |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the |
||
8 | * "Software"), to deal in the Software without restriction, including |
||
9 | * without limitation the rights to use, copy, modify, merge, publish, |
||
10 | * distribute, sub license, and/or sell copies of the Software, and to |
||
11 | * permit persons to whom the Software is furnished to do so, subject to |
||
12 | * the following conditions: |
||
13 | * |
||
14 | * The above copyright notice and this permission notice (including the |
||
15 | * next paragraph) shall be included in all copies or substantial portions |
||
16 | * of the Software. |
||
17 | * |
||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
||
21 | * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR |
||
22 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
||
23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
||
24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
25 | * |
||
26 | **************************************************************************/ |
||
27 | |||
28 | |||
29 | #include "main/glheader.h" |
||
30 | #include "main/context.h" |
||
31 | #include "main/extensions.h" |
||
32 | #include "main/fbobject.h" |
||
33 | #include "main/framebuffer.h" |
||
34 | #include "main/imports.h" |
||
35 | #include "main/points.h" |
||
36 | #include "main/renderbuffer.h" |
||
37 | |||
38 | #include "swrast/swrast.h" |
||
39 | #include "swrast_setup/swrast_setup.h" |
||
40 | #include "tnl/tnl.h" |
||
41 | #include "drivers/common/driverfuncs.h" |
||
42 | #include "drivers/common/meta.h" |
||
43 | |||
44 | #include "intel_chipset.h" |
||
45 | #include "intel_buffers.h" |
||
46 | #include "intel_tex.h" |
||
47 | #include "intel_batchbuffer.h" |
||
48 | #include "intel_clear.h" |
||
49 | #include "intel_extensions.h" |
||
50 | #include "intel_pixel.h" |
||
51 | #include "intel_regions.h" |
||
52 | #include "intel_buffer_objects.h" |
||
53 | #include "intel_fbo.h" |
||
54 | #include "intel_bufmgr.h" |
||
55 | #include "intel_screen.h" |
||
56 | #include "intel_mipmap_tree.h" |
||
57 | |||
58 | #include "utils.h" |
||
59 | #include "../glsl/ralloc.h" |
||
60 | |||
61 | #ifndef INTEL_DEBUG |
||
62 | int INTEL_DEBUG = (0); |
||
63 | #endif |
||
64 | |||
65 | |||
66 | static const GLubyte * |
||
67 | intelGetString(struct gl_context * ctx, GLenum name) |
||
68 | { |
||
69 | const struct intel_context *const intel = intel_context(ctx); |
||
70 | const char *chipset; |
||
71 | static char buffer[128]; |
||
4633 | Serge | 72 | static char driver_name[] = "i915_dri.drv"; |
4358 | Serge | 73 | |
74 | switch (name) { |
||
75 | case GL_VENDOR: |
||
76 | return (GLubyte *) "Intel Open Source Technology Center"; |
||
77 | break; |
||
78 | |||
79 | case GL_RENDERER: |
||
80 | switch (intel->intelScreen->deviceID) { |
||
81 | #undef CHIPSET |
||
82 | #define CHIPSET(id, symbol, str) case id: chipset = str; break; |
||
83 | #include "pci_ids/i915_pci_ids.h" |
||
84 | default: |
||
85 | chipset = "Unknown Intel Chipset"; |
||
86 | break; |
||
87 | } |
||
88 | |||
89 | (void) driGetRendererString(buffer, chipset, 0); |
||
90 | return (GLubyte *) buffer; |
||
91 | |||
4633 | Serge | 92 | case 0x1F04: /* GL_DRIVER_NAME */ |
93 | return (GLubyte*)driver_name; |
||
94 | |||
4358 | Serge | 95 | default: |
96 | return NULL; |
||
97 | } |
||
98 | } |
||
99 | |||
100 | static void |
||
101 | intel_flush_front(struct gl_context *ctx) |
||
102 | { |
||
103 | struct intel_context *intel = intel_context(ctx); |
||
104 | __DRIcontext *driContext = intel->driContext; |
||
105 | __DRIdrawable *driDrawable = driContext->driDrawablePriv; |
||
106 | __DRIscreen *const screen = intel->intelScreen->driScrnPriv; |
||
107 | |||
108 | if (intel->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
||
109 | if (screen->dri2.loader->flushFrontBuffer != NULL && |
||
110 | driDrawable && |
||
111 | driDrawable->loaderPrivate) { |
||
112 | screen->dri2.loader->flushFrontBuffer(driDrawable, |
||
113 | driDrawable->loaderPrivate); |
||
114 | |||
115 | /* We set the dirty bit in intel_prepare_render() if we're |
||
116 | * front buffer rendering once we get there. |
||
117 | */ |
||
118 | intel->front_buffer_dirty = false; |
||
119 | } |
||
120 | } |
||
121 | } |
||
122 | |||
123 | static unsigned |
||
124 | intel_bits_per_pixel(const struct intel_renderbuffer *rb) |
||
125 | { |
||
126 | return _mesa_get_format_bytes(intel_rb_format(rb)) * 8; |
||
127 | } |
||
128 | |||
129 | static void |
||
130 | intel_query_dri2_buffers(struct intel_context *intel, |
||
131 | __DRIdrawable *drawable, |
||
132 | __DRIbuffer **buffers, |
||
133 | int *count); |
||
134 | |||
135 | static void |
||
136 | intel_process_dri2_buffer(struct intel_context *intel, |
||
137 | __DRIdrawable *drawable, |
||
138 | __DRIbuffer *buffer, |
||
139 | struct intel_renderbuffer *rb, |
||
140 | const char *buffer_name); |
||
141 | |||
142 | void |
||
143 | intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) |
||
144 | { |
||
145 | struct gl_framebuffer *fb = drawable->driverPrivate; |
||
146 | struct intel_renderbuffer *rb; |
||
147 | struct intel_context *intel = context->driverPrivate; |
||
148 | __DRIbuffer *buffers = NULL; |
||
149 | int i, count; |
||
150 | const char *region_name; |
||
151 | |||
152 | /* Set this up front, so that in case our buffers get invalidated |
||
153 | * while we're getting new buffers, we don't clobber the stamp and |
||
154 | * thus ignore the invalidate. */ |
||
155 | drawable->lastStamp = drawable->dri2.stamp; |
||
156 | |||
157 | if (unlikely(INTEL_DEBUG & DEBUG_DRI)) |
||
158 | fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); |
||
159 | |||
160 | intel_query_dri2_buffers(intel, drawable, &buffers, &count); |
||
161 | |||
162 | if (buffers == NULL) |
||
163 | return; |
||
164 | |||
165 | for (i = 0; i < count; i++) { |
||
166 | switch (buffers[i].attachment) { |
||
167 | case __DRI_BUFFER_FRONT_LEFT: |
||
168 | rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
||
169 | region_name = "dri2 front buffer"; |
||
170 | break; |
||
171 | |||
172 | case __DRI_BUFFER_FAKE_FRONT_LEFT: |
||
173 | rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
||
174 | region_name = "dri2 fake front buffer"; |
||
175 | break; |
||
176 | |||
177 | case __DRI_BUFFER_BACK_LEFT: |
||
178 | rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); |
||
179 | region_name = "dri2 back buffer"; |
||
180 | break; |
||
181 | |||
182 | case __DRI_BUFFER_DEPTH: |
||
183 | case __DRI_BUFFER_HIZ: |
||
184 | case __DRI_BUFFER_DEPTH_STENCIL: |
||
185 | case __DRI_BUFFER_STENCIL: |
||
186 | case __DRI_BUFFER_ACCUM: |
||
187 | default: |
||
188 | fprintf(stderr, |
||
189 | "unhandled buffer attach event, attachment type %d\n", |
||
190 | buffers[i].attachment); |
||
191 | return; |
||
192 | } |
||
193 | |||
194 | intel_process_dri2_buffer(intel, drawable, &buffers[i], rb, region_name); |
||
195 | } |
||
196 | |||
197 | driUpdateFramebufferSize(&intel->ctx, drawable); |
||
198 | } |
||
199 | |||
200 | /** |
||
201 | * intel_prepare_render should be called anywhere that curent read/drawbuffer |
||
202 | * state is required. |
||
203 | */ |
||
204 | void |
||
205 | intel_prepare_render(struct intel_context *intel) |
||
206 | { |
||
207 | __DRIcontext *driContext = intel->driContext; |
||
208 | __DRIdrawable *drawable; |
||
209 | |||
210 | drawable = driContext->driDrawablePriv; |
||
211 | if (drawable && drawable->dri2.stamp != driContext->dri2.draw_stamp) { |
||
212 | if (drawable->lastStamp != drawable->dri2.stamp) |
||
213 | intel_update_renderbuffers(driContext, drawable); |
||
214 | intel_draw_buffer(&intel->ctx); |
||
215 | driContext->dri2.draw_stamp = drawable->dri2.stamp; |
||
216 | } |
||
217 | |||
218 | drawable = driContext->driReadablePriv; |
||
219 | if (drawable && drawable->dri2.stamp != driContext->dri2.read_stamp) { |
||
220 | if (drawable->lastStamp != drawable->dri2.stamp) |
||
221 | intel_update_renderbuffers(driContext, drawable); |
||
222 | driContext->dri2.read_stamp = drawable->dri2.stamp; |
||
223 | } |
||
224 | |||
225 | /* If we're currently rendering to the front buffer, the rendering |
||
226 | * that will happen next will probably dirty the front buffer. So |
||
227 | * mark it as dirty here. |
||
228 | */ |
||
229 | if (intel->is_front_buffer_rendering) |
||
230 | intel->front_buffer_dirty = true; |
||
231 | |||
232 | /* Wait for the swapbuffers before the one we just emitted, so we |
||
233 | * don't get too many swaps outstanding for apps that are GPU-heavy |
||
234 | * but not CPU-heavy. |
||
235 | * |
||
236 | * We're using intelDRI2Flush (called from the loader before |
||
237 | * swapbuffer) and glFlush (for front buffer rendering) as the |
||
238 | * indicator that a frame is done and then throttle when we get |
||
239 | * here as we prepare to render the next frame. At this point for |
||
240 | * round trips for swap/copy and getting new buffers are done and |
||
241 | * we'll spend less time waiting on the GPU. |
||
242 | * |
||
243 | * Unfortunately, we don't have a handle to the batch containing |
||
244 | * the swap, and getting our hands on that doesn't seem worth it, |
||
245 | * so we just us the first batch we emitted after the last swap. |
||
246 | */ |
||
247 | if (intel->need_throttle && intel->first_post_swapbuffers_batch) { |
||
248 | if (!intel->disable_throttling) |
||
249 | drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch); |
||
250 | drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); |
||
251 | intel->first_post_swapbuffers_batch = NULL; |
||
252 | intel->need_throttle = false; |
||
253 | } |
||
254 | } |
||
255 | |||
256 | static void |
||
257 | intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
||
258 | { |
||
259 | struct intel_context *intel = intel_context(ctx); |
||
260 | __DRIcontext *driContext = intel->driContext; |
||
261 | |||
262 | if (intel->saved_viewport) |
||
263 | intel->saved_viewport(ctx, x, y, w, h); |
||
264 | |||
265 | if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
||
266 | dri2InvalidateDrawable(driContext->driDrawablePriv); |
||
267 | dri2InvalidateDrawable(driContext->driReadablePriv); |
||
268 | } |
||
269 | } |
||
270 | |||
271 | static const struct dri_debug_control debug_control[] = { |
||
272 | { "tex", DEBUG_TEXTURE}, |
||
273 | { "state", DEBUG_STATE}, |
||
274 | { "blit", DEBUG_BLIT}, |
||
275 | { "mip", DEBUG_MIPTREE}, |
||
276 | { "fall", DEBUG_PERF}, |
||
277 | { "perf", DEBUG_PERF}, |
||
278 | { "bat", DEBUG_BATCH}, |
||
279 | { "pix", DEBUG_PIXEL}, |
||
280 | { "buf", DEBUG_BUFMGR}, |
||
281 | { "reg", DEBUG_REGION}, |
||
282 | { "fbo", DEBUG_FBO}, |
||
283 | { "fs", DEBUG_WM }, |
||
284 | { "sync", DEBUG_SYNC}, |
||
285 | { "dri", DEBUG_DRI }, |
||
286 | { "stats", DEBUG_STATS }, |
||
287 | { "wm", DEBUG_WM }, |
||
288 | { "aub", DEBUG_AUB }, |
||
289 | { NULL, 0 } |
||
290 | }; |
||
291 | |||
292 | |||
293 | static void |
||
294 | intelInvalidateState(struct gl_context * ctx, GLuint new_state) |
||
295 | { |
||
296 | struct intel_context *intel = intel_context(ctx); |
||
297 | |||
298 | if (ctx->swrast_context) |
||
299 | _swrast_InvalidateState(ctx, new_state); |
||
300 | _vbo_InvalidateState(ctx, new_state); |
||
301 | |||
302 | intel->NewGLState |= new_state; |
||
303 | |||
304 | if (intel->vtbl.invalidate_state) |
||
305 | intel->vtbl.invalidate_state( intel, new_state ); |
||
306 | } |
||
307 | |||
308 | void |
||
309 | intel_flush_rendering_to_batch(struct gl_context *ctx) |
||
310 | { |
||
311 | struct intel_context *intel = intel_context(ctx); |
||
312 | |||
313 | if (intel->Fallback) |
||
314 | _swrast_flush(ctx); |
||
315 | |||
316 | INTEL_FIREVERTICES(intel); |
||
317 | } |
||
318 | |||
319 | void |
||
320 | _intel_flush(struct gl_context *ctx, const char *file, int line) |
||
321 | { |
||
322 | struct intel_context *intel = intel_context(ctx); |
||
323 | |||
324 | intel_flush_rendering_to_batch(ctx); |
||
325 | |||
326 | if (intel->batch.used) |
||
327 | _intel_batchbuffer_flush(intel, file, line); |
||
328 | } |
||
329 | |||
330 | static void |
||
331 | intel_glFlush(struct gl_context *ctx) |
||
332 | { |
||
333 | struct intel_context *intel = intel_context(ctx); |
||
334 | |||
335 | intel_flush(ctx); |
||
336 | intel_flush_front(ctx); |
||
337 | if (intel->is_front_buffer_rendering) |
||
338 | intel->need_throttle = true; |
||
339 | } |
||
340 | |||
341 | void |
||
342 | intelFinish(struct gl_context * ctx) |
||
343 | { |
||
344 | struct intel_context *intel = intel_context(ctx); |
||
345 | |||
346 | intel_flush(ctx); |
||
347 | intel_flush_front(ctx); |
||
348 | |||
349 | if (intel->batch.last_bo) |
||
350 | drm_intel_bo_wait_rendering(intel->batch.last_bo); |
||
351 | } |
||
352 | |||
353 | void |
||
354 | intelInitDriverFunctions(struct dd_function_table *functions) |
||
355 | { |
||
356 | _mesa_init_driver_functions(functions); |
||
357 | |||
358 | functions->Flush = intel_glFlush; |
||
359 | functions->Finish = intelFinish; |
||
360 | functions->GetString = intelGetString; |
||
361 | functions->UpdateState = intelInvalidateState; |
||
362 | |||
363 | intelInitTextureFuncs(functions); |
||
364 | intelInitTextureImageFuncs(functions); |
||
365 | intelInitTextureSubImageFuncs(functions); |
||
366 | intelInitTextureCopyImageFuncs(functions); |
||
367 | intelInitClearFuncs(functions); |
||
368 | intelInitBufferFuncs(functions); |
||
369 | intelInitPixelFuncs(functions); |
||
370 | intelInitBufferObjectFuncs(functions); |
||
371 | intel_init_syncobj_functions(functions); |
||
372 | } |
||
373 | |||
374 | static bool |
||
375 | validate_context_version(struct intel_screen *screen, |
||
376 | int mesa_api, |
||
377 | unsigned major_version, |
||
378 | unsigned minor_version, |
||
379 | unsigned *dri_ctx_error) |
||
380 | { |
||
381 | unsigned req_version = 10 * major_version + minor_version; |
||
382 | unsigned max_version = 0; |
||
383 | |||
384 | switch (mesa_api) { |
||
385 | case API_OPENGL_COMPAT: |
||
386 | max_version = screen->max_gl_compat_version; |
||
387 | break; |
||
388 | case API_OPENGL_CORE: |
||
389 | max_version = screen->max_gl_core_version; |
||
390 | break; |
||
391 | case API_OPENGLES: |
||
392 | max_version = screen->max_gl_es1_version; |
||
393 | break; |
||
394 | case API_OPENGLES2: |
||
395 | max_version = screen->max_gl_es2_version; |
||
396 | break; |
||
397 | default: |
||
398 | max_version = 0; |
||
399 | break; |
||
400 | } |
||
401 | |||
402 | if (max_version == 0) { |
||
403 | *dri_ctx_error = __DRI_CTX_ERROR_BAD_API; |
||
404 | return false; |
||
405 | } else if (req_version > max_version) { |
||
406 | *dri_ctx_error = __DRI_CTX_ERROR_BAD_VERSION; |
||
407 | return false; |
||
408 | } |
||
409 | |||
410 | return true; |
||
411 | } |
||
412 | |||
413 | bool |
||
414 | intelInitContext(struct intel_context *intel, |
||
415 | int api, |
||
416 | unsigned major_version, |
||
417 | unsigned minor_version, |
||
418 | const struct gl_config * mesaVis, |
||
419 | __DRIcontext * driContextPriv, |
||
420 | void *sharedContextPrivate, |
||
421 | struct dd_function_table *functions, |
||
422 | unsigned *dri_ctx_error) |
||
423 | { |
||
424 | struct gl_context *ctx = &intel->ctx; |
||
425 | struct gl_context *shareCtx = (struct gl_context *) sharedContextPrivate; |
||
426 | __DRIscreen *sPriv = driContextPriv->driScreenPriv; |
||
427 | struct intel_screen *intelScreen = sPriv->driverPrivate; |
||
428 | int bo_reuse_mode; |
||
429 | struct gl_config visual; |
||
430 | |||
431 | /* we can't do anything without a connection to the device */ |
||
432 | if (intelScreen->bufmgr == NULL) { |
||
433 | *dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY; |
||
434 | return false; |
||
435 | } |
||
436 | |||
437 | if (!validate_context_version(intelScreen, |
||
438 | api, major_version, minor_version, |
||
439 | dri_ctx_error)) |
||
440 | return false; |
||
441 | |||
442 | /* Can't rely on invalidate events, fall back to glViewport hack */ |
||
443 | if (!driContextPriv->driScreenPriv->dri2.useInvalidate) { |
||
444 | intel->saved_viewport = functions->Viewport; |
||
445 | functions->Viewport = intel_viewport; |
||
446 | } |
||
447 | |||
448 | if (mesaVis == NULL) { |
||
449 | memset(&visual, 0, sizeof visual); |
||
450 | mesaVis = &visual; |
||
451 | } |
||
452 | |||
453 | intel->intelScreen = intelScreen; |
||
454 | |||
455 | if (!_mesa_initialize_context(&intel->ctx, api, mesaVis, shareCtx, |
||
456 | functions)) { |
||
457 | *dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY; |
||
458 | printf("%s: failed to init mesa context\n", __FUNCTION__); |
||
459 | return false; |
||
460 | } |
||
461 | |||
462 | driContextPriv->driverPrivate = intel; |
||
463 | intel->driContext = driContextPriv; |
||
464 | intel->driFd = sPriv->fd; |
||
465 | |||
466 | intel->gen = intelScreen->gen; |
||
467 | |||
468 | const int devID = intelScreen->deviceID; |
||
469 | |||
470 | intel->is_945 = IS_945(devID); |
||
471 | |||
472 | intel->has_swizzling = intel->intelScreen->hw_has_swizzling; |
||
473 | |||
474 | memset(&ctx->TextureFormatSupported, |
||
475 | 0, sizeof(ctx->TextureFormatSupported)); |
||
476 | |||
477 | driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache, |
||
478 | sPriv->myNum, "i915"); |
||
479 | intel->maxBatchSize = 4096; |
||
480 | |||
481 | /* Estimate the size of the mappable aperture into the GTT. There's an |
||
482 | * ioctl to get the whole GTT size, but not one to get the mappable subset. |
||
483 | * It turns out it's basically always 256MB, though some ancient hardware |
||
484 | * was smaller. |
||
485 | */ |
||
486 | uint32_t gtt_size = 256 * 1024 * 1024; |
||
487 | if (intel->gen == 2) |
||
488 | gtt_size = 128 * 1024 * 1024; |
||
489 | |||
490 | /* We don't want to map two objects such that a memcpy between them would |
||
491 | * just fault one mapping in and then the other over and over forever. So |
||
492 | * we would need to divide the GTT size by 2. Additionally, some GTT is |
||
493 | * taken up by things like the framebuffer and the ringbuffer and such, so |
||
494 | * be more conservative. |
||
495 | */ |
||
496 | intel->max_gtt_map_object_size = gtt_size / 4; |
||
497 | |||
498 | intel->bufmgr = intelScreen->bufmgr; |
||
499 | |||
500 | bo_reuse_mode = driQueryOptioni(&intel->optionCache, "bo_reuse"); |
||
501 | switch (bo_reuse_mode) { |
||
502 | case DRI_CONF_BO_REUSE_DISABLED: |
||
503 | break; |
||
504 | case DRI_CONF_BO_REUSE_ALL: |
||
505 | intel_bufmgr_gem_enable_reuse(intel->bufmgr); |
||
506 | break; |
||
507 | } |
||
508 | |||
509 | ctx->Const.MinLineWidth = 1.0; |
||
510 | ctx->Const.MinLineWidthAA = 1.0; |
||
511 | ctx->Const.MaxLineWidth = 5.0; |
||
512 | ctx->Const.MaxLineWidthAA = 5.0; |
||
513 | ctx->Const.LineWidthGranularity = 0.5; |
||
514 | |||
515 | ctx->Const.MinPointSize = 1.0; |
||
516 | ctx->Const.MinPointSizeAA = 1.0; |
||
517 | ctx->Const.MaxPointSize = 255.0; |
||
518 | ctx->Const.MaxPointSizeAA = 3.0; |
||
519 | ctx->Const.PointSizeGranularity = 1.0; |
||
520 | |||
521 | ctx->Const.StripTextureBorder = GL_TRUE; |
||
522 | |||
523 | /* reinitialize the context point state. |
||
524 | * It depend on constants in __struct gl_contextRec::Const |
||
525 | */ |
||
526 | _mesa_init_point(ctx); |
||
527 | |||
528 | ctx->Const.MaxRenderbufferSize = 2048; |
||
529 | |||
530 | _swrast_CreateContext(ctx); |
||
531 | _vbo_CreateContext(ctx); |
||
532 | if (ctx->swrast_context) { |
||
533 | _tnl_CreateContext(ctx); |
||
534 | _swsetup_CreateContext(ctx); |
||
535 | |||
536 | /* Configure swrast to match hardware characteristics: */ |
||
537 | _swrast_allow_pixel_fog(ctx, false); |
||
538 | _swrast_allow_vertex_fog(ctx, true); |
||
539 | } |
||
540 | |||
541 | _mesa_meta_init(ctx); |
||
542 | |||
543 | intel->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24; |
||
544 | intel->hw_stipple = 1; |
||
545 | |||
546 | intel->RenderIndex = ~0; |
||
547 | |||
548 | intelInitExtensions(ctx); |
||
549 | |||
550 | INTEL_DEBUG = driParseDebugString(getenv("INTEL_DEBUG"), debug_control); |
||
551 | if (INTEL_DEBUG & DEBUG_BUFMGR) |
||
552 | dri_bufmgr_set_debug(intel->bufmgr, true); |
||
553 | if (INTEL_DEBUG & DEBUG_PERF) |
||
554 | intel->perf_debug = true; |
||
555 | |||
556 | if (INTEL_DEBUG & DEBUG_AUB) |
||
557 | drm_intel_bufmgr_gem_set_aub_dump(intel->bufmgr, true); |
||
558 | |||
559 | intel_batchbuffer_init(intel); |
||
560 | |||
561 | intel_fbo_init(intel); |
||
562 | |||
563 | intel->use_early_z = driQueryOptionb(&intel->optionCache, "early_z"); |
||
564 | |||
565 | intel->prim.primitive = ~0; |
||
566 | |||
567 | /* Force all software fallbacks */ |
||
568 | if (driQueryOptionb(&intel->optionCache, "no_rast")) { |
||
569 | fprintf(stderr, "disabling 3D rasterization\n"); |
||
570 | intel->no_rast = 1; |
||
571 | } |
||
572 | |||
573 | if (driQueryOptionb(&intel->optionCache, "always_flush_batch")) { |
||
574 | fprintf(stderr, "flushing batchbuffer before/after each draw call\n"); |
||
575 | intel->always_flush_batch = 1; |
||
576 | } |
||
577 | |||
578 | if (driQueryOptionb(&intel->optionCache, "always_flush_cache")) { |
||
579 | fprintf(stderr, "flushing GPU caches before/after each draw call\n"); |
||
580 | intel->always_flush_cache = 1; |
||
581 | } |
||
582 | |||
583 | if (driQueryOptionb(&intel->optionCache, "disable_throttling")) { |
||
584 | fprintf(stderr, "disabling flush throttling\n"); |
||
585 | intel->disable_throttling = 1; |
||
586 | } |
||
587 | |||
588 | return true; |
||
589 | } |
||
590 | |||
591 | void |
||
592 | intelDestroyContext(__DRIcontext * driContextPriv) |
||
593 | { |
||
594 | struct intel_context *intel = |
||
595 | (struct intel_context *) driContextPriv->driverPrivate; |
||
596 | struct gl_context *ctx = &intel->ctx; |
||
597 | |||
598 | assert(intel); /* should never be null */ |
||
599 | if (intel) { |
||
600 | INTEL_FIREVERTICES(intel); |
||
601 | |||
602 | /* Dump a final BMP in case the application doesn't call SwapBuffers */ |
||
603 | if (INTEL_DEBUG & DEBUG_AUB) { |
||
604 | intel_batchbuffer_flush(intel); |
||
605 | aub_dump_bmp(&intel->ctx); |
||
606 | } |
||
607 | |||
608 | _mesa_meta_free(&intel->ctx); |
||
609 | |||
610 | intel->vtbl.destroy(intel); |
||
611 | |||
612 | if (ctx->swrast_context) { |
||
613 | _swsetup_DestroyContext(&intel->ctx); |
||
614 | _tnl_DestroyContext(&intel->ctx); |
||
615 | } |
||
616 | _vbo_DestroyContext(&intel->ctx); |
||
617 | |||
618 | if (ctx->swrast_context) |
||
619 | _swrast_DestroyContext(&intel->ctx); |
||
620 | intel->Fallback = 0x0; /* don't call _swrast_Flush later */ |
||
621 | |||
622 | intel_batchbuffer_free(intel); |
||
623 | |||
624 | free(intel->prim.vb); |
||
625 | intel->prim.vb = NULL; |
||
626 | drm_intel_bo_unreference(intel->prim.vb_bo); |
||
627 | intel->prim.vb_bo = NULL; |
||
628 | drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); |
||
629 | intel->first_post_swapbuffers_batch = NULL; |
||
630 | |||
631 | driDestroyOptionCache(&intel->optionCache); |
||
632 | |||
633 | /* free the Mesa context */ |
||
634 | _mesa_free_context_data(&intel->ctx); |
||
635 | |||
636 | _math_matrix_dtr(&intel->ViewportMatrix); |
||
637 | |||
638 | ralloc_free(intel); |
||
639 | driContextPriv->driverPrivate = NULL; |
||
640 | } |
||
641 | } |
||
642 | |||
643 | GLboolean |
||
644 | intelUnbindContext(__DRIcontext * driContextPriv) |
||
645 | { |
||
646 | /* Unset current context and dispath table */ |
||
647 | _mesa_make_current(NULL, NULL, NULL); |
||
648 | |||
649 | return true; |
||
650 | } |
||
651 | |||
652 | GLboolean |
||
653 | intelMakeCurrent(__DRIcontext * driContextPriv, |
||
654 | __DRIdrawable * driDrawPriv, |
||
655 | __DRIdrawable * driReadPriv) |
||
656 | { |
||
657 | struct intel_context *intel; |
||
658 | GET_CURRENT_CONTEXT(curCtx); |
||
659 | |||
660 | if (driContextPriv) |
||
661 | intel = (struct intel_context *) driContextPriv->driverPrivate; |
||
662 | else |
||
663 | intel = NULL; |
||
664 | |||
665 | /* According to the glXMakeCurrent() man page: "Pending commands to |
||
666 | * the previous context, if any, are flushed before it is released." |
||
667 | * But only flush if we're actually changing contexts. |
||
668 | */ |
||
669 | if (intel_context(curCtx) && intel_context(curCtx) != intel) { |
||
670 | _mesa_flush(curCtx); |
||
671 | } |
||
672 | |||
673 | if (driContextPriv) { |
||
674 | struct gl_context *ctx = &intel->ctx; |
||
675 | struct gl_framebuffer *fb, *readFb; |
||
676 | |||
677 | if (driDrawPriv == NULL && driReadPriv == NULL) { |
||
678 | fb = _mesa_get_incomplete_framebuffer(); |
||
679 | readFb = _mesa_get_incomplete_framebuffer(); |
||
680 | } else { |
||
681 | fb = driDrawPriv->driverPrivate; |
||
682 | readFb = driReadPriv->driverPrivate; |
||
683 | driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; |
||
684 | driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; |
||
685 | } |
||
686 | |||
687 | intel_prepare_render(intel); |
||
688 | _mesa_make_current(ctx, fb, readFb); |
||
689 | |||
690 | /* We do this in intel_prepare_render() too, but intel->ctx.DrawBuffer |
||
691 | * is NULL at that point. We can't call _mesa_makecurrent() |
||
692 | * first, since we need the buffer size for the initial |
||
693 | * viewport. So just call intel_draw_buffer() again here. */ |
||
694 | intel_draw_buffer(ctx); |
||
695 | } |
||
696 | else { |
||
697 | _mesa_make_current(NULL, NULL, NULL); |
||
698 | } |
||
699 | |||
700 | return true; |
||
701 | } |
||
702 | |||
703 | /** |
||
704 | * \brief Query DRI2 to obtain a DRIdrawable's buffers. |
||
705 | * |
||
706 | * To determine which DRI buffers to request, examine the renderbuffers |
||
707 | * attached to the drawable's framebuffer. Then request the buffers with |
||
708 | * DRI2GetBuffers() or DRI2GetBuffersWithFormat(). |
||
709 | * |
||
710 | * This is called from intel_update_renderbuffers(). |
||
711 | * |
||
712 | * \param drawable Drawable whose buffers are queried. |
||
713 | * \param buffers [out] List of buffers returned by DRI2 query. |
||
714 | * \param buffer_count [out] Number of buffers returned. |
||
715 | * |
||
716 | * \see intel_update_renderbuffers() |
||
717 | * \see DRI2GetBuffers() |
||
718 | * \see DRI2GetBuffersWithFormat() |
||
719 | */ |
||
720 | static void |
||
721 | intel_query_dri2_buffers(struct intel_context *intel, |
||
722 | __DRIdrawable *drawable, |
||
723 | __DRIbuffer **buffers, |
||
724 | int *buffer_count) |
||
725 | { |
||
726 | __DRIscreen *screen = intel->intelScreen->driScrnPriv; |
||
727 | struct gl_framebuffer *fb = drawable->driverPrivate; |
||
728 | int i = 0; |
||
729 | unsigned attachments[8]; |
||
730 | |||
731 | struct intel_renderbuffer *front_rb; |
||
732 | struct intel_renderbuffer *back_rb; |
||
733 | |||
734 | front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
||
735 | back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); |
||
736 | |||
737 | memset(attachments, 0, sizeof(attachments)); |
||
738 | if ((intel->is_front_buffer_rendering || |
||
739 | intel->is_front_buffer_reading || |
||
740 | !back_rb) && front_rb) { |
||
741 | /* If a fake front buffer is in use, then querying for |
||
742 | * __DRI_BUFFER_FRONT_LEFT will cause the server to copy the image from |
||
743 | * the real front buffer to the fake front buffer. So before doing the |
||
744 | * query, we need to make sure all the pending drawing has landed in the |
||
745 | * real front buffer. |
||
746 | */ |
||
747 | intel_flush(&intel->ctx); |
||
748 | intel_flush_front(&intel->ctx); |
||
749 | |||
750 | attachments[i++] = __DRI_BUFFER_FRONT_LEFT; |
||
751 | attachments[i++] = intel_bits_per_pixel(front_rb); |
||
752 | } else if (front_rb && intel->front_buffer_dirty) { |
||
753 | /* We have pending front buffer rendering, but we aren't querying for a |
||
754 | * front buffer. If the front buffer we have is a fake front buffer, |
||
755 | * the X server is going to throw it away when it processes the query. |
||
756 | * So before doing the query, make sure all the pending drawing has |
||
757 | * landed in the real front buffer. |
||
758 | */ |
||
759 | intel_flush(&intel->ctx); |
||
760 | intel_flush_front(&intel->ctx); |
||
761 | } |
||
762 | |||
763 | if (back_rb) { |
||
764 | attachments[i++] = __DRI_BUFFER_BACK_LEFT; |
||
765 | attachments[i++] = intel_bits_per_pixel(back_rb); |
||
766 | } |
||
767 | |||
768 | assert(i <= ARRAY_SIZE(attachments)); |
||
769 | |||
770 | *buffers = screen->dri2.loader->getBuffersWithFormat(drawable, |
||
771 | &drawable->w, |
||
772 | &drawable->h, |
||
773 | attachments, i / 2, |
||
774 | buffer_count, |
||
775 | drawable->loaderPrivate); |
||
776 | } |
||
777 | |||
778 | /** |
||
779 | * \brief Assign a DRI buffer's DRM region to a renderbuffer. |
||
780 | * |
||
781 | * This is called from intel_update_renderbuffers(). |
||
782 | * |
||
783 | * \par Note: |
||
784 | * DRI buffers whose attachment point is DRI2BufferStencil or |
||
785 | * DRI2BufferDepthStencil are handled as special cases. |
||
786 | * |
||
787 | * \param buffer_name is a human readable name, such as "dri2 front buffer", |
||
788 | * that is passed to intel_region_alloc_for_handle(). |
||
789 | * |
||
790 | * \see intel_update_renderbuffers() |
||
791 | * \see intel_region_alloc_for_handle() |
||
792 | */ |
||
793 | static void |
||
794 | intel_process_dri2_buffer(struct intel_context *intel, |
||
795 | __DRIdrawable *drawable, |
||
796 | __DRIbuffer *buffer, |
||
797 | struct intel_renderbuffer *rb, |
||
798 | const char *buffer_name) |
||
799 | { |
||
800 | struct intel_region *region = NULL; |
||
801 | |||
802 | if (!rb) |
||
803 | return; |
||
804 | |||
805 | /* We try to avoid closing and reopening the same BO name, because the first |
||
806 | * use of a mapping of the buffer involves a bunch of page faulting which is |
||
807 | * moderately expensive. |
||
808 | */ |
||
809 | if (rb->mt && |
||
810 | rb->mt->region && |
||
811 | rb->mt->region->name == buffer->name) |
||
812 | return; |
||
813 | |||
814 | if (unlikely(INTEL_DEBUG & DEBUG_DRI)) { |
||
815 | fprintf(stderr, |
||
816 | "attaching buffer %d, at %d, cpp %d, pitch %d\n", |
||
817 | buffer->name, buffer->attachment, |
||
818 | buffer->cpp, buffer->pitch); |
||
819 | } |
||
820 | |||
821 | intel_miptree_release(&rb->mt); |
||
822 | region = intel_region_alloc_for_handle(intel->intelScreen, |
||
823 | buffer->cpp, |
||
824 | drawable->w, |
||
825 | drawable->h, |
||
826 | buffer->pitch, |
||
827 | buffer->name, |
||
828 | buffer_name); |
||
829 | if (!region) |
||
830 | return; |
||
831 | |||
832 | rb->mt = intel_miptree_create_for_dri2_buffer(intel, |
||
833 | buffer->attachment, |
||
834 | intel_rb_format(rb), |
||
835 | region); |
||
836 | intel_region_release(®ion); |
||
837 | }=>> |