intel_screen.c revision e67c338b415c983bee570e6644b9684d8d1fc99b
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#include "main/hash.h" 33#include "main/fbobject.h" 34 35#include "utils.h" 36#include "xmlpool.h" 37 38#include "intel_batchbuffer.h" 39#include "intel_buffers.h" 40#include "intel_bufmgr.h" 41#include "intel_chipset.h" 42#include "intel_fbo.h" 43#include "intel_screen.h" 44#include "intel_tex.h" 45#include "intel_regions.h" 46 47#include "i915_drm.h" 48 49#define DRI_CONF_TEXTURE_TILING(def) \ 50 51PUBLIC const char __driConfigOptions[] = 52 DRI_CONF_BEGIN 53 DRI_CONF_SECTION_PERFORMANCE 54 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_ALWAYS_SYNC) 55 /* Options correspond to DRI_CONF_BO_REUSE_DISABLED, 56 * DRI_CONF_BO_REUSE_ALL 57 */ 58 DRI_CONF_OPT_BEGIN_V(bo_reuse, enum, 1, "0:1") 59 DRI_CONF_DESC_BEGIN(en, "Buffer object reuse") 60 DRI_CONF_ENUM(0, "Disable buffer object reuse") 61 DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects") 62 DRI_CONF_DESC_END 63 DRI_CONF_OPT_END 64 65 DRI_CONF_OPT_BEGIN(texture_tiling, bool, true) 66 DRI_CONF_DESC(en, "Enable texture tiling") 67 DRI_CONF_OPT_END 68 69 DRI_CONF_OPT_BEGIN(early_z, bool, false) 70 DRI_CONF_DESC(en, "Enable early Z in classic mode (unstable, 945-only).") 71 DRI_CONF_OPT_END 72 73 DRI_CONF_OPT_BEGIN(fragment_shader, bool, false) 74 DRI_CONF_DESC(en, "Enable limited ARB_fragment_shader support on 915/945.") 75 DRI_CONF_OPT_END 76 77 DRI_CONF_SECTION_END 78 DRI_CONF_SECTION_QUALITY 79 DRI_CONF_FORCE_S3TC_ENABLE(false) 80 DRI_CONF_ALLOW_LARGE_TEXTURES(2) 81 DRI_CONF_SECTION_END 82 DRI_CONF_SECTION_DEBUG 83 DRI_CONF_NO_RAST(false) 84 DRI_CONF_ALWAYS_FLUSH_BATCH(false) 85 DRI_CONF_ALWAYS_FLUSH_CACHE(false) 86 87 DRI_CONF_OPT_BEGIN(stub_occlusion_query, bool, false) 88 DRI_CONF_DESC(en, "Enable stub ARB_occlusion_query support on 915/945.") 89 DRI_CONF_OPT_END 90 DRI_CONF_SECTION_END 91DRI_CONF_END; 92 93const GLuint __driNConfigOptions = 11; 94 95#ifdef USE_NEW_INTERFACE 96static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; 97#endif /*USE_NEW_INTERFACE */ 98 99static const __DRItexBufferExtension intelTexBufferExtension = { 100 { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, 101 intelSetTexBuffer, 102 intelSetTexBuffer2, 103}; 104 105static void 106intelDRI2Flush(__DRIdrawable *drawable) 107{ 108 struct intel_context *intel = drawable->driContextPriv->driverPrivate; 109 110 if (intel->gen < 4) 111 INTEL_FIREVERTICES(intel); 112 113 intel->need_throttle = GL_TRUE; 114 115 if (intel->batch->map != intel->batch->ptr) 116 intel_batchbuffer_flush(intel->batch); 117} 118 119static const struct __DRI2flushExtensionRec intelFlushExtension = { 120 { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, 121 intelDRI2Flush, 122 dri2InvalidateDrawable, 123}; 124 125static __DRIimage * 126intel_create_image_from_name(__DRIcontext *context, 127 int width, int height, int format, 128 int name, int pitch, void *loaderPrivate) 129{ 130 __DRIimage *image; 131 struct intel_context *intel = context->driverPrivate; 132 int cpp; 133 134 image = CALLOC(sizeof *image); 135 if (image == NULL) 136 return NULL; 137 138 switch (format) { 139 case __DRI_IMAGE_FORMAT_RGB565: 140 image->format = MESA_FORMAT_RGB565; 141 image->internal_format = GL_RGB; 142 image->data_type = GL_UNSIGNED_BYTE; 143 break; 144 case __DRI_IMAGE_FORMAT_XRGB8888: 145 image->format = MESA_FORMAT_XRGB8888; 146 image->internal_format = GL_RGB; 147 image->data_type = GL_UNSIGNED_BYTE; 148 break; 149 case __DRI_IMAGE_FORMAT_ARGB8888: 150 image->format = MESA_FORMAT_ARGB8888; 151 image->internal_format = GL_RGBA; 152 image->data_type = GL_UNSIGNED_BYTE; 153 break; 154 default: 155 free(image); 156 return NULL; 157 } 158 159 image->data = loaderPrivate; 160 cpp = _mesa_get_format_bytes(image->format); 161 162 image->region = intel_region_alloc_for_handle(intel, cpp, width, height, 163 pitch, name, "image"); 164 if (image->region == NULL) { 165 FREE(image); 166 return NULL; 167 } 168 169 return image; 170} 171 172static __DRIimage * 173intel_create_image_from_renderbuffer(__DRIcontext *context, 174 int renderbuffer, void *loaderPrivate) 175{ 176 __DRIimage *image; 177 struct intel_context *intel = context->driverPrivate; 178 struct gl_renderbuffer *rb; 179 struct intel_renderbuffer *irb; 180 181 rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer); 182 if (!rb) { 183 _mesa_error(&intel->ctx, 184 GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); 185 return NULL; 186 } 187 188 irb = intel_renderbuffer(rb); 189 image = CALLOC(sizeof *image); 190 if (image == NULL) 191 return NULL; 192 193 image->internal_format = rb->InternalFormat; 194 image->format = rb->Format; 195 image->data_type = rb->DataType; 196 image->data = loaderPrivate; 197 intel_region_reference(&image->region, irb->region); 198 199 return image; 200} 201 202static void 203intel_destroy_image(__DRIimage *image) 204{ 205 intel_region_release(&image->region); 206 FREE(image); 207} 208 209static struct __DRIimageExtensionRec intelImageExtension = { 210 { __DRI_IMAGE, __DRI_IMAGE_VERSION }, 211 intel_create_image_from_name, 212 intel_create_image_from_renderbuffer, 213 intel_destroy_image, 214}; 215 216static const __DRIextension *intelScreenExtensions[] = { 217 &driReadDrawableExtension, 218 &intelTexBufferExtension.base, 219 &intelFlushExtension.base, 220 &intelImageExtension.base, 221 &dri2ConfigQueryExtension.base, 222 NULL 223}; 224 225static GLboolean 226intel_get_param(__DRIscreen *psp, int param, int *value) 227{ 228 int ret; 229 struct drm_i915_getparam gp; 230 231 gp.param = param; 232 gp.value = value; 233 234 ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); 235 if (ret) { 236 _mesa_warning(NULL, "drm_i915_getparam: %d", ret); 237 return GL_FALSE; 238 } 239 240 return GL_TRUE; 241} 242 243static void 244nop_callback(GLuint key, void *data, void *userData) 245{ 246} 247 248static void 249intelDestroyScreen(__DRIscreen * sPriv) 250{ 251 struct intel_screen *intelScreen = sPriv->private; 252 253 dri_bufmgr_destroy(intelScreen->bufmgr); 254 driDestroyOptionInfo(&intelScreen->optionCache); 255 256 /* Some regions may still have references to them at this point, so 257 * flush the hash table to prevent _mesa_DeleteHashTable() from 258 * complaining about the hash not being empty; */ 259 _mesa_HashDeleteAll(intelScreen->named_regions, nop_callback, NULL); 260 _mesa_DeleteHashTable(intelScreen->named_regions); 261 262 FREE(intelScreen); 263 sPriv->private = NULL; 264} 265 266 267/** 268 * This is called when we need to set up GL rendering to a new X window. 269 */ 270static GLboolean 271intelCreateBuffer(__DRIscreen * driScrnPriv, 272 __DRIdrawable * driDrawPriv, 273 const __GLcontextModes * mesaVis, GLboolean isPixmap) 274{ 275 struct intel_renderbuffer *rb; 276 277 if (isPixmap) { 278 return GL_FALSE; /* not implemented */ 279 } 280 else { 281 GLboolean swStencil = (mesaVis->stencilBits > 0 && 282 mesaVis->depthBits != 24); 283 gl_format rgbFormat; 284 285 struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); 286 287 if (!fb) 288 return GL_FALSE; 289 290 _mesa_initialize_window_framebuffer(fb, mesaVis); 291 292 if (mesaVis->redBits == 5) 293 rgbFormat = MESA_FORMAT_RGB565; 294 else if (mesaVis->alphaBits == 0) 295 rgbFormat = MESA_FORMAT_XRGB8888; 296 else 297 rgbFormat = MESA_FORMAT_ARGB8888; 298 299 /* setup the hardware-based renderbuffers */ 300 rb = intel_create_renderbuffer(rgbFormat); 301 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &rb->Base); 302 303 if (mesaVis->doubleBufferMode) { 304 rb = intel_create_renderbuffer(rgbFormat); 305 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &rb->Base); 306 } 307 308 if (mesaVis->depthBits == 24) { 309 assert(mesaVis->stencilBits == 8); 310 /* combined depth/stencil buffer */ 311 struct intel_renderbuffer *depthStencilRb 312 = intel_create_renderbuffer(MESA_FORMAT_S8_Z24); 313 /* note: bind RB to two attachment points */ 314 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base); 315 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base); 316 } 317 else if (mesaVis->depthBits == 16) { 318 /* just 16-bit depth buffer, no hw stencil */ 319 struct intel_renderbuffer *depthRb 320 = intel_create_renderbuffer(MESA_FORMAT_Z16); 321 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); 322 } 323 324 /* now add any/all software-based renderbuffers we may need */ 325 _mesa_add_soft_renderbuffers(fb, 326 GL_FALSE, /* never sw color */ 327 GL_FALSE, /* never sw depth */ 328 swStencil, mesaVis->accumRedBits > 0, 329 GL_FALSE, /* never sw alpha */ 330 GL_FALSE /* never sw aux */ ); 331 driDrawPriv->driverPrivate = fb; 332 333 return GL_TRUE; 334 } 335} 336 337static void 338intelDestroyBuffer(__DRIdrawable * driDrawPriv) 339{ 340 struct gl_framebuffer *fb = driDrawPriv->driverPrivate; 341 342 _mesa_reference_framebuffer(&fb, NULL); 343} 344 345/* There are probably better ways to do this, such as an 346 * init-designated function to register chipids and createcontext 347 * functions. 348 */ 349extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis, 350 __DRIcontext * driContextPriv, 351 void *sharedContextPrivate); 352 353extern GLboolean i915CreateContext(int api, 354 const __GLcontextModes * mesaVis, 355 __DRIcontext * driContextPriv, 356 void *sharedContextPrivate); 357extern GLboolean brwCreateContext(int api, 358 const __GLcontextModes * mesaVis, 359 __DRIcontext * driContextPriv, 360 void *sharedContextPrivate); 361 362static GLboolean 363intelCreateContext(gl_api api, 364 const __GLcontextModes * mesaVis, 365 __DRIcontext * driContextPriv, 366 void *sharedContextPrivate) 367{ 368 __DRIscreen *sPriv = driContextPriv->driScreenPriv; 369 struct intel_screen *intelScreen = sPriv->private; 370 371#ifdef I915 372 if (IS_9XX(intelScreen->deviceID)) { 373 if (!IS_965(intelScreen->deviceID)) { 374 return i915CreateContext(api, mesaVis, driContextPriv, 375 sharedContextPrivate); 376 } 377 } else { 378 intelScreen->no_vbo = GL_TRUE; 379 return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate); 380 } 381#else 382 if (IS_965(intelScreen->deviceID)) 383 return brwCreateContext(api, mesaVis, 384 driContextPriv, sharedContextPrivate); 385#endif 386 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID); 387 return GL_FALSE; 388} 389 390static GLboolean 391intel_init_bufmgr(struct intel_screen *intelScreen) 392{ 393 __DRIscreen *spriv = intelScreen->driScrnPriv; 394 int num_fences = 0; 395 396 intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL; 397 398 intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ); 399 /* Otherwise, use the classic buffer manager. */ 400 if (intelScreen->bufmgr == NULL) { 401 fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n", 402 __func__, __LINE__); 403 return GL_FALSE; 404 } 405 406 if (!intel_get_param(spriv, I915_PARAM_NUM_FENCES_AVAIL, &num_fences) || 407 num_fences == 0) { 408 fprintf(stderr, "[%s: %u] Kernel 2.6.29 required.\n", __func__, __LINE__); 409 return GL_FALSE; 410 } 411 412 drm_intel_bufmgr_gem_enable_fenced_relocs(intelScreen->bufmgr); 413 414 intelScreen->named_regions = _mesa_NewHashTable(); 415 416 return GL_TRUE; 417} 418 419/** 420 * This is the driver specific part of the createNewScreen entry point. 421 * Called when using DRI2. 422 * 423 * \return the __GLcontextModes supported by this driver 424 */ 425static const 426__DRIconfig **intelInitScreen2(__DRIscreen *psp) 427{ 428 struct intel_screen *intelScreen; 429 GLenum fb_format[3]; 430 GLenum fb_type[3]; 431 unsigned int api_mask; 432 433 static const GLenum back_buffer_modes[] = { 434 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML 435 }; 436 uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1]; 437 int color; 438 __DRIconfig **configs = NULL; 439 440 /* Allocate the private area */ 441 intelScreen = CALLOC(sizeof *intelScreen); 442 if (!intelScreen) { 443 fprintf(stderr, "\nERROR! Allocating private area failed\n"); 444 return GL_FALSE; 445 } 446 /* parse information in __driConfigOptions */ 447 driParseOptionInfo(&intelScreen->optionCache, 448 __driConfigOptions, __driNConfigOptions); 449 450 intelScreen->driScrnPriv = psp; 451 psp->private = (void *) intelScreen; 452 453 /* Determine chipset ID */ 454 if (!intel_get_param(psp, I915_PARAM_CHIPSET_ID, 455 &intelScreen->deviceID)) 456 return GL_FALSE; 457 458 api_mask = (1 << __DRI_API_OPENGL); 459#if FEATURE_ES1 460 api_mask |= (1 << __DRI_API_GLES); 461#endif 462#if FEATURE_ES2 463 api_mask |= (1 << __DRI_API_GLES2); 464#endif 465 466 if (IS_9XX(intelScreen->deviceID) || IS_965(intelScreen->deviceID)) 467 psp->api_mask = api_mask; 468 469 if (!intel_init_bufmgr(intelScreen)) 470 return GL_FALSE; 471 472 psp->extensions = intelScreenExtensions; 473 474 msaa_samples_array[0] = 0; 475 476 fb_format[0] = GL_RGB; 477 fb_type[0] = GL_UNSIGNED_SHORT_5_6_5; 478 479 fb_format[1] = GL_BGR; 480 fb_type[1] = GL_UNSIGNED_INT_8_8_8_8_REV; 481 482 fb_format[2] = GL_BGRA; 483 fb_type[2] = GL_UNSIGNED_INT_8_8_8_8_REV; 484 485 depth_bits[0] = 0; 486 stencil_bits[0] = 0; 487 488 /* Generate a rich set of useful configs that do not include an 489 * accumulation buffer. 490 */ 491 for (color = 0; color < ARRAY_SIZE(fb_format); color++) { 492 __DRIconfig **new_configs; 493 int depth_factor; 494 495 /* Starting with DRI2 protocol version 1.1 we can request a depth/stencil 496 * buffer that has a diffferent number of bits per pixel than the color 497 * buffer. This isn't yet supported here. 498 */ 499 if (fb_type[color] == GL_UNSIGNED_SHORT_5_6_5) { 500 depth_bits[1] = 16; 501 stencil_bits[1] = 0; 502 } else { 503 depth_bits[1] = 24; 504 stencil_bits[1] = 8; 505 } 506 507 depth_factor = 2; 508 509 new_configs = driCreateConfigs(fb_format[color], fb_type[color], 510 depth_bits, 511 stencil_bits, 512 depth_factor, 513 back_buffer_modes, 514 ARRAY_SIZE(back_buffer_modes), 515 msaa_samples_array, 516 ARRAY_SIZE(msaa_samples_array), 517 GL_FALSE); 518 if (configs == NULL) 519 configs = new_configs; 520 else 521 configs = driConcatConfigs(configs, new_configs); 522 } 523 524 /* Generate the minimum possible set of configs that include an 525 * accumulation buffer. 526 */ 527 for (color = 0; color < ARRAY_SIZE(fb_format); color++) { 528 __DRIconfig **new_configs; 529 530 if (fb_type[color] == GL_UNSIGNED_SHORT_5_6_5) { 531 depth_bits[0] = 16; 532 stencil_bits[0] = 0; 533 } else { 534 depth_bits[0] = 24; 535 stencil_bits[0] = 8; 536 } 537 538 new_configs = driCreateConfigs(fb_format[color], fb_type[color], 539 depth_bits, stencil_bits, 1, 540 back_buffer_modes + 1, 1, 541 msaa_samples_array, 1, 542 GL_TRUE); 543 if (configs == NULL) 544 configs = new_configs; 545 else 546 configs = driConcatConfigs(configs, new_configs); 547 } 548 549 if (configs == NULL) { 550 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 551 __LINE__); 552 return NULL; 553 } 554 555 return (const __DRIconfig **)configs; 556} 557 558const struct __DriverAPIRec driDriverAPI = { 559 .DestroyScreen = intelDestroyScreen, 560 .CreateContext = intelCreateContext, 561 .DestroyContext = intelDestroyContext, 562 .CreateBuffer = intelCreateBuffer, 563 .DestroyBuffer = intelDestroyBuffer, 564 .MakeCurrent = intelMakeCurrent, 565 .UnbindContext = intelUnbindContext, 566 .InitScreen2 = intelInitScreen2, 567}; 568 569/* This is the table of extensions that the loader will dlsym() for. */ 570PUBLIC const __DRIextension *__driDriverExtensions[] = { 571 &driCoreExtension.base, 572 &driDRI2Extension.base, 573 NULL 574}; 575