intel_screen.c revision d61f07318c8678901b948fdaa8ccdf37aa3203e9
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 "main/glheader.h" 29#include "main/context.h" 30#include "main/framebuffer.h" 31#include "main/renderbuffer.h" 32 33#include "utils.h" 34#include "vblank.h" 35#include "xmlpool.h" 36 37#include "intel_batchbuffer.h" 38#include "intel_buffers.h" 39#include "intel_bufmgr.h" 40#include "intel_chipset.h" 41#include "intel_extensions.h" 42#include "intel_fbo.h" 43#include "intel_regions.h" 44#include "intel_swapbuffers.h" 45#include "intel_screen.h" 46#include "intel_span.h" 47#include "intel_tex.h" 48 49#include "i915_drm.h" 50#include "i830_dri.h" 51 52#define DRI_CONF_TEXTURE_TILING(def) \ 53 DRI_CONF_OPT_BEGIN(texture_tiling, bool, def) \ 54 DRI_CONF_DESC(en, "Enable texture tiling") \ 55 DRI_CONF_OPT_END \ 56 57PUBLIC const char __driConfigOptions[] = 58 DRI_CONF_BEGIN 59 DRI_CONF_SECTION_PERFORMANCE 60 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_ALWAYS_SYNC) 61 /* Options correspond to DRI_CONF_BO_REUSE_DISABLED, 62 * DRI_CONF_BO_REUSE_ALL 63 */ 64 DRI_CONF_OPT_BEGIN_V(bo_reuse, enum, 1, "0:1") 65 DRI_CONF_DESC_BEGIN(en, "Buffer object reuse") 66 DRI_CONF_ENUM(0, "Disable buffer object reuse") 67 DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects") 68 DRI_CONF_DESC_END 69 DRI_CONF_OPT_END 70 71#ifdef I915 72 DRI_CONF_TEXTURE_TILING(false) 73#else 74 DRI_CONF_TEXTURE_TILING(true) 75#endif 76 77 DRI_CONF_OPT_BEGIN(early_z, bool, false) 78 DRI_CONF_DESC(en, "Enable early Z in classic mode (unstable, 945-only).") 79 DRI_CONF_OPT_END 80 81 DRI_CONF_OPT_BEGIN(fragment_shader, bool, false) 82 DRI_CONF_DESC(en, "Enable limited ARB_fragment_shader support on 915/945.") 83 DRI_CONF_OPT_END 84 85 DRI_CONF_SECTION_END 86 DRI_CONF_SECTION_QUALITY 87 DRI_CONF_FORCE_S3TC_ENABLE(false) 88 DRI_CONF_ALLOW_LARGE_TEXTURES(2) 89 DRI_CONF_SECTION_END 90 DRI_CONF_SECTION_DEBUG 91 DRI_CONF_NO_RAST(false) 92 DRI_CONF_ALWAYS_FLUSH_BATCH(false) 93 DRI_CONF_ALWAYS_FLUSH_CACHE(false) 94 95 DRI_CONF_OPT_BEGIN(stub_occlusion_query, bool, false) 96 DRI_CONF_DESC(en, "Enable stub ARB_occlusion_query support on 915/945.") 97 DRI_CONF_OPT_END 98 DRI_CONF_SECTION_END 99DRI_CONF_END; 100 101const GLuint __driNConfigOptions = 11; 102 103#ifdef USE_NEW_INTERFACE 104static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; 105#endif /*USE_NEW_INTERFACE */ 106 107/** 108 * Map all the memory regions described by the screen. 109 * \return GL_TRUE if success, GL_FALSE if error. 110 */ 111GLboolean 112intelMapScreenRegions(__DRIscreen * sPriv) 113{ 114 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 115 116 if (0) 117 _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle); 118 if (intelScreen->tex.size != 0) { 119 if (drmMap(sPriv->fd, 120 intelScreen->tex.handle, 121 intelScreen->tex.size, 122 (drmAddress *) & intelScreen->tex.map) != 0) { 123 intelUnmapScreenRegions(intelScreen); 124 return GL_FALSE; 125 } 126 } 127 128 return GL_TRUE; 129} 130 131void 132intelUnmapScreenRegions(intelScreenPrivate * intelScreen) 133{ 134 if (intelScreen->tex.map) { 135 drmUnmap(intelScreen->tex.map, intelScreen->tex.size); 136 intelScreen->tex.map = NULL; 137 } 138} 139 140 141static void 142intelPrintDRIInfo(intelScreenPrivate * intelScreen, 143 __DRIscreen * sPriv, I830DRIPtr gDRIPriv) 144{ 145 fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n", 146 intelScreen->front.size, intelScreen->front.offset, 147 intelScreen->pitch); 148 fprintf(stderr, "*** Back size: 0x%x offset: 0x%x pitch: %d\n", 149 intelScreen->back.size, intelScreen->back.offset, 150 intelScreen->pitch); 151 fprintf(stderr, "*** Depth size: 0x%x offset: 0x%x pitch: %d\n", 152 intelScreen->depth.size, intelScreen->depth.offset, 153 intelScreen->pitch); 154 fprintf(stderr, "*** Texture size: 0x%x offset: 0x%x\n", 155 intelScreen->tex.size, intelScreen->tex.offset); 156 fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem); 157} 158 159 160static void 161intelPrintSAREA(const drm_i915_sarea_t * sarea) 162{ 163 fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width, 164 sarea->height); 165 fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch); 166 fprintf(stderr, 167 "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x tiled: %d\n", 168 sarea->front_offset, sarea->front_size, 169 (unsigned) sarea->front_handle, sarea->front_tiled); 170 fprintf(stderr, 171 "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x tiled: %d\n", 172 sarea->back_offset, sarea->back_size, 173 (unsigned) sarea->back_handle, sarea->back_tiled); 174 fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x tiled: %d\n", 175 sarea->depth_offset, sarea->depth_size, 176 (unsigned) sarea->depth_handle, sarea->depth_tiled); 177 fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n", 178 sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle); 179} 180 181 182/** 183 * A number of the screen parameters are obtained/computed from 184 * information in the SAREA. This function updates those parameters. 185 */ 186static void 187intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen, 188 drm_i915_sarea_t * sarea) 189{ 190 intelScreen->width = sarea->width; 191 intelScreen->height = sarea->height; 192 intelScreen->pitch = sarea->pitch; 193 194 intelScreen->front.offset = sarea->front_offset; 195 intelScreen->front.handle = sarea->front_handle; 196 intelScreen->front.size = sarea->front_size; 197 intelScreen->front.tiled = sarea->front_tiled; 198 199 intelScreen->back.offset = sarea->back_offset; 200 intelScreen->back.handle = sarea->back_handle; 201 intelScreen->back.size = sarea->back_size; 202 intelScreen->back.tiled = sarea->back_tiled; 203 204 intelScreen->depth.offset = sarea->depth_offset; 205 intelScreen->depth.handle = sarea->depth_handle; 206 intelScreen->depth.size = sarea->depth_size; 207 intelScreen->depth.tiled = sarea->depth_tiled; 208 209 if (intelScreen->driScrnPriv->ddx_version.minor >= 9) { 210 intelScreen->front.bo_handle = sarea->front_bo_handle; 211 intelScreen->back.bo_handle = sarea->back_bo_handle; 212 intelScreen->depth.bo_handle = sarea->depth_bo_handle; 213 } else { 214 intelScreen->front.bo_handle = -1; 215 intelScreen->back.bo_handle = -1; 216 intelScreen->depth.bo_handle = -1; 217 } 218 219 intelScreen->tex.offset = sarea->tex_offset; 220 intelScreen->logTextureGranularity = sarea->log_tex_granularity; 221 intelScreen->tex.handle = sarea->tex_handle; 222 intelScreen->tex.size = sarea->tex_size; 223 224 if (0) 225 intelPrintSAREA(sarea); 226} 227 228static const __DRItexOffsetExtension intelTexOffsetExtension = { 229 { __DRI_TEX_OFFSET }, 230 intelSetTexOffset, 231}; 232 233static const __DRItexBufferExtension intelTexBufferExtension = { 234 { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, 235 intelSetTexBuffer, 236 intelSetTexBuffer2, 237}; 238 239static const __DRIextension *intelScreenExtensions[] = { 240 &driReadDrawableExtension, 241 &driCopySubBufferExtension.base, 242 &driSwapControlExtension.base, 243 &driFrameTrackingExtension.base, 244 &driMediaStreamCounterExtension.base, 245 &intelTexOffsetExtension.base, 246 &intelTexBufferExtension.base, 247 NULL 248}; 249 250static GLboolean 251intel_get_param(__DRIscreen *psp, int param, int *value) 252{ 253 int ret; 254 struct drm_i915_getparam gp; 255 256 gp.param = param; 257 gp.value = value; 258 259 ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); 260 if (ret) { 261 _mesa_warning(NULL, "drm_i915_getparam: %d", ret); 262 return GL_FALSE; 263 } 264 265 return GL_TRUE; 266} 267 268static GLboolean intelInitDriver(__DRIscreen *sPriv) 269{ 270 intelScreenPrivate *intelScreen; 271 I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv; 272 drm_i915_sarea_t *sarea; 273 274 if (sPriv->devPrivSize != sizeof(I830DRIRec)) { 275 fprintf(stderr, 276 "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n"); 277 return GL_FALSE; 278 } 279 280 /* Allocate the private area */ 281 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate)); 282 if (!intelScreen) { 283 fprintf(stderr, "\nERROR! Allocating private area failed\n"); 284 return GL_FALSE; 285 } 286 /* parse information in __driConfigOptions */ 287 driParseOptionInfo(&intelScreen->optionCache, 288 __driConfigOptions, __driNConfigOptions); 289 290 intelScreen->driScrnPriv = sPriv; 291 sPriv->private = (void *) intelScreen; 292 sarea = (drm_i915_sarea_t *) 293 (((GLubyte *) sPriv->pSAREA) + gDRIPriv->sarea_priv_offset); 294 intelScreen->sarea = sarea; 295 296 intelScreen->deviceID = gDRIPriv->deviceID; 297 298 intelUpdateScreenFromSAREA(intelScreen, sarea); 299 300 if (!intelMapScreenRegions(sPriv)) { 301 fprintf(stderr, "\nERROR! mapping regions\n"); 302 _mesa_free(intelScreen); 303 sPriv->private = NULL; 304 return GL_FALSE; 305 } 306 307 if (0) 308 intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); 309 310 intelScreen->drmMinor = sPriv->drm_version.minor; 311 312 /* Determine if IRQs are active? */ 313 if (!intel_get_param(sPriv, I915_PARAM_IRQ_ACTIVE, 314 &intelScreen->irq_active)) 315 return GL_FALSE; 316 317 sPriv->extensions = intelScreenExtensions; 318 319 return GL_TRUE; 320} 321 322 323static void 324intelDestroyScreen(__DRIscreen * sPriv) 325{ 326 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 327 328 dri_bufmgr_destroy(intelScreen->bufmgr); 329 intelUnmapScreenRegions(intelScreen); 330 driDestroyOptionInfo(&intelScreen->optionCache); 331 332 FREE(intelScreen); 333 sPriv->private = NULL; 334} 335 336 337/** 338 * This is called when we need to set up GL rendering to a new X window. 339 */ 340static GLboolean 341intelCreateBuffer(__DRIscreen * driScrnPriv, 342 __DRIdrawable * driDrawPriv, 343 const __GLcontextModes * mesaVis, GLboolean isPixmap) 344{ 345 if (isPixmap) { 346 return GL_FALSE; /* not implemented */ 347 } 348 else { 349 GLboolean swStencil = (mesaVis->stencilBits > 0 && 350 mesaVis->depthBits != 24); 351 gl_format rgbFormat; 352 353 struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer); 354 355 if (!intel_fb) 356 return GL_FALSE; 357 358 _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis); 359 360 if (mesaVis->redBits == 5) 361 rgbFormat = MESA_FORMAT_RGB565; 362 else if (mesaVis->alphaBits == 0) 363 rgbFormat = MESA_FORMAT_XRGB8888; 364 else 365 rgbFormat = MESA_FORMAT_ARGB8888; 366 367 /* setup the hardware-based renderbuffers */ 368 intel_fb->color_rb[0] = intel_create_renderbuffer(rgbFormat); 369 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, 370 &intel_fb->color_rb[0]->Base); 371 372 if (mesaVis->doubleBufferMode) { 373 intel_fb->color_rb[1] = intel_create_renderbuffer(rgbFormat); 374 375 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, 376 &intel_fb->color_rb[1]->Base); 377 378 } 379 380 if (mesaVis->depthBits == 24) { 381 if (mesaVis->stencilBits == 8) { 382 /* combined depth/stencil buffer */ 383 struct intel_renderbuffer *depthStencilRb 384 = intel_create_renderbuffer(MESA_FORMAT_S8_Z24); 385 /* note: bind RB to two attachment points */ 386 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, 387 &depthStencilRb->Base); 388 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL, 389 &depthStencilRb->Base); 390 } else { 391 struct intel_renderbuffer *depthRb 392 = intel_create_renderbuffer(MESA_FORMAT_X8_Z24); 393 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, 394 &depthRb->Base); 395 } 396 } 397 else if (mesaVis->depthBits == 16) { 398 /* just 16-bit depth buffer, no hw stencil */ 399 struct intel_renderbuffer *depthRb 400 = intel_create_renderbuffer(MESA_FORMAT_Z16); 401 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base); 402 } 403 404 /* now add any/all software-based renderbuffers we may need */ 405 _mesa_add_soft_renderbuffers(&intel_fb->Base, 406 GL_FALSE, /* never sw color */ 407 GL_FALSE, /* never sw depth */ 408 swStencil, mesaVis->accumRedBits > 0, 409 GL_FALSE, /* never sw alpha */ 410 GL_FALSE /* never sw aux */ ); 411 driDrawPriv->driverPrivate = (void *) intel_fb; 412 413 return GL_TRUE; 414 } 415} 416 417static void 418intelDestroyBuffer(__DRIdrawable * driDrawPriv) 419{ 420 struct intel_framebuffer *intel_fb = driDrawPriv->driverPrivate; 421 struct intel_renderbuffer *depth_rb; 422 struct intel_renderbuffer *stencil_rb; 423 424 if (intel_fb) { 425 if (intel_fb->color_rb[0]) { 426 intel_renderbuffer_set_region(intel_fb->color_rb[0], NULL); 427 } 428 429 if (intel_fb->color_rb[1]) { 430 intel_renderbuffer_set_region(intel_fb->color_rb[1], NULL); 431 } 432 433 depth_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH); 434 if (depth_rb) { 435 intel_renderbuffer_set_region(depth_rb, NULL); 436 } 437 438 stencil_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL); 439 if (stencil_rb) { 440 intel_renderbuffer_set_region(stencil_rb, NULL); 441 } 442 } 443 444 _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL); 445} 446 447 448/** 449 * Get information about previous buffer swaps. 450 */ 451static int 452intelGetSwapInfo(__DRIdrawable * dPriv, __DRIswapInfo * sInfo) 453{ 454 struct intel_framebuffer *intel_fb; 455 456 if ((dPriv == NULL) || (dPriv->driverPrivate == NULL) 457 || (sInfo == NULL)) { 458 return -1; 459 } 460 461 intel_fb = dPriv->driverPrivate; 462 sInfo->swap_count = intel_fb->swap_count; 463 sInfo->swap_ust = intel_fb->swap_ust; 464 sInfo->swap_missed_count = intel_fb->swap_missed_count; 465 466 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) 467 ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust) 468 : 0.0; 469 470 return 0; 471} 472 473 474/* There are probably better ways to do this, such as an 475 * init-designated function to register chipids and createcontext 476 * functions. 477 */ 478extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis, 479 __DRIcontext * driContextPriv, 480 void *sharedContextPrivate); 481 482extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis, 483 __DRIcontext * driContextPriv, 484 void *sharedContextPrivate); 485extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis, 486 __DRIcontext * driContextPriv, 487 void *sharedContextPrivate); 488 489static GLboolean 490intelCreateContext(const __GLcontextModes * mesaVis, 491 __DRIcontext * driContextPriv, 492 void *sharedContextPrivate) 493{ 494 __DRIscreen *sPriv = driContextPriv->driScreenPriv; 495 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 496 497#ifdef I915 498 if (IS_9XX(intelScreen->deviceID)) { 499 if (!IS_965(intelScreen->deviceID)) { 500 return i915CreateContext(mesaVis, driContextPriv, 501 sharedContextPrivate); 502 } 503 } else { 504 intelScreen->no_vbo = GL_TRUE; 505 return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate); 506 } 507#else 508 if (IS_965(intelScreen->deviceID)) 509 return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate); 510#endif 511 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID); 512 return GL_FALSE; 513} 514 515 516static __DRIconfig ** 517intelFillInModes(__DRIscreen *psp, 518 unsigned pixel_bits, unsigned depth_bits, 519 unsigned stencil_bits, GLboolean have_back_buffer) 520{ 521 __DRIconfig **configs; 522 __GLcontextModes *m; 523 unsigned depth_buffer_factor; 524 unsigned back_buffer_factor; 525 int i; 526 527 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't 528 * support pageflipping at all. 529 */ 530 static const GLenum back_buffer_modes[] = { 531 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML 532 }; 533 534 uint8_t depth_bits_array[3]; 535 uint8_t stencil_bits_array[3]; 536 uint8_t msaa_samples_array[1]; 537 538 depth_bits_array[0] = 0; 539 depth_bits_array[1] = depth_bits; 540 depth_bits_array[2] = depth_bits; 541 542 /* Just like with the accumulation buffer, always provide some modes 543 * with a stencil buffer. It will be a sw fallback, but some apps won't 544 * care about that. 545 */ 546 stencil_bits_array[0] = 0; 547 stencil_bits_array[1] = 0; 548 if (depth_bits == 24) 549 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; 550 551 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits; 552 553 msaa_samples_array[0] = 0; 554 555 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1; 556 back_buffer_factor = (have_back_buffer) ? 3 : 1; 557 558 if (pixel_bits == 16) { 559 configs = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 560 depth_bits_array, stencil_bits_array, 561 depth_buffer_factor, back_buffer_modes, 562 back_buffer_factor, 563 msaa_samples_array, 1); 564 } 565 else { 566 __DRIconfig **configs_a8r8g8b8; 567 __DRIconfig **configs_x8r8g8b8; 568 569 configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 570 depth_bits_array, 571 stencil_bits_array, 572 depth_buffer_factor, 573 back_buffer_modes, 574 back_buffer_factor, 575 msaa_samples_array, 1); 576 configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV, 577 depth_bits_array, 578 stencil_bits_array, 579 depth_buffer_factor, 580 back_buffer_modes, 581 back_buffer_factor, 582 msaa_samples_array, 1); 583 configs = driConcatConfigs(configs_a8r8g8b8, configs_x8r8g8b8); 584 } 585 586 if (configs == NULL) { 587 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 588 __LINE__); 589 return NULL; 590 } 591 592 /* Mark the visual as slow if there are "fake" stencil bits. 593 */ 594 for (i = 0; configs[i]; i++) { 595 m = &configs[i]->modes; 596 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) { 597 m->visualRating = GLX_SLOW_CONFIG; 598 } 599 } 600 601 return configs; 602} 603 604static GLboolean 605intel_init_bufmgr(intelScreenPrivate *intelScreen) 606{ 607 int gem_kernel = 0; 608 struct drm_i915_getparam gp; 609 __DRIscreen *spriv = intelScreen->driScrnPriv; 610 int num_fences = 0; 611 612 intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL; 613 614 gp.param = I915_PARAM_HAS_GEM; 615 gp.value = &gem_kernel; 616 617 (void) drmCommandWriteRead(spriv->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); 618 619 /* If we've got a new enough DDX that's initializing GEM and giving us 620 * object handles for the shared buffers, use that. 621 */ 622 if (!intelScreen->driScrnPriv->dri2.enabled && 623 intelScreen->driScrnPriv->ddx_version.minor < 9) { 624 fprintf(stderr, "[%s:%u] Error initializing GEM.\n", 625 __func__, __LINE__); 626 return GL_FALSE; 627 } 628 629 intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ); 630 /* Otherwise, use the classic buffer manager. */ 631 if (intelScreen->bufmgr == NULL) { 632 fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n", 633 __func__, __LINE__); 634 return GL_FALSE; 635 } 636 637 if (intel_get_param(spriv, I915_PARAM_NUM_FENCES_AVAIL, &num_fences)) 638 intelScreen->kernel_exec_fencing = !!num_fences; 639 else 640 intelScreen->kernel_exec_fencing = GL_FALSE; 641 642 return GL_TRUE; 643} 644 645/** 646 * This is the driver specific part of the createNewScreen entry point. 647 * Called when using legacy DRI. 648 * 649 * \todo maybe fold this into intelInitDriver 650 * 651 * \return the __GLcontextModes supported by this driver 652 */ 653static const __DRIconfig **intelInitScreen(__DRIscreen *psp) 654{ 655 intelScreenPrivate *intelScreen; 656#ifdef I915 657 static const __DRIversion ddx_expected = { 1, 5, 0 }; 658#else 659 static const __DRIversion ddx_expected = { 1, 6, 0 }; 660#endif 661 static const __DRIversion dri_expected = { 4, 0, 0 }; 662 static const __DRIversion drm_expected = { 1, 5, 0 }; 663 I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv; 664 665 if (!driCheckDriDdxDrmVersions2("i915", 666 &psp->dri_version, &dri_expected, 667 &psp->ddx_version, &ddx_expected, 668 &psp->drm_version, &drm_expected)) { 669 return NULL; 670 } 671 672 if (!intelInitDriver(psp)) 673 return NULL; 674 675 psp->extensions = intelScreenExtensions; 676 677 intelScreen = psp->private; 678 if (!intel_init_bufmgr(intelScreen)) 679 return GL_FALSE; 680 681 return (const __DRIconfig **) 682 intelFillInModes(psp, dri_priv->cpp * 8, 683 (dri_priv->cpp == 2) ? 16 : 24, 684 (dri_priv->cpp == 2) ? 0 : 8, 1); 685} 686 687struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen) 688{ 689 /* 690 * This should probably change to have the screen allocate a dummy 691 * context at screen creation. For now just use the current context. 692 */ 693 694 GET_CURRENT_CONTEXT(ctx); 695 if (ctx == NULL) { 696 _mesa_problem(NULL, "No current context in intelScreenContext\n"); 697 return NULL; 698 } 699 return intel_context(ctx); 700} 701 702/** 703 * This is the driver specific part of the createNewScreen entry point. 704 * Called when using DRI2. 705 * 706 * \return the __GLcontextModes supported by this driver 707 */ 708static const 709__DRIconfig **intelInitScreen2(__DRIscreen *psp) 710{ 711 intelScreenPrivate *intelScreen; 712 GLenum fb_format[3]; 713 GLenum fb_type[3]; 714 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't 715 * support pageflipping at all. 716 */ 717 static const GLenum back_buffer_modes[] = { 718 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML 719 }; 720 uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1]; 721 int color; 722 __DRIconfig **configs = NULL; 723 724 /* Allocate the private area */ 725 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate)); 726 if (!intelScreen) { 727 fprintf(stderr, "\nERROR! Allocating private area failed\n"); 728 return GL_FALSE; 729 } 730 /* parse information in __driConfigOptions */ 731 driParseOptionInfo(&intelScreen->optionCache, 732 __driConfigOptions, __driNConfigOptions); 733 734 intelScreen->driScrnPriv = psp; 735 psp->private = (void *) intelScreen; 736 737 intelScreen->drmMinor = psp->drm_version.minor; 738 739 /* Determine chipset ID */ 740 if (!intel_get_param(psp, I915_PARAM_CHIPSET_ID, 741 &intelScreen->deviceID)) 742 return GL_FALSE; 743 744 if (!intel_init_bufmgr(intelScreen)) 745 return GL_FALSE; 746 747 intelScreen->irq_active = 1; 748 psp->extensions = intelScreenExtensions; 749 750 depth_bits[0] = 0; 751 stencil_bits[0] = 0; 752 depth_bits[1] = 16; 753 stencil_bits[1] = 0; 754 depth_bits[2] = 24; 755 stencil_bits[2] = 0; 756 depth_bits[3] = 24; 757 stencil_bits[3] = 8; 758 759 msaa_samples_array[0] = 0; 760 761 fb_format[0] = GL_RGB; 762 fb_type[0] = GL_UNSIGNED_SHORT_5_6_5; 763 764 fb_format[1] = GL_BGR; 765 fb_type[1] = GL_UNSIGNED_INT_8_8_8_8_REV; 766 767 fb_format[2] = GL_BGRA; 768 fb_type[2] = GL_UNSIGNED_INT_8_8_8_8_REV; 769 770 depth_bits[0] = 0; 771 stencil_bits[0] = 0; 772 773 for (color = 0; color < ARRAY_SIZE(fb_format); color++) { 774 __DRIconfig **new_configs; 775 int depth_factor; 776 777 /* With DRI2 right now, GetBuffers always returns a depth/stencil buffer 778 * with the same cpp as the drawable. So we can't support depth cpp != 779 * color cpp currently. 780 */ 781 if (fb_type[color] == GL_UNSIGNED_SHORT_5_6_5) { 782 depth_bits[1] = 16; 783 stencil_bits[1] = 0; 784 785 depth_factor = 2; 786 } else { 787 depth_bits[1] = 24; 788 stencil_bits[1] = 0; 789 depth_bits[2] = 24; 790 stencil_bits[2] = 8; 791 792 depth_factor = 3; 793 } 794 new_configs = driCreateConfigs(fb_format[color], fb_type[color], 795 depth_bits, 796 stencil_bits, 797 depth_factor, 798 back_buffer_modes, 799 ARRAY_SIZE(back_buffer_modes), 800 msaa_samples_array, 801 ARRAY_SIZE(msaa_samples_array)); 802 if (configs == NULL) 803 configs = new_configs; 804 else 805 configs = driConcatConfigs(configs, new_configs); 806 } 807 808 if (configs == NULL) { 809 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 810 __LINE__); 811 return NULL; 812 } 813 814 return (const __DRIconfig **)configs; 815} 816 817const struct __DriverAPIRec driDriverAPI = { 818 .InitScreen = intelInitScreen, 819 .DestroyScreen = intelDestroyScreen, 820 .CreateContext = intelCreateContext, 821 .DestroyContext = intelDestroyContext, 822 .CreateBuffer = intelCreateBuffer, 823 .DestroyBuffer = intelDestroyBuffer, 824 .SwapBuffers = intelSwapBuffers, 825 .MakeCurrent = intelMakeCurrent, 826 .UnbindContext = intelUnbindContext, 827 .GetSwapInfo = intelGetSwapInfo, 828 .GetDrawableMSC = driDrawableGetMSC32, 829 .WaitForMSC = driWaitForMSC32, 830 .CopySubBuffer = intelCopySubBuffer, 831 832 .InitScreen2 = intelInitScreen2, 833}; 834