Subversion Repositories Kolibri OS

Rev

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 <unistd.h>
  30. #include "xa_tracker.h"
  31. #include "xa_priv.h"
  32. #include "pipe/p_state.h"
  33. #include "pipe/p_format.h"
  34. #include "pipe-loader/pipe_loader.h"
  35. #include "state_tracker/drm_driver.h"
  36. #include "util/u_inlines.h"
  37.  
  38. /*
  39.  * format_map [xa_surface_type][first..last in list].
  40.  * Needs to be updated when enum xa_formats is updated.
  41.  */
  42.  
  43. static const enum xa_formats preferred_a[] = { xa_format_a8 };
  44.  
  45. static const enum xa_formats preferred_argb[] =
  46.     { xa_format_a8r8g8b8, xa_format_x8r8g8b8, xa_format_r5g6b5,
  47.     xa_format_x1r5g5b5
  48. };
  49. static const enum xa_formats preferred_z[] =
  50.     { xa_format_z32, xa_format_z24, xa_format_z16 };
  51. static const enum xa_formats preferred_sz[] =
  52.     { xa_format_x8z24, xa_format_s8z24 };
  53. static const enum xa_formats preferred_zs[] =
  54.     { xa_format_z24x8, xa_format_z24s8 };
  55. static const enum xa_formats preferred_yuv[] = { xa_format_yuv8 };
  56.  
  57. static const enum xa_formats *preferred[] =
  58.     { NULL, preferred_a, preferred_argb, NULL, NULL,
  59.     preferred_z, preferred_zs, preferred_sz, preferred_yuv
  60. };
  61.  
  62. static const unsigned int num_preferred[] = { 0,
  63.     sizeof(preferred_a) / sizeof(enum xa_formats),
  64.     sizeof(preferred_argb) / sizeof(enum xa_formats),
  65.     0,
  66.     0,
  67.     sizeof(preferred_z) / sizeof(enum xa_formats),
  68.     sizeof(preferred_zs) / sizeof(enum xa_formats),
  69.     sizeof(preferred_sz) / sizeof(enum xa_formats),
  70.     sizeof(preferred_yuv) / sizeof(enum xa_formats)
  71. };
  72.  
  73. static const unsigned int stype_bind[XA_LAST_SURFACE_TYPE] = { 0,
  74.     PIPE_BIND_SAMPLER_VIEW,
  75.     PIPE_BIND_SAMPLER_VIEW,
  76.     PIPE_BIND_SAMPLER_VIEW,
  77.     PIPE_BIND_SAMPLER_VIEW,
  78.     PIPE_BIND_DEPTH_STENCIL,
  79.     PIPE_BIND_DEPTH_STENCIL,
  80.     PIPE_BIND_DEPTH_STENCIL,
  81.     PIPE_BIND_SAMPLER_VIEW
  82. };
  83.  
  84. static struct xa_format_descriptor
  85. xa_get_pipe_format(enum xa_formats xa_format)
  86. {
  87.     struct xa_format_descriptor fdesc;
  88.  
  89.     fdesc.xa_format = xa_format;
  90.  
  91.     switch (xa_format) {
  92.     case xa_format_a8r8g8b8:
  93.         fdesc.format = PIPE_FORMAT_B8G8R8A8_UNORM;
  94.         break;
  95.     case xa_format_x8r8g8b8:
  96.         fdesc.format = PIPE_FORMAT_B8G8R8X8_UNORM;
  97.         break;
  98.     case xa_format_r5g6b5:
  99.         fdesc.format = PIPE_FORMAT_B5G6R5_UNORM;
  100.         break;
  101.     case xa_format_x1r5g5b5:
  102.         fdesc.format = PIPE_FORMAT_B5G5R5A1_UNORM;
  103.         break;
  104.     case xa_format_a8:
  105.         fdesc.format = PIPE_FORMAT_L8_UNORM;
  106.         break;
  107.     case xa_format_z24:
  108.         fdesc.format = PIPE_FORMAT_Z24X8_UNORM;
  109.         break;
  110.     case xa_format_z16:
  111.         fdesc.format = PIPE_FORMAT_Z16_UNORM;
  112.         break;
  113.     case xa_format_z32:
  114.         fdesc.format = PIPE_FORMAT_Z32_UNORM;
  115.         break;
  116.     case xa_format_x8z24:
  117.         fdesc.format = PIPE_FORMAT_Z24X8_UNORM;
  118.         break;
  119.     case xa_format_z24x8:
  120.         fdesc.format = PIPE_FORMAT_X8Z24_UNORM;
  121.         break;
  122.     case xa_format_s8z24:
  123.         fdesc.format = PIPE_FORMAT_Z24_UNORM_S8_UINT;
  124.         break;
  125.     case xa_format_z24s8:
  126.         fdesc.format = PIPE_FORMAT_S8_UINT_Z24_UNORM;
  127.         break;
  128.     case xa_format_yuv8:
  129.         fdesc.format = PIPE_FORMAT_L8_UNORM;
  130.         break;
  131.     default:
  132.         fdesc.xa_format = xa_format_unknown;
  133.         break;
  134.     }
  135.     return fdesc;
  136. }
  137.  
  138. XA_EXPORT struct xa_tracker *
  139. xa_tracker_create(int drm_fd)
  140. {
  141.     struct xa_tracker *xa = calloc(1, sizeof(struct xa_tracker));
  142.     enum xa_surface_type stype;
  143.     unsigned int num_formats;
  144.     int loader_fd;
  145.  
  146.     if (!xa)
  147.         return NULL;
  148.  
  149. #if GALLIUM_STATIC_TARGETS
  150.     xa->screen = dd_create_screen(drm_fd);
  151.     (void) loader_fd; /* silence unused var warning */
  152. #else
  153.     loader_fd = dup(drm_fd);
  154.     if (loader_fd == -1)
  155.         return NULL;
  156.     if (pipe_loader_drm_probe_fd(&xa->dev, loader_fd, false))
  157.         xa->screen = pipe_loader_create_screen(xa->dev, PIPE_SEARCH_DIR);
  158. #endif
  159.     if (!xa->screen)
  160.         goto out_no_screen;
  161.  
  162.     xa->default_ctx = xa_context_create(xa);
  163.     if (!xa->default_ctx)
  164.         goto out_no_pipe;
  165.  
  166.     num_formats = 0;
  167.     for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype)
  168.         num_formats += num_preferred[stype];
  169.  
  170.     num_formats += 1;
  171.     xa->supported_formats = calloc(num_formats, sizeof(*xa->supported_formats));
  172.     if (!xa->supported_formats)
  173.         goto out_sf_alloc_fail;
  174.  
  175.     xa->supported_formats[0] = xa_format_unknown;
  176.     num_formats = 1;
  177.     memset(xa->format_map, 0, sizeof(xa->format_map));
  178.  
  179.     for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) {
  180.         unsigned int bind = stype_bind[stype];
  181.         enum xa_formats xa_format;
  182.         int i;
  183.  
  184.         for (i = 0; i < num_preferred[stype]; ++i) {
  185.             xa_format = preferred[stype][i];
  186.  
  187.             struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format);
  188.  
  189.             if (xa->screen->is_format_supported(xa->screen, fdesc.format,
  190.                                                 PIPE_TEXTURE_2D, 0, bind)) {
  191.                 if (xa->format_map[stype][0] == 0)
  192.                     xa->format_map[stype][0] = num_formats;
  193.                 xa->format_map[stype][1] = num_formats;
  194.                 xa->supported_formats[num_formats++] = xa_format;
  195.             }
  196.         }
  197.     }
  198.     return xa;
  199.  
  200.  out_sf_alloc_fail:
  201.     xa_context_destroy(xa->default_ctx);
  202.  out_no_pipe:
  203.     xa->screen->destroy(xa->screen);
  204.  out_no_screen:
  205. #if !GALLIUM_STATIC_TARGETS
  206.     if (xa->dev)
  207.         pipe_loader_release(&xa->dev, 1);
  208. #endif
  209.     free(xa);
  210.     return NULL;
  211. }
  212.  
  213. XA_EXPORT void
  214. xa_tracker_destroy(struct xa_tracker *xa)
  215. {
  216.     free(xa->supported_formats);
  217.     xa_context_destroy(xa->default_ctx);
  218.     xa->screen->destroy(xa->screen);
  219. #if !GALLIUM_STATIC_TARGETS
  220.     pipe_loader_release(&xa->dev, 1);
  221. #endif
  222.     free(xa);
  223. }
  224.  
  225. static int
  226. xa_flags_compat(unsigned int old_flags, unsigned int new_flags)
  227. {
  228.     unsigned int flag_diff = (old_flags ^ new_flags);
  229.  
  230.     if (flag_diff == 0)
  231.         return 1;
  232.  
  233.     if (flag_diff & XA_FLAG_SHARED)
  234.         return 0;
  235.     /*
  236.      * Don't recreate if we're dropping the render target flag.
  237.      */
  238.     if (flag_diff & XA_FLAG_RENDER_TARGET)
  239.         return ((new_flags & XA_FLAG_RENDER_TARGET) == 0);
  240.  
  241.     /*
  242.      * Don't recreate if we're dropping the scanout flag.
  243.      */
  244.     if (flag_diff & XA_FLAG_SCANOUT)
  245.         return ((new_flags & XA_FLAG_SCANOUT) == 0);
  246.  
  247.     /*
  248.      * Always recreate for unknown / unimplemented flags.
  249.      */
  250.     return 0;
  251. }
  252.  
  253. static struct xa_format_descriptor
  254. xa_get_format_stype_depth(struct xa_tracker *xa,
  255.                           enum xa_surface_type stype, unsigned int depth)
  256. {
  257.     unsigned int i;
  258.     struct xa_format_descriptor fdesc;
  259.     int found = 0;
  260.  
  261.     for (i = xa->format_map[stype][0]; i <= xa->format_map[stype][1]; ++i) {
  262.         fdesc = xa_get_pipe_format(xa->supported_formats[i]);
  263.         if (fdesc.xa_format != xa_format_unknown &&
  264.             xa_format_depth(fdesc.xa_format) == depth) {
  265.             found = 1;
  266.             break;
  267.         }
  268.     }
  269.  
  270.     if (!found)
  271.         fdesc.xa_format = xa_format_unknown;
  272.  
  273.     return fdesc;
  274. }
  275.  
  276. XA_EXPORT int
  277. xa_format_check_supported(struct xa_tracker *xa,
  278.                           enum xa_formats xa_format, unsigned int flags)
  279. {
  280.     struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format);
  281.     unsigned int bind;
  282.  
  283.     if (fdesc.xa_format == xa_format_unknown)
  284.         return -XA_ERR_INVAL;
  285.  
  286.     bind = stype_bind[xa_format_type(fdesc.xa_format)];
  287.     if (flags & XA_FLAG_SHARED)
  288.         bind |= PIPE_BIND_SHARED;
  289.     if (flags & XA_FLAG_RENDER_TARGET)
  290.         bind |= PIPE_BIND_RENDER_TARGET;
  291.     if (flags & XA_FLAG_SCANOUT)
  292.         bind |= PIPE_BIND_SCANOUT;
  293.  
  294.     if (!xa->screen->is_format_supported(xa->screen, fdesc.format,
  295.                                          PIPE_TEXTURE_2D, 0, bind))
  296.         return -XA_ERR_INVAL;
  297.  
  298.     return XA_ERR_NONE;
  299. }
  300.  
  301. static struct xa_surface *
  302. surface_create(struct xa_tracker *xa,
  303.                   int width,
  304.                   int height,
  305.                   int depth,
  306.                   enum xa_surface_type stype,
  307.                   enum xa_formats xa_format, unsigned int flags,
  308.                   struct winsys_handle *whandle)
  309. {
  310.     struct pipe_resource *template;
  311.     struct xa_surface *srf;
  312.     struct xa_format_descriptor fdesc;
  313.  
  314.     if (xa_format == xa_format_unknown)
  315.         fdesc = xa_get_format_stype_depth(xa, stype, depth);
  316.     else
  317.         fdesc = xa_get_pipe_format(xa_format);
  318.  
  319.     if (fdesc.xa_format == xa_format_unknown)
  320.         return NULL;
  321.  
  322.     srf = calloc(1, sizeof(*srf));
  323.     if (!srf)
  324.         return NULL;
  325.  
  326.     template = &srf->template;
  327.     template->format = fdesc.format;
  328.     template->target = PIPE_TEXTURE_2D;
  329.     template->width0 = width;
  330.     template->height0 = height;
  331.     template->depth0 = 1;
  332.     template->array_size = 1;
  333.     template->last_level = 0;
  334.     template->bind = stype_bind[xa_format_type(fdesc.xa_format)];
  335.  
  336.     if (flags & XA_FLAG_SHARED)
  337.         template->bind |= PIPE_BIND_SHARED;
  338.     if (flags & XA_FLAG_RENDER_TARGET)
  339.         template->bind |= PIPE_BIND_RENDER_TARGET;
  340.     if (flags & XA_FLAG_SCANOUT)
  341.         template->bind |= PIPE_BIND_SCANOUT;
  342.  
  343.     if (whandle)
  344.         srf->tex = xa->screen->resource_from_handle(xa->screen, template, whandle);
  345.     else
  346.         srf->tex = xa->screen->resource_create(xa->screen, template);
  347.     if (!srf->tex)
  348.         goto out_no_tex;
  349.  
  350.     srf->refcount = 1;
  351.     srf->xa = xa;
  352.     srf->flags = flags;
  353.     srf->fdesc = fdesc;
  354.  
  355.     return srf;
  356.  out_no_tex:
  357.     free(srf);
  358.     return NULL;
  359. }
  360.  
  361.  
  362. XA_EXPORT struct xa_surface *
  363. xa_surface_create(struct xa_tracker *xa,
  364.                   int width,
  365.                   int height,
  366.                   int depth,
  367.                   enum xa_surface_type stype,
  368.                   enum xa_formats xa_format, unsigned int flags)
  369. {
  370.     return surface_create(xa, width, height, depth, stype, xa_format, flags, NULL);
  371. }
  372.  
  373.  
  374. XA_EXPORT struct xa_surface *
  375. xa_surface_from_handle(struct xa_tracker *xa,
  376.                   int width,
  377.                   int height,
  378.                   int depth,
  379.                   enum xa_surface_type stype,
  380.                   enum xa_formats xa_format, unsigned int flags,
  381.                   uint32_t handle, uint32_t stride)
  382. {
  383.     struct winsys_handle whandle;
  384.     memset(&whandle, 0, sizeof(whandle));
  385.     whandle.type = DRM_API_HANDLE_TYPE_SHARED;
  386.     whandle.handle = handle;
  387.     whandle.stride = stride;
  388.     return surface_create(xa, width, height, depth, stype, xa_format, flags, &whandle);
  389. }
  390.  
  391. XA_EXPORT int
  392. xa_surface_redefine(struct xa_surface *srf,
  393.                     int width,
  394.                     int height,
  395.                     int depth,
  396.                     enum xa_surface_type stype,
  397.                     enum xa_formats xa_format,
  398.                     unsigned int new_flags,
  399.                     int copy_contents)
  400. {
  401.     struct pipe_resource *template = &srf->template;
  402.     struct pipe_resource *texture;
  403.     struct pipe_box src_box;
  404.     struct xa_tracker *xa = srf->xa;
  405.     int save_width;
  406.     int save_height;
  407.     unsigned int save_format;
  408.     struct xa_format_descriptor fdesc;
  409.  
  410.  
  411.     if (xa_format == xa_format_unknown)
  412.         fdesc = xa_get_format_stype_depth(xa, stype, depth);
  413.     else
  414.         fdesc = xa_get_pipe_format(xa_format);
  415.  
  416.     if (width == template->width0 && height == template->height0 &&
  417.         template->format == fdesc.format &&
  418.         xa_flags_compat(srf->flags, new_flags))
  419.         return XA_ERR_NONE;
  420.  
  421.     template->bind = stype_bind[xa_format_type(fdesc.xa_format)];
  422.     if (new_flags & XA_FLAG_SHARED)
  423.         template->bind |= PIPE_BIND_SHARED;
  424.     if (new_flags & XA_FLAG_RENDER_TARGET)
  425.         template->bind |= PIPE_BIND_RENDER_TARGET;
  426.     if (new_flags & XA_FLAG_SCANOUT)
  427.         template->bind |= PIPE_BIND_SCANOUT;
  428.  
  429.     if (copy_contents) {
  430.         if (!xa_format_type_is_color(fdesc.xa_format) ||
  431.             xa_format_type(fdesc.xa_format) == xa_type_a)
  432.             return -XA_ERR_INVAL;
  433.  
  434.         if (!xa->screen->is_format_supported(xa->screen, fdesc.format,
  435.                                              PIPE_TEXTURE_2D, 0,
  436.                                              template->bind |
  437.                                              PIPE_BIND_RENDER_TARGET))
  438.             return -XA_ERR_INVAL;
  439.     }
  440.  
  441.     save_width = template->width0;
  442.     save_height = template->height0;
  443.     save_format = template->format;
  444.  
  445.     template->width0 = width;
  446.     template->height0 = height;
  447.     template->format = fdesc.format;
  448.  
  449.     texture = xa->screen->resource_create(xa->screen, template);
  450.     if (!texture) {
  451.         template->width0 = save_width;
  452.         template->height0 = save_height;
  453.         template->format = save_format;
  454.         return -XA_ERR_NORES;
  455.     }
  456.  
  457.     if (copy_contents) {
  458.         struct pipe_context *pipe = xa->default_ctx->pipe;
  459.  
  460.         u_box_origin_2d(xa_min(save_width, template->width0),
  461.                         xa_min(save_height, template->height0), &src_box);
  462.         pipe->resource_copy_region(pipe, texture,
  463.                                    0, 0, 0, 0, srf->tex, 0, &src_box);
  464.         pipe->flush(pipe, &xa->default_ctx->last_fence, 0);
  465.     }
  466.  
  467.     pipe_resource_reference(&srf->tex, texture);
  468.     pipe_resource_reference(&texture, NULL);
  469.     srf->fdesc = fdesc;
  470.     srf->flags = new_flags;
  471.  
  472.     return XA_ERR_NONE;
  473. }
  474.  
  475. XA_EXPORT struct xa_surface*
  476. xa_surface_ref(struct xa_surface *srf)
  477. {
  478.     if (srf == NULL) {
  479.         return NULL;
  480.     }
  481.     srf->refcount++;
  482.     return srf;
  483. }
  484.  
  485. XA_EXPORT void
  486. xa_surface_unref(struct xa_surface *srf)
  487. {
  488.     if (srf == NULL || --srf->refcount) {
  489.         return;
  490.     }
  491.     pipe_resource_reference(&srf->tex, NULL);
  492.     free(srf);
  493. }
  494.  
  495. XA_EXPORT void
  496. xa_tracker_version(int *major, int *minor, int *patch)
  497. {
  498.     *major = XA_TRACKER_VERSION_MAJOR;
  499.     *minor = XA_TRACKER_VERSION_MINOR;
  500.     *patch = XA_TRACKER_VERSION_PATCH;
  501. }
  502.  
  503. XA_EXPORT int
  504. xa_surface_handle(struct xa_surface *srf,
  505.                   enum xa_handle_type type,
  506.                   uint32_t * handle, unsigned int *stride)
  507. {
  508.     struct winsys_handle whandle;
  509.  
  510.     struct pipe_screen *screen = srf->xa->screen;
  511.     boolean res;
  512.  
  513.     memset(&whandle, 0, sizeof(whandle));
  514.     switch (type) {
  515.     case xa_handle_type_kms:
  516.         whandle.type = DRM_API_HANDLE_TYPE_KMS;
  517.         break;
  518.     case xa_handle_type_shared:
  519.     default:
  520.         whandle.type = DRM_API_HANDLE_TYPE_SHARED;
  521.         break;
  522.     }
  523.     res = screen->resource_get_handle(screen, srf->tex, &whandle);
  524.     if (!res)
  525.         return -XA_ERR_INVAL;
  526.  
  527.     *handle = whandle.handle;
  528.     *stride = whandle.stride;
  529.  
  530.     return XA_ERR_NONE;
  531. }
  532.  
  533. XA_EXPORT enum xa_formats
  534. xa_surface_format(const struct xa_surface *srf)
  535. {
  536.     return srf->fdesc.xa_format;
  537. }
  538.  
  539. /*
  540.  * _mesa_error_no_memory() is expected by NIR to be provided by the
  541.  * user.  Normally this is in mesa st, but other state trackers
  542.  * must provide their own.
  543.  */
  544. void _mesa_error_no_memory(const char *caller);
  545. void
  546. _mesa_error_no_memory(const char *caller)
  547. {
  548.         debug_printf("Mesa error: out of memory in %s", caller);
  549. }
  550.