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