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