Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 TUNGSTEN GRAPHICS 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. {
  152.    const enum pipe_format *resource_formats;
  153.    unsigned i;
  154.  
  155.    resource_formats = vl_video_buffer_formats(screen, format);
  156.    if (!resource_formats)
  157.       return false;
  158.  
  159.    for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
  160.       enum pipe_format format = resource_formats[i];
  161.  
  162.       if (format == PIPE_FORMAT_NONE)
  163.          continue;
  164.  
  165.       /* we at least need to sample from it */
  166.       if (!screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW))
  167.          return false;
  168.  
  169.       format = vl_video_buffer_surface_format(format);
  170.       if (!screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET))
  171.          return false;
  172.    }
  173.  
  174.    return true;
  175. }
  176.  
  177. unsigned
  178. vl_video_buffer_max_size(struct pipe_screen *screen)
  179. {
  180.    uint32_t max_2d_texture_level;
  181.  
  182.    max_2d_texture_level = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
  183.  
  184.    return 1 << (max_2d_texture_level-1);
  185. }
  186.  
  187. void
  188. vl_video_buffer_set_associated_data(struct pipe_video_buffer *vbuf,
  189.                                     struct pipe_video_decoder *vdec,
  190.                                     void *associated_data,
  191.                                     void (*destroy_associated_data)(void *))
  192. {
  193.    vbuf->decoder = vdec;
  194.  
  195.    if (vbuf->associated_data == associated_data)
  196.       return;
  197.  
  198.    if (vbuf->associated_data)
  199.       vbuf->destroy_associated_data(vbuf->associated_data);
  200.  
  201.    vbuf->associated_data = associated_data;
  202.    vbuf->destroy_associated_data = destroy_associated_data;
  203. }
  204.  
  205. void *
  206. vl_video_buffer_get_associated_data(struct pipe_video_buffer *vbuf,
  207.                                     struct pipe_video_decoder *vdec)
  208. {
  209.    if (vbuf->decoder == vdec)
  210.       return vbuf->associated_data;
  211.    else
  212.       return NULL;
  213. }
  214.  
  215. void
  216. vl_video_buffer_template(struct pipe_resource *templ,
  217.                          const struct pipe_video_buffer *tmpl,
  218.                          enum pipe_format resource_format,
  219.                          unsigned depth, unsigned array_size,
  220.                          unsigned usage, unsigned plane)
  221. {
  222.    memset(templ, 0, sizeof(*templ));
  223.    if (depth > 1)
  224.       templ->target = PIPE_TEXTURE_3D;
  225.    else if (array_size > 1)
  226.       templ->target = PIPE_TEXTURE_2D_ARRAY;
  227.    else
  228.       templ->target = PIPE_TEXTURE_2D;
  229.    templ->format = resource_format;
  230.    templ->width0 = tmpl->width;
  231.    templ->height0 = tmpl->height;
  232.    templ->depth0 = depth;
  233.    templ->array_size = array_size;
  234.    templ->bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
  235.    templ->usage = usage;
  236.  
  237.    if (plane > 0) {
  238.       if (tmpl->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
  239.          templ->width0 /= 2;
  240.          templ->height0 /= 2;
  241.       } else if (tmpl->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) {
  242.          templ->height0 /= 2;
  243.       }
  244.    }
  245. }
  246.  
  247. static void
  248. vl_video_buffer_destroy(struct pipe_video_buffer *buffer)
  249. {
  250.    struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
  251.    unsigned i;
  252.  
  253.    assert(buf);
  254.  
  255.    for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
  256.       pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
  257.       pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
  258.       pipe_resource_reference(&buf->resources[i], NULL);
  259.    }
  260.  
  261.    for (i = 0; i < VL_NUM_COMPONENTS * 2; ++i)
  262.       pipe_surface_reference(&buf->surfaces[i], NULL);
  263.  
  264.    vl_video_buffer_set_associated_data(buffer, NULL, NULL, NULL);
  265.  
  266.    FREE(buffer);
  267. }
  268.  
  269. static struct pipe_sampler_view **
  270. vl_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
  271. {
  272.    struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
  273.    struct pipe_sampler_view sv_templ;
  274.    struct pipe_context *pipe;
  275.    unsigned i;
  276.  
  277.    assert(buf);
  278.  
  279.    pipe = buf->base.context;
  280.  
  281.    for (i = 0; i < buf->num_planes; ++i ) {
  282.       if (!buf->sampler_view_planes[i]) {
  283.          memset(&sv_templ, 0, sizeof(sv_templ));
  284.          u_sampler_view_default_template(&sv_templ, buf->resources[i], buf->resources[i]->format);
  285.  
  286.          if (util_format_get_nr_components(buf->resources[i]->format) == 1)
  287.             sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = sv_templ.swizzle_a = PIPE_SWIZZLE_RED;
  288.  
  289.          buf->sampler_view_planes[i] = pipe->create_sampler_view(pipe, buf->resources[i], &sv_templ);
  290.          if (!buf->sampler_view_planes[i])
  291.             goto error;
  292.       }
  293.    }
  294.  
  295.    return buf->sampler_view_planes;
  296.  
  297. error:
  298.    for (i = 0; i < buf->num_planes; ++i )
  299.       pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
  300.  
  301.    return NULL;
  302. }
  303.  
  304. static struct pipe_sampler_view **
  305. vl_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
  306. {
  307.    struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
  308.    struct pipe_sampler_view sv_templ;
  309.    struct pipe_context *pipe;
  310.    const enum pipe_format *sampler_format;
  311.    const unsigned *plane_order;
  312.    unsigned i, j, component;
  313.  
  314.    assert(buf);
  315.  
  316.    pipe = buf->base.context;
  317.  
  318.    sampler_format = vl_video_buffer_formats(pipe->screen, buf->base.buffer_format);
  319.    plane_order = vl_video_buffer_plane_order(buf->base.buffer_format);
  320.  
  321.    for (component = 0, i = 0; i < buf->num_planes; ++i ) {
  322.       struct pipe_resource *res = buf->resources[plane_order[i]];
  323.       const struct util_format_description *desc = util_format_description(res->format);
  324.       unsigned nr_components = util_format_get_nr_components(res->format);
  325.       if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED)
  326.          nr_components = 3;
  327.  
  328.       for (j = 0; j < nr_components && component < VL_NUM_COMPONENTS; ++j, ++component) {
  329.          if (buf->sampler_view_components[component])
  330.             continue;
  331.  
  332.          memset(&sv_templ, 0, sizeof(sv_templ));
  333.          u_sampler_view_default_template(&sv_templ, res, sampler_format[plane_order[i]]);
  334.          sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j;
  335.          sv_templ.swizzle_a = PIPE_SWIZZLE_ONE;
  336.          buf->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
  337.          if (!buf->sampler_view_components[component])
  338.             goto error;
  339.       }
  340.    }
  341.    assert(component == VL_NUM_COMPONENTS);
  342.  
  343.    return buf->sampler_view_components;
  344.  
  345. error:
  346.    for (i = 0; i < VL_NUM_COMPONENTS; ++i )
  347.       pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
  348.  
  349.    return NULL;
  350. }
  351.  
  352. static struct pipe_surface **
  353. vl_video_buffer_surfaces(struct pipe_video_buffer *buffer)
  354. {
  355.    struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
  356.    struct pipe_surface surf_templ;
  357.    struct pipe_context *pipe;
  358.    unsigned i, j, array_size, surf;
  359.  
  360.    assert(buf);
  361.  
  362.    pipe = buf->base.context;
  363.  
  364.    array_size = buffer->interlaced ? 2 : 1;
  365.    for (i = 0, surf = 0; i < VL_NUM_COMPONENTS; ++i) {
  366.       for (j = 0; j < array_size; ++j, ++surf) {
  367.          assert(surf < (VL_NUM_COMPONENTS * 2));
  368.  
  369.          if (!buf->resources[i]) {
  370.             pipe_surface_reference(&buf->surfaces[surf], NULL);
  371.             continue;
  372.          }
  373.  
  374.          if (!buf->surfaces[surf]) {
  375.             memset(&surf_templ, 0, sizeof(surf_templ));
  376.             surf_templ.format = vl_video_buffer_surface_format(buf->resources[i]->format);
  377.             surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = j;
  378.             buf->surfaces[surf] = pipe->create_surface(pipe, buf->resources[i], &surf_templ);
  379.             if (!buf->surfaces[surf])
  380.                goto error;
  381.          }
  382.       }
  383.    }
  384.  
  385.    return buf->surfaces;
  386.  
  387. error:
  388.    for (i = 0; i < (VL_NUM_COMPONENTS * 2); ++i )
  389.       pipe_surface_reference(&buf->surfaces[i], NULL);
  390.  
  391.    return NULL;
  392. }
  393.  
  394. struct pipe_video_buffer *
  395. vl_video_buffer_create(struct pipe_context *pipe,
  396.                        const struct pipe_video_buffer *tmpl)
  397. {
  398.    const enum pipe_format *resource_formats;
  399.    struct pipe_video_buffer templat, *result;
  400.    bool pot_buffers;
  401.  
  402.    assert(pipe);
  403.    assert(tmpl->width > 0 && tmpl->height > 0);
  404.  
  405.    pot_buffers = !pipe->screen->get_video_param
  406.    (
  407.       pipe->screen,
  408.       PIPE_VIDEO_PROFILE_UNKNOWN,
  409.       PIPE_VIDEO_CAP_NPOT_TEXTURES
  410.    );
  411.  
  412.    resource_formats = vl_video_buffer_formats(pipe->screen, tmpl->buffer_format);
  413.    if (!resource_formats)
  414.       return NULL;
  415.  
  416.    templat = *tmpl;
  417.    templat.width = pot_buffers ? util_next_power_of_two(tmpl->width)
  418.                  : align(tmpl->width, VL_MACROBLOCK_WIDTH);
  419.    templat.height = pot_buffers ? util_next_power_of_two(tmpl->height)
  420.                   : align(tmpl->height, VL_MACROBLOCK_HEIGHT);
  421.  
  422.    if (tmpl->interlaced)
  423.       templat.height /= 2;
  424.  
  425.    result = vl_video_buffer_create_ex
  426.    (
  427.       pipe, &templat, resource_formats,
  428.       1, tmpl->interlaced ? 2 : 1, PIPE_USAGE_STATIC
  429.    );
  430.  
  431.  
  432.    if (result && tmpl->interlaced)
  433.       result->height *= 2;
  434.  
  435.    return result;
  436. }
  437.  
  438. struct pipe_video_buffer *
  439. vl_video_buffer_create_ex(struct pipe_context *pipe,
  440.                           const struct pipe_video_buffer *tmpl,
  441.                           const enum pipe_format resource_formats[VL_NUM_COMPONENTS],
  442.                           unsigned depth, unsigned array_size, unsigned usage)
  443. {
  444.    struct pipe_resource res_tmpl;
  445.    struct pipe_resource *resources[VL_NUM_COMPONENTS];
  446.    unsigned i;
  447.  
  448.    assert(pipe);
  449.  
  450.    memset(resources, 0, sizeof resources);
  451.  
  452.    vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[0], depth, array_size, usage, 0);
  453.    resources[0] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
  454.    if (!resources[0])
  455.       goto error;
  456.  
  457.    if (resource_formats[1] == PIPE_FORMAT_NONE) {
  458.       assert(resource_formats[2] == PIPE_FORMAT_NONE);
  459.       return vl_video_buffer_create_ex2(pipe, tmpl, resources);
  460.    }
  461.  
  462.    vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[1], depth, array_size, usage, 1);
  463.    resources[1] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
  464.    if (!resources[1])
  465.       goto error;
  466.  
  467.    if (resource_formats[2] == PIPE_FORMAT_NONE)
  468.       return vl_video_buffer_create_ex2(pipe, tmpl, resources);
  469.  
  470.    vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[2], depth, array_size, usage, 2);
  471.    resources[2] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
  472.    if (!resources[2])
  473.       goto error;
  474.  
  475.    return vl_video_buffer_create_ex2(pipe, tmpl, resources);
  476.  
  477. error:
  478.    for (i = 0; i < VL_NUM_COMPONENTS; ++i)
  479.       pipe_resource_reference(&resources[i], NULL);
  480.  
  481.    return NULL;
  482. }
  483.  
  484. struct pipe_video_buffer *
  485. vl_video_buffer_create_ex2(struct pipe_context *pipe,
  486.                            const struct pipe_video_buffer *tmpl,
  487.                            struct pipe_resource *resources[VL_NUM_COMPONENTS])
  488. {
  489.    struct vl_video_buffer *buffer;
  490.    unsigned i;
  491.  
  492.    buffer = CALLOC_STRUCT(vl_video_buffer);
  493.  
  494.    buffer->base = *tmpl;
  495.    buffer->base.context = pipe;
  496.    buffer->base.destroy = vl_video_buffer_destroy;
  497.    buffer->base.get_sampler_view_planes = vl_video_buffer_sampler_view_planes;
  498.    buffer->base.get_sampler_view_components = vl_video_buffer_sampler_view_components;
  499.    buffer->base.get_surfaces = vl_video_buffer_surfaces;
  500.    buffer->num_planes = 0;
  501.  
  502.    for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
  503.       buffer->resources[i] = resources[i];
  504.       if (resources[i])
  505.          buffer->num_planes++;
  506.    }
  507.  
  508.    return &buffer->base;
  509. }
  510.