Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2011 Christian König.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include <assert.h>
  29.  
  30. #include "pipe/p_screen.h"
  31. #include "pipe/p_context.h"
  32. #include "pipe/p_state.h"
  33.  
  34. #include "util/u_format.h"
  35. #include "util/u_inlines.h"
  36. #include "util/u_sampler.h"
  37. #include "util/u_memory.h"
  38.  
  39. #include "vl_video_buffer.h"
  40.  
  41. const enum pipe_format const_resource_formats_YV12[3] = {
  42.    PIPE_FORMAT_R8_UNORM,
  43.    PIPE_FORMAT_R8_UNORM,
  44.    PIPE_FORMAT_R8_UNORM
  45. };
  46.  
  47. const enum pipe_format const_resource_formats_NV12[3] = {
  48.    PIPE_FORMAT_R8_UNORM,
  49.    PIPE_FORMAT_R8G8_UNORM,
  50.    PIPE_FORMAT_NONE
  51. };
  52.  
  53. const enum pipe_format const_resource_formats_YUVA[3] = {
  54.    PIPE_FORMAT_R8G8B8A8_UNORM,
  55.    PIPE_FORMAT_NONE,
  56.    PIPE_FORMAT_NONE
  57. };
  58.  
  59. const enum pipe_format const_resource_formats_VUYA[3] = {
  60.    PIPE_FORMAT_B8G8R8A8_UNORM,
  61.    PIPE_FORMAT_NONE,
  62.    PIPE_FORMAT_NONE
  63. };
  64.  
  65. const enum pipe_format const_resource_formats_YUYV[3] = {
  66.    PIPE_FORMAT_R8G8_R8B8_UNORM,
  67.    PIPE_FORMAT_NONE,
  68.    PIPE_FORMAT_NONE
  69. };
  70.  
  71. const enum pipe_format const_resource_formats_UYVY[3] = {
  72.    PIPE_FORMAT_G8R8_B8R8_UNORM,
  73.    PIPE_FORMAT_NONE,
  74.    PIPE_FORMAT_NONE
  75. };
  76.  
  77. const unsigned const_resource_plane_order_YUV[3] = {
  78.    0,
  79.    1,
  80.    2
  81. };
  82.  
  83. const unsigned const_resource_plane_order_YVU[3] = {
  84.    0,
  85.    2,
  86.    1
  87. };
  88.  
  89. const enum pipe_format *
  90. vl_video_buffer_formats(struct pipe_screen *screen, enum pipe_format format)
  91. {
  92.    switch(format) {
  93.    case PIPE_FORMAT_YV12:
  94.       return const_resource_formats_YV12;
  95.  
  96.    case PIPE_FORMAT_NV12:
  97.       return const_resource_formats_NV12;
  98.  
  99.    case PIPE_FORMAT_R8G8B8A8_UNORM:
  100.       return const_resource_formats_YUVA;
  101.  
  102.    case PIPE_FORMAT_B8G8R8A8_UNORM:
  103.       return const_resource_formats_VUYA;
  104.  
  105.    case PIPE_FORMAT_YUYV:
  106.       return const_resource_formats_YUYV;
  107.  
  108.    case PIPE_FORMAT_UYVY:
  109.       return const_resource_formats_UYVY;
  110.  
  111.    default:
  112.       return NULL;
  113.    }
  114. }
  115.  
  116. const unsigned *
  117. vl_video_buffer_plane_order(enum pipe_format format)
  118. {
  119.    switch(format) {
  120.    case PIPE_FORMAT_YV12:
  121.       return const_resource_plane_order_YVU;
  122.  
  123.    case PIPE_FORMAT_NV12:
  124.    case PIPE_FORMAT_R8G8B8A8_UNORM:
  125.    case PIPE_FORMAT_B8G8R8A8_UNORM:
  126.    case PIPE_FORMAT_YUYV:
  127.    case PIPE_FORMAT_UYVY:
  128.       return const_resource_plane_order_YUV;
  129.  
  130.    default:
  131.       return NULL;
  132.    }
  133. }
  134.  
  135. static enum pipe_format
  136. vl_video_buffer_surface_format(enum pipe_format format)
  137. {
  138.    const struct util_format_description *desc = util_format_description(format);
  139.  
  140.    /* a subsampled formats can't work as surface use RGBA instead */
  141.    if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED)
  142.       return PIPE_FORMAT_R8G8B8A8_UNORM;
  143.  
  144.    return format;
  145. }
  146.  
  147. boolean
  148. vl_video_buffer_is_format_supported(struct pipe_screen *screen,
  149.                                     enum pipe_format format,
  150.                                     enum pipe_video_profile profile,
  151.                                     enum pipe_video_entrypoint entrypoint)
  152. {
  153.    const enum pipe_format *resource_formats;
  154.    unsigned i;
  155.  
  156.    resource_formats = vl_video_buffer_formats(screen, format);
  157.    if (!resource_formats)
  158.       return false;
  159.  
  160.    for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
  161.       enum pipe_format format = resource_formats[i];
  162.  
  163.       if (format == PIPE_FORMAT_NONE)
  164.          continue;
  165.  
  166.       /* we at least need to sample from it */
  167.       if (!screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW))
  168.          return false;
  169.  
  170.       format = vl_video_buffer_surface_format(format);
  171.       if (!screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET))
  172.          return false;
  173.    }
  174.  
  175.    return true;
  176. }
  177.  
  178. unsigned
  179. vl_video_buffer_max_size(struct pipe_screen *screen)
  180. {
  181.    uint32_t max_2d_texture_level;
  182.  
  183.    max_2d_texture_level = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
  184.  
  185.    return 1 << (max_2d_texture_level-1);
  186. }
  187.  
  188. void
  189. vl_video_buffer_set_associated_data(struct pipe_video_buffer *vbuf,
  190.                                     struct pipe_video_codec *vcodec,
  191.                                     void *associated_data,
  192.                                     void (*destroy_associated_data)(void *))
  193. {
  194.    vbuf->codec = vcodec;
  195.  
  196.    if (vbuf->associated_data == associated_data)
  197.       return;
  198.  
  199.    if (vbuf->associated_data)
  200.       vbuf->destroy_associated_data(vbuf->associated_data);
  201.  
  202.    vbuf->associated_data = associated_data;
  203.    vbuf->destroy_associated_data = destroy_associated_data;
  204. }
  205.  
  206. void *
  207. vl_video_buffer_get_associated_data(struct pipe_video_buffer *vbuf,
  208.                                     struct pipe_video_codec *vcodec)
  209. {
  210.    if (vbuf->codec == vcodec)
  211.       return vbuf->associated_data;
  212.    else
  213.       return NULL;
  214. }
  215.  
  216. void
  217. vl_video_buffer_template(struct pipe_resource *templ,
  218.                          const struct pipe_video_buffer *tmpl,
  219.                          enum pipe_format resource_format,
  220.                          unsigned depth, unsigned array_size,
  221.                          unsigned usage, unsigned plane)
  222. {
  223.    memset(templ, 0, sizeof(*templ));
  224.    if (depth > 1)
  225.       templ->target = PIPE_TEXTURE_3D;
  226.    else if (array_size > 1)
  227.       templ->target = PIPE_TEXTURE_2D_ARRAY;
  228.    else
  229.       templ->target = PIPE_TEXTURE_2D;
  230.    templ->format = resource_format;
  231.    templ->width0 = tmpl->width;
  232.    templ->height0 = tmpl->height;
  233.    templ->depth0 = depth;
  234.    templ->array_size = array_size;
  235.    templ->bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
  236.    templ->usage = usage;
  237.  
  238.    if (plane > 0) {
  239.       if (tmpl->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
  240.          templ->width0 /= 2;
  241.          templ->height0 /= 2;
  242.       } else if (tmpl->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) {
  243.          templ->width0 /= 2;
  244.       }
  245.    }
  246. }
  247.  
  248. static void
  249. vl_video_buffer_destroy(struct pipe_video_buffer *buffer)
  250. {
  251.    struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
  252.    unsigned i;
  253.  
  254.    assert(buf);
  255.  
  256.    for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
  257.       pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
  258.       pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
  259.       pipe_resource_reference(&buf->resources[i], NULL);
  260.    }
  261.  
  262.    for (i = 0; i < VL_MAX_SURFACES; ++i)
  263.       pipe_surface_reference(&buf->surfaces[i], NULL);
  264.  
  265.    vl_video_buffer_set_associated_data(buffer, NULL, NULL, NULL);
  266.  
  267.    FREE(buffer);
  268. }
  269.  
  270. static struct pipe_sampler_view **
  271. vl_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
  272. {
  273.    struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
  274.    struct pipe_sampler_view sv_templ;
  275.    struct pipe_context *pipe;
  276.    unsigned i;
  277.  
  278.    assert(buf);
  279.  
  280.    pipe = buf->base.context;
  281.  
  282.    for (i = 0; i < buf->num_planes; ++i ) {
  283.       if (!buf->sampler_view_planes[i]) {
  284.          memset(&sv_templ, 0, sizeof(sv_templ));
  285.          u_sampler_view_default_template(&sv_templ, buf->resources[i], buf->resources[i]->format);
  286.  
  287.          if (util_format_get_nr_components(buf->resources[i]->format) == 1)
  288.             sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = sv_templ.swizzle_a = PIPE_SWIZZLE_RED;
  289.  
  290.          buf->sampler_view_planes[i] = pipe->create_sampler_view(pipe, buf->resources[i], &sv_templ);
  291.          if (!buf->sampler_view_planes[i])
  292.             goto error;
  293.       }
  294.    }
  295.  
  296.    return buf->sampler_view_planes;
  297.  
  298. error:
  299.    for (i = 0; i < buf->num_planes; ++i )
  300.       pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
  301.  
  302.    return NULL;
  303. }
  304.  
  305. static struct pipe_sampler_view **
  306. vl_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
  307. {
  308.    struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
  309.    struct pipe_sampler_view sv_templ;
  310.    struct pipe_context *pipe;
  311.    const enum pipe_format *sampler_format;
  312.    const unsigned *plane_order;
  313.    unsigned i, j, component;
  314.  
  315.    assert(buf);
  316.  
  317.    pipe = buf->base.context;
  318.  
  319.    sampler_format = vl_video_buffer_formats(pipe->screen, buf->base.buffer_format);
  320.    plane_order = vl_video_buffer_plane_order(buf->base.buffer_format);
  321.  
  322.    for (component = 0, i = 0; i < buf->num_planes; ++i ) {
  323.       struct pipe_resource *res = buf->resources[plane_order[i]];
  324.       const struct util_format_description *desc = util_format_description(res->format);
  325.       unsigned nr_components = util_format_get_nr_components(res->format);
  326.       if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED)
  327.          nr_components = 3;
  328.  
  329.       for (j = 0; j < nr_components && component < VL_NUM_COMPONENTS; ++j, ++component) {
  330.          if (buf->sampler_view_components[component])
  331.             continue;
  332.  
  333.          memset(&sv_templ, 0, sizeof(sv_templ));
  334.          u_sampler_view_default_template(&sv_templ, res, sampler_format[plane_order[i]]);
  335.          sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j;
  336.          sv_templ.swizzle_a = PIPE_SWIZZLE_ONE;
  337.          buf->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
  338.          if (!buf->sampler_view_components[component])
  339.             goto error;
  340.       }
  341.    }
  342.    assert(component == VL_NUM_COMPONENTS);
  343.  
  344.    return buf->sampler_view_components;
  345.  
  346. error:
  347.    for (i = 0; i < VL_NUM_COMPONENTS; ++i )
  348.       pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
  349.  
  350.    return NULL;
  351. }
  352.  
  353. static struct pipe_surface **
  354. vl_video_buffer_surfaces(struct pipe_video_buffer *buffer)
  355. {
  356.    struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
  357.    struct pipe_surface surf_templ;
  358.    struct pipe_context *pipe;
  359.    unsigned i, j, array_size, surf;
  360.  
  361.    assert(buf);
  362.  
  363.    pipe = buf->base.context;
  364.  
  365.    array_size = buffer->interlaced ? 2 : 1;
  366.    for (i = 0, surf = 0; i < VL_NUM_COMPONENTS; ++i) {
  367.       for (j = 0; j < array_size; ++j, ++surf) {
  368.          assert(surf < VL_MAX_SURFACES);
  369.  
  370.          if (!buf->resources[i]) {
  371.             pipe_surface_reference(&buf->surfaces[surf], NULL);
  372.             continue;
  373.          }
  374.  
  375.          if (!buf->surfaces[surf]) {
  376.             memset(&surf_templ, 0, sizeof(surf_templ));
  377.             surf_templ.format = vl_video_buffer_surface_format(buf->resources[i]->format);
  378.             surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = j;
  379.             buf->surfaces[surf] = pipe->create_surface(pipe, buf->resources[i], &surf_templ);
  380.             if (!buf->surfaces[surf])
  381.                goto error;
  382.          }
  383.       }
  384.    }
  385.  
  386.    return buf->surfaces;
  387.  
  388. error:
  389.    for (i = 0; i < VL_MAX_SURFACES; ++i )
  390.       pipe_surface_reference(&buf->surfaces[i], NULL);
  391.  
  392.    return NULL;
  393. }
  394.  
  395. struct pipe_video_buffer *
  396. vl_video_buffer_create(struct pipe_context *pipe,
  397.                        const struct pipe_video_buffer *tmpl)
  398. {
  399.    const enum pipe_format *resource_formats;
  400.    struct pipe_video_buffer templat, *result;
  401.    bool pot_buffers;
  402.  
  403.    assert(pipe);
  404.    assert(tmpl->width > 0 && tmpl->height > 0);
  405.  
  406.    pot_buffers = !pipe->screen->get_video_param
  407.    (
  408.       pipe->screen,
  409.       PIPE_VIDEO_PROFILE_UNKNOWN,
  410.       PIPE_VIDEO_ENTRYPOINT_UNKNOWN,
  411.       PIPE_VIDEO_CAP_NPOT_TEXTURES
  412.    );
  413.  
  414.    resource_formats = vl_video_buffer_formats(pipe->screen, tmpl->buffer_format);
  415.    if (!resource_formats)
  416.       return NULL;
  417.  
  418.    templat = *tmpl;
  419.    templat.width = pot_buffers ? util_next_power_of_two(tmpl->width)
  420.                  : align(tmpl->width, VL_MACROBLOCK_WIDTH);
  421.    templat.height = pot_buffers ? util_next_power_of_two(tmpl->height)
  422.                   : align(tmpl->height, VL_MACROBLOCK_HEIGHT);
  423.  
  424.    if (tmpl->interlaced)
  425.       templat.height /= 2;
  426.  
  427.    result = vl_video_buffer_create_ex
  428.    (
  429.       pipe, &templat, resource_formats,
  430.       1, tmpl->interlaced ? 2 : 1, PIPE_USAGE_DEFAULT
  431.    );
  432.  
  433.  
  434.    if (result && tmpl->interlaced)
  435.       result->height *= 2;
  436.  
  437.    return result;
  438. }
  439.  
  440. struct pipe_video_buffer *
  441. vl_video_buffer_create_ex(struct pipe_context *pipe,
  442.                           const struct pipe_video_buffer *tmpl,
  443.                           const enum pipe_format resource_formats[VL_NUM_COMPONENTS],
  444.                           unsigned depth, unsigned array_size, unsigned usage)
  445. {
  446.    struct pipe_resource res_tmpl;
  447.    struct pipe_resource *resources[VL_NUM_COMPONENTS];
  448.    unsigned i;
  449.  
  450.    assert(pipe);
  451.  
  452.    memset(resources, 0, sizeof resources);
  453.  
  454.    vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[0], depth, array_size, usage, 0);
  455.    resources[0] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
  456.    if (!resources[0])
  457.       goto error;
  458.  
  459.    if (resource_formats[1] == PIPE_FORMAT_NONE) {
  460.       assert(resource_formats[2] == PIPE_FORMAT_NONE);
  461.       return vl_video_buffer_create_ex2(pipe, tmpl, resources);
  462.    }
  463.  
  464.    vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[1], depth, array_size, usage, 1);
  465.    resources[1] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
  466.    if (!resources[1])
  467.       goto error;
  468.  
  469.    if (resource_formats[2] == PIPE_FORMAT_NONE)
  470.       return vl_video_buffer_create_ex2(pipe, tmpl, resources);
  471.  
  472.    vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[2], depth, array_size, usage, 2);
  473.    resources[2] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
  474.    if (!resources[2])
  475.       goto error;
  476.  
  477.    return vl_video_buffer_create_ex2(pipe, tmpl, resources);
  478.  
  479. error:
  480.    for (i = 0; i < VL_NUM_COMPONENTS; ++i)
  481.       pipe_resource_reference(&resources[i], NULL);
  482.  
  483.    return NULL;
  484. }
  485.  
  486. struct pipe_video_buffer *
  487. vl_video_buffer_create_ex2(struct pipe_context *pipe,
  488.                            const struct pipe_video_buffer *tmpl,
  489.                            struct pipe_resource *resources[VL_NUM_COMPONENTS])
  490. {
  491.    struct vl_video_buffer *buffer;
  492.    unsigned i;
  493.  
  494.    buffer = CALLOC_STRUCT(vl_video_buffer);
  495.    if (!buffer)
  496.       return NULL;
  497.  
  498.    buffer->base = *tmpl;
  499.    buffer->base.context = pipe;
  500.    buffer->base.destroy = vl_video_buffer_destroy;
  501.    buffer->base.get_sampler_view_planes = vl_video_buffer_sampler_view_planes;
  502.    buffer->base.get_sampler_view_components = vl_video_buffer_sampler_view_components;
  503.    buffer->base.get_surfaces = vl_video_buffer_surfaces;
  504.    buffer->num_planes = 0;
  505.  
  506.    for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
  507.       buffer->resources[i] = resources[i];
  508.       if (resources[i])
  509.          buffer->num_planes++;
  510.    }
  511.  
  512.    return &buffer->base;
  513. }
  514.