1/************************************************************************** 2 * 3 * Copyright 2009, VMware, Inc. 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 VMWARE 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 * Author: Keith Whitwell <keithw@vmware.com> 29 * Author: Jakob Bornecrantz <wallbraker@gmail.com> 30 */ 31 32#include "utils.h" 33 34#include "dri_screen.h" 35#include "dri_context.h" 36#include "dri_helpers.h" 37 38#include "util/u_inlines.h" 39#include "pipe/p_screen.h" 40#include "pipe/p_format.h" 41#include "pipe-loader/pipe_loader.h" 42#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ 43#include "frontend/drm_driver.h" 44 45#include "util/u_debug.h" 46#include "util/u_driconf.h" 47#include "util/format/u_format_s3tc.h" 48 49#define MSAA_VISUAL_MAX_SAMPLES 32 50 51#undef false 52 53const __DRIconfigOptionsExtension gallium_config_options = { 54 .base = { __DRI_CONFIG_OPTIONS, 2 }, 55 .getXml = pipe_loader_get_driinfo_xml 56}; 57 58#define false 0 59 60void 61dri_init_options(struct dri_screen *screen) 62{ 63 pipe_loader_config_options(screen->dev); 64 65 struct st_config_options *options = &screen->options; 66 const struct driOptionCache *optionCache = &screen->dev->option_cache; 67 68 u_driconf_fill_st_options(options, optionCache); 69} 70 71static unsigned 72dri_loader_get_cap(struct dri_screen *screen, enum dri_loader_cap cap) 73{ 74 const __DRIdri2LoaderExtension *dri2_loader = screen->sPriv->dri2.loader; 75 const __DRIimageLoaderExtension *image_loader = screen->sPriv->image.loader; 76 77 if (dri2_loader && dri2_loader->base.version >= 4 && 78 dri2_loader->getCapability) 79 return dri2_loader->getCapability(screen->sPriv->loaderPrivate, cap); 80 81 if (image_loader && image_loader->base.version >= 2 && 82 image_loader->getCapability) 83 return image_loader->getCapability(screen->sPriv->loaderPrivate, cap); 84 85 return 0; 86} 87 88static const __DRIconfig ** 89dri_fill_in_modes(struct dri_screen *screen) 90{ 91 static const mesa_format mesa_formats[] = { 92 MESA_FORMAT_B10G10R10A2_UNORM, 93 MESA_FORMAT_B10G10R10X2_UNORM, 94 MESA_FORMAT_R10G10B10A2_UNORM, 95 MESA_FORMAT_R10G10B10X2_UNORM, 96 MESA_FORMAT_B8G8R8A8_UNORM, 97 MESA_FORMAT_B8G8R8X8_UNORM, 98 MESA_FORMAT_B8G8R8A8_SRGB, 99 MESA_FORMAT_B8G8R8X8_SRGB, 100 MESA_FORMAT_B5G6R5_UNORM, 101 MESA_FORMAT_RGBA_FLOAT16, 102 MESA_FORMAT_RGBX_FLOAT16, 103 104 /* The 32-bit RGBA format must not precede the 32-bit BGRA format. 105 * Likewise for RGBX and BGRX. Otherwise, the GLX client and the GLX 106 * server may disagree on which format the GLXFBConfig represents, 107 * resulting in swapped color channels. 108 * 109 * The problem, as of 2017-05-30: 110 * When matching a GLXFBConfig to a __DRIconfig, GLX ignores the channel 111 * order and chooses the first __DRIconfig with the expected channel 112 * sizes. Specifically, GLX compares the GLXFBConfig's and __DRIconfig's 113 * __DRI_ATTRIB_{CHANNEL}_SIZE but ignores __DRI_ATTRIB_{CHANNEL}_MASK. 114 * 115 * EGL does not suffer from this problem. It correctly compares the 116 * channel masks when matching EGLConfig to __DRIconfig. 117 */ 118 119 /* Required by Android, for HAL_PIXEL_FORMAT_RGBA_8888. */ 120 MESA_FORMAT_R8G8B8A8_UNORM, 121 122 /* Required by Android, for HAL_PIXEL_FORMAT_RGBX_8888. */ 123 MESA_FORMAT_R8G8B8X8_UNORM, 124 125 /* Required by Android, for HAL_PIXEL_FORMAT_RGBA_8888. */ 126 MESA_FORMAT_R8G8B8A8_SRGB, 127 128 /* Required by Android, for HAL_PIXEL_FORMAT_RGBX_8888. */ 129 MESA_FORMAT_R8G8B8X8_SRGB, 130 }; 131 static const enum pipe_format pipe_formats[] = { 132 PIPE_FORMAT_B10G10R10A2_UNORM, 133 PIPE_FORMAT_B10G10R10X2_UNORM, 134 PIPE_FORMAT_R10G10B10A2_UNORM, 135 PIPE_FORMAT_R10G10B10X2_UNORM, 136 PIPE_FORMAT_BGRA8888_UNORM, 137 PIPE_FORMAT_BGRX8888_UNORM, 138 PIPE_FORMAT_BGRA8888_SRGB, 139 PIPE_FORMAT_BGRX8888_SRGB, 140 PIPE_FORMAT_B5G6R5_UNORM, 141 PIPE_FORMAT_R16G16B16A16_FLOAT, 142 PIPE_FORMAT_R16G16B16X16_FLOAT, 143 PIPE_FORMAT_RGBA8888_UNORM, 144 PIPE_FORMAT_RGBX8888_UNORM, 145 PIPE_FORMAT_RGBA8888_SRGB, 146 PIPE_FORMAT_RGBX8888_SRGB, 147 }; 148 mesa_format format; 149 __DRIconfig **configs = NULL; 150 uint8_t depth_bits_array[5]; 151 uint8_t stencil_bits_array[5]; 152 unsigned depth_buffer_factor; 153 unsigned msaa_samples_max; 154 unsigned i; 155 struct pipe_screen *p_screen = screen->base.screen; 156 bool pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32; 157 bool mixed_color_depth; 158 bool allow_rgba_ordering; 159 bool allow_rgb10; 160 bool allow_fp16; 161 162 static const GLenum back_buffer_modes[] = { 163 __DRI_ATTRIB_SWAP_NONE, __DRI_ATTRIB_SWAP_UNDEFINED, 164 __DRI_ATTRIB_SWAP_COPY 165 }; 166 167 if (driQueryOptionb(&screen->dev->option_cache, "always_have_depth_buffer")) { 168 /* all visuals will have a depth buffer */ 169 depth_buffer_factor = 0; 170 } 171 else { 172 depth_bits_array[0] = 0; 173 stencil_bits_array[0] = 0; 174 depth_buffer_factor = 1; 175 } 176 177 allow_rgba_ordering = dri_loader_get_cap(screen, DRI_LOADER_CAP_RGBA_ORDERING); 178 allow_rgb10 = driQueryOptionb(&screen->dev->option_cache, "allow_rgb10_configs"); 179 allow_fp16 = dri_loader_get_cap(screen, DRI_LOADER_CAP_FP16); 180 181 msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS_MASK) 182 ? MSAA_VISUAL_MAX_SAMPLES : 1; 183 184 pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM, 185 PIPE_TEXTURE_2D, 0, 0, 186 PIPE_BIND_DEPTH_STENCIL); 187 pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, 188 PIPE_TEXTURE_2D, 0, 0, 189 PIPE_BIND_DEPTH_STENCIL); 190 pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_UINT, 191 PIPE_TEXTURE_2D, 0, 0, 192 PIPE_BIND_DEPTH_STENCIL); 193 pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_UINT_Z24_UNORM, 194 PIPE_TEXTURE_2D, 0, 0, 195 PIPE_BIND_DEPTH_STENCIL); 196 pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM, 197 PIPE_TEXTURE_2D, 0, 0, 198 PIPE_BIND_DEPTH_STENCIL); 199 pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM, 200 PIPE_TEXTURE_2D, 0, 0, 201 PIPE_BIND_DEPTH_STENCIL); 202 203 if (pf_z16) { 204 depth_bits_array[depth_buffer_factor] = 16; 205 stencil_bits_array[depth_buffer_factor++] = 0; 206 } 207 if (pf_x8z24 || pf_z24x8) { 208 depth_bits_array[depth_buffer_factor] = 24; 209 stencil_bits_array[depth_buffer_factor++] = 0; 210 screen->d_depth_bits_last = pf_x8z24; 211 } 212 if (pf_s8z24 || pf_z24s8) { 213 depth_bits_array[depth_buffer_factor] = 24; 214 stencil_bits_array[depth_buffer_factor++] = 8; 215 screen->sd_depth_bits_last = pf_s8z24; 216 } 217 if (pf_z32) { 218 depth_bits_array[depth_buffer_factor] = 32; 219 stencil_bits_array[depth_buffer_factor++] = 0; 220 } 221 222 mixed_color_depth = 223 p_screen->get_param(p_screen, PIPE_CAP_MIXED_COLOR_DEPTH_BITS); 224 225 assert(ARRAY_SIZE(mesa_formats) == ARRAY_SIZE(pipe_formats)); 226 227 /* Add configs. */ 228 for (format = 0; format < ARRAY_SIZE(mesa_formats); format++) { 229 __DRIconfig **new_configs = NULL; 230 unsigned num_msaa_modes = 0; /* includes a single-sample mode */ 231 uint8_t msaa_modes[MSAA_VISUAL_MAX_SAMPLES]; 232 233 /* Expose only BGRA ordering if the loader doesn't support RGBA ordering. */ 234 if (!allow_rgba_ordering && 235 (mesa_formats[format] == MESA_FORMAT_R8G8B8A8_UNORM || 236 mesa_formats[format] == MESA_FORMAT_R8G8B8X8_UNORM || 237 mesa_formats[format] == MESA_FORMAT_R8G8B8A8_SRGB || 238 mesa_formats[format] == MESA_FORMAT_R8G8B8X8_SRGB)) 239 continue; 240 241 if (!allow_rgb10 && 242 (mesa_formats[format] == MESA_FORMAT_B10G10R10A2_UNORM || 243 mesa_formats[format] == MESA_FORMAT_B10G10R10X2_UNORM || 244 mesa_formats[format] == MESA_FORMAT_R10G10B10A2_UNORM || 245 mesa_formats[format] == MESA_FORMAT_R10G10B10X2_UNORM)) 246 continue; 247 248 if (!allow_fp16 && 249 (mesa_formats[format] == MESA_FORMAT_RGBA_FLOAT16 || 250 mesa_formats[format] == MESA_FORMAT_RGBX_FLOAT16)) 251 continue; 252 253 if (!p_screen->is_format_supported(p_screen, pipe_formats[format], 254 PIPE_TEXTURE_2D, 0, 0, 255 PIPE_BIND_RENDER_TARGET | 256 PIPE_BIND_DISPLAY_TARGET)) 257 continue; 258 259 for (i = 1; i <= msaa_samples_max; i++) { 260 int samples = i > 1 ? i : 0; 261 262 if (p_screen->is_format_supported(p_screen, pipe_formats[format], 263 PIPE_TEXTURE_2D, samples, samples, 264 PIPE_BIND_RENDER_TARGET)) { 265 msaa_modes[num_msaa_modes++] = samples; 266 } 267 } 268 269 if (num_msaa_modes) { 270 /* Single-sample configs with an accumulation buffer. */ 271 new_configs = driCreateConfigs(mesa_formats[format], 272 depth_bits_array, stencil_bits_array, 273 depth_buffer_factor, back_buffer_modes, 274 ARRAY_SIZE(back_buffer_modes), 275 msaa_modes, 1, 276 GL_TRUE, !mixed_color_depth); 277 configs = driConcatConfigs(configs, new_configs); 278 279 /* Multi-sample configs without an accumulation buffer. */ 280 if (num_msaa_modes > 1) { 281 new_configs = driCreateConfigs(mesa_formats[format], 282 depth_bits_array, stencil_bits_array, 283 depth_buffer_factor, back_buffer_modes, 284 ARRAY_SIZE(back_buffer_modes), 285 msaa_modes+1, num_msaa_modes-1, 286 GL_FALSE, !mixed_color_depth); 287 configs = driConcatConfigs(configs, new_configs); 288 } 289 } 290 } 291 292 if (configs == NULL) { 293 debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__); 294 return NULL; 295 } 296 297 return (const __DRIconfig **)configs; 298} 299 300/** 301 * Roughly the converse of dri_fill_in_modes. 302 */ 303void 304dri_fill_st_visual(struct st_visual *stvis, 305 const struct dri_screen *screen, 306 const struct gl_config *mode) 307{ 308 memset(stvis, 0, sizeof(*stvis)); 309 310 if (!mode) 311 return; 312 313 /* Deduce the color format. */ 314 switch (mode->redMask) { 315 case 0: 316 /* Formats > 32 bpp */ 317 assert(mode->floatMode); 318 if (mode->alphaShift > -1) { 319 assert(mode->alphaShift == 48); 320 stvis->color_format = PIPE_FORMAT_R16G16B16A16_FLOAT; 321 } else { 322 stvis->color_format = PIPE_FORMAT_R16G16B16X16_FLOAT; 323 } 324 break; 325 326 case 0x3FF00000: 327 if (mode->alphaMask) { 328 assert(mode->alphaMask == 0xC0000000); 329 stvis->color_format = PIPE_FORMAT_B10G10R10A2_UNORM; 330 } else { 331 stvis->color_format = PIPE_FORMAT_B10G10R10X2_UNORM; 332 } 333 break; 334 335 case 0x000003FF: 336 if (mode->alphaMask) { 337 assert(mode->alphaMask == 0xC0000000); 338 stvis->color_format = PIPE_FORMAT_R10G10B10A2_UNORM; 339 } else { 340 stvis->color_format = PIPE_FORMAT_R10G10B10X2_UNORM; 341 } 342 break; 343 344 case 0x00FF0000: 345 if (mode->alphaMask) { 346 assert(mode->alphaMask == 0xFF000000); 347 stvis->color_format = mode->sRGBCapable ? 348 PIPE_FORMAT_BGRA8888_SRGB : 349 PIPE_FORMAT_BGRA8888_UNORM; 350 } else { 351 stvis->color_format = mode->sRGBCapable ? 352 PIPE_FORMAT_BGRX8888_SRGB : 353 PIPE_FORMAT_BGRX8888_UNORM; 354 } 355 break; 356 357 case 0x000000FF: 358 if (mode->alphaMask) { 359 assert(mode->alphaMask == 0xFF000000); 360 stvis->color_format = mode->sRGBCapable ? 361 PIPE_FORMAT_RGBA8888_SRGB : 362 PIPE_FORMAT_RGBA8888_UNORM; 363 } else { 364 stvis->color_format = mode->sRGBCapable ? 365 PIPE_FORMAT_RGBX8888_SRGB : 366 PIPE_FORMAT_RGBX8888_UNORM; 367 } 368 break; 369 370 case 0x0000F800: 371 stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM; 372 break; 373 374 default: 375 assert(!"unsupported visual: invalid red mask"); 376 return; 377 } 378 379 if (mode->samples > 0) { 380 if (debug_get_bool_option("DRI_NO_MSAA", false)) 381 stvis->samples = 0; 382 else 383 stvis->samples = mode->samples; 384 } 385 386 switch (mode->depthBits) { 387 default: 388 case 0: 389 stvis->depth_stencil_format = PIPE_FORMAT_NONE; 390 break; 391 case 16: 392 stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; 393 break; 394 case 24: 395 if (mode->stencilBits == 0) { 396 stvis->depth_stencil_format = (screen->d_depth_bits_last) ? 397 PIPE_FORMAT_Z24X8_UNORM: 398 PIPE_FORMAT_X8Z24_UNORM; 399 } else { 400 stvis->depth_stencil_format = (screen->sd_depth_bits_last) ? 401 PIPE_FORMAT_Z24_UNORM_S8_UINT: 402 PIPE_FORMAT_S8_UINT_Z24_UNORM; 403 } 404 break; 405 case 32: 406 stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; 407 break; 408 } 409 410 stvis->accum_format = (mode->accumRedBits > 0) ? 411 PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; 412 413 stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; 414 if (mode->doubleBufferMode) { 415 stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; 416 } 417 if (mode->stereoMode) { 418 stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; 419 if (mode->doubleBufferMode) 420 stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; 421 } 422 423 if (mode->depthBits > 0 || mode->stencilBits > 0) 424 stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; 425 /* let the gallium frontend allocate the accum buffer */ 426} 427 428static bool 429dri_get_egl_image(struct st_manager *smapi, 430 void *egl_image, 431 struct st_egl_image *stimg) 432{ 433 struct dri_screen *screen = (struct dri_screen *)smapi; 434 __DRIimage *img = NULL; 435 const struct dri2_format_mapping *map; 436 437 if (screen->lookup_egl_image_validated) { 438 img = screen->lookup_egl_image_validated(screen, egl_image); 439 } else if (screen->lookup_egl_image) { 440 img = screen->lookup_egl_image(screen, egl_image); 441 } 442 443 if (!img) 444 return FALSE; 445 446 stimg->texture = NULL; 447 pipe_resource_reference(&stimg->texture, img->texture); 448 map = dri2_get_mapping_by_fourcc(img->dri_fourcc); 449 stimg->format = map ? map->pipe_format : img->texture->format; 450 stimg->level = img->level; 451 stimg->layer = img->layer; 452 453 if (img->imported_dmabuf && map) { 454 /* Guess sized internal format for dma-bufs. Could be used 455 * by EXT_EGL_image_storage. 456 */ 457 mesa_format mesa_format = driImageFormatToGLFormat(map->dri_format); 458 stimg->internalformat = driGLFormatToSizedInternalGLFormat(mesa_format); 459 } 460 461 return TRUE; 462} 463 464static bool 465dri_validate_egl_image(struct st_manager *smapi, 466 void *egl_image) 467{ 468 struct dri_screen *screen = (struct dri_screen *)smapi; 469 470 return screen->validate_egl_image(screen, egl_image); 471} 472 473static int 474dri_get_param(struct st_manager *smapi, 475 enum st_manager_param param) 476{ 477 struct dri_screen *screen = (struct dri_screen *)smapi; 478 479 switch(param) { 480 case ST_MANAGER_BROKEN_INVALIDATE: 481 return screen->broken_invalidate; 482 default: 483 return 0; 484 } 485} 486 487void 488dri_destroy_screen_helper(struct dri_screen * screen) 489{ 490 if (screen->base.destroy) 491 screen->base.destroy(&screen->base); 492 493 if (screen->st_api && screen->st_api->destroy) 494 screen->st_api->destroy(screen->st_api); 495 496 if (screen->base.screen) 497 screen->base.screen->destroy(screen->base.screen); 498 499 mtx_destroy(&screen->opencl_func_mutex); 500} 501 502void 503dri_destroy_screen(__DRIscreen * sPriv) 504{ 505 struct dri_screen *screen = dri_screen(sPriv); 506 507 dri_destroy_screen_helper(screen); 508 509 pipe_loader_release(&screen->dev, 1); 510 511 free(screen->options.force_gl_vendor); 512 free(screen->options.force_gl_renderer); 513 514 /* The caller in dri_util preserves the fd ownership */ 515 free(screen); 516 sPriv->driverPrivate = NULL; 517 sPriv->extensions = NULL; 518} 519 520static void 521dri_postprocessing_init(struct dri_screen *screen) 522{ 523 unsigned i; 524 525 for (i = 0; i < PP_FILTERS; i++) { 526 screen->pp_enabled[i] = driQueryOptioni(&screen->dev->option_cache, 527 pp_filters[i].name); 528 } 529} 530 531static void 532dri_set_background_context(struct st_context_iface *st, 533 struct util_queue_monitoring *queue_info) 534{ 535 struct dri_context *ctx = (struct dri_context *)st->st_manager_private; 536 const __DRIbackgroundCallableExtension *backgroundCallable = 537 ctx->sPriv->dri2.backgroundCallable; 538 539 /* Note: Mesa will only call this function if GL multithreading is enabled 540 * We only do that if the loader exposed the __DRI_BACKGROUND_CALLABLE 541 * extension. So we know that backgroundCallable is not NULL. 542 */ 543 assert(backgroundCallable); 544 backgroundCallable->setBackgroundContext(ctx->cPriv->loaderPrivate); 545 546 if (ctx->hud) 547 hud_add_queue_for_monitoring(ctx->hud, queue_info); 548} 549 550const __DRIconfig ** 551dri_init_screen_helper(struct dri_screen *screen, 552 struct pipe_screen *pscreen) 553{ 554 screen->base.screen = pscreen; 555 screen->base.get_egl_image = dri_get_egl_image; 556 screen->base.get_param = dri_get_param; 557 screen->base.set_background_context = dri_set_background_context; 558 559 if (screen->validate_egl_image) 560 screen->base.validate_egl_image = dri_validate_egl_image; 561 562 screen->st_api = st_gl_api_create(); 563 if (!screen->st_api) 564 return NULL; 565 566 if(pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES)) 567 screen->target = PIPE_TEXTURE_2D; 568 else 569 screen->target = PIPE_TEXTURE_RECT; 570 571 dri_postprocessing_init(screen); 572 573 screen->st_api->query_versions(screen->st_api, &screen->base, 574 &screen->options, 575 &screen->sPriv->max_gl_core_version, 576 &screen->sPriv->max_gl_compat_version, 577 &screen->sPriv->max_gl_es1_version, 578 &screen->sPriv->max_gl_es2_version); 579 580 return dri_fill_in_modes(screen); 581} 582 583/* vim: set sw=3 ts=8 sts=3 expandtab: */ 584