intel_screen.c revision 8e7a8d65931a650534e0f5c4e0d8118cd6f7636e
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 __DRItexOffsetExtension intelTexOffsetExtension = { 100 { __DRI_TEX_OFFSET }, 101 intelSetTexOffset, 102}; 103 104static const __DRItexBufferExtension intelTexBufferExtension = { 105 { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, 106 intelSetTexBuffer, 107 intelSetTexBuffer2, 108}; 109 110static void 111intelDRI2Flush(__DRIdrawable *drawable) 112{ 113 struct intel_context *intel = drawable->driContextPriv->driverPrivate; 114 115 if (intel->gen < 4) 116 INTEL_FIREVERTICES(intel); 117 118 if (intel->batch->map != intel->batch->ptr) 119 intel_batchbuffer_flush(intel->batch); 120} 121 122static void 123intelDRI2Invalidate(__DRIdrawable *drawable) 124{ 125 struct intel_context *intel = drawable->driContextPriv->driverPrivate; 126 127 intel->using_dri2_swapbuffers = GL_TRUE; 128 dri2InvalidateDrawable(drawable); 129} 130 131static const struct __DRI2flushExtensionRec intelFlushExtension = { 132 { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, 133 intelDRI2Flush, 134 intelDRI2Invalidate, 135}; 136 137static __DRIimage * 138intel_create_image_from_name(__DRIcontext *context, 139 int width, int height, int format, 140 int name, int pitch, void *loaderPrivate) 141{ 142 __DRIimage *image; 143 struct intel_context *intel = context->driverPrivate; 144 int cpp; 145 146 image = CALLOC(sizeof *image); 147 if (image == NULL) 148 return NULL; 149 150 switch (format) { 151 case __DRI_IMAGE_FORMAT_RGB565: 152 image->format = MESA_FORMAT_RGB565; 153 image->internal_format = GL_RGB; 154 image->data_type = GL_UNSIGNED_BYTE; 155 break; 156 case __DRI_IMAGE_FORMAT_XRGB8888: 157 image->format = MESA_FORMAT_XRGB8888; 158 image->internal_format = GL_RGB; 159 image->data_type = GL_UNSIGNED_BYTE; 160 break; 161 case __DRI_IMAGE_FORMAT_ARGB8888: 162 image->format = MESA_FORMAT_ARGB8888; 163 image->internal_format = GL_RGBA; 164 image->data_type = GL_UNSIGNED_BYTE; 165 break; 166 default: 167 free(image); 168 return NULL; 169 } 170 171 image->data = loaderPrivate; 172 cpp = _mesa_get_format_bytes(image->format); 173 174 image->region = intel_region_alloc_for_handle(intel, cpp, width, height, 175 pitch, name, "image"); 176 if (image->region == NULL) { 177 FREE(image); 178 return NULL; 179 } 180 181 return image; 182} 183 184static __DRIimage * 185intel_create_image_from_renderbuffer(__DRIcontext *context, 186 int renderbuffer, void *loaderPrivate) 187{ 188 __DRIimage *image; 189 struct intel_context *intel = context->driverPrivate; 190 struct gl_renderbuffer *rb; 191 struct intel_renderbuffer *irb; 192 193 rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer); 194 if (!rb) { 195 _mesa_error(&intel->ctx, 196 GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); 197 return NULL; 198 } 199 200 irb = intel_renderbuffer(rb); 201 image = CALLOC(sizeof *image); 202 if (image == NULL) 203 return NULL; 204 205 image->internal_format = rb->InternalFormat; 206 image->format = rb->Format; 207 image->data_type = rb->DataType; 208 image->data = loaderPrivate; 209 intel_region_reference(&image->region, irb->region); 210 211 return image; 212} 213 214static void 215intel_destroy_image(__DRIimage *image) 216{ 217 intel_region_release(&image->region); 218 FREE(image); 219} 220 221static struct __DRIimageExtensionRec intelImageExtension = { 222 { __DRI_IMAGE, __DRI_IMAGE_VERSION }, 223 intel_create_image_from_name, 224 intel_create_image_from_renderbuffer, 225 intel_destroy_image, 226}; 227 228static const __DRIextension *intelScreenExtensions[] = { 229 &driReadDrawableExtension, 230 &intelTexOffsetExtension.base, 231 &intelTexBufferExtension.base, 232 &intelFlushExtension.base, 233 &intelImageExtension.base, 234 NULL 235}; 236 237static GLboolean 238intel_get_param(__DRIscreen *psp, int param, int *value) 239{ 240 int ret; 241 struct drm_i915_getparam gp; 242 243 gp.param = param; 244 gp.value = value; 245 246 ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); 247 if (ret) { 248 _mesa_warning(NULL, "drm_i915_getparam: %d", ret); 249 return GL_FALSE; 250 } 251 252 return GL_TRUE; 253} 254 255static void 256nop_callback(GLuint key, void *data, void *userData) 257{ 258} 259 260static void 261intelDestroyScreen(__DRIscreen * sPriv) 262{ 263 struct intel_screen *intelScreen = sPriv->private; 264 265 dri_bufmgr_destroy(intelScreen->bufmgr); 266 driDestroyOptionInfo(&intelScreen->optionCache); 267 268 /* Some regions may still have references to them at this point, so 269 * flush the hash table to prevent _mesa_DeleteHashTable() from 270 * complaining about the hash not being empty; */ 271 _mesa_HashDeleteAll(intelScreen->named_regions, nop_callback, NULL); 272 _mesa_DeleteHashTable(intelScreen->named_regions); 273 274 FREE(intelScreen); 275 sPriv->private = NULL; 276} 277 278 279/** 280 * This is called when we need to set up GL rendering to a new X window. 281 */ 282static GLboolean 283intelCreateBuffer(__DRIscreen * driScrnPriv, 284 __DRIdrawable * driDrawPriv, 285 const __GLcontextModes * mesaVis, GLboolean isPixmap) 286{ 287 struct intel_renderbuffer *rb; 288 289 if (isPixmap) { 290 return GL_FALSE; /* not implemented */ 291 } 292 else { 293 GLboolean swStencil = (mesaVis->stencilBits > 0 && 294 mesaVis->depthBits != 24); 295 gl_format rgbFormat; 296 297 struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); 298 299 if (!fb) 300 return GL_FALSE; 301 302 _mesa_initialize_window_framebuffer(fb, mesaVis); 303 304 if (mesaVis->redBits == 5) 305 rgbFormat = MESA_FORMAT_RGB565; 306 else if (mesaVis->alphaBits == 0) 307 rgbFormat = MESA_FORMAT_XRGB8888; 308 else 309 rgbFormat = MESA_FORMAT_ARGB8888; 310 311 /* setup the hardware-based renderbuffers */ 312 rb = intel_create_renderbuffer(rgbFormat); 313 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &rb->Base); 314 315 if (mesaVis->doubleBufferMode) { 316 rb = intel_create_renderbuffer(rgbFormat); 317 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &rb->Base); 318 } 319 320 if (mesaVis->depthBits == 24) { 321 if (mesaVis->stencilBits == 8) { 322 /* combined depth/stencil buffer */ 323 struct intel_renderbuffer *depthStencilRb 324 = intel_create_renderbuffer(MESA_FORMAT_S8_Z24); 325 /* note: bind RB to two attachment points */ 326 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base); 327 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base); 328 } else { 329 struct intel_renderbuffer *depthRb 330 = intel_create_renderbuffer(MESA_FORMAT_X8_Z24); 331 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); 332 } 333 } 334 else if (mesaVis->depthBits == 16) { 335 /* just 16-bit depth buffer, no hw stencil */ 336 struct intel_renderbuffer *depthRb 337 = intel_create_renderbuffer(MESA_FORMAT_Z16); 338 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); 339 } 340 341 /* now add any/all software-based renderbuffers we may need */ 342 _mesa_add_soft_renderbuffers(fb, 343 GL_FALSE, /* never sw color */ 344 GL_FALSE, /* never sw depth */ 345 swStencil, mesaVis->accumRedBits > 0, 346 GL_FALSE, /* never sw alpha */ 347 GL_FALSE /* never sw aux */ ); 348 driDrawPriv->driverPrivate = fb; 349 350 return GL_TRUE; 351 } 352} 353 354static void 355intelDestroyBuffer(__DRIdrawable * driDrawPriv) 356{ 357 struct gl_framebuffer *fb = driDrawPriv->driverPrivate; 358 359 _mesa_reference_framebuffer(&fb, NULL); 360} 361 362/* There are probably better ways to do this, such as an 363 * init-designated function to register chipids and createcontext 364 * functions. 365 */ 366extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis, 367 __DRIcontext * driContextPriv, 368 void *sharedContextPrivate); 369 370extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis, 371 __DRIcontext * driContextPriv, 372 void *sharedContextPrivate); 373extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis, 374 __DRIcontext * driContextPriv, 375 void *sharedContextPrivate); 376 377static GLboolean 378intelCreateContext(const __GLcontextModes * mesaVis, 379 __DRIcontext * driContextPriv, 380 void *sharedContextPrivate) 381{ 382 __DRIscreen *sPriv = driContextPriv->driScreenPriv; 383 struct intel_screen *intelScreen = sPriv->private; 384 385#ifdef I915 386 if (IS_9XX(intelScreen->deviceID)) { 387 if (!IS_965(intelScreen->deviceID)) { 388 return i915CreateContext(mesaVis, driContextPriv, 389 sharedContextPrivate); 390 } 391 } else { 392 intelScreen->no_vbo = GL_TRUE; 393 return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate); 394 } 395#else 396 if (IS_965(intelScreen->deviceID)) 397 return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate); 398#endif 399 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID); 400 return GL_FALSE; 401} 402 403static GLboolean 404intel_init_bufmgr(struct intel_screen *intelScreen) 405{ 406 __DRIscreen *spriv = intelScreen->driScrnPriv; 407 int num_fences = 0; 408 409 intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL; 410 411 intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ); 412 /* Otherwise, use the classic buffer manager. */ 413 if (intelScreen->bufmgr == NULL) { 414 fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n", 415 __func__, __LINE__); 416 return GL_FALSE; 417 } 418 419 if (intel_get_param(spriv, I915_PARAM_NUM_FENCES_AVAIL, &num_fences)) 420 intelScreen->kernel_exec_fencing = !!num_fences; 421 else 422 intelScreen->kernel_exec_fencing = GL_FALSE; 423 424 drm_intel_bufmgr_gem_enable_fenced_relocs(intelScreen->bufmgr); 425 426 intelScreen->named_regions = _mesa_NewHashTable(); 427 428 return GL_TRUE; 429} 430 431/** 432 * This is the driver specific part of the createNewScreen entry point. 433 * Called when using DRI2. 434 * 435 * \return the __GLcontextModes supported by this driver 436 */ 437static const 438__DRIconfig **intelInitScreen2(__DRIscreen *psp) 439{ 440 struct intel_screen *intelScreen; 441 GLenum fb_format[3]; 442 GLenum fb_type[3]; 443 444 static const GLenum back_buffer_modes[] = { 445 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML 446 }; 447 uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1]; 448 int color; 449 __DRIconfig **configs = NULL; 450 451 /* Allocate the private area */ 452 intelScreen = CALLOC(sizeof *intelScreen); 453 if (!intelScreen) { 454 fprintf(stderr, "\nERROR! Allocating private area failed\n"); 455 return GL_FALSE; 456 } 457 /* parse information in __driConfigOptions */ 458 driParseOptionInfo(&intelScreen->optionCache, 459 __driConfigOptions, __driNConfigOptions); 460 461 intelScreen->driScrnPriv = psp; 462 psp->private = (void *) intelScreen; 463 464 /* Determine chipset ID */ 465 if (!intel_get_param(psp, I915_PARAM_CHIPSET_ID, 466 &intelScreen->deviceID)) 467 return GL_FALSE; 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