intel_screen.c revision a232cc59e3f8ac8462c23b1a83e0ba60b451e681
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 if (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 } else { 323 struct intel_renderbuffer *depthRb 324 = intel_create_renderbuffer(MESA_FORMAT_X8_Z24); 325 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); 326 } 327 } 328 else if (mesaVis->depthBits == 16) { 329 /* just 16-bit depth buffer, no hw stencil */ 330 struct intel_renderbuffer *depthRb 331 = intel_create_renderbuffer(MESA_FORMAT_Z16); 332 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); 333 } 334 335 /* now add any/all software-based renderbuffers we may need */ 336 _mesa_add_soft_renderbuffers(fb, 337 GL_FALSE, /* never sw color */ 338 GL_FALSE, /* never sw depth */ 339 swStencil, mesaVis->accumRedBits > 0, 340 GL_FALSE, /* never sw alpha */ 341 GL_FALSE /* never sw aux */ ); 342 driDrawPriv->driverPrivate = fb; 343 344 return GL_TRUE; 345 } 346} 347 348static void 349intelDestroyBuffer(__DRIdrawable * driDrawPriv) 350{ 351 struct gl_framebuffer *fb = driDrawPriv->driverPrivate; 352 353 _mesa_reference_framebuffer(&fb, NULL); 354} 355 356/* There are probably better ways to do this, such as an 357 * init-designated function to register chipids and createcontext 358 * functions. 359 */ 360extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis, 361 __DRIcontext * driContextPriv, 362 void *sharedContextPrivate); 363 364extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis, 365 __DRIcontext * driContextPriv, 366 void *sharedContextPrivate); 367extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis, 368 __DRIcontext * driContextPriv, 369 void *sharedContextPrivate); 370 371static GLboolean 372intelCreateContext(const __GLcontextModes * mesaVis, 373 __DRIcontext * driContextPriv, 374 void *sharedContextPrivate) 375{ 376 __DRIscreen *sPriv = driContextPriv->driScreenPriv; 377 struct intel_screen *intelScreen = sPriv->private; 378 379#ifdef I915 380 if (IS_9XX(intelScreen->deviceID)) { 381 if (!IS_965(intelScreen->deviceID)) { 382 return i915CreateContext(mesaVis, driContextPriv, 383 sharedContextPrivate); 384 } 385 } else { 386 intelScreen->no_vbo = GL_TRUE; 387 return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate); 388 } 389#else 390 if (IS_965(intelScreen->deviceID)) 391 return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate); 392#endif 393 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID); 394 return GL_FALSE; 395} 396 397static GLboolean 398intel_init_bufmgr(struct intel_screen *intelScreen) 399{ 400 __DRIscreen *spriv = intelScreen->driScrnPriv; 401 int num_fences = 0; 402 403 intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL; 404 405 intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ); 406 /* Otherwise, use the classic buffer manager. */ 407 if (intelScreen->bufmgr == NULL) { 408 fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n", 409 __func__, __LINE__); 410 return GL_FALSE; 411 } 412 413 if (!intel_get_param(spriv, I915_PARAM_NUM_FENCES_AVAIL, &num_fences) || 414 num_fences == 0) { 415 fprintf(stderr, "[%s: %u] Kernel 2.6.29 required.\n", __func__, __LINE__); 416 return GL_FALSE; 417 } 418 419 drm_intel_bufmgr_gem_enable_fenced_relocs(intelScreen->bufmgr); 420 421 intelScreen->named_regions = _mesa_NewHashTable(); 422 423 return GL_TRUE; 424} 425 426/** 427 * This is the driver specific part of the createNewScreen entry point. 428 * Called when using DRI2. 429 * 430 * \return the __GLcontextModes supported by this driver 431 */ 432static const 433__DRIconfig **intelInitScreen2(__DRIscreen *psp) 434{ 435 struct intel_screen *intelScreen; 436 GLenum fb_format[3]; 437 GLenum fb_type[3]; 438 439 static const GLenum back_buffer_modes[] = { 440 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML 441 }; 442 uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1]; 443 int color; 444 __DRIconfig **configs = NULL; 445 446 /* Allocate the private area */ 447 intelScreen = CALLOC(sizeof *intelScreen); 448 if (!intelScreen) { 449 fprintf(stderr, "\nERROR! Allocating private area failed\n"); 450 return GL_FALSE; 451 } 452 /* parse information in __driConfigOptions */ 453 driParseOptionInfo(&intelScreen->optionCache, 454 __driConfigOptions, __driNConfigOptions); 455 456 intelScreen->driScrnPriv = psp; 457 psp->private = (void *) intelScreen; 458 459 /* Determine chipset ID */ 460 if (!intel_get_param(psp, I915_PARAM_CHIPSET_ID, 461 &intelScreen->deviceID)) 462 return GL_FALSE; 463 464 if (!intel_init_bufmgr(intelScreen)) 465 return GL_FALSE; 466 467 psp->extensions = intelScreenExtensions; 468 469 msaa_samples_array[0] = 0; 470 471 fb_format[0] = GL_RGB; 472 fb_type[0] = GL_UNSIGNED_SHORT_5_6_5; 473 474 fb_format[1] = GL_BGR; 475 fb_type[1] = GL_UNSIGNED_INT_8_8_8_8_REV; 476 477 fb_format[2] = GL_BGRA; 478 fb_type[2] = GL_UNSIGNED_INT_8_8_8_8_REV; 479 480 depth_bits[0] = 0; 481 stencil_bits[0] = 0; 482 483 /* Generate a rich set of useful configs that do not include an 484 * accumulation buffer. 485 */ 486 for (color = 0; color < ARRAY_SIZE(fb_format); color++) { 487 __DRIconfig **new_configs; 488 int depth_factor; 489 490 /* Starting with DRI2 protocol version 1.1 we can request a depth/stencil 491 * buffer that has a diffferent number of bits per pixel than the color 492 * buffer. This isn't yet supported here. 493 */ 494 if (fb_type[color] == GL_UNSIGNED_SHORT_5_6_5) { 495 depth_bits[1] = 16; 496 stencil_bits[1] = 0; 497 } else { 498 depth_bits[1] = 24; 499 stencil_bits[1] = 8; 500 } 501 502 depth_factor = 2; 503 504 new_configs = driCreateConfigs(fb_format[color], fb_type[color], 505 depth_bits, 506 stencil_bits, 507 depth_factor, 508 back_buffer_modes, 509 ARRAY_SIZE(back_buffer_modes), 510 msaa_samples_array, 511 ARRAY_SIZE(msaa_samples_array), 512 GL_FALSE); 513 if (configs == NULL) 514 configs = new_configs; 515 else 516 configs = driConcatConfigs(configs, new_configs); 517 } 518 519 /* Generate the minimum possible set of configs that include an 520 * accumulation buffer. 521 */ 522 for (color = 0; color < ARRAY_SIZE(fb_format); color++) { 523 __DRIconfig **new_configs; 524 525 if (fb_type[color] == GL_UNSIGNED_SHORT_5_6_5) { 526 depth_bits[0] = 16; 527 stencil_bits[0] = 0; 528 } else { 529 depth_bits[0] = 24; 530 stencil_bits[0] = 8; 531 } 532 533 new_configs = driCreateConfigs(fb_format[color], fb_type[color], 534 depth_bits, stencil_bits, 1, 535 back_buffer_modes + 1, 1, 536 msaa_samples_array, 1, 537 GL_TRUE); 538 if (configs == NULL) 539 configs = new_configs; 540 else 541 configs = driConcatConfigs(configs, new_configs); 542 } 543 544 if (configs == NULL) { 545 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 546 __LINE__); 547 return NULL; 548 } 549 550 return (const __DRIconfig **)configs; 551} 552 553const struct __DriverAPIRec driDriverAPI = { 554 .DestroyScreen = intelDestroyScreen, 555 .CreateContext = intelCreateContext, 556 .DestroyContext = intelDestroyContext, 557 .CreateBuffer = intelCreateBuffer, 558 .DestroyBuffer = intelDestroyBuffer, 559 .MakeCurrent = intelMakeCurrent, 560 .UnbindContext = intelUnbindContext, 561 .InitScreen2 = intelInitScreen2, 562}; 563 564/* This is the table of extensions that the loader will dlsym() for. */ 565PUBLIC const __DRIextension *__driDriverExtensions[] = { 566 &driCoreExtension.base, 567 &driDRI2Extension.base, 568 NULL 569}; 570