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