native_ximage.c revision 94bf657b2390a1cb72d748047e5c7014e4bc1752
182ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan/* 282ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * Mesa 3-D graphics library 39c2b7692cd8a2ad205359e4eac046da1f4767c90Hung-ying Tyan * Version: 7.8 482ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * 582ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> 682ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * 782ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * Permission is hereby granted, free of charge, to any person obtaining a 882ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * copy of this software and associated documentation files (the "Software"), 982ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * to deal in the Software without restriction, including without limitation 1082ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1182ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * and/or sell copies of the Software, and to permit persons to whom the 1282ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * Software is furnished to do so, subject to the following conditions: 1382ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * 1482ea0633e3a0e2d77feed89f033e1dcf4a656c20Hung-ying Tyan * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 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 "util/u_debug.h" 35#include "egllog.h" 36 37#include "common/native_helper.h" 38#include "native_x11.h" 39#include "x11_screen.h" 40 41enum ximage_surface_type { 42 XIMAGE_SURFACE_TYPE_WINDOW, 43 XIMAGE_SURFACE_TYPE_PIXMAP, 44}; 45 46struct ximage_display { 47 struct native_display base; 48 Display *dpy; 49 boolean own_dpy; 50 51 struct native_event_handler *event_handler; 52 53 struct x11_screen *xscr; 54 int xscr_number; 55 56 struct ximage_config *configs; 57 int num_configs; 58}; 59 60struct ximage_surface { 61 struct native_surface base; 62 Drawable drawable; 63 enum ximage_surface_type type; 64 enum pipe_format color_format; 65 XVisualInfo visual; 66 struct ximage_display *xdpy; 67 68 unsigned int server_stamp; 69 unsigned int client_stamp; 70 71 struct resource_surface *rsurf; 72 struct xlib_drawable xdraw; 73}; 74 75struct ximage_config { 76 struct native_config base; 77 const XVisualInfo *visual; 78}; 79 80static INLINE struct ximage_display * 81ximage_display(const struct native_display *ndpy) 82{ 83 return (struct ximage_display *) ndpy; 84} 85 86static INLINE struct ximage_surface * 87ximage_surface(const struct native_surface *nsurf) 88{ 89 return (struct ximage_surface *) nsurf; 90} 91 92static INLINE struct ximage_config * 93ximage_config(const struct native_config *nconf) 94{ 95 return (struct ximage_config *) nconf; 96} 97 98/** 99 * Update the geometry of the surface. This is a slow functions. 100 */ 101static void 102ximage_surface_update_geometry(struct native_surface *nsurf) 103{ 104 struct ximage_surface *xsurf = ximage_surface(nsurf); 105 Status ok; 106 Window root; 107 int x, y; 108 unsigned int w, h, border, depth; 109 110 ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable, 111 &root, &x, &y, &w, &h, &border, &depth); 112 if (ok && resource_surface_set_size(xsurf->rsurf, w, h)) 113 xsurf->server_stamp++; 114} 115 116/** 117 * Update the buffers of the surface. 118 */ 119static boolean 120ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) 121{ 122 struct ximage_surface *xsurf = ximage_surface(nsurf); 123 124 if (xsurf->client_stamp != xsurf->server_stamp) { 125 ximage_surface_update_geometry(&xsurf->base); 126 xsurf->client_stamp = xsurf->server_stamp; 127 } 128 129 return resource_surface_add_resources(xsurf->rsurf, buffer_mask); 130} 131 132/** 133 * Emulate an invalidate event. 134 */ 135static void 136ximage_surface_invalidate(struct native_surface *nsurf) 137{ 138 struct ximage_surface *xsurf = ximage_surface(nsurf); 139 struct ximage_display *xdpy = xsurf->xdpy; 140 141 xsurf->server_stamp++; 142 xdpy->event_handler->invalid_surface(&xdpy->base, 143 &xsurf->base, xsurf->server_stamp); 144} 145 146static boolean 147ximage_surface_flush_frontbuffer(struct native_surface *nsurf) 148{ 149 struct ximage_surface *xsurf = ximage_surface(nsurf); 150 boolean ret; 151 152 ret = resource_surface_present(xsurf->rsurf, 153 NATIVE_ATTACHMENT_FRONT_LEFT, (void *) &xsurf->xdraw); 154 /* force buffers to be updated in next validation call */ 155 ximage_surface_invalidate(&xsurf->base); 156 157 return ret; 158} 159 160static boolean 161ximage_surface_swap_buffers(struct native_surface *nsurf) 162{ 163 struct ximage_surface *xsurf = ximage_surface(nsurf); 164 boolean ret; 165 166 ret = resource_surface_present(xsurf->rsurf, 167 NATIVE_ATTACHMENT_BACK_LEFT, (void *) &xsurf->xdraw); 168 169 resource_surface_swap_buffers(xsurf->rsurf, 170 NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, TRUE); 171 /* the front/back buffers have been swapped */ 172 ximage_surface_invalidate(&xsurf->base); 173 174 return ret; 175} 176 177static boolean 178ximage_surface_present(struct native_surface *nsurf, 179 enum native_attachment natt, 180 boolean preserve, 181 uint swap_interval) 182{ 183 boolean ret; 184 185 if (preserve || swap_interval) 186 return FALSE; 187 188 switch (natt) { 189 case NATIVE_ATTACHMENT_FRONT_LEFT: 190 ret = ximage_surface_flush_frontbuffer(nsurf); 191 break; 192 case NATIVE_ATTACHMENT_BACK_LEFT: 193 ret = ximage_surface_swap_buffers(nsurf); 194 break; 195 default: 196 ret = FALSE; 197 break; 198 } 199 200 return ret; 201} 202 203static boolean 204ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, 205 unsigned int *seq_num, struct pipe_resource **textures, 206 int *width, int *height) 207{ 208 struct ximage_surface *xsurf = ximage_surface(nsurf); 209 uint w, h; 210 211 if (!ximage_surface_update_buffers(&xsurf->base, attachment_mask)) 212 return FALSE; 213 214 if (seq_num) 215 *seq_num = xsurf->client_stamp; 216 217 if (textures) 218 resource_surface_get_resources(xsurf->rsurf, textures, attachment_mask); 219 220 resource_surface_get_size(xsurf->rsurf, &w, &h); 221 if (width) 222 *width = w; 223 if (height) 224 *height = h; 225 226 return TRUE; 227} 228 229static void 230ximage_surface_wait(struct native_surface *nsurf) 231{ 232 struct ximage_surface *xsurf = ximage_surface(nsurf); 233 XSync(xsurf->xdpy->dpy, FALSE); 234 /* TODO XGetImage and update the front texture */ 235} 236 237static void 238ximage_surface_destroy(struct native_surface *nsurf) 239{ 240 struct ximage_surface *xsurf = ximage_surface(nsurf); 241 242 resource_surface_destroy(xsurf->rsurf); 243 FREE(xsurf); 244} 245 246static struct ximage_surface * 247ximage_display_create_surface(struct native_display *ndpy, 248 enum ximage_surface_type type, 249 Drawable drawable, 250 const struct native_config *nconf) 251{ 252 struct ximage_display *xdpy = ximage_display(ndpy); 253 struct ximage_config *xconf = ximage_config(nconf); 254 struct ximage_surface *xsurf; 255 256 xsurf = CALLOC_STRUCT(ximage_surface); 257 if (!xsurf) 258 return NULL; 259 260 xsurf->xdpy = xdpy; 261 xsurf->type = type; 262 xsurf->color_format = xconf->base.color_format; 263 xsurf->drawable = drawable; 264 265 xsurf->rsurf = resource_surface_create(xdpy->base.screen, 266 xsurf->color_format, 267 PIPE_BIND_RENDER_TARGET | 268 PIPE_BIND_SAMPLER_VIEW | 269 PIPE_BIND_DISPLAY_TARGET | 270 PIPE_BIND_SCANOUT); 271 if (!xsurf->rsurf) { 272 FREE(xsurf); 273 return NULL; 274 } 275 276 xsurf->drawable = drawable; 277 xsurf->visual = *xconf->visual; 278 /* initialize the geometry */ 279 ximage_surface_update_geometry(&xsurf->base); 280 281 xsurf->xdraw.visual = xsurf->visual.visual; 282 xsurf->xdraw.depth = xsurf->visual.depth; 283 xsurf->xdraw.drawable = xsurf->drawable; 284 285 xsurf->base.destroy = ximage_surface_destroy; 286 xsurf->base.swap_buffers = ximage_surface_swap_buffers; 287 xsurf->base.flush_frontbuffer = ximage_surface_flush_frontbuffer; 288 xsurf->base.present = ximage_surface_present; 289 xsurf->base.validate = ximage_surface_validate; 290 xsurf->base.wait = ximage_surface_wait; 291 292 return xsurf; 293} 294 295static struct native_surface * 296ximage_display_create_window_surface(struct native_display *ndpy, 297 EGLNativeWindowType win, 298 const struct native_config *nconf) 299{ 300 struct ximage_surface *xsurf; 301 302 xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_WINDOW, 303 (Drawable) win, nconf); 304 return (xsurf) ? &xsurf->base : NULL; 305} 306 307static struct native_surface * 308ximage_display_create_pixmap_surface(struct native_display *ndpy, 309 EGLNativePixmapType pix, 310 const struct native_config *nconf) 311{ 312 struct ximage_surface *xsurf; 313 314 xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PIXMAP, 315 (Drawable) pix, nconf); 316 return (xsurf) ? &xsurf->base : NULL; 317} 318 319static enum pipe_format 320choose_format(const XVisualInfo *vinfo) 321{ 322 enum pipe_format fmt; 323 /* TODO elaborate the formats */ 324 switch (vinfo->depth) { 325 case 32: 326 fmt = PIPE_FORMAT_B8G8R8A8_UNORM; 327 break; 328 case 24: 329 fmt = PIPE_FORMAT_B8G8R8X8_UNORM; 330 break; 331 case 16: 332 fmt = PIPE_FORMAT_B5G6R5_UNORM; 333 break; 334 default: 335 fmt = PIPE_FORMAT_NONE; 336 break; 337 } 338 339 return fmt; 340} 341 342static const struct native_config ** 343ximage_display_get_configs(struct native_display *ndpy, int *num_configs) 344{ 345 struct ximage_display *xdpy = ximage_display(ndpy); 346 const struct native_config **configs; 347 int i; 348 349 /* first time */ 350 if (!xdpy->configs) { 351 const XVisualInfo *visuals; 352 int num_visuals, count; 353 354 visuals = x11_screen_get_visuals(xdpy->xscr, &num_visuals); 355 if (!visuals) 356 return NULL; 357 358 /* 359 * Create two configs for each visual. 360 * One with depth/stencil buffer; one without 361 */ 362 xdpy->configs = CALLOC(num_visuals * 2, sizeof(*xdpy->configs)); 363 if (!xdpy->configs) 364 return NULL; 365 366 count = 0; 367 for (i = 0; i < num_visuals; i++) { 368 struct ximage_config *xconf = &xdpy->configs[count]; 369 370 xconf->visual = &visuals[i]; 371 xconf->base.color_format = choose_format(xconf->visual); 372 if (xconf->base.color_format == PIPE_FORMAT_NONE) 373 continue; 374 375 xconf->base.buffer_mask = 376 (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | 377 (1 << NATIVE_ATTACHMENT_BACK_LEFT); 378 379 xconf->base.window_bit = TRUE; 380 xconf->base.pixmap_bit = TRUE; 381 382 xconf->base.native_visual_id = xconf->visual->visualid; 383#if defined(__cplusplus) || defined(c_plusplus) 384 xconf->base.native_visual_type = xconf->visual->c_class; 385#else 386 xconf->base.native_visual_type = xconf->visual->class; 387#endif 388 389 xconf->base.slow_config = TRUE; 390 391 count++; 392 } 393 394 xdpy->num_configs = count; 395 } 396 397 configs = MALLOC(xdpy->num_configs * sizeof(*configs)); 398 if (configs) { 399 for (i = 0; i < xdpy->num_configs; i++) 400 configs[i] = (const struct native_config *) &xdpy->configs[i]; 401 if (num_configs) 402 *num_configs = xdpy->num_configs; 403 } 404 return configs; 405} 406 407static boolean 408ximage_display_is_pixmap_supported(struct native_display *ndpy, 409 EGLNativePixmapType pix, 410 const struct native_config *nconf) 411{ 412 struct ximage_display *xdpy = ximage_display(ndpy); 413 enum pipe_format fmt; 414 uint depth; 415 416 depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix); 417 switch (depth) { 418 case 32: 419 fmt = PIPE_FORMAT_B8G8R8A8_UNORM; 420 break; 421 case 24: 422 fmt = PIPE_FORMAT_B8G8R8X8_UNORM; 423 break; 424 case 16: 425 fmt = PIPE_FORMAT_B5G6R5_UNORM; 426 break; 427 default: 428 fmt = PIPE_FORMAT_NONE; 429 break; 430 } 431 432 return (fmt == nconf->color_format); 433} 434 435static int 436ximage_display_get_param(struct native_display *ndpy, 437 enum native_param_type param) 438{ 439 int val; 440 441 switch (param) { 442 case NATIVE_PARAM_USE_NATIVE_BUFFER: 443 /* private buffers are allocated */ 444 val = FALSE; 445 break; 446 case NATIVE_PARAM_PRESERVE_BUFFER: 447 case NATIVE_PARAM_MAX_SWAP_INTERVAL: 448 default: 449 val = 0; 450 break; 451 } 452 453 return val; 454} 455 456static void 457ximage_display_destroy(struct native_display *ndpy) 458{ 459 struct ximage_display *xdpy = ximage_display(ndpy); 460 461 if (xdpy->configs) 462 FREE(xdpy->configs); 463 464 xdpy->base.screen->destroy(xdpy->base.screen); 465 466 x11_screen_destroy(xdpy->xscr); 467 if (xdpy->own_dpy) 468 XCloseDisplay(xdpy->dpy); 469 FREE(xdpy); 470} 471 472struct native_display * 473x11_create_ximage_display(Display *dpy, 474 struct native_event_handler *event_handler, 475 void *user_data) 476{ 477 struct ximage_display *xdpy; 478 struct sw_winsys *winsys = NULL; 479 480 xdpy = CALLOC_STRUCT(ximage_display); 481 if (!xdpy) 482 return NULL; 483 484 xdpy->dpy = dpy; 485 if (!xdpy->dpy) { 486 xdpy->dpy = XOpenDisplay(NULL); 487 if (!xdpy->dpy) { 488 FREE(xdpy); 489 return NULL; 490 } 491 xdpy->own_dpy = TRUE; 492 } 493 494 xdpy->event_handler = event_handler; 495 xdpy->base.user_data = user_data; 496 497 xdpy->xscr_number = DefaultScreen(xdpy->dpy); 498 xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number); 499 if (!xdpy->xscr) 500 goto fail; 501 502 winsys = xlib_create_sw_winsys(xdpy->dpy); 503 if (!winsys) 504 goto fail; 505 506 xdpy->base.screen = 507 xdpy->event_handler->new_sw_screen(&xdpy->base, winsys); 508 if (!xdpy->base.screen) 509 goto fail; 510 511 xdpy->base.destroy = ximage_display_destroy; 512 xdpy->base.get_param = ximage_display_get_param; 513 514 xdpy->base.get_configs = ximage_display_get_configs; 515 xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported; 516 xdpy->base.create_window_surface = ximage_display_create_window_surface; 517 xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface; 518 519 return &xdpy->base; 520 521fail: 522 if (winsys && winsys->destroy) 523 winsys->destroy(winsys); 524 if (xdpy->xscr) 525 x11_screen_destroy(xdpy->xscr); 526 if (xdpy->dpy && xdpy->own_dpy) 527 XCloseDisplay(xdpy->dpy); 528 FREE(xdpy); 529 return NULL; 530} 531