native_ximage.c revision f38a20b4616632d8a5e604362dd661e1900b4ab8
1bcbc1788b478b1e54079318ad073e8490aa66faetfarina/* 2bcbc1788b478b1e54079318ad073e8490aa66faetfarina * Mesa 3-D graphics library 3bcbc1788b478b1e54079318ad073e8490aa66faetfarina * Version: 7.8 4bcbc1788b478b1e54079318ad073e8490aa66faetfarina * 5bcbc1788b478b1e54079318ad073e8490aa66faetfarina * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> 6bcbc1788b478b1e54079318ad073e8490aa66faetfarina * 7bcbc1788b478b1e54079318ad073e8490aa66faetfarina * Permission is hereby granted, free of charge, to any person obtaining a 8bcbc1788b478b1e54079318ad073e8490aa66faetfarina * copy of this software and associated documentation files (the "Software"), 9bcbc1788b478b1e54079318ad073e8490aa66faetfarina * to deal in the Software without restriction, including without limitation 10bcbc1788b478b1e54079318ad073e8490aa66faetfarina * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11bcbc1788b478b1e54079318ad073e8490aa66faetfarina * and/or sell copies of the Software, and to permit persons to whom the 12bcbc1788b478b1e54079318ad073e8490aa66faetfarina * Software is furnished to do so, subject to the following conditions: 13bcbc1788b478b1e54079318ad073e8490aa66faetfarina * 14936b73424f7393994be832376287da988a52b993caryclark * The above copyright notice and this permission notice shall be included 15bcbc1788b478b1e54079318ad073e8490aa66faetfarina * in all copies or substantial portions of the Software. 16bcbc1788b478b1e54079318ad073e8490aa66faetfarina * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 */ 25 26#include <X11/Xlib.h> 27#include <X11/Xutil.h> 28#include "util/u_memory.h" 29#include "util/u_math.h" 30#include "util/u_format.h" 31#include "pipe/p_compiler.h" 32#include "util/u_inlines.h" 33#include "state_tracker/xlib_sw_winsys.h" 34#include "target-helpers/wrap_screen.h" 35#include "util/u_debug.h" 36#include "softpipe/sp_public.h" 37#include "llvmpipe/lp_public.h" 38#include "egllog.h" 39 40#include "common/native_helper.h" 41#include "native_x11.h" 42#include "x11_screen.h" 43 44enum ximage_surface_type { 45 XIMAGE_SURFACE_TYPE_WINDOW, 46 XIMAGE_SURFACE_TYPE_PIXMAP, 47}; 48 49struct ximage_display { 50 struct native_display base; 51 Display *dpy; 52 boolean own_dpy; 53 54 struct native_event_handler *event_handler; 55 56 struct x11_screen *xscr; 57 int xscr_number; 58 59 struct ximage_config *configs; 60 int num_configs; 61}; 62 63struct ximage_surface { 64 struct native_surface base; 65 Drawable drawable; 66 enum ximage_surface_type type; 67 enum pipe_format color_format; 68 XVisualInfo visual; 69 struct ximage_display *xdpy; 70 71 unsigned int server_stamp; 72 unsigned int client_stamp; 73 74 struct resource_surface *rsurf; 75 struct xlib_drawable xdraw; 76}; 77 78struct ximage_config { 79 struct native_config base; 80 const XVisualInfo *visual; 81}; 82 83static INLINE struct ximage_display * 84ximage_display(const struct native_display *ndpy) 85{ 86 return (struct ximage_display *) ndpy; 87} 88 89static INLINE struct ximage_surface * 90ximage_surface(const struct native_surface *nsurf) 91{ 92 return (struct ximage_surface *) nsurf; 93} 94 95static INLINE struct ximage_config * 96ximage_config(const struct native_config *nconf) 97{ 98 return (struct ximage_config *) nconf; 99} 100 101/** 102 * Update the geometry of the surface. This is a slow functions. 103 */ 104static void 105ximage_surface_update_geometry(struct native_surface *nsurf) 106{ 107 struct ximage_surface *xsurf = ximage_surface(nsurf); 108 Status ok; 109 Window root; 110 int x, y; 111 unsigned int w, h, border, depth; 112 113 ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable, 114 &root, &x, &y, &w, &h, &border, &depth); 115 if (ok && resource_surface_set_size(xsurf->rsurf, w, h)) 116 xsurf->server_stamp++; 117} 118 119/** 120 * Update the buffers of the surface. 121 */ 122static boolean 123ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) 124{ 125 struct ximage_surface *xsurf = ximage_surface(nsurf); 126 boolean ret; 127 128 ximage_surface_update_geometry(&xsurf->base); 129 ret = resource_surface_add_resources(xsurf->rsurf, buffer_mask); 130 xsurf->client_stamp = xsurf->server_stamp; 131 132 return ret; 133} 134 135/** 136 * Emulate an invalidate event. 137 */ 138static void 139ximage_surface_invalidate(struct native_surface *nsurf) 140{ 141 struct ximage_surface *xsurf = ximage_surface(nsurf); 142 struct ximage_display *xdpy = xsurf->xdpy; 143 144 xsurf->server_stamp++; 145 xdpy->event_handler->invalid_surface(&xdpy->base, 146 &xsurf->base, xsurf->server_stamp); 147} 148 149static boolean 150ximage_surface_flush_frontbuffer(struct native_surface *nsurf) 151{ 152 struct ximage_surface *xsurf = ximage_surface(nsurf); 153 boolean ret; 154 155 ret = resource_surface_present(xsurf->rsurf, 156 NATIVE_ATTACHMENT_FRONT_LEFT, (void *) &xsurf->xdraw); 157 /* force buffers to be updated in next validation call */ 158 ximage_surface_invalidate(&xsurf->base); 159 160 return ret; 161} 162 163static boolean 164ximage_surface_swap_buffers(struct native_surface *nsurf) 165{ 166 struct ximage_surface *xsurf = ximage_surface(nsurf); 167 boolean ret; 168 169 ret = resource_surface_present(xsurf->rsurf, 170 NATIVE_ATTACHMENT_BACK_LEFT, (void *) &xsurf->xdraw); 171 172 resource_surface_swap_buffers(xsurf->rsurf, 173 NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, TRUE); 174 /* the front/back buffers have been swapped */ 175 ximage_surface_invalidate(&xsurf->base); 176 177 return ret; 178} 179 180static boolean 181ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, 182 unsigned int *seq_num, struct pipe_resource **textures, 183 int *width, int *height) 184{ 185 struct ximage_surface *xsurf = ximage_surface(nsurf); 186 uint w, h; 187 188 if (xsurf->client_stamp != xsurf->server_stamp) { 189 if (!ximage_surface_update_buffers(&xsurf->base, attachment_mask)) 190 return FALSE; 191 } 192 193 if (seq_num) 194 *seq_num = xsurf->client_stamp; 195 196 if (textures) 197 resource_surface_get_resources(xsurf->rsurf, textures, attachment_mask); 198 199 resource_surface_get_size(xsurf->rsurf, &w, &h); 200 if (width) 201 *width = w; 202 if (height) 203 *height = h; 204 205 return TRUE; 206} 207 208static void 209ximage_surface_wait(struct native_surface *nsurf) 210{ 211 struct ximage_surface *xsurf = ximage_surface(nsurf); 212 XSync(xsurf->xdpy->dpy, FALSE); 213 /* TODO XGetImage and update the front texture */ 214} 215 216static void 217ximage_surface_destroy(struct native_surface *nsurf) 218{ 219 struct ximage_surface *xsurf = ximage_surface(nsurf); 220 221 resource_surface_destroy(xsurf->rsurf); 222 FREE(xsurf); 223} 224 225static struct ximage_surface * 226ximage_display_create_surface(struct native_display *ndpy, 227 enum ximage_surface_type type, 228 Drawable drawable, 229 const struct native_config *nconf) 230{ 231 struct ximage_display *xdpy = ximage_display(ndpy); 232 struct ximage_config *xconf = ximage_config(nconf); 233 struct ximage_surface *xsurf; 234 235 xsurf = CALLOC_STRUCT(ximage_surface); 236 if (!xsurf) 237 return NULL; 238 239 xsurf->xdpy = xdpy; 240 xsurf->type = type; 241 xsurf->color_format = xconf->base.color_format; 242 xsurf->drawable = drawable; 243 244 xsurf->rsurf = resource_surface_create(xdpy->base.screen, 245 xsurf->color_format, 246 PIPE_BIND_RENDER_TARGET | 247 PIPE_BIND_SAMPLER_VIEW | 248 PIPE_BIND_DISPLAY_TARGET | 249 PIPE_BIND_SCANOUT); 250 if (!xsurf->rsurf) { 251 FREE(xsurf); 252 return NULL; 253 } 254 255 xsurf->drawable = drawable; 256 xsurf->visual = *xconf->visual; 257 /* initialize the geometry */ 258 ximage_surface_update_buffers(&xsurf->base, 0x0); 259 260 xsurf->xdraw.visual = xsurf->visual.visual; 261 xsurf->xdraw.depth = xsurf->visual.depth; 262 xsurf->xdraw.drawable = xsurf->drawable; 263 264 xsurf->base.destroy = ximage_surface_destroy; 265 xsurf->base.swap_buffers = ximage_surface_swap_buffers; 266 xsurf->base.flush_frontbuffer = ximage_surface_flush_frontbuffer; 267 xsurf->base.validate = ximage_surface_validate; 268 xsurf->base.wait = ximage_surface_wait; 269 270 return xsurf; 271} 272 273static struct native_surface * 274ximage_display_create_window_surface(struct native_display *ndpy, 275 EGLNativeWindowType win, 276 const struct native_config *nconf) 277{ 278 struct ximage_surface *xsurf; 279 280 xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_WINDOW, 281 (Drawable) win, nconf); 282 return (xsurf) ? &xsurf->base : NULL; 283} 284 285static struct native_surface * 286ximage_display_create_pixmap_surface(struct native_display *ndpy, 287 EGLNativePixmapType pix, 288 const struct native_config *nconf) 289{ 290 struct ximage_surface *xsurf; 291 292 xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PIXMAP, 293 (Drawable) pix, nconf); 294 return (xsurf) ? &xsurf->base : NULL; 295} 296 297static enum pipe_format 298choose_format(const XVisualInfo *vinfo) 299{ 300 enum pipe_format fmt; 301 /* TODO elaborate the formats */ 302 switch (vinfo->depth) { 303 case 32: 304 fmt = PIPE_FORMAT_B8G8R8A8_UNORM; 305 break; 306 case 24: 307 fmt = PIPE_FORMAT_B8G8R8X8_UNORM; 308 break; 309 case 16: 310 fmt = PIPE_FORMAT_B5G6R5_UNORM; 311 break; 312 default: 313 fmt = PIPE_FORMAT_NONE; 314 break; 315 } 316 317 return fmt; 318} 319 320static const struct native_config ** 321ximage_display_get_configs(struct native_display *ndpy, int *num_configs) 322{ 323 struct ximage_display *xdpy = ximage_display(ndpy); 324 const struct native_config **configs; 325 int i; 326 327 /* first time */ 328 if (!xdpy->configs) { 329 const XVisualInfo *visuals; 330 int num_visuals, count; 331 332 visuals = x11_screen_get_visuals(xdpy->xscr, &num_visuals); 333 if (!visuals) 334 return NULL; 335 336 /* 337 * Create two configs for each visual. 338 * One with depth/stencil buffer; one without 339 */ 340 xdpy->configs = CALLOC(num_visuals * 2, sizeof(*xdpy->configs)); 341 if (!xdpy->configs) 342 return NULL; 343 344 count = 0; 345 for (i = 0; i < num_visuals; i++) { 346 struct ximage_config *xconf = &xdpy->configs[count]; 347 348 xconf->visual = &visuals[i]; 349 xconf->base.color_format = choose_format(xconf->visual); 350 if (xconf->base.color_format == PIPE_FORMAT_NONE) 351 continue; 352 353 xconf->base.buffer_mask = 354 (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | 355 (1 << NATIVE_ATTACHMENT_BACK_LEFT); 356 357 xconf->base.window_bit = TRUE; 358 xconf->base.pixmap_bit = TRUE; 359 360 xconf->base.native_visual_id = xconf->visual->visualid; 361#if defined(__cplusplus) || defined(c_plusplus) 362 xconf->base.native_visual_type = xconf->visual->c_class; 363#else 364 xconf->base.native_visual_type = xconf->visual->class; 365#endif 366 367 xconf->base.slow_config = TRUE; 368 369 count++; 370 } 371 372 xdpy->num_configs = count; 373 } 374 375 configs = MALLOC(xdpy->num_configs * sizeof(*configs)); 376 if (configs) { 377 for (i = 0; i < xdpy->num_configs; i++) 378 configs[i] = (const struct native_config *) &xdpy->configs[i]; 379 if (num_configs) 380 *num_configs = xdpy->num_configs; 381 } 382 return configs; 383} 384 385static boolean 386ximage_display_is_pixmap_supported(struct native_display *ndpy, 387 EGLNativePixmapType pix, 388 const struct native_config *nconf) 389{ 390 struct ximage_display *xdpy = ximage_display(ndpy); 391 enum pipe_format fmt; 392 uint depth; 393 394 depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix); 395 switch (depth) { 396 case 32: 397 fmt = PIPE_FORMAT_B8G8R8A8_UNORM; 398 break; 399 case 24: 400 fmt = PIPE_FORMAT_B8G8R8X8_UNORM; 401 break; 402 case 16: 403 fmt = PIPE_FORMAT_B5G6R5_UNORM; 404 break; 405 default: 406 fmt = PIPE_FORMAT_NONE; 407 break; 408 } 409 410 return (fmt == nconf->color_format); 411} 412 413static int 414ximage_display_get_param(struct native_display *ndpy, 415 enum native_param_type param) 416{ 417 int val; 418 419 switch (param) { 420 case NATIVE_PARAM_USE_NATIVE_BUFFER: 421 /* private buffers are allocated */ 422 val = FALSE; 423 break; 424 default: 425 val = 0; 426 break; 427 } 428 429 return val; 430} 431 432static void 433ximage_display_destroy(struct native_display *ndpy) 434{ 435 struct ximage_display *xdpy = ximage_display(ndpy); 436 437 if (xdpy->configs) 438 FREE(xdpy->configs); 439 440 xdpy->base.screen->destroy(xdpy->base.screen); 441 442 x11_screen_destroy(xdpy->xscr); 443 if (xdpy->own_dpy) 444 XCloseDisplay(xdpy->dpy); 445 FREE(xdpy); 446} 447 448 449/* Helper function to build a subset of a driver stack consisting of 450 * one of the software rasterizers (cell, llvmpipe, softpipe) and the 451 * xlib winsys. 452 * 453 * This function could be shared, but currently causes headaches for 454 * the build systems, particularly scons if we try. 455 * 456 * Long term, want to avoid having global #defines for things like 457 * GALLIUM_LLVMPIPE, GALLIUM_CELL, etc. Scons already eliminates 458 * those #defines, so things that are painful for it now are likely to 459 * be painful for other build systems in the future. 460 */ 461static struct pipe_screen * 462swrast_xlib_create_screen( Display *display ) 463{ 464 struct sw_winsys *winsys; 465 struct pipe_screen *screen = NULL; 466 467 /* Create the underlying winsys, which performs presents to Xlib 468 * drawables: 469 */ 470 winsys = xlib_create_sw_winsys( display ); 471 if (winsys == NULL) 472 return NULL; 473 474 /* Create a software rasterizer on top of that winsys. Use 475 * llvmpipe if it is available. 476 */ 477#if defined(GALLIUM_LLVMPIPE) 478 if (screen == NULL && 479 !debug_get_bool_option("GALLIUM_NO_LLVM", FALSE)) 480 screen = llvmpipe_create_screen( winsys ); 481#endif 482 483 if (screen == NULL) 484 screen = softpipe_create_screen( winsys ); 485 486 if (screen == NULL) 487 goto fail; 488 489 /* Inject any wrapping layers we want to here: 490 */ 491 return gallium_wrap_screen( screen ); 492 493fail: 494 if (winsys) 495 winsys->destroy( winsys ); 496 497 return NULL; 498} 499 500 501 502struct native_display * 503x11_create_ximage_display(EGLNativeDisplayType dpy, 504 struct native_event_handler *event_handler) 505{ 506 struct ximage_display *xdpy; 507 508 xdpy = CALLOC_STRUCT(ximage_display); 509 if (!xdpy) 510 return NULL; 511 512 xdpy->dpy = dpy; 513 if (!xdpy->dpy) { 514 xdpy->dpy = XOpenDisplay(NULL); 515 if (!xdpy->dpy) { 516 FREE(xdpy); 517 return NULL; 518 } 519 xdpy->own_dpy = TRUE; 520 } 521 522 xdpy->event_handler = event_handler; 523 524 xdpy->xscr_number = DefaultScreen(xdpy->dpy); 525 xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number); 526 if (!xdpy->xscr) { 527 FREE(xdpy); 528 return NULL; 529 } 530 531 xdpy->base.screen = swrast_xlib_create_screen(xdpy->dpy); 532 533 xdpy->base.destroy = ximage_display_destroy; 534 xdpy->base.get_param = ximage_display_get_param; 535 536 xdpy->base.get_configs = ximage_display_get_configs; 537 xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported; 538 xdpy->base.create_window_surface = ximage_display_create_window_surface; 539 xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface; 540 541 return &xdpy->base; 542} 543