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/renderbuffer.h" |
||
36 | |||
37 | #include "swrast/swrast.h" |
||
38 | #include "swrast_setup/swrast_setup.h" |
||
39 | #include "tnl/tnl.h" |
||
40 | #include "drivers/common/driverfuncs.h" |
||
41 | #include "drivers/common/meta.h" |
||
42 | |||
43 | #include "intel_chipset.h" |
||
44 | #include "intel_buffers.h" |
||
45 | #include "intel_tex.h" |
||
46 | #include "intel_batchbuffer.h" |
||
47 | #include "intel_pixel.h" |
||
48 | #include "intel_regions.h" |
||
49 | #include "intel_buffer_objects.h" |
||
50 | #include "intel_fbo.h" |
||
51 | #include "intel_bufmgr.h" |
||
52 | #include "intel_screen.h" |
||
53 | #include "intel_mipmap_tree.h" |
||
54 | |||
55 | #include "utils.h" |
||
56 | #include "../glsl/ralloc.h" |
||
57 | |||
58 | #ifndef INTEL_DEBUG |
||
59 | int INTEL_DEBUG = (0); |
||
60 | #endif |
||
61 | |||
62 | |||
63 | static const GLubyte * |
||
64 | intelGetString(struct gl_context * ctx, GLenum name) |
||
65 | { |
||
66 | const struct brw_context *const brw = brw_context(ctx); |
||
67 | const char *chipset; |
||
68 | static char buffer[128]; |
||
4632 | Serge | 69 | static char driver_name[] = "i965_dri.drv"; |
4358 | Serge | 70 | |
71 | switch (name) { |
||
72 | case GL_VENDOR: |
||
73 | return (GLubyte *) "Intel Open Source Technology Center"; |
||
74 | break; |
||
75 | |||
76 | case GL_RENDERER: |
||
77 | switch (brw->intelScreen->deviceID) { |
||
78 | #undef CHIPSET |
||
79 | #define CHIPSET(id, symbol, str) case id: chipset = str; break; |
||
80 | #include "pci_ids/i965_pci_ids.h" |
||
81 | default: |
||
82 | chipset = "Unknown Intel Chipset"; |
||
83 | break; |
||
84 | } |
||
85 | |||
86 | (void) driGetRendererString(buffer, chipset, 0); |
||
87 | return (GLubyte *) buffer; |
||
88 | |||
4632 | Serge | 89 | case 0x1F04: /* GL_DRIVER_NAME */ |
90 | return (GLubyte*)driver_name; |
||
91 | |||
4358 | Serge | 92 | default: |
93 | return NULL; |
||
94 | } |
||
95 | } |
||
96 | |||
97 | void |
||
98 | intel_resolve_for_dri2_flush(struct brw_context *brw, |
||
99 | __DRIdrawable *drawable) |
||
100 | { |
||
101 | if (brw->gen < 6) { |
||
102 | /* MSAA and fast color clear are not supported, so don't waste time |
||
103 | * checking whether a resolve is needed. |
||
104 | */ |
||
105 | return; |
||
106 | } |
||
107 | |||
108 | struct gl_framebuffer *fb = drawable->driverPrivate; |
||
109 | struct intel_renderbuffer *rb; |
||
110 | |||
111 | /* Usually, only the back buffer will need to be downsampled. However, |
||
112 | * the front buffer will also need it if the user has rendered into it. |
||
113 | */ |
||
114 | static const gl_buffer_index buffers[2] = { |
||
115 | BUFFER_BACK_LEFT, |
||
116 | BUFFER_FRONT_LEFT, |
||
117 | }; |
||
118 | |||
119 | for (int i = 0; i < 2; ++i) { |
||
120 | rb = intel_get_renderbuffer(fb, buffers[i]); |
||
121 | if (rb == NULL || rb->mt == NULL) |
||
122 | continue; |
||
123 | if (rb->mt->num_samples <= 1) |
||
124 | intel_miptree_resolve_color(brw, rb->mt); |
||
125 | else |
||
126 | intel_miptree_downsample(brw, rb->mt); |
||
127 | } |
||
128 | } |
||
129 | |||
130 | static void |
||
131 | intel_flush_front(struct gl_context *ctx) |
||
132 | { |
||
133 | struct brw_context *brw = brw_context(ctx); |
||
134 | __DRIcontext *driContext = brw->driContext; |
||
135 | __DRIdrawable *driDrawable = driContext->driDrawablePriv; |
||
136 | __DRIscreen *const screen = brw->intelScreen->driScrnPriv; |
||
137 | |||
138 | if (brw->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
||
139 | if (screen->dri2.loader->flushFrontBuffer != NULL && |
||
140 | driDrawable && |
||
141 | driDrawable->loaderPrivate) { |
||
142 | |||
143 | /* Resolve before flushing FAKE_FRONT_LEFT to FRONT_LEFT. |
||
144 | * |
||
145 | * This potentially resolves both front and back buffer. It |
||
146 | * is unnecessary to resolve the back, but harms nothing except |
||
147 | * performance. And no one cares about front-buffer render |
||
148 | * performance. |
||
149 | */ |
||
150 | intel_resolve_for_dri2_flush(brw, driDrawable); |
||
151 | |||
152 | screen->dri2.loader->flushFrontBuffer(driDrawable, |
||
153 | driDrawable->loaderPrivate); |
||
154 | |||
155 | /* We set the dirty bit in intel_prepare_render() if we're |
||
156 | * front buffer rendering once we get there. |
||
157 | */ |
||
158 | brw->front_buffer_dirty = false; |
||
159 | } |
||
160 | } |
||
161 | } |
||
162 | |||
163 | static unsigned |
||
164 | intel_bits_per_pixel(const struct intel_renderbuffer *rb) |
||
165 | { |
||
166 | return _mesa_get_format_bytes(intel_rb_format(rb)) * 8; |
||
167 | } |
||
168 | |||
169 | static void |
||
170 | intel_query_dri2_buffers(struct brw_context *brw, |
||
171 | __DRIdrawable *drawable, |
||
172 | __DRIbuffer **buffers, |
||
173 | int *count); |
||
174 | |||
175 | static void |
||
176 | intel_process_dri2_buffer(struct brw_context *brw, |
||
177 | __DRIdrawable *drawable, |
||
178 | __DRIbuffer *buffer, |
||
179 | struct intel_renderbuffer *rb, |
||
180 | const char *buffer_name); |
||
181 | |||
182 | void |
||
183 | intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) |
||
184 | { |
||
185 | struct gl_framebuffer *fb = drawable->driverPrivate; |
||
186 | struct intel_renderbuffer *rb; |
||
187 | struct brw_context *brw = context->driverPrivate; |
||
188 | __DRIbuffer *buffers = NULL; |
||
189 | int i, count; |
||
190 | const char *region_name; |
||
191 | |||
192 | /* Set this up front, so that in case our buffers get invalidated |
||
193 | * while we're getting new buffers, we don't clobber the stamp and |
||
194 | * thus ignore the invalidate. */ |
||
195 | drawable->lastStamp = drawable->dri2.stamp; |
||
196 | |||
197 | if (unlikely(INTEL_DEBUG & DEBUG_DRI)) |
||
198 | fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); |
||
199 | |||
200 | intel_query_dri2_buffers(brw, drawable, &buffers, &count); |
||
201 | |||
202 | if (buffers == NULL) |
||
203 | return; |
||
204 | |||
205 | for (i = 0; i < count; i++) { |
||
206 | switch (buffers[i].attachment) { |
||
207 | case __DRI_BUFFER_FRONT_LEFT: |
||
208 | rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
||
209 | region_name = "dri2 front buffer"; |
||
210 | break; |
||
211 | |||
212 | case __DRI_BUFFER_FAKE_FRONT_LEFT: |
||
213 | rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
||
214 | region_name = "dri2 fake front buffer"; |
||
215 | break; |
||
216 | |||
217 | case __DRI_BUFFER_BACK_LEFT: |
||
218 | rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); |
||
219 | region_name = "dri2 back buffer"; |
||
220 | break; |
||
221 | |||
222 | case __DRI_BUFFER_DEPTH: |
||
223 | case __DRI_BUFFER_HIZ: |
||
224 | case __DRI_BUFFER_DEPTH_STENCIL: |
||
225 | case __DRI_BUFFER_STENCIL: |
||
226 | case __DRI_BUFFER_ACCUM: |
||
227 | default: |
||
228 | fprintf(stderr, |
||
229 | "unhandled buffer attach event, attachment type %d\n", |
||
230 | buffers[i].attachment); |
||
231 | return; |
||
232 | } |
||
233 | |||
234 | intel_process_dri2_buffer(brw, drawable, &buffers[i], rb, region_name); |
||
235 | } |
||
236 | |||
237 | driUpdateFramebufferSize(&brw->ctx, drawable); |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * intel_prepare_render should be called anywhere that curent read/drawbuffer |
||
242 | * state is required. |
||
243 | */ |
||
244 | void |
||
245 | intel_prepare_render(struct brw_context *brw) |
||
246 | { |
||
247 | __DRIcontext *driContext = brw->driContext; |
||
248 | __DRIdrawable *drawable; |
||
249 | |||
250 | drawable = driContext->driDrawablePriv; |
||
251 | if (drawable && drawable->dri2.stamp != driContext->dri2.draw_stamp) { |
||
252 | if (drawable->lastStamp != drawable->dri2.stamp) |
||
253 | intel_update_renderbuffers(driContext, drawable); |
||
254 | driContext->dri2.draw_stamp = drawable->dri2.stamp; |
||
255 | } |
||
256 | |||
257 | drawable = driContext->driReadablePriv; |
||
258 | if (drawable && drawable->dri2.stamp != driContext->dri2.read_stamp) { |
||
259 | if (drawable->lastStamp != drawable->dri2.stamp) |
||
260 | intel_update_renderbuffers(driContext, drawable); |
||
261 | driContext->dri2.read_stamp = drawable->dri2.stamp; |
||
262 | } |
||
263 | |||
264 | /* If we're currently rendering to the front buffer, the rendering |
||
265 | * that will happen next will probably dirty the front buffer. So |
||
266 | * mark it as dirty here. |
||
267 | */ |
||
268 | if (brw->is_front_buffer_rendering) |
||
269 | brw->front_buffer_dirty = true; |
||
270 | |||
271 | /* Wait for the swapbuffers before the one we just emitted, so we |
||
272 | * don't get too many swaps outstanding for apps that are GPU-heavy |
||
273 | * but not CPU-heavy. |
||
274 | * |
||
275 | * We're using intelDRI2Flush (called from the loader before |
||
276 | * swapbuffer) and glFlush (for front buffer rendering) as the |
||
277 | * indicator that a frame is done and then throttle when we get |
||
278 | * here as we prepare to render the next frame. At this point for |
||
279 | * round trips for swap/copy and getting new buffers are done and |
||
280 | * we'll spend less time waiting on the GPU. |
||
281 | * |
||
282 | * Unfortunately, we don't have a handle to the batch containing |
||
283 | * the swap, and getting our hands on that doesn't seem worth it, |
||
284 | * so we just us the first batch we emitted after the last swap. |
||
285 | */ |
||
286 | if (brw->need_throttle && brw->first_post_swapbuffers_batch) { |
||
287 | if (!brw->disable_throttling) |
||
288 | drm_intel_bo_wait_rendering(brw->first_post_swapbuffers_batch); |
||
289 | drm_intel_bo_unreference(brw->first_post_swapbuffers_batch); |
||
290 | brw->first_post_swapbuffers_batch = NULL; |
||
291 | brw->need_throttle = false; |
||
292 | } |
||
293 | } |
||
294 | |||
295 | static void |
||
296 | intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
||
297 | { |
||
298 | struct brw_context *brw = brw_context(ctx); |
||
299 | __DRIcontext *driContext = brw->driContext; |
||
300 | |||
301 | if (brw->saved_viewport) |
||
302 | brw->saved_viewport(ctx, x, y, w, h); |
||
303 | |||
304 | if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
||
305 | dri2InvalidateDrawable(driContext->driDrawablePriv); |
||
306 | dri2InvalidateDrawable(driContext->driReadablePriv); |
||
307 | } |
||
308 | } |
||
309 | |||
310 | static const struct dri_debug_control debug_control[] = { |
||
311 | { "tex", DEBUG_TEXTURE}, |
||
312 | { "state", DEBUG_STATE}, |
||
313 | { "ioctl", DEBUG_IOCTL}, |
||
314 | { "blit", DEBUG_BLIT}, |
||
315 | { "mip", DEBUG_MIPTREE}, |
||
316 | { "fall", DEBUG_PERF}, |
||
317 | { "perf", DEBUG_PERF}, |
||
318 | { "bat", DEBUG_BATCH}, |
||
319 | { "pix", DEBUG_PIXEL}, |
||
320 | { "buf", DEBUG_BUFMGR}, |
||
321 | { "reg", DEBUG_REGION}, |
||
322 | { "fbo", DEBUG_FBO}, |
||
323 | { "fs", DEBUG_WM }, |
||
324 | { "gs", DEBUG_GS}, |
||
325 | { "sync", DEBUG_SYNC}, |
||
326 | { "prim", DEBUG_PRIMS }, |
||
327 | { "vert", DEBUG_VERTS }, |
||
328 | { "dri", DEBUG_DRI }, |
||
329 | { "sf", DEBUG_SF }, |
||
330 | { "stats", DEBUG_STATS }, |
||
331 | { "wm", DEBUG_WM }, |
||
332 | { "urb", DEBUG_URB }, |
||
333 | { "vs", DEBUG_VS }, |
||
334 | { "clip", DEBUG_CLIP }, |
||
335 | { "aub", DEBUG_AUB }, |
||
336 | { "shader_time", DEBUG_SHADER_TIME }, |
||
337 | { "no16", DEBUG_NO16 }, |
||
338 | { "blorp", DEBUG_BLORP }, |
||
339 | { NULL, 0 } |
||
340 | }; |
||
341 | |||
342 | |||
343 | static void |
||
344 | intelInvalidateState(struct gl_context * ctx, GLuint new_state) |
||
345 | { |
||
346 | struct brw_context *brw = brw_context(ctx); |
||
347 | |||
348 | if (ctx->swrast_context) |
||
349 | _swrast_InvalidateState(ctx, new_state); |
||
350 | _vbo_InvalidateState(ctx, new_state); |
||
351 | |||
352 | brw->NewGLState |= new_state; |
||
353 | } |
||
354 | |||
355 | void |
||
356 | _intel_flush(struct gl_context *ctx, const char *file, int line) |
||
357 | { |
||
358 | struct brw_context *brw = brw_context(ctx); |
||
359 | |||
360 | if (brw->batch.used) |
||
361 | _intel_batchbuffer_flush(brw, file, line); |
||
362 | } |
||
363 | |||
364 | static void |
||
365 | intel_glFlush(struct gl_context *ctx) |
||
366 | { |
||
367 | struct brw_context *brw = brw_context(ctx); |
||
368 | |||
369 | intel_flush(ctx); |
||
370 | intel_flush_front(ctx); |
||
371 | if (brw->is_front_buffer_rendering) |
||
372 | brw->need_throttle = true; |
||
373 | } |
||
374 | |||
375 | void |
||
376 | intelFinish(struct gl_context * ctx) |
||
377 | { |
||
378 | struct brw_context *brw = brw_context(ctx); |
||
379 | |||
380 | intel_flush(ctx); |
||
381 | intel_flush_front(ctx); |
||
382 | |||
383 | if (brw->batch.last_bo) |
||
384 | drm_intel_bo_wait_rendering(brw->batch.last_bo); |
||
385 | } |
||
386 | |||
387 | void |
||
388 | intelInitDriverFunctions(struct dd_function_table *functions) |
||
389 | { |
||
390 | _mesa_init_driver_functions(functions); |
||
391 | |||
392 | functions->Flush = intel_glFlush; |
||
393 | functions->Finish = intelFinish; |
||
394 | functions->GetString = intelGetString; |
||
395 | functions->UpdateState = intelInvalidateState; |
||
396 | |||
397 | intelInitTextureFuncs(functions); |
||
398 | intelInitTextureImageFuncs(functions); |
||
399 | intelInitTextureSubImageFuncs(functions); |
||
400 | intelInitTextureCopyImageFuncs(functions); |
||
401 | intelInitClearFuncs(functions); |
||
402 | intelInitBufferFuncs(functions); |
||
403 | intelInitPixelFuncs(functions); |
||
404 | intelInitBufferObjectFuncs(functions); |
||
405 | intel_init_syncobj_functions(functions); |
||
406 | } |
||
407 | |||
408 | static bool |
||
409 | validate_context_version(struct intel_screen *screen, |
||
410 | int mesa_api, |
||
411 | unsigned major_version, |
||
412 | unsigned minor_version, |
||
413 | unsigned *dri_ctx_error) |
||
414 | { |
||
415 | unsigned req_version = 10 * major_version + minor_version; |
||
416 | unsigned max_version = 0; |
||
417 | |||
418 | switch (mesa_api) { |
||
419 | case API_OPENGL_COMPAT: |
||
420 | max_version = screen->max_gl_compat_version; |
||
421 | break; |
||
422 | case API_OPENGL_CORE: |
||
423 | max_version = screen->max_gl_core_version; |
||
424 | break; |
||
425 | case API_OPENGLES: |
||
426 | max_version = screen->max_gl_es1_version; |
||
427 | break; |
||
428 | case API_OPENGLES2: |
||
429 | max_version = screen->max_gl_es2_version; |
||
430 | break; |
||
431 | default: |
||
432 | max_version = 0; |
||
433 | break; |
||
434 | } |
||
435 | |||
436 | if (max_version == 0) { |
||
437 | *dri_ctx_error = __DRI_CTX_ERROR_BAD_API; |
||
438 | return false; |
||
439 | } else if (req_version > max_version) { |
||
440 | *dri_ctx_error = __DRI_CTX_ERROR_BAD_VERSION; |
||
441 | return false; |
||
442 | } |
||
443 | |||
444 | return true; |
||
445 | } |
||
446 | |||
447 | bool |
||
448 | intelInitContext(struct brw_context *brw, |
||
449 | int api, |
||
450 | unsigned major_version, |
||
451 | unsigned minor_version, |
||
452 | const struct gl_config * mesaVis, |
||
453 | __DRIcontext * driContextPriv, |
||
454 | void *sharedContextPrivate, |
||
455 | struct dd_function_table *functions, |
||
456 | unsigned *dri_ctx_error) |
||
457 | { |
||
458 | struct gl_context *ctx = &brw->ctx; |
||
459 | struct gl_context *shareCtx = (struct gl_context *) sharedContextPrivate; |
||
460 | __DRIscreen *sPriv = driContextPriv->driScreenPriv; |
||
461 | struct intel_screen *intelScreen = sPriv->driverPrivate; |
||
462 | int bo_reuse_mode; |
||
463 | struct gl_config visual; |
||
464 | |||
465 | /* we can't do anything without a connection to the device */ |
||
466 | if (intelScreen->bufmgr == NULL) { |
||
467 | *dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY; |
||
468 | return false; |
||
469 | } |
||
470 | |||
471 | if (!validate_context_version(intelScreen, |
||
472 | api, major_version, minor_version, |
||
473 | dri_ctx_error)) |
||
474 | return false; |
||
475 | |||
476 | /* Can't rely on invalidate events, fall back to glViewport hack */ |
||
477 | if (!driContextPriv->driScreenPriv->dri2.useInvalidate) { |
||
478 | brw->saved_viewport = functions->Viewport; |
||
479 | functions->Viewport = intel_viewport; |
||
480 | } |
||
481 | |||
482 | if (mesaVis == NULL) { |
||
483 | memset(&visual, 0, sizeof visual); |
||
484 | mesaVis = &visual; |
||
485 | } |
||
486 | |||
487 | brw->intelScreen = intelScreen; |
||
488 | |||
489 | if (!_mesa_initialize_context(&brw->ctx, api, mesaVis, shareCtx, |
||
490 | functions)) { |
||
491 | *dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY; |
||
492 | printf("%s: failed to init mesa context\n", __FUNCTION__); |
||
493 | return false; |
||
494 | } |
||
495 | |||
496 | driContextPriv->driverPrivate = brw; |
||
497 | brw->driContext = driContextPriv; |
||
498 | |||
499 | brw->gen = intelScreen->gen; |
||
500 | |||
501 | const int devID = intelScreen->deviceID; |
||
502 | if (IS_SNB_GT1(devID) || IS_IVB_GT1(devID) || IS_HSW_GT1(devID)) |
||
503 | brw->gt = 1; |
||
504 | else if (IS_SNB_GT2(devID) || IS_IVB_GT2(devID) || IS_HSW_GT2(devID)) |
||
505 | brw->gt = 2; |
||
506 | else if (IS_HSW_GT3(devID)) |
||
507 | brw->gt = 3; |
||
508 | else |
||
509 | brw->gt = 0; |
||
510 | |||
511 | if (IS_HASWELL(devID)) { |
||
512 | brw->is_haswell = true; |
||
513 | } else if (IS_BAYTRAIL(devID)) { |
||
514 | brw->is_baytrail = true; |
||
515 | brw->gt = 1; |
||
516 | } else if (IS_G4X(devID)) { |
||
517 | brw->is_g4x = true; |
||
518 | } |
||
519 | |||
520 | brw->has_separate_stencil = brw->intelScreen->hw_has_separate_stencil; |
||
521 | brw->must_use_separate_stencil = brw->intelScreen->hw_must_use_separate_stencil; |
||
522 | brw->has_hiz = brw->gen >= 6; |
||
523 | brw->has_llc = brw->intelScreen->hw_has_llc; |
||
524 | brw->has_swizzling = brw->intelScreen->hw_has_swizzling; |
||
525 | |||
526 | memset(&ctx->TextureFormatSupported, |
||
527 | 0, sizeof(ctx->TextureFormatSupported)); |
||
528 | |||
529 | driParseConfigFiles(&brw->optionCache, &intelScreen->optionCache, |
||
530 | sPriv->myNum, "i965"); |
||
531 | |||
532 | /* Estimate the size of the mappable aperture into the GTT. There's an |
||
533 | * ioctl to get the whole GTT size, but not one to get the mappable subset. |
||
534 | * It turns out it's basically always 256MB, though some ancient hardware |
||
535 | * was smaller. |
||
536 | */ |
||
537 | uint32_t gtt_size = 256 * 1024 * 1024; |
||
538 | |||
539 | /* We don't want to map two objects such that a memcpy between them would |
||
540 | * just fault one mapping in and then the other over and over forever. So |
||
541 | * we would need to divide the GTT size by 2. Additionally, some GTT is |
||
542 | * taken up by things like the framebuffer and the ringbuffer and such, so |
||
543 | * be more conservative. |
||
544 | */ |
||
545 | brw->max_gtt_map_object_size = gtt_size / 4; |
||
546 | |||
547 | brw->bufmgr = intelScreen->bufmgr; |
||
548 | |||
549 | bo_reuse_mode = driQueryOptioni(&brw->optionCache, "bo_reuse"); |
||
550 | switch (bo_reuse_mode) { |
||
551 | case DRI_CONF_BO_REUSE_DISABLED: |
||
552 | break; |
||
553 | case DRI_CONF_BO_REUSE_ALL: |
||
554 | intel_bufmgr_gem_enable_reuse(brw->bufmgr); |
||
555 | break; |
||
556 | } |
||
557 | |||
558 | /* Initialize the software rasterizer and helper modules. |
||
559 | * |
||
560 | * As of GL 3.1 core, the gen4+ driver doesn't need the swrast context for |
||
561 | * software fallbacks (which we have to support on legacy GL to do weird |
||
562 | * glDrawPixels(), glBitmap(), and other functions). |
||
563 | */ |
||
564 | if (api != API_OPENGL_CORE) { |
||
565 | _swrast_CreateContext(ctx); |
||
566 | } |
||
567 | |||
568 | _vbo_CreateContext(ctx); |
||
569 | if (ctx->swrast_context) { |
||
570 | _tnl_CreateContext(ctx); |
||
571 | _swsetup_CreateContext(ctx); |
||
572 | |||
573 | /* Configure swrast to match hardware characteristics: */ |
||
574 | _swrast_allow_pixel_fog(ctx, false); |
||
575 | _swrast_allow_vertex_fog(ctx, true); |
||
576 | } |
||
577 | |||
578 | _mesa_meta_init(ctx); |
||
579 | |||
580 | intelInitExtensions(ctx); |
||
581 | |||
582 | INTEL_DEBUG = driParseDebugString(getenv("INTEL_DEBUG"), debug_control); |
||
583 | if (INTEL_DEBUG & DEBUG_BUFMGR) |
||
584 | dri_bufmgr_set_debug(brw->bufmgr, true); |
||
585 | if ((INTEL_DEBUG & DEBUG_SHADER_TIME) && brw->gen < 7) { |
||
586 | fprintf(stderr, |
||
587 | "shader_time debugging requires gen7 (Ivybridge) or better.\n"); |
||
588 | INTEL_DEBUG &= ~DEBUG_SHADER_TIME; |
||
589 | } |
||
590 | if (INTEL_DEBUG & DEBUG_PERF) |
||
591 | brw->perf_debug = true; |
||
592 | |||
593 | if (INTEL_DEBUG & DEBUG_AUB) |
||
594 | drm_intel_bufmgr_gem_set_aub_dump(brw->bufmgr, true); |
||
595 | |||
596 | intel_batchbuffer_init(brw); |
||
597 | |||
598 | intel_fbo_init(brw); |
||
599 | |||
600 | if (!driQueryOptionb(&brw->optionCache, "hiz")) { |
||
601 | brw->has_hiz = false; |
||
602 | /* On gen6, you can only do separate stencil with HIZ. */ |
||
603 | if (brw->gen == 6) |
||
604 | brw->has_separate_stencil = false; |
||
605 | } |
||
606 | |||
607 | if (driQueryOptionb(&brw->optionCache, "always_flush_batch")) { |
||
608 | fprintf(stderr, "flushing batchbuffer before/after each draw call\n"); |
||
609 | brw->always_flush_batch = 1; |
||
610 | } |
||
611 | |||
612 | if (driQueryOptionb(&brw->optionCache, "always_flush_cache")) { |
||
613 | fprintf(stderr, "flushing GPU caches before/after each draw call\n"); |
||
614 | brw->always_flush_cache = 1; |
||
615 | } |
||
616 | |||
617 | if (driQueryOptionb(&brw->optionCache, "disable_throttling")) { |
||
618 | fprintf(stderr, "disabling flush throttling\n"); |
||
619 | brw->disable_throttling = 1; |
||
620 | } |
||
621 | |||
622 | return true; |
||
623 | } |
||
624 | |||
625 | void |
||
626 | intelDestroyContext(__DRIcontext * driContextPriv) |
||
627 | { |
||
628 | struct brw_context *brw = |
||
629 | (struct brw_context *) driContextPriv->driverPrivate; |
||
630 | struct gl_context *ctx = &brw->ctx; |
||
631 | |||
632 | assert(brw); /* should never be null */ |
||
633 | if (brw) { |
||
634 | /* Dump a final BMP in case the application doesn't call SwapBuffers */ |
||
635 | if (INTEL_DEBUG & DEBUG_AUB) { |
||
636 | intel_batchbuffer_flush(brw); |
||
637 | aub_dump_bmp(&brw->ctx); |
||
638 | } |
||
639 | |||
640 | _mesa_meta_free(&brw->ctx); |
||
641 | |||
642 | brw->vtbl.destroy(brw); |
||
643 | |||
644 | if (ctx->swrast_context) { |
||
645 | _swsetup_DestroyContext(&brw->ctx); |
||
646 | _tnl_DestroyContext(&brw->ctx); |
||
647 | } |
||
648 | _vbo_DestroyContext(&brw->ctx); |
||
649 | |||
650 | if (ctx->swrast_context) |
||
651 | _swrast_DestroyContext(&brw->ctx); |
||
652 | |||
653 | intel_batchbuffer_free(brw); |
||
654 | |||
655 | drm_intel_bo_unreference(brw->first_post_swapbuffers_batch); |
||
656 | brw->first_post_swapbuffers_batch = NULL; |
||
657 | |||
658 | driDestroyOptionCache(&brw->optionCache); |
||
659 | |||
660 | /* free the Mesa context */ |
||
661 | _mesa_free_context_data(&brw->ctx); |
||
662 | |||
663 | ralloc_free(brw); |
||
664 | driContextPriv->driverPrivate = NULL; |
||
665 | } |
||
666 | } |
||
667 | |||
668 | GLboolean |
||
669 | intelUnbindContext(__DRIcontext * driContextPriv) |
||
670 | { |
||
671 | /* Unset current context and dispath table */ |
||
672 | _mesa_make_current(NULL, NULL, NULL); |
||
673 | |||
674 | return true; |
||
675 | } |
||
676 | |||
677 | /** |
||
678 | * Fixes up the context for GLES23 with our default-to-sRGB-capable behavior |
||
679 | * on window system framebuffers. |
||
680 | * |
||
681 | * Desktop GL is fairly reasonable in its handling of sRGB: You can ask if |
||
682 | * your renderbuffer can do sRGB encode, and you can flip a switch that does |
||
683 | * sRGB encode if the renderbuffer can handle it. You can ask specifically |
||
684 | * for a visual where you're guaranteed to be capable, but it turns out that |
||
685 | * everyone just makes all their ARGB8888 visuals capable and doesn't offer |
||
686 | * incapable ones, becuase there's no difference between the two in resources |
||
687 | * used. Applications thus get built that accidentally rely on the default |
||
688 | * visual choice being sRGB, so we make ours sRGB capable. Everything sounds |
||
689 | * great... |
||
690 | * |
||
691 | * But for GLES2/3, they decided that it was silly to not turn on sRGB encode |
||
692 | * for sRGB renderbuffers you made with the GL_EXT_texture_sRGB equivalent. |
||
693 | * So they removed the enable knob and made it "if the renderbuffer is sRGB |
||
694 | * capable, do sRGB encode". Then, for your window system renderbuffers, you |
||
695 | * can ask for sRGB visuals and get sRGB encode, or not ask for sRGB visuals |
||
696 | * and get no sRGB encode (assuming that both kinds of visual are available). |
||
697 | * Thus our choice to support sRGB by default on our visuals for desktop would |
||
698 | * result in broken rendering of GLES apps that aren't expecting sRGB encode. |
||
699 | * |
||
700 | * Unfortunately, renderbuffer setup happens before a context is created. So |
||
701 | * in intel_screen.c we always set up sRGB, and here, if you're a GLES2/3 |
||
702 | * context (without an sRGB visual, though we don't have sRGB visuals exposed |
||
703 | * yet), we go turn that back off before anyone finds out. |
||
704 | */ |
||
705 | static void |
||
706 | intel_gles3_srgb_workaround(struct brw_context *brw, |
||
707 | struct gl_framebuffer *fb) |
||
708 | { |
||
709 | struct gl_context *ctx = &brw->ctx; |
||
710 | |||
711 | if (_mesa_is_desktop_gl(ctx) || !fb->Visual.sRGBCapable) |
||
712 | return; |
||
713 | |||
714 | /* Some day when we support the sRGB capable bit on visuals available for |
||
715 | * GLES, we'll need to respect that and not disable things here. |
||
716 | */ |
||
717 | fb->Visual.sRGBCapable = false; |
||
718 | for (int i = 0; i < BUFFER_COUNT; i++) { |
||
719 | if (fb->Attachment[i].Renderbuffer && |
||
720 | fb->Attachment[i].Renderbuffer->Format == MESA_FORMAT_SARGB8) { |
||
721 | fb->Attachment[i].Renderbuffer->Format = MESA_FORMAT_ARGB8888; |
||
722 | } |
||
723 | } |
||
724 | } |
||
725 | |||
726 | GLboolean |
||
727 | intelMakeCurrent(__DRIcontext * driContextPriv, |
||
728 | __DRIdrawable * driDrawPriv, |
||
729 | __DRIdrawable * driReadPriv) |
||
730 | { |
||
731 | struct brw_context *brw; |
||
732 | GET_CURRENT_CONTEXT(curCtx); |
||
733 | |||
734 | if (driContextPriv) |
||
735 | brw = (struct brw_context *) driContextPriv->driverPrivate; |
||
736 | else |
||
737 | brw = NULL; |
||
738 | |||
739 | /* According to the glXMakeCurrent() man page: "Pending commands to |
||
740 | * the previous context, if any, are flushed before it is released." |
||
741 | * But only flush if we're actually changing contexts. |
||
742 | */ |
||
743 | if (brw_context(curCtx) && brw_context(curCtx) != brw) { |
||
744 | _mesa_flush(curCtx); |
||
745 | } |
||
746 | |||
747 | if (driContextPriv) { |
||
748 | struct gl_context *ctx = &brw->ctx; |
||
749 | struct gl_framebuffer *fb, *readFb; |
||
750 | |||
751 | if (driDrawPriv == NULL && driReadPriv == NULL) { |
||
752 | fb = _mesa_get_incomplete_framebuffer(); |
||
753 | readFb = _mesa_get_incomplete_framebuffer(); |
||
754 | } else { |
||
755 | fb = driDrawPriv->driverPrivate; |
||
756 | readFb = driReadPriv->driverPrivate; |
||
757 | driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; |
||
758 | driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; |
||
759 | } |
||
760 | |||
761 | /* The sRGB workaround changes the renderbuffer's format. We must change |
||
762 | * the format before the renderbuffer's miptree get's allocated, otherwise |
||
763 | * the formats of the renderbuffer and its miptree will differ. |
||
764 | */ |
||
765 | intel_gles3_srgb_workaround(brw, fb); |
||
766 | intel_gles3_srgb_workaround(brw, readFb); |
||
767 | |||
768 | intel_prepare_render(brw); |
||
769 | _mesa_make_current(ctx, fb, readFb); |
||
770 | } |
||
771 | else { |
||
772 | _mesa_make_current(NULL, NULL, NULL); |
||
773 | } |
||
774 | |||
775 | return true; |
||
776 | } |
||
777 | |||
778 | /** |
||
779 | * \brief Query DRI2 to obtain a DRIdrawable's buffers. |
||
780 | * |
||
781 | * To determine which DRI buffers to request, examine the renderbuffers |
||
782 | * attached to the drawable's framebuffer. Then request the buffers with |
||
783 | * DRI2GetBuffers() or DRI2GetBuffersWithFormat(). |
||
784 | * |
||
785 | * This is called from intel_update_renderbuffers(). |
||
786 | * |
||
787 | * \param drawable Drawable whose buffers are queried. |
||
788 | * \param buffers [out] List of buffers returned by DRI2 query. |
||
789 | * \param buffer_count [out] Number of buffers returned. |
||
790 | * |
||
791 | * \see intel_update_renderbuffers() |
||
792 | * \see DRI2GetBuffers() |
||
793 | * \see DRI2GetBuffersWithFormat() |
||
794 | */ |
||
795 | static void |
||
796 | intel_query_dri2_buffers(struct brw_context *brw, |
||
797 | __DRIdrawable *drawable, |
||
798 | __DRIbuffer **buffers, |
||
799 | int *buffer_count) |
||
800 | { |
||
801 | __DRIscreen *screen = brw->intelScreen->driScrnPriv; |
||
802 | struct gl_framebuffer *fb = drawable->driverPrivate; |
||
803 | int i = 0; |
||
804 | unsigned attachments[8]; |
||
805 | |||
806 | struct intel_renderbuffer *front_rb; |
||
807 | struct intel_renderbuffer *back_rb; |
||
808 | |||
809 | front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
||
810 | back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); |
||
811 | |||
812 | memset(attachments, 0, sizeof(attachments)); |
||
813 | if ((brw->is_front_buffer_rendering || |
||
814 | brw->is_front_buffer_reading || |
||
815 | !back_rb) && front_rb) { |
||
816 | /* If a fake front buffer is in use, then querying for |
||
817 | * __DRI_BUFFER_FRONT_LEFT will cause the server to copy the image from |
||
818 | * the real front buffer to the fake front buffer. So before doing the |
||
819 | * query, we need to make sure all the pending drawing has landed in the |
||
820 | * real front buffer. |
||
821 | */ |
||
822 | intel_flush(&brw->ctx); |
||
823 | intel_flush_front(&brw->ctx); |
||
824 | |||
825 | attachments[i++] = __DRI_BUFFER_FRONT_LEFT; |
||
826 | attachments[i++] = intel_bits_per_pixel(front_rb); |
||
827 | } else if (front_rb && brw->front_buffer_dirty) { |
||
828 | /* We have pending front buffer rendering, but we aren't querying for a |
||
829 | * front buffer. If the front buffer we have is a fake front buffer, |
||
830 | * the X server is going to throw it away when it processes the query. |
||
831 | * So before doing the query, make sure all the pending drawing has |
||
832 | * landed in the real front buffer. |
||
833 | */ |
||
834 | intel_flush(&brw->ctx); |
||
835 | intel_flush_front(&brw->ctx); |
||
836 | } |
||
837 | |||
838 | if (back_rb) { |
||
839 | attachments[i++] = __DRI_BUFFER_BACK_LEFT; |
||
840 | attachments[i++] = intel_bits_per_pixel(back_rb); |
||
841 | } |
||
842 | |||
843 | assert(i <= ARRAY_SIZE(attachments)); |
||
844 | |||
845 | *buffers = screen->dri2.loader->getBuffersWithFormat(drawable, |
||
846 | &drawable->w, |
||
847 | &drawable->h, |
||
848 | attachments, i / 2, |
||
849 | buffer_count, |
||
850 | drawable->loaderPrivate); |
||
851 | } |
||
852 | |||
853 | /** |
||
854 | * \brief Assign a DRI buffer's DRM region to a renderbuffer. |
||
855 | * |
||
856 | * This is called from intel_update_renderbuffers(). |
||
857 | * |
||
858 | * \par Note: |
||
859 | * DRI buffers whose attachment point is DRI2BufferStencil or |
||
860 | * DRI2BufferDepthStencil are handled as special cases. |
||
861 | * |
||
862 | * \param buffer_name is a human readable name, such as "dri2 front buffer", |
||
863 | * that is passed to intel_region_alloc_for_handle(). |
||
864 | * |
||
865 | * \see intel_update_renderbuffers() |
||
866 | * \see intel_region_alloc_for_handle() |
||
867 | */ |
||
868 | static void |
||
869 | intel_process_dri2_buffer(struct brw_context *brw, |
||
870 | __DRIdrawable *drawable, |
||
871 | __DRIbuffer *buffer, |
||
872 | struct intel_renderbuffer *rb, |
||
873 | const char *buffer_name) |
||
874 | { |
||
875 | struct intel_region *region = NULL; |
||
876 | |||
877 | if (!rb) |
||
878 | return; |
||
879 | |||
880 | unsigned num_samples = rb->Base.Base.NumSamples; |
||
881 | |||
882 | /* We try to avoid closing and reopening the same BO name, because the first |
||
883 | * use of a mapping of the buffer involves a bunch of page faulting which is |
||
884 | * moderately expensive. |
||
885 | */ |
||
886 | if (num_samples == 0) { |
||
887 | if (rb->mt && |
||
888 | rb->mt->region && |
||
889 | rb->mt->region->name == buffer->name) |
||
890 | return; |
||
891 | } else { |
||
892 | if (rb->mt && |
||
893 | rb->mt->singlesample_mt && |
||
894 | rb->mt->singlesample_mt->region && |
||
895 | rb->mt->singlesample_mt->region->name == buffer->name) |
||
896 | return; |
||
897 | } |
||
898 | |||
899 | if (unlikely(INTEL_DEBUG & DEBUG_DRI)) { |
||
900 | fprintf(stderr, |
||
901 | "attaching buffer %d, at %d, cpp %d, pitch %d\n", |
||
902 | buffer->name, buffer->attachment, |
||
903 | buffer->cpp, buffer->pitch); |
||
904 | } |
||
905 | |||
906 | intel_miptree_release(&rb->mt); |
||
907 | region = intel_region_alloc_for_handle(brw->intelScreen, |
||
908 | buffer->cpp, |
||
909 | drawable->w, |
||
910 | drawable->h, |
||
911 | buffer->pitch, |
||
912 | buffer->name, |
||
913 | buffer_name); |
||
914 | if (!region) |
||
915 | return; |
||
916 | |||
917 | rb->mt = intel_miptree_create_for_dri2_buffer(brw, |
||
918 | buffer->attachment, |
||
919 | intel_rb_format(rb), |
||
920 | num_samples, |
||
921 | region); |
||
922 | intel_region_release(®ion); |
||
923 | }=>>>>=>>> |