intel_screen.c revision d282128ff68cc58bc3f5b808031c5fe7325bd69b
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 33#include "utils.h" 34#include "xmlpool.h" 35 36#include "intel_batchbuffer.h" 37#include "intel_buffers.h" 38#include "intel_bufmgr.h" 39#include "intel_chipset.h" 40#include "intel_extensions.h" 41#include "intel_fbo.h" 42#include "intel_regions.h" 43#include "intel_screen.h" 44#include "intel_span.h" 45#include "intel_tex.h" 46 47#include "i915_drm.h" 48#include "i830_dri.h" 49 50#define DRI_CONF_TEXTURE_TILING(def) \ 51 DRI_CONF_OPT_BEGIN(texture_tiling, bool, def) \ 52 DRI_CONF_DESC(en, "Enable texture tiling") \ 53 DRI_CONF_OPT_END \ 54 55PUBLIC const char __driConfigOptions[] = 56 DRI_CONF_BEGIN 57 DRI_CONF_SECTION_PERFORMANCE 58 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_ALWAYS_SYNC) 59 /* Options correspond to DRI_CONF_BO_REUSE_DISABLED, 60 * DRI_CONF_BO_REUSE_ALL 61 */ 62 DRI_CONF_OPT_BEGIN_V(bo_reuse, enum, 1, "0:1") 63 DRI_CONF_DESC_BEGIN(en, "Buffer object reuse") 64 DRI_CONF_ENUM(0, "Disable buffer object reuse") 65 DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects") 66 DRI_CONF_DESC_END 67 DRI_CONF_OPT_END 68 69#ifdef I915 70 DRI_CONF_TEXTURE_TILING(false) 71#else 72 DRI_CONF_TEXTURE_TILING(true) 73#endif 74 75 DRI_CONF_OPT_BEGIN(early_z, bool, false) 76 DRI_CONF_DESC(en, "Enable early Z in classic mode (unstable, 945-only).") 77 DRI_CONF_OPT_END 78 79 DRI_CONF_OPT_BEGIN(fragment_shader, bool, false) 80 DRI_CONF_DESC(en, "Enable limited ARB_fragment_shader support on 915/945.") 81 DRI_CONF_OPT_END 82 83 DRI_CONF_SECTION_END 84 DRI_CONF_SECTION_QUALITY 85 DRI_CONF_FORCE_S3TC_ENABLE(false) 86 DRI_CONF_ALLOW_LARGE_TEXTURES(2) 87 DRI_CONF_SECTION_END 88 DRI_CONF_SECTION_DEBUG 89 DRI_CONF_NO_RAST(false) 90 DRI_CONF_ALWAYS_FLUSH_BATCH(false) 91 DRI_CONF_ALWAYS_FLUSH_CACHE(false) 92 93 DRI_CONF_OPT_BEGIN(stub_occlusion_query, bool, false) 94 DRI_CONF_DESC(en, "Enable stub ARB_occlusion_query support on 915/945.") 95 DRI_CONF_OPT_END 96 DRI_CONF_SECTION_END 97DRI_CONF_END; 98 99const GLuint __driNConfigOptions = 11; 100 101#ifdef USE_NEW_INTERFACE 102static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; 103#endif /*USE_NEW_INTERFACE */ 104 105static const __DRItexOffsetExtension intelTexOffsetExtension = { 106 { __DRI_TEX_OFFSET }, 107 intelSetTexOffset, 108}; 109 110static const __DRItexBufferExtension intelTexBufferExtension = { 111 { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, 112 intelSetTexBuffer, 113 intelSetTexBuffer2, 114}; 115 116static const __DRIextension *intelScreenExtensions[] = { 117 &driReadDrawableExtension, 118 &intelTexOffsetExtension.base, 119 &intelTexBufferExtension.base, 120 NULL 121}; 122 123static GLboolean 124intel_get_param(__DRIscreen *psp, int param, int *value) 125{ 126 int ret; 127 struct drm_i915_getparam gp; 128 129 gp.param = param; 130 gp.value = value; 131 132 ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); 133 if (ret) { 134 _mesa_warning(NULL, "drm_i915_getparam: %d", ret); 135 return GL_FALSE; 136 } 137 138 return GL_TRUE; 139} 140 141static void 142intelDestroyScreen(__DRIscreen * sPriv) 143{ 144 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 145 146 dri_bufmgr_destroy(intelScreen->bufmgr); 147 driDestroyOptionInfo(&intelScreen->optionCache); 148 149 FREE(intelScreen); 150 sPriv->private = NULL; 151} 152 153 154/** 155 * This is called when we need to set up GL rendering to a new X window. 156 */ 157static GLboolean 158intelCreateBuffer(__DRIscreen * driScrnPriv, 159 __DRIdrawable * driDrawPriv, 160 const __GLcontextModes * mesaVis, GLboolean isPixmap) 161{ 162 struct intel_renderbuffer *rb; 163 164 if (isPixmap) { 165 return GL_FALSE; /* not implemented */ 166 } 167 else { 168 GLboolean swStencil = (mesaVis->stencilBits > 0 && 169 mesaVis->depthBits != 24); 170 gl_format rgbFormat; 171 172 struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); 173 174 if (!fb) 175 return GL_FALSE; 176 177 _mesa_initialize_framebuffer(fb, mesaVis); 178 179 if (mesaVis->redBits == 5) 180 rgbFormat = MESA_FORMAT_RGB565; 181 else if (mesaVis->alphaBits == 0) 182 rgbFormat = MESA_FORMAT_XRGB8888; 183 else 184 rgbFormat = MESA_FORMAT_ARGB8888; 185 186 /* setup the hardware-based renderbuffers */ 187 rb = intel_create_renderbuffer(rgbFormat); 188 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &rb->Base); 189 190 if (mesaVis->doubleBufferMode) { 191 rb = intel_create_renderbuffer(rgbFormat); 192 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &rb->Base); 193 } 194 195 if (mesaVis->depthBits == 24) { 196 if (mesaVis->stencilBits == 8) { 197 /* combined depth/stencil buffer */ 198 struct intel_renderbuffer *depthStencilRb 199 = intel_create_renderbuffer(MESA_FORMAT_S8_Z24); 200 /* note: bind RB to two attachment points */ 201 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base); 202 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base); 203 } else { 204 struct intel_renderbuffer *depthRb 205 = intel_create_renderbuffer(MESA_FORMAT_X8_Z24); 206 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); 207 } 208 } 209 else if (mesaVis->depthBits == 16) { 210 /* just 16-bit depth buffer, no hw stencil */ 211 struct intel_renderbuffer *depthRb 212 = intel_create_renderbuffer(MESA_FORMAT_Z16); 213 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); 214 } 215 216 /* now add any/all software-based renderbuffers we may need */ 217 _mesa_add_soft_renderbuffers(fb, 218 GL_FALSE, /* never sw color */ 219 GL_FALSE, /* never sw depth */ 220 swStencil, mesaVis->accumRedBits > 0, 221 GL_FALSE, /* never sw alpha */ 222 GL_FALSE /* never sw aux */ ); 223 driDrawPriv->driverPrivate = fb; 224 225 return GL_TRUE; 226 } 227} 228 229static void 230intelDestroyBuffer(__DRIdrawable * driDrawPriv) 231{ 232 struct gl_framebuffer *fb = driDrawPriv->driverPrivate; 233 234 _mesa_reference_framebuffer(&fb, NULL); 235} 236 237/* There are probably better ways to do this, such as an 238 * init-designated function to register chipids and createcontext 239 * functions. 240 */ 241extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis, 242 __DRIcontext * driContextPriv, 243 void *sharedContextPrivate); 244 245extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis, 246 __DRIcontext * driContextPriv, 247 void *sharedContextPrivate); 248extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis, 249 __DRIcontext * driContextPriv, 250 void *sharedContextPrivate); 251 252static GLboolean 253intelCreateContext(const __GLcontextModes * mesaVis, 254 __DRIcontext * driContextPriv, 255 void *sharedContextPrivate) 256{ 257 __DRIscreen *sPriv = driContextPriv->driScreenPriv; 258 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 259 260#ifdef I915 261 if (IS_9XX(intelScreen->deviceID)) { 262 if (!IS_965(intelScreen->deviceID)) { 263 return i915CreateContext(mesaVis, driContextPriv, 264 sharedContextPrivate); 265 } 266 } else { 267 intelScreen->no_vbo = GL_TRUE; 268 return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate); 269 } 270#else 271 if (IS_965(intelScreen->deviceID)) 272 return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate); 273#endif 274 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID); 275 return GL_FALSE; 276} 277 278static GLboolean 279intel_init_bufmgr(intelScreenPrivate *intelScreen) 280{ 281 int gem_kernel = 0; 282 struct drm_i915_getparam gp; 283 __DRIscreen *spriv = intelScreen->driScrnPriv; 284 int num_fences = 0; 285 286 intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL; 287 288 gp.param = I915_PARAM_HAS_GEM; 289 gp.value = &gem_kernel; 290 291 (void) drmCommandWriteRead(spriv->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); 292 293 /* If we've got a new enough DDX that's initializing GEM and giving us 294 * object handles for the shared buffers, use that. 295 */ 296 if (!intelScreen->driScrnPriv->dri2.enabled && 297 intelScreen->driScrnPriv->ddx_version.minor < 9) { 298 fprintf(stderr, "[%s:%u] Error initializing GEM.\n", 299 __func__, __LINE__); 300 return GL_FALSE; 301 } 302 303 intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ); 304 /* Otherwise, use the classic buffer manager. */ 305 if (intelScreen->bufmgr == NULL) { 306 fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n", 307 __func__, __LINE__); 308 return GL_FALSE; 309 } 310 311 if (intel_get_param(spriv, I915_PARAM_NUM_FENCES_AVAIL, &num_fences)) 312 intelScreen->kernel_exec_fencing = !!num_fences; 313 else 314 intelScreen->kernel_exec_fencing = GL_FALSE; 315 316 return GL_TRUE; 317} 318 319struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen) 320{ 321 /* 322 * This should probably change to have the screen allocate a dummy 323 * context at screen creation. For now just use the current context. 324 */ 325 326 GET_CURRENT_CONTEXT(ctx); 327 if (ctx == NULL) { 328 _mesa_problem(NULL, "No current context in intelScreenContext\n"); 329 return NULL; 330 } 331 return intel_context(ctx); 332} 333 334/** 335 * This is the driver specific part of the createNewScreen entry point. 336 * Called when using DRI2. 337 * 338 * \return the __GLcontextModes supported by this driver 339 */ 340static const 341__DRIconfig **intelInitScreen2(__DRIscreen *psp) 342{ 343 intelScreenPrivate *intelScreen; 344 GLenum fb_format[3]; 345 GLenum fb_type[3]; 346 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't 347 * support pageflipping at all. 348 */ 349 static const GLenum back_buffer_modes[] = { 350 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML 351 }; 352 uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1]; 353 int color; 354 __DRIconfig **configs = NULL; 355 356 /* Allocate the private area */ 357 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate)); 358 if (!intelScreen) { 359 fprintf(stderr, "\nERROR! Allocating private area failed\n"); 360 return GL_FALSE; 361 } 362 /* parse information in __driConfigOptions */ 363 driParseOptionInfo(&intelScreen->optionCache, 364 __driConfigOptions, __driNConfigOptions); 365 366 intelScreen->driScrnPriv = psp; 367 psp->private = (void *) intelScreen; 368 369 intelScreen->drmMinor = psp->drm_version.minor; 370 371 /* Determine chipset ID */ 372 if (!intel_get_param(psp, I915_PARAM_CHIPSET_ID, 373 &intelScreen->deviceID)) 374 return GL_FALSE; 375 376 if (!intel_init_bufmgr(intelScreen)) 377 return GL_FALSE; 378 379 intelScreen->irq_active = 1; 380 psp->extensions = intelScreenExtensions; 381 382 depth_bits[0] = 0; 383 stencil_bits[0] = 0; 384 depth_bits[1] = 16; 385 stencil_bits[1] = 0; 386 depth_bits[2] = 24; 387 stencil_bits[2] = 0; 388 depth_bits[3] = 24; 389 stencil_bits[3] = 8; 390 391 msaa_samples_array[0] = 0; 392 393 fb_format[0] = GL_RGB; 394 fb_type[0] = GL_UNSIGNED_SHORT_5_6_5; 395 396 fb_format[1] = GL_BGR; 397 fb_type[1] = GL_UNSIGNED_INT_8_8_8_8_REV; 398 399 fb_format[2] = GL_BGRA; 400 fb_type[2] = GL_UNSIGNED_INT_8_8_8_8_REV; 401 402 depth_bits[0] = 0; 403 stencil_bits[0] = 0; 404 405 for (color = 0; color < ARRAY_SIZE(fb_format); color++) { 406 __DRIconfig **new_configs; 407 int depth_factor; 408 409 /* With DRI2 right now, GetBuffers always returns a depth/stencil buffer 410 * with the same cpp as the drawable. So we can't support depth cpp != 411 * color cpp currently. 412 */ 413 if (fb_type[color] == GL_UNSIGNED_SHORT_5_6_5) { 414 depth_bits[1] = 16; 415 stencil_bits[1] = 0; 416 417 depth_factor = 2; 418 } else { 419 depth_bits[1] = 24; 420 stencil_bits[1] = 0; 421 depth_bits[2] = 24; 422 stencil_bits[2] = 8; 423 424 depth_factor = 3; 425 } 426 new_configs = driCreateConfigs(fb_format[color], fb_type[color], 427 depth_bits, 428 stencil_bits, 429 depth_factor, 430 back_buffer_modes, 431 ARRAY_SIZE(back_buffer_modes), 432 msaa_samples_array, 433 ARRAY_SIZE(msaa_samples_array)); 434 if (configs == NULL) 435 configs = new_configs; 436 else 437 configs = driConcatConfigs(configs, new_configs); 438 } 439 440 if (configs == NULL) { 441 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 442 __LINE__); 443 return NULL; 444 } 445 446 return (const __DRIconfig **)configs; 447} 448 449const struct __DriverAPIRec driDriverAPI = { 450 .DestroyScreen = intelDestroyScreen, 451 .CreateContext = intelCreateContext, 452 .DestroyContext = intelDestroyContext, 453 .CreateBuffer = intelCreateBuffer, 454 .DestroyBuffer = intelDestroyBuffer, 455 .MakeCurrent = intelMakeCurrent, 456 .UnbindContext = intelUnbindContext, 457 .InitScreen2 = intelInitScreen2, 458}; 459 460/* This is the table of extensions that the loader will dlsym() for. */ 461PUBLIC const __DRIextension *__driDriverExtensions[] = { 462 &driCoreExtension.base, 463 &driDRI2Extension.base, 464 NULL 465}; 466