driconf: drop now unused translation facility
[mesa.git] / src / mesa / drivers / dri / i915 / intel_screen.c
1 /**************************************************************************
2 *
3 * Copyright 2003 VMware, Inc.
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 VMWARE 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 #include <errno.h>
29 #include <time.h>
30 #include <unistd.h>
31 #include "drm-uapi/drm_fourcc.h"
32 #include "main/glheader.h"
33 #include "main/context.h"
34 #include "main/framebuffer.h"
35 #include "main/renderbuffer.h"
36 #include "main/texobj.h"
37 #include "main/hash.h"
38 #include "main/fbobject.h"
39 #include "main/version.h"
40 #include "swrast/s_renderbuffer.h"
41
42 #include "utils.h"
43 #include "util/xmlpool.h"
44 #include "util/u_memory.h"
45
46 static const __DRIconfigOptionsExtension i915_config_options = {
47 .base = { __DRI_CONFIG_OPTIONS, 1 },
48 .xml =
49
50 DRI_CONF_BEGIN
51 DRI_CONF_SECTION_PERFORMANCE
52 /* Options correspond to DRI_CONF_BO_REUSE_DISABLED,
53 * DRI_CONF_BO_REUSE_ALL
54 */
55 DRI_CONF_OPT_BEGIN_V(bo_reuse, enum, 1, "0:1")
56 DRI_CONF_DESC_BEGIN("Buffer object reuse")
57 DRI_CONF_ENUM(0, "Disable buffer object reuse")
58 DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects")
59 DRI_CONF_DESC_END
60 DRI_CONF_OPT_END
61
62 DRI_CONF_OPT_BEGIN_B(fragment_shader, "true")
63 DRI_CONF_DESC("Enable limited ARB_fragment_shader support on 915/945.")
64 DRI_CONF_OPT_END
65
66 DRI_CONF_SECTION_END
67 DRI_CONF_SECTION_QUALITY
68 DRI_CONF_SECTION_END
69 DRI_CONF_SECTION_DEBUG
70 DRI_CONF_ALWAYS_FLUSH_BATCH("false")
71 DRI_CONF_ALWAYS_FLUSH_CACHE("false")
72 DRI_CONF_DISABLE_THROTTLING("false")
73 DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN("false")
74 DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS("false")
75 DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED("false")
76
77 DRI_CONF_OPT_BEGIN_B(stub_occlusion_query, "false")
78 DRI_CONF_DESC("Enable stub ARB_occlusion_query support on 915/945.")
79 DRI_CONF_OPT_END
80
81 DRI_CONF_OPT_BEGIN_B(shader_precompile, "true")
82 DRI_CONF_DESC("Perform code generation at shader link time.")
83 DRI_CONF_OPT_END
84 DRI_CONF_SECTION_END
85 DRI_CONF_END
86 };
87
88 #include "intel_batchbuffer.h"
89 #include "intel_buffers.h"
90 #include "intel_bufmgr.h"
91 #include "intel_chipset.h"
92 #include "intel_fbo.h"
93 #include "intel_mipmap_tree.h"
94 #include "intel_screen.h"
95 #include "intel_tex.h"
96 #include "intel_regions.h"
97
98 #include "drm-uapi/i915_drm.h"
99
100 /**
101 * For debugging purposes, this returns a time in seconds.
102 */
103 double
104 get_time(void)
105 {
106 struct timespec tp;
107
108 clock_gettime(CLOCK_MONOTONIC, &tp);
109
110 return tp.tv_sec + tp.tv_nsec / 1000000000.0;
111 }
112
113 void
114 aub_dump_bmp(struct gl_context *ctx)
115 {
116 struct gl_framebuffer *fb = ctx->DrawBuffer;
117
118 for (int i = 0; i < fb->_NumColorDrawBuffers; i++) {
119 struct intel_renderbuffer *irb =
120 intel_renderbuffer(fb->_ColorDrawBuffers[i]);
121
122 if (irb && irb->mt) {
123 enum aub_dump_bmp_format format;
124
125 switch (irb->Base.Base.Format) {
126 case MESA_FORMAT_B8G8R8A8_UNORM:
127 case MESA_FORMAT_B8G8R8X8_UNORM:
128 format = AUB_DUMP_BMP_FORMAT_ARGB_8888;
129 break;
130 default:
131 continue;
132 }
133
134 assert(irb->mt->region->pitch % irb->mt->region->cpp == 0);
135 drm_intel_gem_bo_aub_dump_bmp(irb->mt->region->bo,
136 irb->draw_x,
137 irb->draw_y,
138 irb->Base.Base.Width,
139 irb->Base.Base.Height,
140 format,
141 irb->mt->region->pitch,
142 0);
143 }
144 }
145 }
146
147 static const __DRItexBufferExtension intelTexBufferExtension = {
148 .base = { __DRI_TEX_BUFFER, 3 },
149
150 .setTexBuffer = intelSetTexBuffer,
151 .setTexBuffer2 = intelSetTexBuffer2,
152 .releaseTexBuffer = NULL,
153 };
154
155 static void
156 intelDRI2Flush(__DRIdrawable *drawable)
157 {
158 GET_CURRENT_CONTEXT(ctx);
159 struct intel_context *intel = intel_context(ctx);
160 if (intel == NULL)
161 return;
162
163 INTEL_FIREVERTICES(intel);
164
165 intel->need_throttle = true;
166
167 if (intel->batch.used)
168 intel_batchbuffer_flush(intel);
169
170 if (INTEL_DEBUG & DEBUG_AUB) {
171 aub_dump_bmp(ctx);
172 }
173 }
174
175 static const struct __DRI2flushExtensionRec intelFlushExtension = {
176 .base = { __DRI2_FLUSH, 3 },
177
178 .flush = intelDRI2Flush,
179 .invalidate = dri2InvalidateDrawable,
180 };
181
182 static struct intel_image_format intel_image_formats[] = {
183 { DRM_FORMAT_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1,
184 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
185
186 { __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1,
187 { { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8, 4 } } },
188
189 { DRM_FORMAT_XRGB8888, __DRI_IMAGE_COMPONENTS_RGB, 1,
190 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } },
191
192 { DRM_FORMAT_YUV410, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
193 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
194 { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 },
195 { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } },
196
197 { DRM_FORMAT_YUV411, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
198 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
199 { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 },
200 { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
201
202 { DRM_FORMAT_YUV420, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
203 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
204 { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 },
205 { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } },
206
207 { DRM_FORMAT_YUV422, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
208 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
209 { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 },
210 { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
211
212 { DRM_FORMAT_YUV444, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
213 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
214 { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
215 { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
216
217 { DRM_FORMAT_NV12, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
218 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
219 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } },
220
221 { DRM_FORMAT_NV16, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
222 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
223 { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } },
224
225 /* For YUYV and UYVY buffers, we set up two overlapping DRI images
226 * and treat them as planar buffers in the compositors.
227 * Plane 0 is GR88 and samples YU or YV pairs and places Y into
228 * the R component, while plane 1 is ARGB/ABGR and samples YUYV/UYVY
229 * clusters and places pairs and places U into the G component and
230 * V into A. This lets the texture sampler interpolate the Y
231 * components correctly when sampling from plane 0, and interpolate
232 * U and V correctly when sampling from plane 1. */
233 { DRM_FORMAT_YUYV, __DRI_IMAGE_COMPONENTS_Y_XUXV, 2,
234 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
235 { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
236 { DRM_FORMAT_UYVY, __DRI_IMAGE_COMPONENTS_Y_UXVX, 2,
237 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
238 { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } }
239 };
240
241 static __DRIimage *
242 intel_allocate_image(int dri_format, void *loaderPrivate)
243 {
244 __DRIimage *image;
245
246 image = calloc(1, sizeof *image);
247 if (image == NULL)
248 return NULL;
249
250 image->dri_format = dri_format;
251 image->offset = 0;
252
253 image->format = driImageFormatToGLFormat(dri_format);
254 if (dri_format != __DRI_IMAGE_FORMAT_NONE &&
255 image->format == MESA_FORMAT_NONE) {
256 free(image);
257 return NULL;
258 }
259
260 image->internal_format = _mesa_get_format_base_format(image->format);
261 image->data = loaderPrivate;
262
263 return image;
264 }
265
266 /**
267 * Sets up a DRIImage structure to point to our shared image in a region
268 */
269 static void
270 intel_setup_image_from_mipmap_tree(struct intel_context *intel, __DRIimage *image,
271 struct intel_mipmap_tree *mt, GLuint level,
272 GLuint zoffset)
273 {
274 unsigned int draw_x, draw_y;
275 uint32_t mask_x, mask_y;
276
277 intel_miptree_check_level_layer(mt, level, zoffset);
278
279 intel_region_get_tile_masks(mt->region, &mask_x, &mask_y);
280 intel_miptree_get_image_offset(mt, level, zoffset, &draw_x, &draw_y);
281
282 image->width = mt->level[level].width;
283 image->height = mt->level[level].height;
284 image->tile_x = draw_x & mask_x;
285 image->tile_y = draw_y & mask_y;
286
287 image->offset = intel_region_get_aligned_offset(mt->region,
288 draw_x & ~mask_x,
289 draw_y & ~mask_y);
290
291 intel_region_reference(&image->region, mt->region);
292 }
293
294 static void
295 intel_setup_image_from_dimensions(__DRIimage *image)
296 {
297 image->width = image->region->width;
298 image->height = image->region->height;
299 image->tile_x = 0;
300 image->tile_y = 0;
301 }
302
303 static __DRIimage *
304 intel_create_image_from_name(__DRIscreen *screen,
305 int width, int height, int format,
306 int name, int pitch, void *loaderPrivate)
307 {
308 struct intel_screen *intelScreen = screen->driverPrivate;
309 __DRIimage *image;
310 int cpp;
311
312 image = intel_allocate_image(format, loaderPrivate);
313 if (image == NULL)
314 return NULL;
315
316 if (image->format == MESA_FORMAT_NONE)
317 cpp = 1;
318 else
319 cpp = _mesa_get_format_bytes(image->format);
320 image->region = intel_region_alloc_for_handle(intelScreen,
321 cpp, width, height,
322 pitch * cpp, name, "image");
323 if (image->region == NULL) {
324 free(image);
325 return NULL;
326 }
327
328 intel_setup_image_from_dimensions(image);
329
330 return image;
331 }
332
333 static __DRIimage *
334 intel_create_image_from_renderbuffer(__DRIcontext *context,
335 int renderbuffer, void *loaderPrivate)
336 {
337 __DRIimage *image;
338 struct intel_context *intel = context->driverPrivate;
339 struct gl_renderbuffer *rb;
340 struct intel_renderbuffer *irb;
341
342 rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer);
343 if (!rb) {
344 _mesa_error(&intel->ctx,
345 GL_INVALID_OPERATION, "glRenderbufferExternalMESA");
346 return NULL;
347 }
348
349 irb = intel_renderbuffer(rb);
350 image = calloc(1, sizeof *image);
351 if (image == NULL)
352 return NULL;
353
354 image->internal_format = rb->InternalFormat;
355 image->format = rb->Format;
356 image->offset = 0;
357 image->data = loaderPrivate;
358 intel_region_reference(&image->region, irb->mt->region);
359 intel_setup_image_from_dimensions(image);
360 image->dri_format = driGLFormatToImageFormat(image->format);
361
362 rb->NeedsFinishRenderTexture = true;
363 return image;
364 }
365
366 static __DRIimage *
367 intel_create_image_from_texture(__DRIcontext *context, int target,
368 unsigned texture, int zoffset,
369 int level,
370 unsigned *error,
371 void *loaderPrivate)
372 {
373 __DRIimage *image;
374 struct intel_context *intel = context->driverPrivate;
375 struct gl_texture_object *obj;
376 struct intel_texture_object *iobj;
377 GLuint face = 0;
378
379 obj = _mesa_lookup_texture(&intel->ctx, texture);
380 if (!obj || obj->Target != target) {
381 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
382 return NULL;
383 }
384
385 if (target == GL_TEXTURE_CUBE_MAP)
386 face = zoffset;
387
388 _mesa_test_texobj_completeness(&intel->ctx, obj);
389 iobj = intel_texture_object(obj);
390 if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
391 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
392 return NULL;
393 }
394
395 if (level < obj->BaseLevel || level > obj->_MaxLevel) {
396 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
397 return NULL;
398 }
399
400 if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < zoffset) {
401 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
402 return NULL;
403 }
404 image = calloc(1, sizeof *image);
405 if (image == NULL) {
406 *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
407 return NULL;
408 }
409
410 image->internal_format = obj->Image[face][level]->InternalFormat;
411 image->format = obj->Image[face][level]->TexFormat;
412 image->data = loaderPrivate;
413 intel_setup_image_from_mipmap_tree(intel, image, iobj->mt, level, zoffset);
414 image->dri_format = driGLFormatToImageFormat(image->format);
415 if (image->dri_format == __DRI_IMAGE_FORMAT_NONE) {
416 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
417 free(image);
418 return NULL;
419 }
420
421 *error = __DRI_IMAGE_ERROR_SUCCESS;
422 return image;
423 }
424
425 static void
426 intel_destroy_image(__DRIimage *image)
427 {
428 intel_region_release(&image->region);
429 free(image);
430 }
431
432 static __DRIimage *
433 intel_create_image(__DRIscreen *screen,
434 int width, int height, int format,
435 unsigned int use,
436 void *loaderPrivate)
437 {
438 __DRIimage *image;
439 struct intel_screen *intelScreen = screen->driverPrivate;
440 uint32_t tiling;
441 int cpp;
442
443 tiling = I915_TILING_X;
444 if (use & __DRI_IMAGE_USE_CURSOR) {
445 if (width != 64 || height != 64)
446 return NULL;
447 tiling = I915_TILING_NONE;
448 }
449
450 if (use & __DRI_IMAGE_USE_LINEAR)
451 tiling = I915_TILING_NONE;
452
453 image = intel_allocate_image(format, loaderPrivate);
454 if (image == NULL)
455 return NULL;
456
457 cpp = _mesa_get_format_bytes(image->format);
458 image->region =
459 intel_region_alloc(intelScreen, tiling, cpp, width, height, true);
460 if (image->region == NULL) {
461 free(image);
462 return NULL;
463 }
464
465 intel_setup_image_from_dimensions(image);
466
467 return image;
468 }
469
470 static GLboolean
471 intel_query_image(__DRIimage *image, int attrib, int *value)
472 {
473 switch (attrib) {
474 case __DRI_IMAGE_ATTRIB_STRIDE:
475 *value = image->region->pitch;
476 return true;
477 case __DRI_IMAGE_ATTRIB_HANDLE:
478 *value = image->region->bo->handle;
479 return true;
480 case __DRI_IMAGE_ATTRIB_NAME:
481 return intel_region_flink(image->region, (uint32_t *) value);
482 case __DRI_IMAGE_ATTRIB_FORMAT:
483 *value = image->dri_format;
484 return true;
485 case __DRI_IMAGE_ATTRIB_WIDTH:
486 *value = image->region->width;
487 return true;
488 case __DRI_IMAGE_ATTRIB_HEIGHT:
489 *value = image->region->height;
490 return true;
491 case __DRI_IMAGE_ATTRIB_COMPONENTS:
492 if (image->planar_format == NULL)
493 return false;
494 *value = image->planar_format->components;
495 return true;
496 case __DRI_IMAGE_ATTRIB_FD:
497 return !drm_intel_bo_gem_export_to_prime(image->region->bo, value);
498 default:
499 return false;
500 }
501 }
502
503 static __DRIimage *
504 intel_dup_image(__DRIimage *orig_image, void *loaderPrivate)
505 {
506 __DRIimage *image;
507
508 image = calloc(1, sizeof *image);
509 if (image == NULL)
510 return NULL;
511
512 intel_region_reference(&image->region, orig_image->region);
513 if (image->region == NULL) {
514 free(image);
515 return NULL;
516 }
517
518 image->internal_format = orig_image->internal_format;
519 image->planar_format = orig_image->planar_format;
520 image->dri_format = orig_image->dri_format;
521 image->format = orig_image->format;
522 image->offset = orig_image->offset;
523 image->width = orig_image->width;
524 image->height = orig_image->height;
525 image->tile_x = orig_image->tile_x;
526 image->tile_y = orig_image->tile_y;
527 image->data = loaderPrivate;
528
529 memcpy(image->strides, orig_image->strides, sizeof(image->strides));
530 memcpy(image->offsets, orig_image->offsets, sizeof(image->offsets));
531
532 return image;
533 }
534
535 static GLboolean
536 intel_validate_usage(__DRIimage *image, unsigned int use)
537 {
538 if (use & __DRI_IMAGE_USE_CURSOR) {
539 if (image->region->width != 64 || image->region->height != 64)
540 return GL_FALSE;
541 }
542
543 return GL_TRUE;
544 }
545
546 static __DRIimage *
547 intel_create_image_from_names(__DRIscreen *screen,
548 int width, int height, int fourcc,
549 int *names, int num_names,
550 int *strides, int *offsets,
551 void *loaderPrivate)
552 {
553 struct intel_image_format *f = NULL;
554 __DRIimage *image;
555 int i, index;
556
557 if (screen == NULL || names == NULL || num_names != 1)
558 return NULL;
559
560 for (i = 0; i < ARRAY_SIZE(intel_image_formats); i++) {
561 if (intel_image_formats[i].fourcc == fourcc) {
562 f = &intel_image_formats[i];
563 }
564 }
565
566 if (f == NULL)
567 return NULL;
568
569 image = intel_create_image_from_name(screen, width, height,
570 __DRI_IMAGE_FORMAT_NONE,
571 names[0], strides[0],
572 loaderPrivate);
573
574 if (image == NULL)
575 return NULL;
576
577 image->planar_format = f;
578 for (i = 0; i < f->nplanes; i++) {
579 index = f->planes[i].buffer_index;
580 image->offsets[index] = offsets[index];
581 image->strides[index] = strides[index];
582 }
583
584 return image;
585 }
586
587 static __DRIimage *
588 intel_create_image_from_fds(__DRIscreen *screen,
589 int width, int height, int fourcc,
590 int *fds, int num_fds, int *strides, int *offsets,
591 void *loaderPrivate)
592 {
593 struct intel_screen *intelScreen = screen->driverPrivate;
594 struct intel_image_format *f = NULL;
595 __DRIimage *image;
596 int i, index;
597
598 if (fds == NULL || num_fds != 1)
599 return NULL;
600
601 for (i = 0; i < ARRAY_SIZE(intel_image_formats); i++) {
602 if (intel_image_formats[i].fourcc == fourcc) {
603 f = &intel_image_formats[i];
604 }
605 }
606
607 if (f == NULL)
608 return NULL;
609
610 image = intel_allocate_image(__DRI_IMAGE_FORMAT_NONE, loaderPrivate);
611 if (image == NULL)
612 return NULL;
613
614 image->region = intel_region_alloc_for_fd(intelScreen,
615 f->planes[0].cpp, width, height, strides[0],
616 height * strides[0], fds[0], "image");
617 if (image->region == NULL) {
618 free(image);
619 return NULL;
620 }
621
622 intel_setup_image_from_dimensions(image);
623
624 image->planar_format = f;
625 for (i = 0; i < f->nplanes; i++) {
626 index = f->planes[i].buffer_index;
627 image->offsets[index] = offsets[index];
628 image->strides[index] = strides[index];
629 }
630
631 return image;
632 }
633
634
635 static __DRIimage *
636 intel_from_planar(__DRIimage *parent, int plane, void *loaderPrivate)
637 {
638 int width, height, offset, stride, dri_format, index;
639 struct intel_image_format *f;
640 uint32_t mask_x, mask_y;
641 __DRIimage *image;
642
643 if (parent == NULL || parent->planar_format == NULL)
644 return NULL;
645
646 f = parent->planar_format;
647
648 if (plane >= f->nplanes)
649 return NULL;
650
651 width = parent->region->width >> f->planes[plane].width_shift;
652 height = parent->region->height >> f->planes[plane].height_shift;
653 dri_format = f->planes[plane].dri_format;
654 index = f->planes[plane].buffer_index;
655 offset = parent->offsets[index];
656 stride = parent->strides[index];
657
658 image = intel_allocate_image(dri_format, loaderPrivate);
659 if (image == NULL)
660 return NULL;
661
662 if (offset + height * stride > parent->region->bo->size) {
663 _mesa_warning(NULL, "intel_create_sub_image: subimage out of bounds");
664 free(image);
665 return NULL;
666 }
667
668 image->region = calloc(sizeof(*image->region), 1);
669 if (image->region == NULL) {
670 free(image);
671 return NULL;
672 }
673
674 image->region->cpp = _mesa_get_format_bytes(image->format);
675 image->region->width = width;
676 image->region->height = height;
677 image->region->pitch = stride;
678 image->region->refcount = 1;
679 image->region->bo = parent->region->bo;
680 drm_intel_bo_reference(image->region->bo);
681 image->region->tiling = parent->region->tiling;
682 image->offset = offset;
683 intel_setup_image_from_dimensions(image);
684
685 intel_region_get_tile_masks(image->region, &mask_x, &mask_y);
686 if (offset & mask_x)
687 _mesa_warning(NULL,
688 "intel_create_sub_image: offset not on tile boundary");
689
690 return image;
691 }
692
693 static const __DRIimageExtension intelImageExtension = {
694 .base = { __DRI_IMAGE, 7 },
695
696 .createImageFromName = intel_create_image_from_name,
697 .createImageFromRenderbuffer = intel_create_image_from_renderbuffer,
698 .destroyImage = intel_destroy_image,
699 .createImage = intel_create_image,
700 .queryImage = intel_query_image,
701 .dupImage = intel_dup_image,
702 .validateUsage = intel_validate_usage,
703 .createImageFromNames = intel_create_image_from_names,
704 .fromPlanar = intel_from_planar,
705 .createImageFromTexture = intel_create_image_from_texture,
706 .createImageFromFds = intel_create_image_from_fds
707 };
708
709 static int
710 i915_query_renderer_integer(__DRIscreen *psp, int param, unsigned int *value)
711 {
712 const struct intel_screen *const intelScreen =
713 (struct intel_screen *) psp->driverPrivate;
714
715 switch (param) {
716 case __DRI2_RENDERER_VENDOR_ID:
717 value[0] = 0x8086;
718 return 0;
719 case __DRI2_RENDERER_DEVICE_ID:
720 value[0] = intelScreen->deviceID;
721 return 0;
722 case __DRI2_RENDERER_ACCELERATED:
723 value[0] = 1;
724 return 0;
725 case __DRI2_RENDERER_VIDEO_MEMORY: {
726 /* Once a batch uses more than 75% of the maximum mappable size, we
727 * assume that there's some fragmentation, and we start doing extra
728 * flushing, etc. That's the big cliff apps will care about.
729 */
730 size_t aper_size;
731 size_t mappable_size;
732
733 drm_intel_get_aperture_sizes(psp->fd, &mappable_size, &aper_size);
734
735 const unsigned gpu_mappable_megabytes =
736 (aper_size / (1024 * 1024)) * 3 / 4;
737
738 const long system_memory_pages = sysconf(_SC_PHYS_PAGES);
739 const long system_page_size = sysconf(_SC_PAGE_SIZE);
740
741 if (system_memory_pages <= 0 || system_page_size <= 0)
742 return -1;
743
744 const uint64_t system_memory_bytes = (uint64_t) system_memory_pages
745 * (uint64_t) system_page_size;
746
747 const unsigned system_memory_megabytes =
748 (unsigned) (system_memory_bytes / (1024 * 1024));
749
750 value[0] = MIN2(system_memory_megabytes, gpu_mappable_megabytes);
751 return 0;
752 }
753 case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
754 value[0] = 1;
755 return 0;
756 case __DRI2_RENDERER_HAS_TEXTURE_3D:
757 value[0] = 1;
758 return 0;
759 default:
760 return driQueryRendererIntegerCommon(psp, param, value);
761 }
762
763 return -1;
764 }
765
766 static int
767 i915_query_renderer_string(__DRIscreen *psp, int param, const char **value)
768 {
769 const struct intel_screen *intelScreen =
770 (struct intel_screen *) psp->driverPrivate;
771
772 switch (param) {
773 case __DRI2_RENDERER_VENDOR_ID:
774 value[0] = i915_vendor_string;
775 return 0;
776 case __DRI2_RENDERER_DEVICE_ID:
777 value[0] = i915_get_renderer_string(intelScreen->deviceID);
778 return 0;
779 default:
780 break;
781 }
782
783 return -1;
784 }
785
786 static const __DRI2rendererQueryExtension intelRendererQueryExtension = {
787 .base = { __DRI2_RENDERER_QUERY, 1 },
788
789 .queryInteger = i915_query_renderer_integer,
790 .queryString = i915_query_renderer_string
791 };
792
793 static const __DRIextension *intelScreenExtensions[] = {
794 &intelTexBufferExtension.base,
795 &intelFenceExtension.base,
796 &intelFlushExtension.base,
797 &intelImageExtension.base,
798 &intelRendererQueryExtension.base,
799 &dri2ConfigQueryExtension.base,
800 &dri2NoErrorExtension.base,
801 NULL
802 };
803
804 static bool
805 intel_get_param(__DRIscreen *psp, int param, int *value)
806 {
807 int ret;
808 struct drm_i915_getparam gp;
809
810 memset(&gp, 0, sizeof(gp));
811 gp.param = param;
812 gp.value = value;
813
814 ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
815 if (ret) {
816 if (ret != -EINVAL)
817 _mesa_warning(NULL, "drm_i915_getparam: %d", ret);
818 return false;
819 }
820
821 return true;
822 }
823
824 static bool
825 intel_get_boolean(__DRIscreen *psp, int param)
826 {
827 int value = 0;
828 return intel_get_param(psp, param, &value) && value;
829 }
830
831 static void
832 intelDestroyScreen(__DRIscreen * sPriv)
833 {
834 struct intel_screen *intelScreen = sPriv->driverPrivate;
835
836 dri_bufmgr_destroy(intelScreen->bufmgr);
837 driDestroyOptionInfo(&intelScreen->optionCache);
838
839 free(intelScreen);
840 sPriv->driverPrivate = NULL;
841 }
842
843
844 /**
845 * This is called when we need to set up GL rendering to a new X window.
846 */
847 static GLboolean
848 intelCreateBuffer(__DRIscreen * driScrnPriv,
849 __DRIdrawable * driDrawPriv,
850 const struct gl_config * mesaVis, GLboolean isPixmap)
851 {
852 struct intel_renderbuffer *rb;
853 mesa_format rgbFormat;
854 struct gl_framebuffer *fb;
855
856 if (isPixmap)
857 return false;
858
859 fb = CALLOC_STRUCT(gl_framebuffer);
860 if (!fb)
861 return false;
862
863 _mesa_initialize_window_framebuffer(fb, mesaVis);
864
865 if (mesaVis->redBits == 5)
866 rgbFormat = MESA_FORMAT_B5G6R5_UNORM;
867 else if (mesaVis->sRGBCapable)
868 rgbFormat = MESA_FORMAT_B8G8R8A8_SRGB;
869 else if (mesaVis->alphaBits == 0)
870 rgbFormat = MESA_FORMAT_B8G8R8X8_UNORM;
871 else
872 rgbFormat = MESA_FORMAT_B8G8R8A8_UNORM;
873
874 /* setup the hardware-based renderbuffers */
875 rb = intel_create_renderbuffer(rgbFormat);
876 _mesa_attach_and_own_rb(fb, BUFFER_FRONT_LEFT, &rb->Base.Base);
877
878 if (mesaVis->doubleBufferMode) {
879 rb = intel_create_renderbuffer(rgbFormat);
880 _mesa_attach_and_own_rb(fb, BUFFER_BACK_LEFT, &rb->Base.Base);
881 }
882
883 /*
884 * Assert here that the gl_config has an expected depth/stencil bit
885 * combination: one of d24/s8, d16/s0, d0/s0. (See intelInitScreen2(),
886 * which constructs the advertised configs.)
887 */
888 if (mesaVis->depthBits == 24) {
889 assert(mesaVis->stencilBits == 8);
890
891 /*
892 * Use combined depth/stencil. Note that the renderbuffer is
893 * attached to two attachment points.
894 */
895 rb = intel_create_private_renderbuffer(MESA_FORMAT_Z24_UNORM_S8_UINT);
896 _mesa_attach_and_own_rb(fb, BUFFER_DEPTH, &rb->Base.Base);
897 _mesa_attach_and_reference_rb(fb, BUFFER_STENCIL, &rb->Base.Base);
898 }
899 else if (mesaVis->depthBits == 16) {
900 assert(mesaVis->stencilBits == 0);
901 rb = intel_create_private_renderbuffer(MESA_FORMAT_Z_UNORM16);
902 _mesa_attach_and_own_rb(fb, BUFFER_DEPTH, &rb->Base.Base);
903 }
904 else {
905 assert(mesaVis->depthBits == 0);
906 assert(mesaVis->stencilBits == 0);
907 }
908
909 /* now add any/all software-based renderbuffers we may need */
910 _swrast_add_soft_renderbuffers(fb,
911 false, /* never sw color */
912 false, /* never sw depth */
913 false, /* never sw stencil */
914 mesaVis->accumRedBits > 0,
915 false, /* never sw alpha */
916 false /* never sw aux */ );
917 driDrawPriv->driverPrivate = fb;
918
919 return true;
920 }
921
922 static void
923 intelDestroyBuffer(__DRIdrawable * driDrawPriv)
924 {
925 struct gl_framebuffer *fb = driDrawPriv->driverPrivate;
926
927 _mesa_reference_framebuffer(&fb, NULL);
928 }
929
930 /* There are probably better ways to do this, such as an
931 * init-designated function to register chipids and createcontext
932 * functions.
933 */
934 extern bool
935 i830CreateContext(int api,
936 const struct gl_config *mesaVis,
937 __DRIcontext *driContextPriv,
938 unsigned major_version,
939 unsigned minor_version,
940 uint32_t flags,
941 unsigned *error,
942 void *sharedContextPrivate);
943
944 extern bool
945 i915CreateContext(int api,
946 const struct gl_config *mesaVis,
947 __DRIcontext *driContextPriv,
948 unsigned major_version,
949 unsigned minor_version,
950 uint32_t flags,
951 unsigned *error,
952 void *sharedContextPrivate);
953
954 static GLboolean
955 intelCreateContext(gl_api api,
956 const struct gl_config * mesaVis,
957 __DRIcontext * driContextPriv,
958 const struct __DriverContextConfig *ctx_config,
959 unsigned *error,
960 void *sharedContextPrivate)
961 {
962 bool success = false;
963
964 __DRIscreen *sPriv = driContextPriv->driScreenPriv;
965 struct intel_screen *intelScreen = sPriv->driverPrivate;
966
967 if (ctx_config->flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_NO_ERROR)) {
968 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
969 return false;
970 }
971
972 if (ctx_config->attribute_mask) {
973 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
974 return false;
975 }
976
977 if (IS_GEN3(intelScreen->deviceID)) {
978 success = i915CreateContext(api, mesaVis, driContextPriv,
979 ctx_config->major_version,
980 ctx_config->minor_version,
981 ctx_config->flags,
982 error, sharedContextPrivate);
983 } else {
984 intelScreen->no_vbo = true;
985 success = i830CreateContext(api, mesaVis, driContextPriv,
986 ctx_config->major_version,
987 ctx_config->minor_version,
988 ctx_config->flags,
989 error, sharedContextPrivate);
990 }
991
992 if (success)
993 return true;
994
995 if (driContextPriv->driverPrivate != NULL)
996 intelDestroyContext(driContextPriv);
997
998 return false;
999 }
1000
1001 static bool
1002 intel_init_bufmgr(struct intel_screen *intelScreen)
1003 {
1004 __DRIscreen *spriv = intelScreen->driScrnPriv;
1005
1006 intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL;
1007
1008 intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ);
1009 if (intelScreen->bufmgr == NULL) {
1010 fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n",
1011 __func__, __LINE__);
1012 return false;
1013 }
1014
1015 drm_intel_bufmgr_gem_enable_fenced_relocs(intelScreen->bufmgr);
1016
1017 if (!intel_get_boolean(spriv, I915_PARAM_HAS_RELAXED_DELTA)) {
1018 fprintf(stderr, "[%s: %u] Kernel 2.6.39 required.\n", __func__, __LINE__);
1019 return false;
1020 }
1021
1022 return true;
1023 }
1024
1025 static __DRIconfig**
1026 intel_screen_make_configs(__DRIscreen *dri_screen)
1027 {
1028 static const mesa_format formats[] = {
1029 MESA_FORMAT_B5G6R5_UNORM,
1030 MESA_FORMAT_B8G8R8A8_UNORM,
1031 MESA_FORMAT_B8G8R8X8_UNORM
1032 };
1033
1034 /* __DRI_ATTRIB_SWAP_COPY is not supported due to page flipping. */
1035 static const GLenum back_buffer_modes[] = {
1036 __DRI_ATTRIB_SWAP_UNDEFINED, __DRI_ATTRIB_SWAP_NONE
1037 };
1038
1039 static const uint8_t singlesample_samples[1] = {0};
1040
1041 uint8_t depth_bits[4], stencil_bits[4];
1042 __DRIconfig **configs = NULL;
1043
1044 /* Generate singlesample configs without accumulation buffer. */
1045 for (int i = 0; i < ARRAY_SIZE(formats); i++) {
1046 __DRIconfig **new_configs;
1047 int num_depth_stencil_bits = 2;
1048
1049 /* Starting with DRI2 protocol version 1.1 we can request a depth/stencil
1050 * buffer that has a different number of bits per pixel than the color
1051 * buffer.
1052 */
1053 depth_bits[0] = 0;
1054 stencil_bits[0] = 0;
1055
1056 if (formats[i] == MESA_FORMAT_B5G6R5_UNORM) {
1057 depth_bits[1] = 16;
1058 stencil_bits[1] = 0;
1059 } else {
1060 depth_bits[1] = 24;
1061 stencil_bits[1] = 8;
1062 }
1063
1064 new_configs = driCreateConfigs(formats[i],
1065 depth_bits,
1066 stencil_bits,
1067 num_depth_stencil_bits,
1068 back_buffer_modes, 2,
1069 singlesample_samples, 1,
1070 false, false, false);
1071 configs = driConcatConfigs(configs, new_configs);
1072 }
1073
1074 /* Generate the minimum possible set of configs that include an
1075 * accumulation buffer.
1076 */
1077 for (int i = 0; i < ARRAY_SIZE(formats); i++) {
1078 __DRIconfig **new_configs;
1079
1080 if (formats[i] == MESA_FORMAT_B5G6R5_UNORM) {
1081 depth_bits[0] = 16;
1082 stencil_bits[0] = 0;
1083 } else {
1084 depth_bits[0] = 24;
1085 stencil_bits[0] = 8;
1086 }
1087
1088 new_configs = driCreateConfigs(formats[i],
1089 depth_bits, stencil_bits, 1,
1090 back_buffer_modes, 1,
1091 singlesample_samples, 1,
1092 true, false, false);
1093 configs = driConcatConfigs(configs, new_configs);
1094 }
1095
1096 if (configs == NULL) {
1097 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
1098 __LINE__);
1099 return NULL;
1100 }
1101
1102 return configs;
1103 }
1104
1105 static void
1106 set_max_gl_versions(struct intel_screen *screen)
1107 {
1108 __DRIscreen *psp = screen->driScrnPriv;
1109
1110 switch (screen->gen) {
1111 case 3: {
1112 bool has_fragment_shader = driQueryOptionb(&screen->optionCache, "fragment_shader");
1113 bool has_occlusion_query = driQueryOptionb(&screen->optionCache, "stub_occlusion_query");
1114
1115 psp->max_gl_core_version = 0;
1116 psp->max_gl_es1_version = 11;
1117 psp->max_gl_es2_version = 20;
1118
1119 if (has_fragment_shader && has_occlusion_query) {
1120 psp->max_gl_compat_version = 21;
1121 } else {
1122 psp->max_gl_compat_version = 14;
1123 }
1124 break;
1125 }
1126 case 2:
1127 psp->max_gl_core_version = 0;
1128 psp->max_gl_compat_version = 13;
1129 psp->max_gl_es1_version = 11;
1130 psp->max_gl_es2_version = 0;
1131 break;
1132 default:
1133 assert(!"unrecognized intel_screen::gen");
1134 break;
1135 }
1136 }
1137
1138 /**
1139 * This is the driver specific part of the createNewScreen entry point.
1140 * Called when using DRI2.
1141 *
1142 * \return the struct gl_config supported by this driver
1143 */
1144 static const
1145 __DRIconfig **intelInitScreen2(__DRIscreen *psp)
1146 {
1147 struct intel_screen *intelScreen;
1148
1149 if (psp->image.loader) {
1150 } else if (psp->dri2.loader->base.version <= 2 ||
1151 psp->dri2.loader->getBuffersWithFormat == NULL) {
1152 fprintf(stderr,
1153 "\nERROR! DRI2 loader with getBuffersWithFormat() "
1154 "support required\n");
1155 return false;
1156 }
1157
1158 /* Allocate the private area */
1159 intelScreen = calloc(1, sizeof *intelScreen);
1160 if (!intelScreen) {
1161 fprintf(stderr, "\nERROR! Allocating private area failed\n");
1162 return false;
1163 }
1164 /* parse information in __driConfigOptions */
1165 driParseOptionInfo(&intelScreen->optionCache, i915_config_options.xml);
1166
1167 intelScreen->driScrnPriv = psp;
1168 psp->driverPrivate = (void *) intelScreen;
1169
1170 if (!intel_init_bufmgr(intelScreen))
1171 return false;
1172
1173 intelScreen->deviceID = drm_intel_bufmgr_gem_get_devid(intelScreen->bufmgr);
1174
1175 if (IS_GEN3(intelScreen->deviceID)) {
1176 intelScreen->gen = 3;
1177 } else {
1178 intelScreen->gen = 2;
1179 }
1180
1181 set_max_gl_versions(intelScreen);
1182
1183 psp->extensions = intelScreenExtensions;
1184
1185 return (const __DRIconfig**) intel_screen_make_configs(psp);
1186 }
1187
1188 struct intel_buffer {
1189 __DRIbuffer base;
1190 struct intel_region *region;
1191 };
1192
1193 static __DRIbuffer *
1194 intelAllocateBuffer(__DRIscreen *screen,
1195 unsigned attachment, unsigned format,
1196 int width, int height)
1197 {
1198 struct intel_buffer *intelBuffer;
1199 struct intel_screen *intelScreen = screen->driverPrivate;
1200
1201 assert(attachment == __DRI_BUFFER_FRONT_LEFT ||
1202 attachment == __DRI_BUFFER_BACK_LEFT);
1203
1204 intelBuffer = calloc(1, sizeof *intelBuffer);
1205 if (intelBuffer == NULL)
1206 return NULL;
1207
1208 /* The front and back buffers are color buffers, which are X tiled. */
1209 intelBuffer->region = intel_region_alloc(intelScreen,
1210 I915_TILING_X,
1211 format / 8,
1212 width,
1213 height,
1214 true);
1215
1216 if (intelBuffer->region == NULL) {
1217 free(intelBuffer);
1218 return NULL;
1219 }
1220
1221 intel_region_flink(intelBuffer->region, &intelBuffer->base.name);
1222
1223 intelBuffer->base.attachment = attachment;
1224 intelBuffer->base.cpp = intelBuffer->region->cpp;
1225 intelBuffer->base.pitch = intelBuffer->region->pitch;
1226
1227 return &intelBuffer->base;
1228 }
1229
1230 static void
1231 intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
1232 {
1233 struct intel_buffer *intelBuffer = (struct intel_buffer *) buffer;
1234
1235 intel_region_release(&intelBuffer->region);
1236 free(intelBuffer);
1237 }
1238
1239
1240 static const struct __DriverAPIRec i915_driver_api = {
1241 .InitScreen = intelInitScreen2,
1242 .DestroyScreen = intelDestroyScreen,
1243 .CreateContext = intelCreateContext,
1244 .DestroyContext = intelDestroyContext,
1245 .CreateBuffer = intelCreateBuffer,
1246 .DestroyBuffer = intelDestroyBuffer,
1247 .MakeCurrent = intelMakeCurrent,
1248 .UnbindContext = intelUnbindContext,
1249 .AllocateBuffer = intelAllocateBuffer,
1250 .ReleaseBuffer = intelReleaseBuffer
1251 };
1252
1253 static const struct __DRIDriverVtableExtensionRec i915_vtable = {
1254 .base = { __DRI_DRIVER_VTABLE, 1 },
1255 .vtable = &i915_driver_api,
1256 };
1257
1258 /* This is the table of extensions that the loader will dlsym() for. */
1259 static const __DRIextension *i915_driver_extensions[] = {
1260 &driCoreExtension.base,
1261 &driImageDriverExtension.base,
1262 &driDRI2Extension.base,
1263 &i915_vtable.base,
1264 &i915_config_options.base,
1265 NULL
1266 };
1267
1268 PUBLIC const __DRIextension **__driDriverGetExtensions_i915(void)
1269 {
1270 globalDriverAPI = &i915_driver_api;
1271
1272 return i915_driver_extensions;
1273 }