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) 2010 LunarG Inc.
  5.  * Copyright (C) 2011 VMware Inc. All rights reserved.
  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.  * Authors:
  26.  *    Chia-I Wu <olv@lunarg.com>
  27.  *    Thomas Hellstrom <thellstrom@vmware.com>
  28.  */
  29.  
  30. #include "util/u_inlines.h"
  31. #include "util/u_memory.h"
  32. #include "pipe/p_screen.h"
  33. #include "pipe/p_context.h"
  34. #include "pipe/p_state.h"
  35.  
  36. #include "native_helper.h"
  37.  
  38. /**
  39.  * Number of swap fences and mask
  40.  */
  41.  
  42. #define EGL_SWAP_FENCES_MAX 4
  43. #define EGL_SWAP_FENCES_MASK 3
  44. #define EGL_SWAP_FENCES_DEFAULT 1
  45.  
  46. struct resource_surface {
  47.    struct pipe_screen *screen;
  48.    enum pipe_format format;
  49.    uint bind;
  50.  
  51.    struct pipe_resource *resources[NUM_NATIVE_ATTACHMENTS];
  52.    uint resource_mask;
  53.    uint width, height;
  54.  
  55.    /**
  56.     * Swap fences.
  57.     */
  58.    struct pipe_fence_handle *swap_fences[EGL_SWAP_FENCES_MAX];
  59.    unsigned int cur_fences;
  60.    unsigned int head;
  61.    unsigned int tail;
  62.    unsigned int desired_fences;
  63. };
  64.  
  65. struct resource_surface *
  66. resource_surface_create(struct pipe_screen *screen,
  67.                         enum pipe_format format, uint bind)
  68. {
  69.    struct resource_surface *rsurf = CALLOC_STRUCT(resource_surface);
  70.    char *swap_fences = getenv("EGL_THROTTLE_FENCES");
  71.  
  72.    if (rsurf) {
  73.       rsurf->screen = screen;
  74.       rsurf->format = format;
  75.       rsurf->bind = bind;
  76.       rsurf->desired_fences = (swap_fences) ? atoi(swap_fences) :
  77.          EGL_SWAP_FENCES_DEFAULT;
  78.       if (rsurf->desired_fences > EGL_SWAP_FENCES_MAX)
  79.          rsurf->desired_fences = EGL_SWAP_FENCES_MAX;
  80.    }
  81.  
  82.    return rsurf;
  83. }
  84.  
  85. static void
  86. resource_surface_free_resources(struct resource_surface *rsurf)
  87. {
  88.    if (rsurf->resource_mask) {
  89.       int i;
  90.  
  91.       for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
  92.          if (rsurf->resources[i])
  93.             pipe_resource_reference(&rsurf->resources[i], NULL);
  94.       }
  95.       rsurf->resource_mask = 0x0;
  96.    }
  97. }
  98.  
  99. void
  100. resource_surface_destroy(struct resource_surface *rsurf)
  101. {
  102.    resource_surface_free_resources(rsurf);
  103.    FREE(rsurf);
  104. }
  105.  
  106. boolean
  107. resource_surface_set_size(struct resource_surface *rsurf,
  108.                           uint width, uint height)
  109. {
  110.    boolean changed = FALSE;
  111.  
  112.    if (rsurf->width != width || rsurf->height != height) {
  113.       resource_surface_free_resources(rsurf);
  114.       rsurf->width = width;
  115.       rsurf->height = height;
  116.       changed = TRUE;
  117.    }
  118.  
  119.    return changed;
  120. }
  121.  
  122. void
  123. resource_surface_get_size(struct resource_surface *rsurf,
  124.                           uint *width, uint *height)
  125. {
  126.    if (width)
  127.       *width = rsurf->width;
  128.    if (height)
  129.       *height = rsurf->height;
  130. }
  131.  
  132. boolean
  133. resource_surface_add_resources(struct resource_surface *rsurf,
  134.                                uint resource_mask)
  135. {
  136.    struct pipe_resource templ;
  137.    int i;
  138.  
  139.    resource_mask &= ~rsurf->resource_mask;
  140.    if (!resource_mask)
  141.       return TRUE;
  142.  
  143.    if (!rsurf->width || !rsurf->height)
  144.       return FALSE;
  145.  
  146.    memset(&templ, 0, sizeof(templ));
  147.    templ.target = PIPE_TEXTURE_2D;
  148.    templ.format = rsurf->format;
  149.    templ.bind = rsurf->bind;
  150.    templ.width0 = rsurf->width;
  151.    templ.height0 = rsurf->height;
  152.    templ.depth0 = 1;
  153.    templ.array_size = 1;
  154.  
  155.    for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
  156.       if (resource_mask & (1 <<i)) {
  157.          assert(!rsurf->resources[i]);
  158.  
  159.          rsurf->resources[i] =
  160.             rsurf->screen->resource_create(rsurf->screen, &templ);
  161.          if (rsurf->resources[i])
  162.             rsurf->resource_mask |= 1 << i;
  163.       }
  164.    }
  165.  
  166.    return ((rsurf->resource_mask & resource_mask) == resource_mask);
  167. }
  168.  
  169. void
  170. resource_surface_import_resource(struct resource_surface *rsurf,
  171.                                  enum native_attachment which,
  172.                                  struct pipe_resource *pres)
  173. {
  174.         pipe_resource_reference(&rsurf->resources[which], pres);
  175.         rsurf->resource_mask |= 1 << which;
  176. }
  177.  
  178. void
  179. resource_surface_get_resources(struct resource_surface *rsurf,
  180.                                struct pipe_resource **resources,
  181.                                uint resource_mask)
  182. {
  183.    int i;
  184.  
  185.    for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
  186.       if (resource_mask & (1 << i)) {
  187.          resources[i] = NULL;
  188.          pipe_resource_reference(&resources[i], rsurf->resources[i]);
  189.       }
  190.    }
  191. }
  192.  
  193. struct pipe_resource *
  194. resource_surface_get_single_resource(struct resource_surface *rsurf,
  195.                                      enum native_attachment which)
  196. {
  197.    struct pipe_resource *pres = NULL;
  198.    pipe_resource_reference(&pres, rsurf->resources[which]);
  199.    return pres;
  200. }
  201.  
  202. static INLINE void
  203. pointer_swap(const void **p1, const void **p2)
  204. {
  205.    const void *tmp = *p1;
  206.    *p1 = *p2;
  207.    *p2 = tmp;
  208. }
  209.  
  210. void
  211. resource_surface_swap_buffers(struct resource_surface *rsurf,
  212.                               enum native_attachment buf1,
  213.                               enum native_attachment buf2,
  214.                               boolean only_if_exist)
  215. {
  216.    const uint buf1_bit = 1 << buf1;
  217.    const uint buf2_bit = 1 << buf2;
  218.    uint mask;
  219.  
  220.    if (only_if_exist && !(rsurf->resources[buf1] && rsurf->resources[buf2]))
  221.       return;
  222.  
  223.    pointer_swap((const void **) &rsurf->resources[buf1],
  224.                 (const void **) &rsurf->resources[buf2]);
  225.  
  226.    /* swap mask bits */
  227.    mask = rsurf->resource_mask & ~(buf1_bit | buf2_bit);
  228.    if (rsurf->resource_mask & buf1_bit)
  229.       mask |= buf2_bit;
  230.    if (rsurf->resource_mask & buf2_bit)
  231.       mask |= buf1_bit;
  232.  
  233.    rsurf->resource_mask = mask;
  234. }
  235.  
  236. boolean
  237. resource_surface_present(struct resource_surface *rsurf,
  238.                          enum native_attachment which,
  239.                          void *winsys_drawable_handle)
  240. {
  241.    struct pipe_resource *pres = rsurf->resources[which];
  242.  
  243.    if (!pres)
  244.       return TRUE;
  245.  
  246.    rsurf->screen->flush_frontbuffer(rsurf->screen,
  247.          pres, 0, 0, winsys_drawable_handle);
  248.  
  249.    return TRUE;
  250. }
  251.  
  252. /**
  253.  * Schedule a copy swap from the back to the front buffer using the
  254.  * native display's copy context.
  255.  */
  256. boolean
  257. resource_surface_copy_swap(struct resource_surface *rsurf,
  258.                            struct native_display *ndpy)
  259. {
  260.    struct pipe_resource *ftex;
  261.    struct pipe_resource *btex;
  262.    struct pipe_context *pipe;
  263.    struct pipe_box src_box;
  264.    boolean ret = FALSE;
  265.  
  266.    pipe = ndpy_get_copy_context(ndpy);
  267.    if (!pipe)
  268.       return FALSE;
  269.  
  270.    ftex = resource_surface_get_single_resource(rsurf,
  271.                                                NATIVE_ATTACHMENT_FRONT_LEFT);
  272.    if (!ftex)
  273.       goto out_no_ftex;
  274.    btex = resource_surface_get_single_resource(rsurf,
  275.                                                NATIVE_ATTACHMENT_BACK_LEFT);
  276.    if (!btex)
  277.       goto out_no_btex;
  278.  
  279.    u_box_origin_2d(ftex->width0, ftex->height0, &src_box);
  280.    pipe->resource_copy_region(pipe, ftex, 0, 0, 0, 0,
  281.                               btex, 0, &src_box);
  282.    ret = TRUE;
  283.  
  284.  out_no_btex:
  285.    pipe_resource_reference(&btex, NULL);
  286.  out_no_ftex:
  287.    pipe_resource_reference(&ftex, NULL);
  288.  
  289.    return ret;
  290. }
  291.  
  292. static struct pipe_fence_handle *
  293. swap_fences_pop_front(struct resource_surface *rsurf)
  294. {
  295.    struct pipe_screen *screen = rsurf->screen;
  296.    struct pipe_fence_handle *fence = NULL;
  297.  
  298.    if (rsurf->desired_fences == 0)
  299.       return NULL;
  300.  
  301.    if (rsurf->cur_fences >= rsurf->desired_fences) {
  302.       screen->fence_reference(screen, &fence, rsurf->swap_fences[rsurf->tail]);
  303.       screen->fence_reference(screen, &rsurf->swap_fences[rsurf->tail++], NULL);
  304.       rsurf->tail &= EGL_SWAP_FENCES_MASK;
  305.       --rsurf->cur_fences;
  306.    }
  307.    return fence;
  308. }
  309.  
  310. static void
  311. swap_fences_push_back(struct resource_surface *rsurf,
  312.                       struct pipe_fence_handle *fence)
  313. {
  314.    struct pipe_screen *screen = rsurf->screen;
  315.  
  316.    if (!fence || rsurf->desired_fences == 0)
  317.       return;
  318.  
  319.    while(rsurf->cur_fences == rsurf->desired_fences)
  320.       swap_fences_pop_front(rsurf);
  321.  
  322.    rsurf->cur_fences++;
  323.    screen->fence_reference(screen, &rsurf->swap_fences[rsurf->head++],
  324.                            fence);
  325.    rsurf->head &= EGL_SWAP_FENCES_MASK;
  326. }
  327.  
  328. boolean
  329. resource_surface_throttle(struct resource_surface *rsurf)
  330. {
  331.    struct pipe_screen *screen = rsurf->screen;
  332.    struct pipe_fence_handle *fence = swap_fences_pop_front(rsurf);
  333.  
  334.    if (fence) {
  335.       (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
  336.       screen->fence_reference(screen, &fence, NULL);
  337.       return TRUE;
  338.    }
  339.  
  340.    return FALSE;
  341. }
  342.  
  343. boolean
  344. resource_surface_flush(struct resource_surface *rsurf,
  345.                        struct native_display *ndpy)
  346. {
  347.    struct pipe_fence_handle *fence = NULL;
  348.    struct pipe_screen *screen = rsurf->screen;
  349.    struct pipe_context *pipe= ndpy_get_copy_context(ndpy);
  350.  
  351.    if (!pipe)
  352.       return FALSE;
  353.  
  354.    pipe->flush(pipe, &fence, 0);
  355.    if (fence == NULL)
  356.       return FALSE;
  357.  
  358.    swap_fences_push_back(rsurf, fence);
  359.    screen->fence_reference(screen, &fence, NULL);
  360.  
  361.    return TRUE;
  362. }
  363.  
  364. void
  365. resource_surface_wait(struct resource_surface *rsurf)
  366. {
  367.    while (resource_surface_throttle(rsurf));
  368. }
  369.  
  370. boolean
  371. native_display_copy_to_pixmap(struct native_display *ndpy,
  372.                               EGLNativePixmapType pix,
  373.                               struct pipe_resource *src)
  374. {
  375.    struct pipe_context *pipe;
  376.    struct native_surface *nsurf;
  377.    struct pipe_resource *dst;
  378.    struct pipe_resource *tmp[NUM_NATIVE_ATTACHMENTS];
  379.    const enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT;
  380.  
  381.    pipe = ndpy_get_copy_context(ndpy);
  382.    if (!pipe)
  383.       return FALSE;
  384.  
  385.    nsurf = ndpy->create_pixmap_surface(ndpy, pix, NULL);
  386.    if (!nsurf)
  387.       return FALSE;
  388.  
  389.    /* get the texutre */
  390.    tmp[natt] = NULL;
  391.    nsurf->validate(nsurf, 1 << natt, NULL, tmp, NULL, NULL);
  392.    dst = tmp[natt];
  393.  
  394.    if (dst && dst->format == src->format) {
  395.       struct native_present_control ctrl;
  396.       struct pipe_box src_box;
  397.  
  398.       u_box_origin_2d(src->width0, src->height0, &src_box);
  399.       pipe->resource_copy_region(pipe, dst, 0, 0, 0, 0, src, 0, &src_box);
  400.       pipe->flush(pipe, NULL, 0);
  401.  
  402.       memset(&ctrl, 0, sizeof(ctrl));
  403.       ctrl.natt = natt;
  404.       nsurf->present(nsurf, &ctrl);
  405.    }
  406.  
  407.    if (dst)
  408.       pipe_resource_reference(&dst, NULL);
  409.  
  410.    nsurf->destroy(nsurf);
  411.  
  412.    return TRUE;
  413. }
  414.  
  415. #include "state_tracker/drm_driver.h"
  416. struct pipe_resource *
  417. drm_display_import_native_buffer(struct native_display *ndpy,
  418.                                  struct native_buffer *nbuf)
  419. {
  420.    struct pipe_screen *screen = ndpy->screen;
  421.    struct pipe_resource *res = NULL;
  422.  
  423.    switch (nbuf->type) {
  424.    case NATIVE_BUFFER_DRM:
  425.       {
  426.          struct winsys_handle wsh;
  427.  
  428.          memset(&wsh, 0, sizeof(wsh));
  429.          wsh.handle = nbuf->u.drm.name;
  430.          wsh.stride = nbuf->u.drm.stride;
  431.  
  432.          res = screen->resource_from_handle(screen, &nbuf->u.drm.templ, &wsh);
  433.       }
  434.       break;
  435.    default:
  436.       break;
  437.    }
  438.  
  439.    return res;
  440. }
  441.  
  442. boolean
  443. drm_display_export_native_buffer(struct native_display *ndpy,
  444.                                  struct pipe_resource *res,
  445.                                  struct native_buffer *nbuf)
  446. {
  447.    struct pipe_screen *screen = ndpy->screen;
  448.    boolean ret = FALSE;
  449.  
  450.    switch (nbuf->type) {
  451.    case NATIVE_BUFFER_DRM:
  452.       {
  453.          struct winsys_handle wsh;
  454.  
  455.          if ((nbuf->u.drm.templ.bind & res->bind) != nbuf->u.drm.templ.bind)
  456.             break;
  457.  
  458.          memset(&wsh, 0, sizeof(wsh));
  459.          wsh.type = DRM_API_HANDLE_TYPE_KMS;
  460.          if (!screen->resource_get_handle(screen, res, &wsh))
  461.             break;
  462.  
  463.          nbuf->u.drm.handle = wsh.handle;
  464.          nbuf->u.drm.stride = wsh.stride;
  465.  
  466.          /* get the name of the GEM object */
  467.          if (nbuf->u.drm.templ.bind & PIPE_BIND_SHARED) {
  468.             memset(&wsh, 0, sizeof(wsh));
  469.             wsh.type = DRM_API_HANDLE_TYPE_SHARED;
  470.             if (!screen->resource_get_handle(screen, res, &wsh))
  471.                break;
  472.  
  473.             nbuf->u.drm.name = wsh.handle;
  474.          }
  475.  
  476.          nbuf->u.drm.templ = *res;
  477.          ret = TRUE;
  478.       }
  479.       break;
  480.    default:
  481.       break;
  482.    }
  483.  
  484.    return ret;
  485. }
  486.