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