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