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