dri_screen.c revision f80c2874eca86a12517fbe2f4c15287edfb4dc89
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#include "xmlpool.h" 34 35#include "dri_screen.h" 36 37#include "util/u_inlines.h" 38#include "pipe/p_screen.h" 39#include "pipe/p_format.h" 40#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ 41 42#include "util/u_debug.h" 43 44#define MSAA_VISUAL_MAX_SAMPLES 8 45 46PUBLIC const char __driConfigOptions[] = 47 DRI_CONF_BEGIN 48 DRI_CONF_SECTION_PERFORMANCE 49 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) 50 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) 51 DRI_CONF_SECTION_END 52 53 DRI_CONF_SECTION_QUALITY 54/* DRI_CONF_FORCE_S3TC_ENABLE(false) */ 55 DRI_CONF_ALLOW_LARGE_TEXTURES(1) 56 DRI_CONF_PP_CELSHADE(0) 57 DRI_CONF_PP_NORED(0) 58 DRI_CONF_PP_NOGREEN(0) 59 DRI_CONF_PP_NOBLUE(0) 60 DRI_CONF_PP_JIMENEZMLAA(0, 0, 32) 61 DRI_CONF_PP_JIMENEZMLAA_COLOR(0, 0, 32) 62 DRI_CONF_SECTION_END 63 DRI_CONF_END; 64 65static const uint __driNConfigOptions = 9; 66 67static const __DRIconfig ** 68dri_fill_in_modes(struct dri_screen *screen, 69 unsigned pixel_bits) 70{ 71 __DRIconfig **configs = NULL; 72 __DRIconfig **configs_r5g6b5 = NULL; 73 __DRIconfig **configs_a8r8g8b8 = NULL; 74 __DRIconfig **configs_x8r8g8b8 = NULL; 75 uint8_t depth_bits_array[5]; 76 uint8_t stencil_bits_array[5]; 77 uint8_t msaa_samples_array[MSAA_VISUAL_MAX_SAMPLES]; 78 unsigned depth_buffer_factor; 79 unsigned back_buffer_factor; 80 unsigned msaa_samples_factor, msaa_samples_max; 81 unsigned i; 82 struct pipe_screen *p_screen = screen->base.screen; 83 boolean pf_r5g6b5, pf_a8r8g8b8, pf_x8r8g8b8; 84 boolean pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32; 85 86 static const GLenum back_buffer_modes[] = { 87 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML 88 }; 89 90 depth_bits_array[0] = 0; 91 stencil_bits_array[0] = 0; 92 depth_buffer_factor = 1; 93 94 msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS) 95 ? MSAA_VISUAL_MAX_SAMPLES : 1; 96 97 pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM, 98 PIPE_TEXTURE_2D, 0, 99 PIPE_BIND_DEPTH_STENCIL); 100 pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, 101 PIPE_TEXTURE_2D, 0, 102 PIPE_BIND_DEPTH_STENCIL); 103 pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_UINT, 104 PIPE_TEXTURE_2D, 0, 105 PIPE_BIND_DEPTH_STENCIL); 106 pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_UINT_Z24_UNORM, 107 PIPE_TEXTURE_2D, 0, 108 PIPE_BIND_DEPTH_STENCIL); 109 pf_a8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM, 110 PIPE_TEXTURE_2D, 0, 111 PIPE_BIND_RENDER_TARGET); 112 pf_x8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM, 113 PIPE_TEXTURE_2D, 0, 114 PIPE_BIND_RENDER_TARGET); 115 pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM, 116 PIPE_TEXTURE_2D, 0, 117 PIPE_BIND_RENDER_TARGET); 118 119 /* We can only get a 16 or 32 bit depth buffer with getBuffersWithFormat */ 120 if (dri_with_format(screen->sPriv)) { 121 pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM, 122 PIPE_TEXTURE_2D, 0, 123 PIPE_BIND_DEPTH_STENCIL); 124 pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM, 125 PIPE_TEXTURE_2D, 0, 126 PIPE_BIND_DEPTH_STENCIL); 127 } else { 128 pf_z16 = FALSE; 129 pf_z32 = FALSE; 130 } 131 132 if (pf_z16) { 133 depth_bits_array[depth_buffer_factor] = 16; 134 stencil_bits_array[depth_buffer_factor++] = 0; 135 } 136 if (pf_x8z24 || pf_z24x8) { 137 depth_bits_array[depth_buffer_factor] = 24; 138 stencil_bits_array[depth_buffer_factor++] = 0; 139 screen->d_depth_bits_last = pf_x8z24; 140 } 141 if (pf_s8z24 || pf_z24s8) { 142 depth_bits_array[depth_buffer_factor] = 24; 143 stencil_bits_array[depth_buffer_factor++] = 8; 144 screen->sd_depth_bits_last = pf_s8z24; 145 } 146 if (pf_z32) { 147 depth_bits_array[depth_buffer_factor] = 32; 148 stencil_bits_array[depth_buffer_factor++] = 0; 149 } 150 151 msaa_samples_array[0] = 0; 152 back_buffer_factor = 3; 153 154 /* Also test for color multisample support - just assume it'll work 155 * for all depth buffers. 156 */ 157 if (pf_r5g6b5) { 158 msaa_samples_factor = 1; 159 for (i = 2; i <= msaa_samples_max; i++) { 160 if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM, 161 PIPE_TEXTURE_2D, i, 162 PIPE_BIND_RENDER_TARGET)) { 163 msaa_samples_array[msaa_samples_factor] = i; 164 msaa_samples_factor++; 165 } 166 } 167 168 configs_r5g6b5 = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 169 depth_bits_array, stencil_bits_array, 170 depth_buffer_factor, back_buffer_modes, 171 back_buffer_factor, 172 msaa_samples_array, msaa_samples_factor, 173 GL_TRUE); 174 } 175 176 if (pf_a8r8g8b8) { 177 msaa_samples_factor = 1; 178 for (i = 2; i <= msaa_samples_max; i++) { 179 if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM, 180 PIPE_TEXTURE_2D, i, 181 PIPE_BIND_RENDER_TARGET)) { 182 msaa_samples_array[msaa_samples_factor] = i; 183 msaa_samples_factor++; 184 } 185 } 186 187 configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 188 depth_bits_array, 189 stencil_bits_array, 190 depth_buffer_factor, 191 back_buffer_modes, 192 back_buffer_factor, 193 msaa_samples_array, 194 msaa_samples_factor, 195 GL_TRUE); 196 } 197 198 if (pf_x8r8g8b8) { 199 msaa_samples_factor = 1; 200 for (i = 2; i <= msaa_samples_max; i++) { 201 if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM, 202 PIPE_TEXTURE_2D, i, 203 PIPE_BIND_RENDER_TARGET)) { 204 msaa_samples_array[msaa_samples_factor] = i; 205 msaa_samples_factor++; 206 } 207 } 208 209 configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV, 210 depth_bits_array, 211 stencil_bits_array, 212 depth_buffer_factor, 213 back_buffer_modes, 214 back_buffer_factor, 215 msaa_samples_array, 216 msaa_samples_factor, 217 GL_TRUE); 218 } 219 220 if (pixel_bits == 16) { 221 configs = configs_r5g6b5; 222 if (configs_a8r8g8b8) 223 configs = configs ? driConcatConfigs(configs, configs_a8r8g8b8) : configs_a8r8g8b8; 224 if (configs_x8r8g8b8) 225 configs = configs ? driConcatConfigs(configs, configs_x8r8g8b8) : configs_x8r8g8b8; 226 } else { 227 configs = configs_a8r8g8b8; 228 if (configs_x8r8g8b8) 229 configs = configs ? driConcatConfigs(configs, configs_x8r8g8b8) : configs_x8r8g8b8; 230 if (configs_r5g6b5) 231 configs = configs ? driConcatConfigs(configs, configs_r5g6b5) : configs_r5g6b5; 232 } 233 234 if (configs == NULL) { 235 debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__); 236 return NULL; 237 } 238 239 return (const __DRIconfig **)configs; 240} 241 242/** 243 * Roughly the converse of dri_fill_in_modes. 244 */ 245void 246dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, 247 const struct gl_config *mode) 248{ 249 memset(stvis, 0, sizeof(*stvis)); 250 251 if (!mode) 252 return; 253 254 stvis->samples = mode->samples; 255 256 if (mode->redBits == 8) { 257 if (mode->alphaBits == 8) 258 stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM; 259 else 260 stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM; 261 } else { 262 stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM; 263 } 264 265 switch (mode->depthBits) { 266 default: 267 case 0: 268 stvis->depth_stencil_format = PIPE_FORMAT_NONE; 269 break; 270 case 16: 271 stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; 272 break; 273 case 24: 274 if (mode->stencilBits == 0) { 275 stvis->depth_stencil_format = (screen->d_depth_bits_last) ? 276 PIPE_FORMAT_Z24X8_UNORM: 277 PIPE_FORMAT_X8Z24_UNORM; 278 } else { 279 stvis->depth_stencil_format = (screen->sd_depth_bits_last) ? 280 PIPE_FORMAT_Z24_UNORM_S8_UINT: 281 PIPE_FORMAT_S8_UINT_Z24_UNORM; 282 } 283 break; 284 case 32: 285 stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; 286 break; 287 } 288 289 stvis->accum_format = (mode->haveAccumBuffer) ? 290 PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; 291 292 stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; 293 stvis->render_buffer = ST_ATTACHMENT_FRONT_LEFT; 294 if (mode->doubleBufferMode) { 295 stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; 296 stvis->render_buffer = ST_ATTACHMENT_BACK_LEFT; 297 } 298 if (mode->stereoMode) { 299 stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; 300 if (mode->doubleBufferMode) 301 stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; 302 } 303 304 if (mode->haveDepthBuffer || mode->haveStencilBuffer) 305 stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; 306 /* let the state tracker allocate the accum buffer */ 307} 308 309static boolean 310dri_get_egl_image(struct st_manager *smapi, 311 void *egl_image, 312 struct st_egl_image *stimg) 313{ 314 struct dri_screen *screen = (struct dri_screen *)smapi; 315 __DRIimage *img = NULL; 316 317 if (screen->lookup_egl_image) { 318 img = screen->lookup_egl_image(screen, egl_image); 319 } 320 321 if (!img) 322 return FALSE; 323 324 stimg->texture = NULL; 325 pipe_resource_reference(&stimg->texture, img->texture); 326 stimg->level = img->level; 327 stimg->layer = img->layer; 328 329 return TRUE; 330} 331 332static int 333dri_get_param(struct st_manager *smapi, 334 enum st_manager_param param) 335{ 336 struct dri_screen *screen = (struct dri_screen *)smapi; 337 338 switch(param) { 339 case ST_MANAGER_BROKEN_INVALIDATE: 340 return screen->broken_invalidate; 341 default: 342 return 0; 343 } 344} 345 346static void 347dri_destroy_option_cache(struct dri_screen * screen) 348{ 349 int i; 350 351 if (screen->optionCache.info) { 352 for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) { 353 FREE(screen->optionCache.info[i].name); 354 FREE(screen->optionCache.info[i].ranges); 355 } 356 FREE(screen->optionCache.info); 357 } 358 359 FREE(screen->optionCache.values); 360} 361 362void 363dri_destroy_screen_helper(struct dri_screen * screen) 364{ 365 if (screen->st_api && screen->st_api->destroy) 366 screen->st_api->destroy(screen->st_api); 367 368 if (screen->base.screen) 369 screen->base.screen->destroy(screen->base.screen); 370 371 dri_destroy_option_cache(screen); 372} 373 374void 375dri_destroy_screen(__DRIscreen * sPriv) 376{ 377 struct dri_screen *screen = dri_screen(sPriv); 378 379 dri_destroy_screen_helper(screen); 380 381 FREE(screen); 382 sPriv->driverPrivate = NULL; 383 sPriv->extensions = NULL; 384} 385 386const __DRIconfig ** 387dri_init_screen_helper(struct dri_screen *screen, 388 struct pipe_screen *pscreen, 389 unsigned pixel_bits) 390{ 391 screen->base.screen = pscreen; 392 if (!screen->base.screen) { 393 debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__); 394 return NULL; 395 } 396 397 screen->base.get_egl_image = dri_get_egl_image; 398 screen->base.get_param = dri_get_param; 399 400 screen->st_api = st_gl_api_create(); 401 if (!screen->st_api) 402 return NULL; 403 404 if(pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES)) 405 screen->target = PIPE_TEXTURE_2D; 406 else 407 screen->target = PIPE_TEXTURE_RECT; 408 409 driParseOptionInfo(&screen->optionCache, 410 __driConfigOptions, __driNConfigOptions); 411 412 return dri_fill_in_modes(screen, pixel_bits); 413} 414 415/* vim: set sw=3 ts=8 sts=3 expandtab: */ 416