intel_screen.c revision 7c50d29f7ced3d60e52ee0146d982b49ea421de2
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(__DRIscreenPrivate * 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 __DRIscreenPrivate * 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 void 240intelDRI2Flush(__DRIdrawable *drawable) 241{ 242 struct intel_context *intel = drawable->driContextPriv->driverPrivate; 243 244 if (intel->gen < 4) 245 INTEL_FIREVERTICES(intel); 246 247 if (intel->batch->map != intel->batch->ptr) 248 intel_batchbuffer_flush(intel->batch); 249} 250 251static void 252intelDRI2FlushInvalidate(__DRIdrawable *drawable) 253{ 254 intelDRI2Flush(drawable); 255 drawable->validBuffers = GL_FALSE; 256} 257 258static const struct __DRI2flushExtensionRec intelFlushExtension = { 259 { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, 260 intelDRI2Flush, 261 intelDRI2FlushInvalidate, 262}; 263 264static const __DRIextension *intelScreenExtensions[] = { 265 &driReadDrawableExtension, 266 &driCopySubBufferExtension.base, 267 &driSwapControlExtension.base, 268 &driFrameTrackingExtension.base, 269 &driMediaStreamCounterExtension.base, 270 &intelTexOffsetExtension.base, 271 &intelTexBufferExtension.base, 272 &intelFlushExtension.base, 273 NULL 274}; 275 276static GLboolean 277intel_get_param(__DRIscreenPrivate *psp, int param, int *value) 278{ 279 int ret; 280 struct drm_i915_getparam gp; 281 282 gp.param = param; 283 gp.value = value; 284 285 ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); 286 if (ret) { 287 _mesa_warning(NULL, "drm_i915_getparam: %d", ret); 288 return GL_FALSE; 289 } 290 291 return GL_TRUE; 292} 293 294static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) 295{ 296 intelScreenPrivate *intelScreen; 297 I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv; 298 drm_i915_sarea_t *sarea; 299 300 if (sPriv->devPrivSize != sizeof(I830DRIRec)) { 301 fprintf(stderr, 302 "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n"); 303 return GL_FALSE; 304 } 305 306 /* Allocate the private area */ 307 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate)); 308 if (!intelScreen) { 309 fprintf(stderr, "\nERROR! Allocating private area failed\n"); 310 return GL_FALSE; 311 } 312 /* parse information in __driConfigOptions */ 313 driParseOptionInfo(&intelScreen->optionCache, 314 __driConfigOptions, __driNConfigOptions); 315 316 intelScreen->driScrnPriv = sPriv; 317 sPriv->private = (void *) intelScreen; 318 sarea = (drm_i915_sarea_t *) 319 (((GLubyte *) sPriv->pSAREA) + gDRIPriv->sarea_priv_offset); 320 intelScreen->sarea = sarea; 321 322 intelScreen->deviceID = gDRIPriv->deviceID; 323 324 intelUpdateScreenFromSAREA(intelScreen, sarea); 325 326 if (!intelMapScreenRegions(sPriv)) { 327 fprintf(stderr, "\nERROR! mapping regions\n"); 328 _mesa_free(intelScreen); 329 sPriv->private = NULL; 330 return GL_FALSE; 331 } 332 333 if (0) 334 intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); 335 336 intelScreen->drmMinor = sPriv->drm_version.minor; 337 338 /* Determine if IRQs are active? */ 339 if (!intel_get_param(sPriv, I915_PARAM_IRQ_ACTIVE, 340 &intelScreen->irq_active)) 341 return GL_FALSE; 342 343 sPriv->extensions = intelScreenExtensions; 344 345 return GL_TRUE; 346} 347 348 349static void 350intelDestroyScreen(__DRIscreenPrivate * sPriv) 351{ 352 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 353 354 dri_bufmgr_destroy(intelScreen->bufmgr); 355 intelUnmapScreenRegions(intelScreen); 356 driDestroyOptionInfo(&intelScreen->optionCache); 357 358 FREE(intelScreen); 359 sPriv->private = NULL; 360} 361 362 363/** 364 * This is called when we need to set up GL rendering to a new X window. 365 */ 366static GLboolean 367intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, 368 __DRIdrawablePrivate * driDrawPriv, 369 const __GLcontextModes * mesaVis, GLboolean isPixmap) 370{ 371 if (isPixmap) { 372 return GL_FALSE; /* not implemented */ 373 } 374 else { 375 GLboolean swStencil = (mesaVis->stencilBits > 0 && 376 mesaVis->depthBits != 24); 377 gl_format rgbFormat; 378 379 struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer); 380 381 if (!intel_fb) 382 return GL_FALSE; 383 384 _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis); 385 386 if (mesaVis->redBits == 5) 387 rgbFormat = MESA_FORMAT_RGB565; 388 else if (mesaVis->alphaBits == 0) 389 rgbFormat = MESA_FORMAT_XRGB8888; 390 else 391 rgbFormat = MESA_FORMAT_ARGB8888; 392 393 /* setup the hardware-based renderbuffers */ 394 intel_fb->color_rb[0] = intel_create_renderbuffer(rgbFormat); 395 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, 396 &intel_fb->color_rb[0]->Base); 397 398 if (mesaVis->doubleBufferMode) { 399 intel_fb->color_rb[1] = intel_create_renderbuffer(rgbFormat); 400 401 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, 402 &intel_fb->color_rb[1]->Base); 403 404 } 405 406 if (mesaVis->depthBits == 24) { 407 if (mesaVis->stencilBits == 8) { 408 /* combined depth/stencil buffer */ 409 struct intel_renderbuffer *depthStencilRb 410 = intel_create_renderbuffer(MESA_FORMAT_S8_Z24); 411 /* note: bind RB to two attachment points */ 412 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, 413 &depthStencilRb->Base); 414 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL, 415 &depthStencilRb->Base); 416 } else { 417 struct intel_renderbuffer *depthRb 418 = intel_create_renderbuffer(MESA_FORMAT_X8_Z24); 419 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, 420 &depthRb->Base); 421 } 422 } 423 else if (mesaVis->depthBits == 16) { 424 /* just 16-bit depth buffer, no hw stencil */ 425 struct intel_renderbuffer *depthRb 426 = intel_create_renderbuffer(MESA_FORMAT_Z16); 427 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base); 428 } 429 430 /* now add any/all software-based renderbuffers we may need */ 431 _mesa_add_soft_renderbuffers(&intel_fb->Base, 432 GL_FALSE, /* never sw color */ 433 GL_FALSE, /* never sw depth */ 434 swStencil, mesaVis->accumRedBits > 0, 435 GL_FALSE, /* never sw alpha */ 436 GL_FALSE /* never sw aux */ ); 437 driDrawPriv->driverPrivate = (void *) intel_fb; 438 439 return GL_TRUE; 440 } 441} 442 443static void 444intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv) 445{ 446 struct intel_framebuffer *intel_fb = driDrawPriv->driverPrivate; 447 struct intel_renderbuffer *depth_rb; 448 struct intel_renderbuffer *stencil_rb; 449 450 if (intel_fb) { 451 if (intel_fb->color_rb[0]) { 452 intel_renderbuffer_set_region(intel_fb->color_rb[0], NULL); 453 } 454 455 if (intel_fb->color_rb[1]) { 456 intel_renderbuffer_set_region(intel_fb->color_rb[1], NULL); 457 } 458 459 depth_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH); 460 if (depth_rb) { 461 intel_renderbuffer_set_region(depth_rb, NULL); 462 } 463 464 stencil_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL); 465 if (stencil_rb) { 466 intel_renderbuffer_set_region(stencil_rb, NULL); 467 } 468 } 469 470 _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL); 471} 472 473 474/** 475 * Get information about previous buffer swaps. 476 */ 477static int 478intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo) 479{ 480 struct intel_framebuffer *intel_fb; 481 482 if ((dPriv == NULL) || (dPriv->driverPrivate == NULL) 483 || (sInfo == NULL)) { 484 return -1; 485 } 486 487 intel_fb = dPriv->driverPrivate; 488 sInfo->swap_count = intel_fb->swap_count; 489 sInfo->swap_ust = intel_fb->swap_ust; 490 sInfo->swap_missed_count = intel_fb->swap_missed_count; 491 492 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) 493 ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust) 494 : 0.0; 495 496 return 0; 497} 498 499 500/* There are probably better ways to do this, such as an 501 * init-designated function to register chipids and createcontext 502 * functions. 503 */ 504extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis, 505 __DRIcontextPrivate * driContextPriv, 506 void *sharedContextPrivate); 507 508extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis, 509 __DRIcontextPrivate * driContextPriv, 510 void *sharedContextPrivate); 511extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis, 512 __DRIcontextPrivate * driContextPriv, 513 void *sharedContextPrivate); 514 515static GLboolean 516intelCreateContext(const __GLcontextModes * mesaVis, 517 __DRIcontextPrivate * driContextPriv, 518 void *sharedContextPrivate) 519{ 520 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; 521 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 522 523#ifdef I915 524 if (IS_9XX(intelScreen->deviceID)) { 525 if (!IS_965(intelScreen->deviceID)) { 526 return i915CreateContext(mesaVis, driContextPriv, 527 sharedContextPrivate); 528 } 529 } else { 530 intelScreen->no_vbo = GL_TRUE; 531 return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate); 532 } 533#else 534 if (IS_965(intelScreen->deviceID)) 535 return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate); 536#endif 537 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID); 538 return GL_FALSE; 539} 540 541 542static __DRIconfig ** 543intelFillInModes(__DRIscreenPrivate *psp, 544 unsigned pixel_bits, unsigned depth_bits, 545 unsigned stencil_bits, GLboolean have_back_buffer) 546{ 547 __DRIconfig **configs; 548 __GLcontextModes *m; 549 unsigned depth_buffer_factor; 550 unsigned back_buffer_factor; 551 int i; 552 553 static const GLenum back_buffer_modes[] = { 554 GLX_NONE, GLX_SWAP_UNDEFINED_OML, 555 GLX_SWAP_EXCHANGE_OML, GLX_SWAP_COPY_OML 556 }; 557 558 uint8_t depth_bits_array[3]; 559 uint8_t stencil_bits_array[3]; 560 uint8_t msaa_samples_array[1]; 561 562 depth_bits_array[0] = 0; 563 depth_bits_array[1] = depth_bits; 564 depth_bits_array[2] = depth_bits; 565 566 /* Just like with the accumulation buffer, always provide some modes 567 * with a stencil buffer. It will be a sw fallback, but some apps won't 568 * care about that. 569 */ 570 stencil_bits_array[0] = 0; 571 stencil_bits_array[1] = 0; 572 if (depth_bits == 24) 573 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; 574 575 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits; 576 577 msaa_samples_array[0] = 0; 578 579 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1; 580 back_buffer_factor = (have_back_buffer) ? 3 : 1; 581 582 if (pixel_bits == 16) { 583 configs = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 584 depth_bits_array, stencil_bits_array, 585 depth_buffer_factor, back_buffer_modes, 586 back_buffer_factor, 587 msaa_samples_array, 1); 588 } 589 else { 590 __DRIconfig **configs_a8r8g8b8; 591 __DRIconfig **configs_x8r8g8b8; 592 593 configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 594 depth_bits_array, 595 stencil_bits_array, 596 depth_buffer_factor, 597 back_buffer_modes, 598 back_buffer_factor, 599 msaa_samples_array, 1); 600 configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV, 601 depth_bits_array, 602 stencil_bits_array, 603 depth_buffer_factor, 604 back_buffer_modes, 605 back_buffer_factor, 606 msaa_samples_array, 1); 607 configs = driConcatConfigs(configs_a8r8g8b8, configs_x8r8g8b8); 608 } 609 610 if (configs == NULL) { 611 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 612 __LINE__); 613 return NULL; 614 } 615 616 /* Mark the visual as slow if there are "fake" stencil bits. 617 */ 618 for (i = 0; configs[i]; i++) { 619 m = &configs[i]->modes; 620 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) { 621 m->visualRating = GLX_SLOW_CONFIG; 622 } 623 } 624 625 return configs; 626} 627 628static GLboolean 629intel_init_bufmgr(intelScreenPrivate *intelScreen) 630{ 631 int gem_kernel = 0; 632 struct drm_i915_getparam gp; 633 __DRIscreenPrivate *spriv = intelScreen->driScrnPriv; 634 int num_fences = 0; 635 636 intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL; 637 638 gp.param = I915_PARAM_HAS_GEM; 639 gp.value = &gem_kernel; 640 641 (void) drmCommandWriteRead(spriv->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); 642 643 /* If we've got a new enough DDX that's initializing GEM and giving us 644 * object handles for the shared buffers, use that. 645 */ 646 if (!intelScreen->driScrnPriv->dri2.enabled && 647 intelScreen->driScrnPriv->ddx_version.minor < 9) { 648 fprintf(stderr, "[%s:%u] Error initializing GEM.\n", 649 __func__, __LINE__); 650 return GL_FALSE; 651 } 652 653 intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ); 654 /* Otherwise, use the classic buffer manager. */ 655 if (intelScreen->bufmgr == NULL) { 656 fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n", 657 __func__, __LINE__); 658 return GL_FALSE; 659 } 660 661 if (intel_get_param(spriv, I915_PARAM_NUM_FENCES_AVAIL, &num_fences)) 662 intelScreen->kernel_exec_fencing = !!num_fences; 663 else 664 intelScreen->kernel_exec_fencing = GL_FALSE; 665 666 return GL_TRUE; 667} 668 669/** 670 * This is the driver specific part of the createNewScreen entry point. 671 * Called when using legacy DRI. 672 * 673 * \todo maybe fold this into intelInitDriver 674 * 675 * \return the __GLcontextModes supported by this driver 676 */ 677static const __DRIconfig **intelInitScreen(__DRIscreenPrivate *psp) 678{ 679 intelScreenPrivate *intelScreen; 680#ifdef I915 681 static const __DRIversion ddx_expected = { 1, 5, 0 }; 682#else 683 static const __DRIversion ddx_expected = { 1, 6, 0 }; 684#endif 685 static const __DRIversion dri_expected = { 4, 0, 0 }; 686 static const __DRIversion drm_expected = { 1, 5, 0 }; 687 I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv; 688 689 if (!driCheckDriDdxDrmVersions2("i915", 690 &psp->dri_version, &dri_expected, 691 &psp->ddx_version, &ddx_expected, 692 &psp->drm_version, &drm_expected)) { 693 return NULL; 694 } 695 696 if (!intelInitDriver(psp)) 697 return NULL; 698 699 psp->extensions = intelScreenExtensions; 700 701 intelScreen = psp->private; 702 if (!intel_init_bufmgr(intelScreen)) 703 return GL_FALSE; 704 705 return (const __DRIconfig **) 706 intelFillInModes(psp, dri_priv->cpp * 8, 707 (dri_priv->cpp == 2) ? 16 : 24, 708 (dri_priv->cpp == 2) ? 0 : 8, 1); 709} 710 711struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen) 712{ 713 /* 714 * This should probably change to have the screen allocate a dummy 715 * context at screen creation. For now just use the current context. 716 */ 717 718 GET_CURRENT_CONTEXT(ctx); 719 if (ctx == NULL) { 720 _mesa_problem(NULL, "No current context in intelScreenContext\n"); 721 return NULL; 722 } 723 return intel_context(ctx); 724} 725 726/** 727 * This is the driver specific part of the createNewScreen entry point. 728 * Called when using DRI2. 729 * 730 * \return the __GLcontextModes supported by this driver 731 */ 732static const 733__DRIconfig **intelInitScreen2(__DRIscreenPrivate *psp) 734{ 735 intelScreenPrivate *intelScreen; 736 GLenum fb_format[3]; 737 GLenum fb_type[3]; 738 739 static const GLenum back_buffer_modes[] = { 740 GLX_NONE, GLX_SWAP_UNDEFINED_OML, 741 GLX_SWAP_EXCHANGE_OML, GLX_SWAP_COPY_OML 742 }; 743 uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1]; 744 int color; 745 __DRIconfig **configs = NULL; 746 747 /* Allocate the private area */ 748 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate)); 749 if (!intelScreen) { 750 fprintf(stderr, "\nERROR! Allocating private area failed\n"); 751 return GL_FALSE; 752 } 753 /* parse information in __driConfigOptions */ 754 driParseOptionInfo(&intelScreen->optionCache, 755 __driConfigOptions, __driNConfigOptions); 756 757 intelScreen->driScrnPriv = psp; 758 psp->private = (void *) intelScreen; 759 760 intelScreen->drmMinor = psp->drm_version.minor; 761 762 /* Determine chipset ID */ 763 if (!intel_get_param(psp, I915_PARAM_CHIPSET_ID, 764 &intelScreen->deviceID)) 765 return GL_FALSE; 766 767 if (!intel_init_bufmgr(intelScreen)) 768 return GL_FALSE; 769 770 intelScreen->irq_active = 1; 771 psp->extensions = intelScreenExtensions; 772 773 depth_bits[0] = 0; 774 stencil_bits[0] = 0; 775 depth_bits[1] = 16; 776 stencil_bits[1] = 0; 777 depth_bits[2] = 24; 778 stencil_bits[2] = 0; 779 depth_bits[3] = 24; 780 stencil_bits[3] = 8; 781 782 msaa_samples_array[0] = 0; 783 784 fb_format[0] = GL_RGB; 785 fb_type[0] = GL_UNSIGNED_SHORT_5_6_5; 786 787 fb_format[1] = GL_BGR; 788 fb_type[1] = GL_UNSIGNED_INT_8_8_8_8_REV; 789 790 fb_format[2] = GL_BGRA; 791 fb_type[2] = GL_UNSIGNED_INT_8_8_8_8_REV; 792 793 depth_bits[0] = 0; 794 stencil_bits[0] = 0; 795 796 for (color = 0; color < ARRAY_SIZE(fb_format); color++) { 797 __DRIconfig **new_configs; 798 int depth_factor; 799 800 /* With DRI2 right now, GetBuffers always returns a depth/stencil buffer 801 * with the same cpp as the drawable. So we can't support depth cpp != 802 * color cpp currently. 803 */ 804 if (fb_type[color] == GL_UNSIGNED_SHORT_5_6_5) { 805 depth_bits[1] = 16; 806 stencil_bits[1] = 0; 807 808 depth_factor = 2; 809 } else { 810 depth_bits[1] = 24; 811 stencil_bits[1] = 0; 812 depth_bits[2] = 24; 813 stencil_bits[2] = 8; 814 815 depth_factor = 3; 816 } 817 new_configs = driCreateConfigs(fb_format[color], fb_type[color], 818 depth_bits, 819 stencil_bits, 820 depth_factor, 821 back_buffer_modes, 822 ARRAY_SIZE(back_buffer_modes), 823 msaa_samples_array, 824 ARRAY_SIZE(msaa_samples_array)); 825 if (configs == NULL) 826 configs = new_configs; 827 else 828 configs = driConcatConfigs(configs, new_configs); 829 } 830 831 if (configs == NULL) { 832 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 833 __LINE__); 834 return NULL; 835 } 836 837 return (const __DRIconfig **)configs; 838} 839 840const struct __DriverAPIRec driDriverAPI = { 841 .InitScreen = intelInitScreen, 842 .DestroyScreen = intelDestroyScreen, 843 .CreateContext = intelCreateContext, 844 .DestroyContext = intelDestroyContext, 845 .CreateBuffer = intelCreateBuffer, 846 .DestroyBuffer = intelDestroyBuffer, 847 .SwapBuffers = intelSwapBuffers, 848 .MakeCurrent = intelMakeCurrent, 849 .UnbindContext = intelUnbindContext, 850 .GetSwapInfo = intelGetSwapInfo, 851 .GetDrawableMSC = driDrawableGetMSC32, 852 .WaitForMSC = driWaitForMSC32, 853 .CopySubBuffer = intelCopySubBuffer, 854 855 .InitScreen2 = intelInitScreen2, 856}; 857