Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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