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