intel_screen.c revision c6ef705e414c8e93ee471f50d15ada3492a9b067
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 void 117intelDRI2Flush(__DRIdrawable *drawable) 118{ 119 struct intel_context *intel = drawable->driContextPriv->driverPrivate; 120 121 if (intel->gen < 4) 122 INTEL_FIREVERTICES(intel); 123 124 if (intel->batch->map != intel->batch->ptr) 125 intel_batchbuffer_flush(intel->batch); 126} 127 128static void 129intelDRI2FlushInvalidate(__DRIdrawable *drawable) 130{ 131 intelDRI2Flush(drawable); 132 drawable->validBuffers = GL_FALSE; 133} 134 135static const struct __DRI2flushExtensionRec intelFlushExtension = { 136 { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, 137 intelDRI2Flush, 138 intelDRI2FlushInvalidate, 139}; 140 141static const __DRIextension *intelScreenExtensions[] = { 142 &driReadDrawableExtension, 143 &intelTexOffsetExtension.base, 144 &intelTexBufferExtension.base, 145 &intelFlushExtension.base, 146 NULL 147}; 148 149static GLboolean 150intel_get_param(__DRIscreen *psp, int param, int *value) 151{ 152 int ret; 153 struct drm_i915_getparam gp; 154 155 gp.param = param; 156 gp.value = value; 157 158 ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); 159 if (ret) { 160 _mesa_warning(NULL, "drm_i915_getparam: %d", ret); 161 return GL_FALSE; 162 } 163 164 return GL_TRUE; 165} 166 167static void 168intelDestroyScreen(__DRIscreen * sPriv) 169{ 170 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 171 172 dri_bufmgr_destroy(intelScreen->bufmgr); 173 driDestroyOptionInfo(&intelScreen->optionCache); 174 175 FREE(intelScreen); 176 sPriv->private = NULL; 177} 178 179 180/** 181 * This is called when we need to set up GL rendering to a new X window. 182 */ 183static GLboolean 184intelCreateBuffer(__DRIscreen * driScrnPriv, 185 __DRIdrawable * driDrawPriv, 186 const __GLcontextModes * mesaVis, GLboolean isPixmap) 187{ 188 struct intel_renderbuffer *rb; 189 190 if (isPixmap) { 191 return GL_FALSE; /* not implemented */ 192 } 193 else { 194 GLboolean swStencil = (mesaVis->stencilBits > 0 && 195 mesaVis->depthBits != 24); 196 gl_format rgbFormat; 197 198 struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); 199 200 if (!fb) 201 return GL_FALSE; 202 203 _mesa_initialize_framebuffer(fb, mesaVis); 204 205 if (mesaVis->redBits == 5) 206 rgbFormat = MESA_FORMAT_RGB565; 207 else if (mesaVis->alphaBits == 0) 208 rgbFormat = MESA_FORMAT_XRGB8888; 209 else 210 rgbFormat = MESA_FORMAT_ARGB8888; 211 212 /* setup the hardware-based renderbuffers */ 213 rb = intel_create_renderbuffer(rgbFormat); 214 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &rb->Base); 215 216 if (mesaVis->doubleBufferMode) { 217 rb = intel_create_renderbuffer(rgbFormat); 218 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &rb->Base); 219 } 220 221 if (mesaVis->depthBits == 24) { 222 if (mesaVis->stencilBits == 8) { 223 /* combined depth/stencil buffer */ 224 struct intel_renderbuffer *depthStencilRb 225 = intel_create_renderbuffer(MESA_FORMAT_S8_Z24); 226 /* note: bind RB to two attachment points */ 227 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base); 228 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base); 229 } else { 230 struct intel_renderbuffer *depthRb 231 = intel_create_renderbuffer(MESA_FORMAT_X8_Z24); 232 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); 233 } 234 } 235 else if (mesaVis->depthBits == 16) { 236 /* just 16-bit depth buffer, no hw stencil */ 237 struct intel_renderbuffer *depthRb 238 = intel_create_renderbuffer(MESA_FORMAT_Z16); 239 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); 240 } 241 242 /* now add any/all software-based renderbuffers we may need */ 243 _mesa_add_soft_renderbuffers(fb, 244 GL_FALSE, /* never sw color */ 245 GL_FALSE, /* never sw depth */ 246 swStencil, mesaVis->accumRedBits > 0, 247 GL_FALSE, /* never sw alpha */ 248 GL_FALSE /* never sw aux */ ); 249 driDrawPriv->driverPrivate = fb; 250 251 return GL_TRUE; 252 } 253} 254 255static void 256intelDestroyBuffer(__DRIdrawable * driDrawPriv) 257{ 258 struct gl_framebuffer *fb = driDrawPriv->driverPrivate; 259 260 _mesa_reference_framebuffer(&fb, NULL); 261} 262 263/* There are probably better ways to do this, such as an 264 * init-designated function to register chipids and createcontext 265 * functions. 266 */ 267extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis, 268 __DRIcontext * driContextPriv, 269 void *sharedContextPrivate); 270 271extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis, 272 __DRIcontext * driContextPriv, 273 void *sharedContextPrivate); 274extern GLboolean brwCreateContext(const __GLcontextModes * mesaVis, 275 __DRIcontext * driContextPriv, 276 void *sharedContextPrivate); 277 278static GLboolean 279intelCreateContext(const __GLcontextModes * mesaVis, 280 __DRIcontext * driContextPriv, 281 void *sharedContextPrivate) 282{ 283 __DRIscreen *sPriv = driContextPriv->driScreenPriv; 284 intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; 285 286#ifdef I915 287 if (IS_9XX(intelScreen->deviceID)) { 288 if (!IS_965(intelScreen->deviceID)) { 289 return i915CreateContext(mesaVis, driContextPriv, 290 sharedContextPrivate); 291 } 292 } else { 293 intelScreen->no_vbo = GL_TRUE; 294 return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate); 295 } 296#else 297 if (IS_965(intelScreen->deviceID)) 298 return brwCreateContext(mesaVis, driContextPriv, sharedContextPrivate); 299#endif 300 fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID); 301 return GL_FALSE; 302} 303 304static GLboolean 305intel_init_bufmgr(intelScreenPrivate *intelScreen) 306{ 307 __DRIscreen *spriv = intelScreen->driScrnPriv; 308 int num_fences = 0; 309 310 intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL; 311 312 intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ); 313 /* Otherwise, use the classic buffer manager. */ 314 if (intelScreen->bufmgr == NULL) { 315 fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n", 316 __func__, __LINE__); 317 return GL_FALSE; 318 } 319 320 if (intel_get_param(spriv, I915_PARAM_NUM_FENCES_AVAIL, &num_fences)) 321 intelScreen->kernel_exec_fencing = !!num_fences; 322 else 323 intelScreen->kernel_exec_fencing = GL_FALSE; 324 325 return GL_TRUE; 326} 327 328/** 329 * This is the driver specific part of the createNewScreen entry point. 330 * Called when using DRI2. 331 * 332 * \return the __GLcontextModes supported by this driver 333 */ 334static const 335__DRIconfig **intelInitScreen2(__DRIscreen *psp) 336{ 337 intelScreenPrivate *intelScreen; 338 GLenum fb_format[3]; 339 GLenum fb_type[3]; 340 341 static const GLenum back_buffer_modes[] = { 342 GLX_NONE, GLX_SWAP_UNDEFINED_OML, 343 GLX_SWAP_EXCHANGE_OML, GLX_SWAP_COPY_OML 344 }; 345 uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1]; 346 int color; 347 __DRIconfig **configs = NULL; 348 349 /* Allocate the private area */ 350 intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate)); 351 if (!intelScreen) { 352 fprintf(stderr, "\nERROR! Allocating private area failed\n"); 353 return GL_FALSE; 354 } 355 /* parse information in __driConfigOptions */ 356 driParseOptionInfo(&intelScreen->optionCache, 357 __driConfigOptions, __driNConfigOptions); 358 359 intelScreen->driScrnPriv = psp; 360 psp->private = (void *) intelScreen; 361 362 intelScreen->drmMinor = psp->drm_version.minor; 363 364 /* Determine chipset ID */ 365 if (!intel_get_param(psp, I915_PARAM_CHIPSET_ID, 366 &intelScreen->deviceID)) 367 return GL_FALSE; 368 369 if (!intel_init_bufmgr(intelScreen)) 370 return GL_FALSE; 371 372 intelScreen->irq_active = 1; 373 psp->extensions = intelScreenExtensions; 374 375 depth_bits[0] = 0; 376 stencil_bits[0] = 0; 377 depth_bits[1] = 16; 378 stencil_bits[1] = 0; 379 depth_bits[2] = 24; 380 stencil_bits[2] = 0; 381 depth_bits[3] = 24; 382 stencil_bits[3] = 8; 383 384 msaa_samples_array[0] = 0; 385 386 fb_format[0] = GL_RGB; 387 fb_type[0] = GL_UNSIGNED_SHORT_5_6_5; 388 389 fb_format[1] = GL_BGR; 390 fb_type[1] = GL_UNSIGNED_INT_8_8_8_8_REV; 391 392 fb_format[2] = GL_BGRA; 393 fb_type[2] = GL_UNSIGNED_INT_8_8_8_8_REV; 394 395 depth_bits[0] = 0; 396 stencil_bits[0] = 0; 397 398 for (color = 0; color < ARRAY_SIZE(fb_format); color++) { 399 __DRIconfig **new_configs; 400 int depth_factor; 401 402 /* With DRI2 right now, GetBuffers always returns a depth/stencil buffer 403 * with the same cpp as the drawable. So we can't support depth cpp != 404 * color cpp currently. 405 */ 406 if (fb_type[color] == GL_UNSIGNED_SHORT_5_6_5) { 407 depth_bits[1] = 16; 408 stencil_bits[1] = 0; 409 410 depth_factor = 2; 411 } else { 412 depth_bits[1] = 24; 413 stencil_bits[1] = 0; 414 depth_bits[2] = 24; 415 stencil_bits[2] = 8; 416 417 depth_factor = 3; 418 } 419 new_configs = driCreateConfigs(fb_format[color], fb_type[color], 420 depth_bits, 421 stencil_bits, 422 depth_factor, 423 back_buffer_modes, 424 ARRAY_SIZE(back_buffer_modes), 425 msaa_samples_array, 426 ARRAY_SIZE(msaa_samples_array)); 427 if (configs == NULL) 428 configs = new_configs; 429 else 430 configs = driConcatConfigs(configs, new_configs); 431 } 432 433 if (configs == NULL) { 434 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, 435 __LINE__); 436 return NULL; 437 } 438 439 return (const __DRIconfig **)configs; 440} 441 442const struct __DriverAPIRec driDriverAPI = { 443 .DestroyScreen = intelDestroyScreen, 444 .CreateContext = intelCreateContext, 445 .DestroyContext = intelDestroyContext, 446 .CreateBuffer = intelCreateBuffer, 447 .DestroyBuffer = intelDestroyBuffer, 448 .MakeCurrent = intelMakeCurrent, 449 .UnbindContext = intelUnbindContext, 450 .InitScreen2 = intelInitScreen2, 451}; 452 453/* This is the table of extensions that the loader will dlsym() for. */ 454PUBLIC const __DRIextension *__driDriverExtensions[] = { 455 &driCoreExtension.base, 456 &driDRI2Extension.base, 457 NULL 458}; 459