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