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