intel_screen.c revision c5c73c1b605611faf0f06df9b5d08d8984388238
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 "glheader.h" 29#include "context.h" 30#include "framebuffer.h" 31#include "matrix.h" 32#include "renderbuffer.h" 33#include "simple_list.h" 34#include "utils.h" 35#include "vblank.h" 36#include "xmlpool.h" 37 38 39#include "intel_screen.h" 40 41#include "intel_buffers.h" 42#include "intel_tex.h" 43#include "intel_span.h" 44#include "intel_ioctl.h" 45#include "intel_fbo.h" 46#include "intel_chipset.h" 47 48#include "i915_drm.h" 49#include "i830_dri.h" 50#include "intel_regions.h" 51#include "intel_batchbuffer.h" 52#include "intel_bufmgr_ttm.h" 53 54PUBLIC const char __driConfigOptions[] = 55 DRI_CONF_BEGIN 56 DRI_CONF_SECTION_PERFORMANCE 57 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) 58 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) 59 DRI_CONF_SECTION_END 60 DRI_CONF_SECTION_QUALITY 61 DRI_CONF_FORCE_S3TC_ENABLE(false) 62 DRI_CONF_ALLOW_LARGE_TEXTURES(1) 63 DRI_CONF_SECTION_END 64 DRI_CONF_SECTION_DEBUG 65 DRI_CONF_NO_RAST(false) 66 DRI_CONF_SECTION_END 67DRI_CONF_END; 68 69const GLuint __driNConfigOptions = 5; 70 71#ifdef USE_NEW_INTERFACE 72static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; 73#endif /*USE_NEW_INTERFACE */ 74 75extern const struct dri_extension card_extensions[]; 76extern const struct dri_extension ttm_extensions[]; 77#ifndef I915 78extern const struct dri_extension arb_oc_extensions[]; 79#endif 80 81/** 82 * Map all the memory regions described by the screen. 83 * \return GL_TRUE if success, GL_FALSE if error. 84 */ 85GLboolean 86intelMapScreenRegions(__DRIscreenPrivate * sPriv) 87{ 88 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 89 90 if (intelScreen->front.handle) { 91 if (drmMap(sPriv->fd, 92 intelScreen->front.handle, 93 intelScreen->front.size, 94 (drmAddress *) & intelScreen->front.map) != 0) { 95 _mesa_problem(NULL, "drmMap(frontbuffer) failed!"); 96 return GL_FALSE; 97 } 98 } 99 else { 100 _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!"); 101 } 102 103 if (0) 104 _mesa_printf("Back 0x%08x ", intelScreen->back.handle); 105 if (drmMap(sPriv->fd, 106 intelScreen->back.handle, 107 intelScreen->back.size, 108 (drmAddress *) & intelScreen->back.map) != 0) { 109 intelUnmapScreenRegions(intelScreen); 110 return GL_FALSE; 111 } 112 113 if (intelScreen->third.handle) { 114 if (0) 115 _mesa_printf("Third 0x%08x ", intelScreen->third.handle); 116 if (drmMap(sPriv->fd, 117 intelScreen->third.handle, 118 intelScreen->third.size, 119 (drmAddress *) & intelScreen->third.map) != 0) { 120 intelUnmapScreenRegions(intelScreen); 121 return GL_FALSE; 122 } 123 } 124 125 if (0) 126 _mesa_printf("Depth 0x%08x ", intelScreen->depth.handle); 127 if (drmMap(sPriv->fd, 128 intelScreen->depth.handle, 129 intelScreen->depth.size, 130 (drmAddress *) & intelScreen->depth.map) != 0) { 131 intelUnmapScreenRegions(intelScreen); 132 return GL_FALSE; 133 } 134 135 if (0) 136 _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle); 137 if (intelScreen->tex.size != 0) { 138 if (drmMap(sPriv->fd, 139 intelScreen->tex.handle, 140 intelScreen->tex.size, 141 (drmAddress *) & intelScreen->tex.map) != 0) { 142 intelUnmapScreenRegions(intelScreen); 143 return GL_FALSE; 144 } 145 } 146 147 if (0) 148 printf("Mappings: front: %p back: %p third: %p depth: %p tex: %p\n", 149 intelScreen->front.map, 150 intelScreen->back.map, intelScreen->third.map, 151 intelScreen->depth.map, intelScreen->tex.map); 152 return GL_TRUE; 153} 154 155void 156intelUnmapScreenRegions(intelScreenPrivate * intelScreen) 157{ 158#define REALLY_UNMAP 1 159 if (intelScreen->front.map) { 160#if REALLY_UNMAP 161 if (drmUnmap(intelScreen->front.map, intelScreen->front.size) != 0) 162 printf("drmUnmap front failed!\n"); 163#endif 164 intelScreen->front.map = NULL; 165 } 166 if (intelScreen->back.map) { 167#if REALLY_UNMAP 168 if (drmUnmap(intelScreen->back.map, intelScreen->back.size) != 0) 169 printf("drmUnmap back failed!\n"); 170#endif 171 intelScreen->back.map = NULL; 172 } 173 if (intelScreen->third.map) { 174#if REALLY_UNMAP 175 if (drmUnmap(intelScreen->third.map, intelScreen->third.size) != 0) 176 printf("drmUnmap third failed!\n"); 177#endif 178 intelScreen->third.map = NULL; 179 } 180 if (intelScreen->depth.map) { 181#if REALLY_UNMAP 182 drmUnmap(intelScreen->depth.map, intelScreen->depth.size); 183 intelScreen->depth.map = NULL; 184#endif 185 } 186 if (intelScreen->tex.map) { 187#if REALLY_UNMAP 188 drmUnmap(intelScreen->tex.map, intelScreen->tex.size); 189 intelScreen->tex.map = NULL; 190#endif 191 } 192} 193 194 195static void 196intelPrintDRIInfo(intelScreenPrivate * intelScreen, 197 __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv) 198{ 199 fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n", 200 intelScreen->front.size, intelScreen->front.offset, 201 intelScreen->pitch); 202 fprintf(stderr, "*** Back size: 0x%x offset: 0x%x pitch: %d\n", 203 intelScreen->back.size, intelScreen->back.offset, 204 intelScreen->pitch); 205 fprintf(stderr, "*** Depth size: 0x%x offset: 0x%x pitch: %d\n", 206 intelScreen->depth.size, intelScreen->depth.offset, 207 intelScreen->pitch); 208 fprintf(stderr, "*** Texture size: 0x%x offset: 0x%x\n", 209 intelScreen->tex.size, intelScreen->tex.offset); 210 fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem); 211} 212 213 214static void 215intelPrintSAREA(const drmI830Sarea * sarea) 216{ 217 fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width, 218 sarea->height); 219 fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch); 220 fprintf(stderr, 221 "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n", 222 sarea->front_offset, sarea->front_size, 223 (unsigned) sarea->front_handle); 224 fprintf(stderr, 225 "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n", 226 sarea->back_offset, sarea->back_size, 227 (unsigned) sarea->back_handle); 228 fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n", 229 sarea->depth_offset, sarea->depth_size, 230 (unsigned) sarea->depth_handle); 231 fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n", 232 sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle); 233} 234 235 236/** 237 * A number of the screen parameters are obtained/computed from 238 * information in the SAREA. This function updates those parameters. 239 */ 240void 241intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen, 242 drmI830Sarea * sarea) 243{ 244 intelScreen->width = sarea->width; 245 intelScreen->height = sarea->height; 246 intelScreen->pitch = sarea->pitch; 247 248 intelScreen->front.offset = sarea->front_offset; 249 intelScreen->front.handle = sarea->front_handle; 250 intelScreen->front.size = sarea->front_size; 251 intelScreen->front.tiled = sarea->front_tiled; 252 253 intelScreen->back.offset = sarea->back_offset; 254 intelScreen->back.handle = sarea->back_handle; 255 intelScreen->back.size = sarea->back_size; 256 intelScreen->back.tiled = sarea->back_tiled; 257 258 if (intelScreen->driScrnPriv->ddx_version.minor >= 8) { 259 intelScreen->third.offset = sarea->third_offset; 260 intelScreen->third.handle = sarea->third_handle; 261 intelScreen->third.size = sarea->third_size; 262 intelScreen->third.tiled = sarea->third_tiled; 263 } 264 265 intelScreen->depth.offset = sarea->depth_offset; 266 intelScreen->depth.handle = sarea->depth_handle; 267 intelScreen->depth.size = sarea->depth_size; 268 intelScreen->depth.tiled = sarea->depth_tiled; 269 270 if (intelScreen->driScrnPriv->ddx_version.minor >= 9) { 271 intelScreen->front.bo_handle = sarea->front_bo_handle; 272 intelScreen->back.bo_handle = sarea->back_bo_handle; 273 intelScreen->third.bo_handle = sarea->third_bo_handle; 274 intelScreen->depth.bo_handle = sarea->depth_bo_handle; 275 } else { 276 intelScreen->front.bo_handle = -1; 277 intelScreen->back.bo_handle = -1; 278 intelScreen->third.bo_handle = -1; 279 intelScreen->depth.bo_handle = -1; 280 } 281 282 intelScreen->tex.offset = sarea->tex_offset; 283 intelScreen->logTextureGranularity = sarea->log_tex_granularity; 284 intelScreen->tex.handle = sarea->tex_handle; 285 intelScreen->tex.size = sarea->tex_size; 286 287 if (0) 288 intelPrintSAREA(sarea); 289} 290 291static void 292intelHandleDrawableConfig(__DRIdrawablePrivate *dPriv, 293 __DRIDrawableConfigEvent *event) 294{ 295 struct intel_framebuffer *intel_fb = dPriv->driverPrivate; 296 struct intel_region *region; 297 struct intel_renderbuffer *rb, *depth_rb, *stencil_rb; 298 struct intel_context *intel = dPriv->driContextPriv->driverPrivate; 299 int cpp = intel->ctx.Visual.rgbBits / 8; 300 GLuint pitch = ((cpp * dPriv->w + 63) & ~63) / cpp; 301 302 rb = intel_fb->color_rb[1]; 303 if (rb) { 304 region = intel_region_alloc(intel, cpp, pitch, dPriv->h); 305 intel_renderbuffer_set_region(rb, region); 306 } 307 308 rb = intel_fb->color_rb[2]; 309 if (rb) { 310 region = intel_region_alloc(intel, cpp, pitch, dPriv->h); 311 intel_renderbuffer_set_region(rb, region); 312 } 313 314 depth_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH); 315 stencil_rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL); 316 if (depth_rb || stencil_rb) 317 region = intel_region_alloc(intel, cpp, pitch, dPriv->h); 318 if (depth_rb) 319 intel_renderbuffer_set_region(depth_rb, region); 320 if (stencil_rb) 321 intel_renderbuffer_set_region(stencil_rb, region); 322 323 /* FIXME: Tell the X server about the regions we just allocated and 324 * attached. */ 325} 326 327#define BUFFER_FLAG_TILED 0x0100 328 329static void 330intelHandleBufferAttach(__DRIdrawablePrivate *dPriv, 331 __DRIBufferAttachEvent *ba) 332{ 333 struct intel_framebuffer *intel_fb = dPriv->driverPrivate; 334 struct intel_renderbuffer *rb; 335 struct intel_region *region; 336 struct intel_context *intel = dPriv->driContextPriv->driverPrivate; 337 GLuint tiled; 338 339 switch (ba->buffer.attachment) { 340 case DRI_DRAWABLE_BUFFER_FRONT_LEFT: 341 rb = intel_fb->color_rb[0]; 342 break; 343 344 case DRI_DRAWABLE_BUFFER_BACK_LEFT: 345 rb = intel_fb->color_rb[0]; 346 break; 347 348 case DRI_DRAWABLE_BUFFER_DEPTH: 349 rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH); 350 break; 351 352 case DRI_DRAWABLE_BUFFER_STENCIL: 353 rb = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL); 354 break; 355 356 case DRI_DRAWABLE_BUFFER_ACCUM: 357 default: 358 fprintf(stderr, "unhandled buffer attach event, attacment type %d\n", 359 ba->buffer.attachment); 360 return; 361 } 362 363#if 0 364 /* FIXME: Add this so we can filter out when the X server sends us 365 * attachment events for the buffers we just allocated. Need to 366 * get the BO handle for a render buffer. */ 367 if (intel_renderbuffer_get_region_handle(rb) == ba->buffer.handle) 368 return; 369#endif 370 371 tiled = (ba->buffer.flags & BUFFER_FLAG_TILED) > 0; 372 region = intel_region_alloc_for_handle(intel, ba->buffer.cpp, 373 ba->buffer.pitch / ba->buffer.cpp, 374 dPriv->h, tiled, 375 ba->buffer.handle); 376 377 intel_renderbuffer_set_region(rb, region); 378} 379 380static void 381intelUpdateBuffer(__DRIdrawablePrivate *dPriv, unsigned int *event) 382{ 383 switch (DRI2_EVENT_TYPE(*event)) { 384 case DRI2_EVENT_DRAWABLE_CONFIG: 385 /* flush all current regions, allocate new ones, except front buffer */ 386 intelHandleDrawableConfig(dPriv, (__DRIDrawableConfigEvent *) event); 387 break; 388 389 case DRI2_EVENT_BUFFER_ATTACH: 390 /* attach buffer if different from what we have */ 391 intelHandleBufferAttach(dPriv, (__DRIBufferAttachEvent *) event); 392 break; 393 } 394} 395 396static const __DRItexOffsetExtension intelTexOffsetExtension = { 397 { __DRI_TEX_OFFSET }, 398 intelSetTexOffset, 399}; 400 401static const __DRIextension *intelExtensions[] = { 402 &driReadDrawableExtension, 403 &driCopySubBufferExtension.base, 404 &driSwapControlExtension.base, 405 &driFrameTrackingExtension.base, 406 &driMediaStreamCounterExtension.base, 407 &intelTexOffsetExtension.base, 408 NULL 409}; 410 411static GLboolean 412intel_get_param(__DRIscreenPrivate *psp, int param, int *value) 413{ 414 int ret; 415 drmI830GetParam gp; 416 417 gp.param = param; 418 gp.value = value; 419 420 ret = drmCommandWriteRead(psp->fd, DRM_I830_GETPARAM, &gp, sizeof(gp)); 421 if (ret) { 422 fprintf(stderr, "drmI830GetParam: %d\n", ret); 423 return GL_FALSE; 424 } 425 426 return GL_TRUE; 427} 428 429static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) 430{ 431 intelScreenPrivate *intelScreen; 432 I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv; 433 drmI830Sarea *sarea; 434 435 if (sPriv->devPrivSize != sizeof(I830DRIRec)) { 436 fprintf(stderr, 437 "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n"); 438 return GL_FALSE; 439 } 440 441 /* Allocate the private area */ 442 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate)); 443 if (!intelScreen) { 444 fprintf(stderr, "\nERROR! Allocating private area failed\n"); 445 return GL_FALSE; 446 } 447 /* parse information in __driConfigOptions */ 448 driParseOptionInfo(&intelScreen->optionCache, 449 __driConfigOptions, __driNConfigOptions); 450 451 intelScreen->driScrnPriv = sPriv; 452 sPriv->private = (void *) intelScreen; 453 intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; 454 sarea = (drmI830Sarea *) 455 (((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset); 456 457 intelScreen->deviceID = gDRIPriv->deviceID; 458 459 intelUpdateScreenFromSAREA(intelScreen, sarea); 460 461 if (!intelMapScreenRegions(sPriv)) { 462 fprintf(stderr, "\nERROR! mapping regions\n"); 463 _mesa_free(intelScreen); 464 sPriv->private = NULL; 465 return GL_FALSE; 466 } 467 468 intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; 469 470 if (0) 471 intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); 472 473 intelScreen->drmMinor = sPriv->drm_version.minor; 474 475 /* Determine if IRQs are active? */ 476 if (!intel_get_param(sPriv, I830_PARAM_IRQ_ACTIVE, 477 &intelScreen->irq_active)) 478 return GL_FALSE; 479 480 /* Determine if batchbuffers are allowed */ 481 if (!intel_get_param(sPriv, I830_PARAM_ALLOW_BATCHBUFFER, 482 &intelScreen->allow_batchbuffer)) 483 return GL_FALSE; 484 485 sPriv->extensions = intelExtensions; 486 487 return GL_TRUE; 488} 489 490 491static void 492intelDestroyScreen(__DRIscreenPrivate * sPriv) 493{ 494 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 495 496 intelUnmapScreenRegions(intelScreen); 497 498 FREE(intelScreen); 499 sPriv->private = NULL; 500} 501 502 503/** 504 * This is called when we need to set up GL rendering to a new X window. 505 */ 506static GLboolean 507intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, 508 __DRIdrawablePrivate * driDrawPriv, 509 const __GLcontextModes * mesaVis, GLboolean isPixmap) 510{ 511 intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private; 512 513 if (isPixmap) { 514 return GL_FALSE; /* not implemented */ 515 } 516 else { 517 GLboolean swStencil = (mesaVis->stencilBits > 0 && 518 mesaVis->depthBits != 24); 519 GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8); 520 521 struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer); 522 523 if (!intel_fb) 524 return GL_FALSE; 525 526 _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis); 527 528 /* setup the hardware-based renderbuffers */ 529 { 530 intel_fb->color_rb[0] = intel_create_renderbuffer(rgbFormat); 531 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, 532 &intel_fb->color_rb[0]->Base); 533 } 534 535 if (mesaVis->doubleBufferMode) { 536 intel_fb->color_rb[1] = intel_create_renderbuffer(rgbFormat); 537 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, 538 &intel_fb->color_rb[1]->Base); 539 540 if (screen->third.handle) { 541 struct gl_renderbuffer *tmp_rb = NULL; 542 543 intel_fb->color_rb[2] = intel_create_renderbuffer(rgbFormat); 544 _mesa_reference_renderbuffer(&tmp_rb, &intel_fb->color_rb[2]->Base); 545 } 546 } 547 548 if (mesaVis->depthBits == 24) { 549 if (mesaVis->stencilBits == 8) { 550 /* combined depth/stencil buffer */ 551 struct intel_renderbuffer *depthStencilRb 552 = intel_create_renderbuffer(GL_DEPTH24_STENCIL8_EXT); 553 /* note: bind RB to two attachment points */ 554 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, 555 &depthStencilRb->Base); 556 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL, 557 &depthStencilRb->Base); 558 } else { 559 struct intel_renderbuffer *depthRb 560 = intel_create_renderbuffer(GL_DEPTH_COMPONENT24); 561 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, 562 &depthRb->Base); 563 } 564 } 565 else if (mesaVis->depthBits == 16) { 566 /* just 16-bit depth buffer, no hw stencil */ 567 struct intel_renderbuffer *depthRb 568 = intel_create_renderbuffer(GL_DEPTH_COMPONENT16); 569 _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base); 570 } 571 572 /* now add any/all software-based renderbuffers we may need */ 573 _mesa_add_soft_renderbuffers(&intel_fb->Base, 574 GL_FALSE, /* never sw color */ 575 GL_FALSE, /* never sw depth */ 576 swStencil, mesaVis->accumRedBits > 0, 577 GL_FALSE, /* never sw alpha */ 578 GL_FALSE /* never sw aux */ ); 579 driDrawPriv->driverPrivate = (void *) intel_fb; 580 581 return GL_TRUE; 582 } 583} 584 585static void 586intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv) 587{ 588 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); 589} 590 591 592/** 593 * Get information about previous buffer swaps. 594 */ 595static int 596intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo) 597{ 598 struct intel_framebuffer *intel_fb; 599 600 if ((dPriv == NULL) || (dPriv->driverPrivate == NULL) 601 || (sInfo == NULL)) { 602 return -1; 603 } 604 605 intel_fb = dPriv->driverPrivate; 606 sInfo->swap_count = intel_fb->swap_count; 607 sInfo->swap_ust = intel_fb->swap_ust; 608 sInfo->swap_missed_count = intel_fb->swap_missed_count; 609 610 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) 611 ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust) 612 : 0.0; 613 614 return 0; 615} 616 617 618/* There are probably better ways to do this, such as an 619 * init-designated function to register chipids and createcontext 620 * functions. 621 */ 622extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis, 623 __DRIcontextPrivate * driContextPriv, 624 void *sharedContextPrivate); 625 626extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis, 627 __DRIcontextPrivate * driContextPriv, 628 void *sharedContextPrivate); 629extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis, 630 __DRIcontextPrivate * driContextPriv, 631 void *sharedContextPrivate); 632 633static GLboolean 634intelCreateContext(const __GLcontextModes * mesaVis, 635 __DRIcontextPrivate * driContextPriv, 636 void *sharedContextPrivate) 637{ 638 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; 639 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 640 641#ifdef I915 642 if (IS_9XX(intelScreen->deviceID)) { 643 if (!IS_965(intelScreen->deviceID)) { 644 return i915CreateContext(mesaVis, driContextPriv, 645 sharedContextPrivate); 646 } 647 } else { 648 return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate); 649 } 650#else 651 if (IS_965(intelScreen->deviceID)) 652 return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate); 653#endif 654 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID); 655 return GL_FALSE; 656} 657 658 659static const struct __DriverAPIRec intelAPI = { 660 .DestroyScreen = intelDestroyScreen, 661 .CreateContext = intelCreateContext, 662 .DestroyContext = intelDestroyContext, 663 .CreateBuffer = intelCreateBuffer, 664 .DestroyBuffer = intelDestroyBuffer, 665 .SwapBuffers = intelSwapBuffers, 666 .MakeCurrent = intelMakeCurrent, 667 .UnbindContext = intelUnbindContext, 668 .GetSwapInfo = intelGetSwapInfo, 669 .GetMSC = driGetMSC32, 670 .GetDrawableMSC = driDrawableGetMSC32, 671 .WaitForMSC = driWaitForMSC32, 672 .WaitForSBC = NULL, 673 .SwapBuffersMSC = NULL, 674 .CopySubBuffer = intelCopySubBuffer, 675#ifdef I915 676 .setTexOffset = intelSetTexOffset, 677#endif 678 .UpdateBuffer = intelUpdateBuffer, 679}; 680 681 682static __GLcontextModes * 683intelFillInModes(unsigned pixel_bits, unsigned depth_bits, 684 unsigned stencil_bits, GLboolean have_back_buffer) 685{ 686 __GLcontextModes *modes; 687 __GLcontextModes *m; 688 unsigned num_modes; 689 unsigned depth_buffer_factor; 690 unsigned back_buffer_factor; 691 GLenum fb_format; 692 GLenum fb_type; 693 694 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't 695 * support pageflipping at all. 696 */ 697 static const GLenum back_buffer_modes[] = { 698 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML 699 }; 700 701 u_int8_t depth_bits_array[3]; 702 u_int8_t stencil_bits_array[3]; 703 704 705 depth_bits_array[0] = 0; 706 depth_bits_array[1] = depth_bits; 707 depth_bits_array[2] = depth_bits; 708 709 /* Just like with the accumulation buffer, always provide some modes 710 * with a stencil buffer. It will be a sw fallback, but some apps won't 711 * care about that. 712 */ 713 stencil_bits_array[0] = 0; 714 stencil_bits_array[1] = 0; 715 if (depth_bits == 24) 716 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; 717 718 stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits; 719 720 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1; 721 back_buffer_factor = (have_back_buffer) ? 3 : 1; 722 723 num_modes = depth_buffer_factor * back_buffer_factor * 4; 724 725 if (pixel_bits == 16) { 726 fb_format = GL_RGB; 727 fb_type = GL_UNSIGNED_SHORT_5_6_5; 728 } 729 else { 730 fb_format = GL_BGRA; 731 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; 732 } 733 734 modes = 735 (*dri_interface->createContextModes) (num_modes, 736 sizeof(__GLcontextModes)); 737 m = modes; 738 if (!driFillInModes(&m, fb_format, fb_type, 739 depth_bits_array, stencil_bits_array, 740 depth_buffer_factor, back_buffer_modes, 741 back_buffer_factor, GLX_TRUE_COLOR)) { 742 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 743 __LINE__); 744 return NULL; 745 } 746 if (!driFillInModes(&m, fb_format, fb_type, 747 depth_bits_array, stencil_bits_array, 748 depth_buffer_factor, back_buffer_modes, 749 back_buffer_factor, GLX_DIRECT_COLOR)) { 750 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 751 __LINE__); 752 return NULL; 753 } 754 755 /* Mark the visual as slow if there are "fake" stencil bits. 756 */ 757 for (m = modes; m != NULL; m = m->next) { 758 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) { 759 m->visualRating = GLX_SLOW_CONFIG; 760 } 761 } 762 763 return modes; 764} 765 766 767/** 768 * This is the driver specific part of the createNewScreen entry point. 769 * 770 * \todo maybe fold this into intelInitDriver 771 * 772 * \return the __GLcontextModes supported by this driver 773 */ 774PUBLIC __GLcontextModes *__driDriverInitScreen(__DRIscreenPrivate *psp) 775{ 776#ifdef I915 777 static const __DRIversion ddx_expected = { 1, 5, 0 }; 778#else 779 static const __DRIversion ddx_expected = { 1, 6, 0 }; 780#endif 781 static const __DRIversion dri_expected = { 4, 0, 0 }; 782 static const __DRIversion drm_expected = { 1, 5, 0 }; 783 I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv; 784 785 psp->DriverAPI = intelAPI; 786 787 if (!driCheckDriDdxDrmVersions2("i915", 788 &psp->dri_version, &dri_expected, 789 &psp->ddx_version, &ddx_expected, 790 &psp->drm_version, &drm_expected)) { 791 return NULL; 792 } 793 794 /* Calling driInitExtensions here, with a NULL context pointer, 795 * does not actually enable the extensions. It just makes sure 796 * that all the dispatch offsets for all the extensions that 797 * *might* be enables are known. This is needed because the 798 * dispatch offsets need to be known when _mesa_context_create is 799 * called, but we can't enable the extensions until we have a 800 * context pointer. 801 * 802 * Hello chicken. Hello egg. How are you two today? 803 */ 804 driInitExtensions(NULL, card_extensions, GL_FALSE); 805 driInitExtensions(NULL, ttm_extensions, GL_FALSE); 806#ifndef I915 807 driInitExtensions(NULL, arb_oc_extensions, GL_FALSE); 808#endif 809 810 if (!intelInitDriver(psp)) 811 return NULL; 812 813 return intelFillInModes(dri_priv->cpp * 8, 814 (dri_priv->cpp == 2) ? 16 : 24, 815 (dri_priv->cpp == 2) ? 0 : 8, 1); 816} 817 818struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen) 819{ 820 /* 821 * This should probably change to have the screen allocate a dummy 822 * context at screen creation. For now just use the current context. 823 */ 824 825 GET_CURRENT_CONTEXT(ctx); 826 if (ctx == NULL) { 827 _mesa_problem(NULL, "No current context in intelScreenContext\n"); 828 return NULL; 829 } 830 return intel_context(ctx); 831} 832 833/** 834 * This is the driver specific part of the createNewScreen entry point. 835 * 836 * \return the __GLcontextModes supported by this driver 837 */ 838PUBLIC __GLcontextModes *__dri2DriverInitScreen(__DRIscreenPrivate *psp) 839{ 840 static const __DRIversion ddx_expected = { 1, 9, 0 }; 841 static const __DRIversion dri_expected = { 4, 0, 0 }; 842 static const __DRIversion drm_expected = { 1, 5, 0 }; 843 intelScreenPrivate *intelScreen; 844 __GLcontextModes *modes, *m; 845 846 psp->DriverAPI = intelAPI; 847 848 if (!driCheckDriDdxDrmVersions2("i915", 849 &psp->dri_version, &dri_expected, 850 &psp->ddx_version, &ddx_expected, 851 &psp->drm_version, &drm_expected)) { 852 fprintf(stderr, "bad version voodoo\n"); 853 return NULL; 854 } 855 856 /* Calling driInitExtensions here, with a NULL context pointer, 857 * does not actually enable the extensions. It just makes sure 858 * that all the dispatch offsets for all the extensions that 859 * *might* be enables are known. This is needed because the 860 * dispatch offsets need to be known when _mesa_context_create is 861 * called, but we can't enable the extensions until we have a 862 * context pointer. 863 * 864 * Hello chicken. Hello egg. How are you two today? 865 */ 866 driInitExtensions(NULL, card_extensions, GL_FALSE); 867 driInitExtensions(NULL, ttm_extensions, GL_FALSE); 868 869 /* Allocate the private area */ 870 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate)); 871 if (!intelScreen) { 872 fprintf(stderr, "\nERROR! Allocating private area failed\n"); 873 return GL_FALSE; 874 } 875 /* parse information in __driConfigOptions */ 876 driParseOptionInfo(&intelScreen->optionCache, 877 __driConfigOptions, __driNConfigOptions); 878 879 intelScreen->driScrnPriv = psp; 880 psp->private = (void *) intelScreen; 881 882 intelScreen->drmMinor = psp->drm_version.minor; 883 884 /* Determine chipset ID? */ 885 if (!intel_get_param(psp, I915_PARAM_CHIPSET_ID, 886 &intelScreen->deviceID)) 887 return GL_FALSE; 888 889 /* Determine if IRQs are active? */ 890 if (!intel_get_param(psp, I830_PARAM_IRQ_ACTIVE, 891 &intelScreen->irq_active)) 892 return GL_FALSE; 893 894 /* Determine if batchbuffers are allowed */ 895 if (!intel_get_param(psp, I830_PARAM_ALLOW_BATCHBUFFER, 896 &intelScreen->allow_batchbuffer)) 897 return GL_FALSE; 898 899 if (!intelScreen->allow_batchbuffer) { 900 fprintf(stderr, "batch buffer not allowed\n"); 901 return GL_FALSE; 902 } 903 904 psp->extensions = intelExtensions; 905 906 modes = intelFillInModes(16, 16, 0, 1); 907 for (m = modes; m->next != NULL; m = m->next) 908 ; 909 m->next = intelFillInModes(32, 24, 8, 1); 910 911 return modes; 912} 913