Subversion Repositories Kolibri OS

Rev

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

  1. /**********************************************************
  2.  * Copyright 2009-2011 VMware, Inc. All rights reserved.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person
  5.  * obtaining a copy of this software and associated documentation
  6.  * files (the "Software"), to deal in the Software without
  7.  * restriction, including without limitation the rights to use, copy,
  8.  * modify, merge, publish, distribute, sublicense, and/or sell copies
  9.  * of the Software, and to permit persons to whom the Software is
  10.  * furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice shall be
  13.  * included in all copies or substantial portions of the Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18.  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19.  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20.  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22.  * SOFTWARE.
  23.  *
  24.  *********************************************************
  25.  * Authors:
  26.  * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
  27.  */
  28.  
  29. #include "xa_tracker.h"
  30. #include "xa_priv.h"
  31. #include "pipe/p_state.h"
  32. #include "pipe/p_format.h"
  33. #include "state_tracker/drm_driver.h"
  34. #include "util/u_inlines.h"
  35.  
  36. /*
  37.  * format_map [xa_surface_type][first..last in list].
  38.  * Needs to be updated when enum xa_formats is updated.
  39.  */
  40.  
  41. static const enum xa_formats preferred_a[] = { xa_format_a8 };
  42.  
  43. static const enum xa_formats preferred_argb[] =
  44.     { xa_format_a8r8g8b8, xa_format_x8r8g8b8, xa_format_r5g6b5,
  45.     xa_format_x1r5g5b5
  46. };
  47. static const enum xa_formats preferred_z[] =
  48.     { xa_format_z32, xa_format_z24, xa_format_z16 };
  49. static const enum xa_formats preferred_sz[] =
  50.     { xa_format_x8z24, xa_format_s8z24 };
  51. static const enum xa_formats preferred_zs[] =
  52.     { xa_format_z24x8, xa_format_z24s8 };
  53. static const enum xa_formats preferred_yuv[] = { xa_format_yuv8 };
  54.  
  55. static const enum xa_formats *preferred[] =
  56.     { NULL, preferred_a, preferred_argb, NULL, NULL,
  57.     preferred_z, preferred_zs, preferred_sz, preferred_yuv
  58. };
  59.  
  60. static const unsigned int num_preferred[] = { 0,
  61.     sizeof(preferred_a) / sizeof(enum xa_formats),
  62.     sizeof(preferred_argb) / sizeof(enum xa_formats),
  63.     0,
  64.     0,
  65.     sizeof(preferred_z) / sizeof(enum xa_formats),
  66.     sizeof(preferred_zs) / sizeof(enum xa_formats),
  67.     sizeof(preferred_sz) / sizeof(enum xa_formats),
  68.     sizeof(preferred_yuv) / sizeof(enum xa_formats)
  69. };
  70.  
  71. static const unsigned int stype_bind[XA_LAST_SURFACE_TYPE] = { 0,
  72.     PIPE_BIND_SAMPLER_VIEW,
  73.     PIPE_BIND_SAMPLER_VIEW,
  74.     PIPE_BIND_SAMPLER_VIEW,
  75.     PIPE_BIND_SAMPLER_VIEW,
  76.     PIPE_BIND_DEPTH_STENCIL,
  77.     PIPE_BIND_DEPTH_STENCIL,
  78.     PIPE_BIND_DEPTH_STENCIL,
  79.     PIPE_BIND_SAMPLER_VIEW
  80. };
  81.  
  82. static struct xa_format_descriptor
  83. xa_get_pipe_format(enum xa_formats xa_format)
  84. {
  85.     struct xa_format_descriptor fdesc;
  86.  
  87.     fdesc.xa_format = xa_format;
  88.  
  89.     switch (xa_format) {
  90.     case xa_format_a8r8g8b8:
  91.         fdesc.format = PIPE_FORMAT_B8G8R8A8_UNORM;
  92.         break;
  93.     case xa_format_x8r8g8b8:
  94.         fdesc.format = PIPE_FORMAT_B8G8R8X8_UNORM;
  95.         break;
  96.     case xa_format_r5g6b5:
  97.         fdesc.format = PIPE_FORMAT_B5G6R5_UNORM;
  98.         break;
  99.     case xa_format_x1r5g5b5:
  100.         fdesc.format = PIPE_FORMAT_B5G5R5A1_UNORM;
  101.         break;
  102.     case xa_format_a8:
  103.         fdesc.format = PIPE_FORMAT_L8_UNORM;
  104.         break;
  105.     case xa_format_z24:
  106.         fdesc.format = PIPE_FORMAT_Z24X8_UNORM;
  107.         break;
  108.     case xa_format_z16:
  109.         fdesc.format = PIPE_FORMAT_Z16_UNORM;
  110.         break;
  111.     case xa_format_z32:
  112.         fdesc.format = PIPE_FORMAT_Z32_UNORM;
  113.         break;
  114.     case xa_format_x8z24:
  115.         fdesc.format = PIPE_FORMAT_Z24X8_UNORM;
  116.         break;
  117.     case xa_format_z24x8:
  118.         fdesc.format = PIPE_FORMAT_X8Z24_UNORM;
  119.         break;
  120.     case xa_format_s8z24:
  121.         fdesc.format = PIPE_FORMAT_Z24_UNORM_S8_UINT;
  122.         break;
  123.     case xa_format_z24s8:
  124.         fdesc.format = PIPE_FORMAT_S8_UINT_Z24_UNORM;
  125.         break;
  126.     case xa_format_yuv8:
  127.         fdesc.format = PIPE_FORMAT_L8_UNORM;
  128.         break;
  129.     default:
  130.         fdesc.xa_format = xa_format_unknown;
  131.         break;
  132.     }
  133.     return fdesc;
  134. }
  135.  
  136. XA_EXPORT struct xa_tracker *
  137. xa_tracker_create(int drm_fd)
  138. {
  139.     struct xa_tracker *xa = calloc(1, sizeof(struct xa_tracker));
  140.     enum xa_surface_type stype;
  141.     unsigned int num_formats;
  142.  
  143.     if (!xa)
  144.         return NULL;
  145.  
  146.     xa->screen = driver_descriptor.create_screen(drm_fd);
  147.     if (!xa->screen)
  148.         goto out_no_screen;
  149.  
  150.     xa->default_ctx = xa_context_create(xa);
  151.     if (!xa->default_ctx)
  152.         goto out_no_pipe;
  153.  
  154.     num_formats = 0;
  155.     for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype)
  156.         num_formats += num_preferred[stype];
  157.  
  158.     num_formats += 1;
  159.     xa->supported_formats = calloc(num_formats, sizeof(*xa->supported_formats));
  160.     if (!xa->supported_formats)
  161.         goto out_sf_alloc_fail;
  162.  
  163.     xa->supported_formats[0] = xa_format_unknown;
  164.     num_formats = 1;
  165.     memset(xa->format_map, 0, sizeof(xa->format_map));
  166.  
  167.     for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) {
  168.         unsigned int bind = stype_bind[stype];
  169.         enum xa_formats xa_format;
  170.         int i;
  171.  
  172.         for (i = 0; i < num_preferred[stype]; ++i) {
  173.             xa_format = preferred[stype][i];
  174.  
  175.             struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format);
  176.  
  177.             if (xa->screen->is_format_supported(xa->screen, fdesc.format,
  178.                                                 PIPE_TEXTURE_2D, 0, bind)) {
  179.                 if (xa->format_map[stype][0] == 0)
  180.                     xa->format_map[stype][0] = num_formats;
  181.                 xa->format_map[stype][1] = num_formats;
  182.                 xa->supported_formats[num_formats++] = xa_format;
  183.             }
  184.         }
  185.     }
  186.     return xa;
  187.  
  188.  out_sf_alloc_fail:
  189.     xa_context_destroy(xa->default_ctx);
  190.  out_no_pipe:
  191.     xa->screen->destroy(xa->screen);
  192.  out_no_screen:
  193.     free(xa);
  194.     return NULL;
  195. }
  196.  
  197. XA_EXPORT void
  198. xa_tracker_destroy(struct xa_tracker *xa)
  199. {
  200.     free(xa->supported_formats);
  201.     xa_context_destroy(xa->default_ctx);
  202.     xa->screen->destroy(xa->screen);
  203.     free(xa);
  204. }
  205.  
  206. static int
  207. xa_flags_compat(unsigned int old_flags, unsigned int new_flags)
  208. {
  209.     unsigned int flag_diff = (old_flags ^ new_flags);
  210.  
  211.     if (flag_diff == 0)
  212.         return 1;
  213.  
  214.     if (flag_diff & XA_FLAG_SHARED)
  215.         return 0;
  216.     /*
  217.      * Don't recreate if we're dropping the render target flag.
  218.      */
  219.     if (flag_diff & XA_FLAG_RENDER_TARGET)
  220.         return ((new_flags & XA_FLAG_RENDER_TARGET) == 0);
  221.  
  222.     /*
  223.      * Don't recreate if we're dropping the scanout flag.
  224.      */
  225.     if (flag_diff & XA_FLAG_SCANOUT)
  226.         return ((new_flags & XA_FLAG_SCANOUT) == 0);
  227.  
  228.     /*
  229.      * Always recreate for unknown / unimplemented flags.
  230.      */
  231.     return 0;
  232. }
  233.  
  234. static struct xa_format_descriptor
  235. xa_get_format_stype_depth(struct xa_tracker *xa,
  236.                           enum xa_surface_type stype, unsigned int depth)
  237. {
  238.     unsigned int i;
  239.     struct xa_format_descriptor fdesc;
  240.     int found = 0;
  241.  
  242.     for (i = xa->format_map[stype][0]; i <= xa->format_map[stype][1]; ++i) {
  243.         fdesc = xa_get_pipe_format(xa->supported_formats[i]);
  244.         if (fdesc.xa_format != xa_format_unknown &&
  245.             xa_format_depth(fdesc.xa_format) == depth) {
  246.             found = 1;
  247.             break;
  248.         }
  249.     }
  250.  
  251.     if (!found)
  252.         fdesc.xa_format = xa_format_unknown;
  253.  
  254.     return fdesc;
  255. }
  256.  
  257. XA_EXPORT int
  258. xa_format_check_supported(struct xa_tracker *xa,
  259.                           enum xa_formats xa_format, unsigned int flags)
  260. {
  261.     struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format);
  262.     unsigned int bind;
  263.  
  264.     if (fdesc.xa_format == xa_format_unknown)
  265.         return -XA_ERR_INVAL;
  266.  
  267.     bind = stype_bind[xa_format_type(fdesc.xa_format)];
  268.     if (flags & XA_FLAG_SHARED)
  269.         bind |= PIPE_BIND_SHARED;
  270.     if (flags & XA_FLAG_RENDER_TARGET)
  271.         bind |= PIPE_BIND_RENDER_TARGET;
  272.     if (flags & XA_FLAG_SCANOUT)
  273.         bind |= PIPE_BIND_SCANOUT;
  274.  
  275.     if (!xa->screen->is_format_supported(xa->screen, fdesc.format,
  276.                                          PIPE_TEXTURE_2D, 0, bind))
  277.         return -XA_ERR_INVAL;
  278.  
  279.     return XA_ERR_NONE;
  280. }
  281.  
  282. XA_EXPORT struct xa_surface *
  283. xa_surface_create(struct xa_tracker *xa,
  284.                   int width,
  285.                   int height,
  286.                   int depth,
  287.                   enum xa_surface_type stype,
  288.                   enum xa_formats xa_format, unsigned int flags)
  289. {
  290.     struct pipe_resource *template;
  291.     struct xa_surface *srf;
  292.     struct xa_format_descriptor fdesc;
  293.  
  294.     if (xa_format == xa_format_unknown)
  295.         fdesc = xa_get_format_stype_depth(xa, stype, depth);
  296.     else
  297.         fdesc = xa_get_pipe_format(xa_format);
  298.  
  299.     if (fdesc.xa_format == xa_format_unknown)
  300.         return NULL;
  301.  
  302.     srf = calloc(1, sizeof(*srf));
  303.     if (!srf)
  304.         return NULL;
  305.  
  306.     template = &srf->template;
  307.     template->format = fdesc.format;
  308.     template->target = PIPE_TEXTURE_2D;
  309.     template->width0 = width;
  310.     template->height0 = height;
  311.     template->depth0 = 1;
  312.     template->array_size = 1;
  313.     template->last_level = 0;
  314.     template->bind = stype_bind[xa_format_type(fdesc.xa_format)];
  315.  
  316.     if (flags & XA_FLAG_SHARED)
  317.         template->bind |= PIPE_BIND_SHARED;
  318.     if (flags & XA_FLAG_RENDER_TARGET)
  319.         template->bind |= PIPE_BIND_RENDER_TARGET;
  320.     if (flags & XA_FLAG_SCANOUT)
  321.         template->bind |= PIPE_BIND_SCANOUT;
  322.  
  323.     srf->tex = xa->screen->resource_create(xa->screen, template);
  324.     if (!srf->tex)
  325.         goto out_no_tex;
  326.  
  327.     srf->xa = xa;
  328.     srf->flags = flags;
  329.     srf->fdesc = fdesc;
  330.  
  331.     return srf;
  332.  out_no_tex:
  333.     free(srf);
  334.     return NULL;
  335. }
  336.  
  337. XA_EXPORT int
  338. xa_surface_redefine(struct xa_surface *srf,
  339.                     int width,
  340.                     int height,
  341.                     int depth,
  342.                     enum xa_surface_type stype,
  343.                     enum xa_formats xa_format,
  344.                     unsigned int new_flags,
  345.                     int copy_contents)
  346. {
  347.     struct pipe_resource *template = &srf->template;
  348.     struct pipe_resource *texture;
  349.     struct pipe_box src_box;
  350.     struct xa_tracker *xa = srf->xa;
  351.     int save_width;
  352.     int save_height;
  353.     unsigned int save_format;
  354.     struct xa_format_descriptor fdesc;
  355.  
  356.  
  357.     if (xa_format == xa_format_unknown)
  358.         fdesc = xa_get_format_stype_depth(xa, stype, depth);
  359.     else
  360.         fdesc = xa_get_pipe_format(xa_format);
  361.  
  362.     if (width == template->width0 && height == template->height0 &&
  363.         template->format == fdesc.format &&
  364.         xa_flags_compat(srf->flags, new_flags))
  365.         return XA_ERR_NONE;
  366.  
  367.     template->bind = stype_bind[xa_format_type(fdesc.xa_format)];
  368.     if (new_flags & XA_FLAG_SHARED)
  369.         template->bind |= PIPE_BIND_SHARED;
  370.     if (new_flags & XA_FLAG_RENDER_TARGET)
  371.         template->bind |= PIPE_BIND_RENDER_TARGET;
  372.     if (new_flags & XA_FLAG_SCANOUT)
  373.         template->bind |= PIPE_BIND_SCANOUT;
  374.  
  375.     if (copy_contents) {
  376.         if (!xa_format_type_is_color(fdesc.xa_format) ||
  377.             xa_format_type(fdesc.xa_format) == xa_type_a)
  378.             return -XA_ERR_INVAL;
  379.  
  380.         if (!xa->screen->is_format_supported(xa->screen, fdesc.format,
  381.                                              PIPE_TEXTURE_2D, 0,
  382.                                              template->bind |
  383.                                              PIPE_BIND_RENDER_TARGET))
  384.             return -XA_ERR_INVAL;
  385.     }
  386.  
  387.     save_width = template->width0;
  388.     save_height = template->height0;
  389.     save_format = template->format;
  390.  
  391.     template->width0 = width;
  392.     template->height0 = height;
  393.     template->format = fdesc.format;
  394.  
  395.     texture = xa->screen->resource_create(xa->screen, template);
  396.     if (!texture) {
  397.         template->width0 = save_width;
  398.         template->height0 = save_height;
  399.         template->format = save_format;
  400.         return -XA_ERR_NORES;
  401.     }
  402.  
  403.     if (copy_contents) {
  404.         struct pipe_context *pipe = xa->default_ctx->pipe;
  405.  
  406.         u_box_origin_2d(xa_min(save_width, template->width0),
  407.                         xa_min(save_height, template->height0), &src_box);
  408.         pipe->resource_copy_region(pipe, texture,
  409.                                    0, 0, 0, 0, srf->tex, 0, &src_box);
  410.         pipe->flush(pipe, &xa->default_ctx->last_fence, 0);
  411.     }
  412.  
  413.     pipe_resource_reference(&srf->tex, texture);
  414.     pipe_resource_reference(&texture, NULL);
  415.     srf->fdesc = fdesc;
  416.     srf->flags = new_flags;
  417.  
  418.     return XA_ERR_NONE;
  419. }
  420.  
  421. XA_EXPORT void
  422. xa_surface_destroy(struct xa_surface *srf)
  423. {
  424.     pipe_resource_reference(&srf->tex, NULL);
  425.     free(srf);
  426. }
  427.  
  428. XA_EXPORT void
  429. xa_tracker_version(int *major, int *minor, int *patch)
  430. {
  431.     *major = XA_TRACKER_VERSION_MAJOR;
  432.     *minor = XA_TRACKER_VERSION_MINOR;
  433.     *patch = XA_TRACKER_VERSION_PATCH;
  434. }
  435.  
  436. XA_EXPORT int
  437. xa_surface_handle(struct xa_surface *srf,
  438.                   uint32_t * handle, unsigned int *stride)
  439. {
  440.     struct winsys_handle whandle;
  441.  
  442.     struct pipe_screen *screen = srf->xa->screen;
  443.     boolean res;
  444.  
  445.     memset(&whandle, 0, sizeof(whandle));
  446.     whandle.type = DRM_API_HANDLE_TYPE_SHARED;
  447.     res = screen->resource_get_handle(screen, srf->tex, &whandle);
  448.     if (!res)
  449.         return -XA_ERR_INVAL;
  450.  
  451.     *handle = whandle.handle;
  452.     *stride = whandle.stride;
  453.  
  454.     return XA_ERR_NONE;
  455. }
  456.  
  457. XA_EXPORT enum xa_formats
  458. xa_surface_format(const struct xa_surface *srf)
  459. {
  460.     return srf->fdesc.xa_format;
  461. }
  462.