Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2013 Advanced Micro Devices, Inc.
  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 THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. /*
  29.  * Authors:
  30.  *      Christian König <christian.koenig@amd.com>
  31.  *
  32.  */
  33.  
  34. #include <unistd.h>
  35.  
  36. #include "util/u_memory.h"
  37. #include "util/u_video.h"
  38.  
  39. #include "vl/vl_defines.h"
  40. #include "vl/vl_video_buffer.h"
  41.  
  42. #include "r600_pipe_common.h"
  43. #include "radeon_video.h"
  44. #include "radeon_vce.h"
  45.  
  46. /* generate an stream handle */
  47. unsigned rvid_alloc_stream_handle()
  48. {
  49.         static unsigned counter = 0;
  50.         unsigned stream_handle = 0;
  51.         unsigned pid = getpid();
  52.         int i;
  53.  
  54.         for (i = 0; i < 32; ++i)
  55.                 stream_handle |= ((pid >> i) & 1) << (31 - i);
  56.  
  57.         stream_handle ^= ++counter;
  58.         return stream_handle;
  59. }
  60.  
  61. /* create a buffer in the winsys */
  62. bool rvid_create_buffer(struct pipe_screen *screen, struct rvid_buffer *buffer,
  63.                         unsigned size, unsigned usage)
  64. {
  65.         memset(buffer, 0, sizeof(*buffer));
  66.         buffer->usage = usage;
  67.         buffer->res = (struct r600_resource *)
  68.                 pipe_buffer_create(screen, PIPE_BIND_CUSTOM, usage, size);
  69.  
  70.         return buffer->res != NULL;
  71. }
  72.  
  73. /* destroy a buffer */
  74. void rvid_destroy_buffer(struct rvid_buffer *buffer)
  75. {
  76.         pipe_resource_reference((struct pipe_resource **)&buffer->res, NULL);
  77. }
  78.  
  79. /* reallocate a buffer, preserving its content */
  80. bool rvid_resize_buffer(struct pipe_screen *screen, struct radeon_winsys_cs *cs,
  81.                         struct rvid_buffer *new_buf, unsigned new_size)
  82. {
  83.         struct r600_common_screen *rscreen = (struct r600_common_screen *)screen;
  84.         struct radeon_winsys* ws = rscreen->ws;
  85.         unsigned bytes = MIN2(new_buf->res->buf->size, new_size);
  86.         struct rvid_buffer old_buf = *new_buf;
  87.         void *src = NULL, *dst = NULL;
  88.  
  89.         if (!rvid_create_buffer(screen, new_buf, new_size, new_buf->usage))
  90.                 goto error;
  91.  
  92.         src = ws->buffer_map(old_buf.res->cs_buf, cs, PIPE_TRANSFER_READ);
  93.         if (!src)
  94.                 goto error;
  95.  
  96.         dst = ws->buffer_map(new_buf->res->cs_buf, cs, PIPE_TRANSFER_WRITE);
  97.         if (!dst)
  98.                 goto error;
  99.  
  100.         memcpy(dst, src, bytes);
  101.         if (new_size > bytes) {
  102.                 new_size -= bytes;
  103.                 dst += bytes;
  104.                 memset(dst, 0, new_size);
  105.         }
  106.         ws->buffer_unmap(new_buf->res->cs_buf);
  107.         ws->buffer_unmap(old_buf.res->cs_buf);
  108.         rvid_destroy_buffer(&old_buf);
  109.         return true;
  110.  
  111. error:
  112.         if (src)
  113.                 ws->buffer_unmap(old_buf.res->cs_buf);
  114.         rvid_destroy_buffer(new_buf);
  115.         *new_buf = old_buf;
  116.         return false;
  117. }
  118.  
  119. /* clear the buffer with zeros */
  120. void rvid_clear_buffer(struct pipe_context *context, struct rvid_buffer* buffer)
  121. {
  122.         struct r600_common_context *rctx = (struct r600_common_context*)context;
  123.  
  124.         rctx->clear_buffer(context, &buffer->res->b.b, 0, buffer->res->buf->size,
  125.                            0, false);
  126.         context->flush(context, NULL, 0);
  127. }
  128.  
  129. /**
  130.  * join surfaces into the same buffer with identical tiling params
  131.  * sumup their sizes and replace the backend buffers with a single bo
  132.  */
  133. void rvid_join_surfaces(struct radeon_winsys* ws, unsigned bind,
  134.                         struct pb_buffer** buffers[VL_NUM_COMPONENTS],
  135.                         struct radeon_surf *surfaces[VL_NUM_COMPONENTS])
  136. {
  137.         unsigned best_tiling, best_wh, off;
  138.         unsigned size, alignment;
  139.         struct pb_buffer *pb;
  140.         unsigned i, j;
  141.  
  142.         for (i = 0, best_tiling = 0, best_wh = ~0; i < VL_NUM_COMPONENTS; ++i) {
  143.                 unsigned wh;
  144.  
  145.                 if (!surfaces[i])
  146.                         continue;
  147.  
  148.                 /* choose the smallest bank w/h for now */
  149.                 wh = surfaces[i]->bankw * surfaces[i]->bankh;
  150.                 if (wh < best_wh) {
  151.                         best_wh = wh;
  152.                         best_tiling = i;
  153.                 }
  154.         }
  155.  
  156.         for (i = 0, off = 0; i < VL_NUM_COMPONENTS; ++i) {
  157.                 if (!surfaces[i])
  158.                         continue;
  159.  
  160.                 /* copy the tiling parameters */
  161.                 surfaces[i]->bankw = surfaces[best_tiling]->bankw;
  162.                 surfaces[i]->bankh = surfaces[best_tiling]->bankh;
  163.                 surfaces[i]->mtilea = surfaces[best_tiling]->mtilea;
  164.                 surfaces[i]->tile_split = surfaces[best_tiling]->tile_split;
  165.  
  166.                 /* adjust the texture layer offsets */
  167.                 off = align(off, surfaces[i]->bo_alignment);
  168.                 for (j = 0; j < Elements(surfaces[i]->level); ++j)
  169.                         surfaces[i]->level[j].offset += off;
  170.                 off += surfaces[i]->bo_size;
  171.         }
  172.  
  173.         for (i = 0, size = 0, alignment = 0; i < VL_NUM_COMPONENTS; ++i) {
  174.                 if (!buffers[i] || !*buffers[i])
  175.                         continue;
  176.  
  177.                 size = align(size, (*buffers[i])->alignment);
  178.                 size += (*buffers[i])->size;
  179.                 alignment = MAX2(alignment, (*buffers[i])->alignment * 1);
  180.         }
  181.  
  182.         if (!size)
  183.                 return;
  184.  
  185.         /* TODO: 2D tiling workaround */
  186.         alignment *= 2;
  187.  
  188.         pb = ws->buffer_create(ws, size, alignment, bind, RADEON_DOMAIN_VRAM, 0);
  189.         if (!pb)
  190.                 return;
  191.  
  192.         for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
  193.                 if (!buffers[i] || !*buffers[i])
  194.                         continue;
  195.  
  196.                 pb_reference(buffers[i], pb);
  197.         }
  198.  
  199.         pb_reference(&pb, NULL);
  200. }
  201.  
  202. int rvid_get_video_param(struct pipe_screen *screen,
  203.                          enum pipe_video_profile profile,
  204.                          enum pipe_video_entrypoint entrypoint,
  205.                          enum pipe_video_cap param)
  206. {
  207.         struct r600_common_screen *rscreen = (struct r600_common_screen *)screen;
  208.  
  209.         if (entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
  210.                 switch (param) {
  211.                 case PIPE_VIDEO_CAP_SUPPORTED:
  212.                         return u_reduce_video_profile(profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC &&
  213.                                 rvce_is_fw_version_supported(rscreen);
  214.                 case PIPE_VIDEO_CAP_NPOT_TEXTURES:
  215.                         return 1;
  216.                 case PIPE_VIDEO_CAP_MAX_WIDTH:
  217.                         return 2048;
  218.                 case PIPE_VIDEO_CAP_MAX_HEIGHT:
  219.                         return 1152;
  220.                 case PIPE_VIDEO_CAP_PREFERED_FORMAT:
  221.                         return PIPE_FORMAT_NV12;
  222.                 case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
  223.                         return false;
  224.                 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
  225.                         return false;
  226.                 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
  227.                         return true;
  228.                 default:
  229.                         return 0;
  230.                 }
  231.         }
  232.  
  233.         /* UVD 2.x limits */
  234.         if (rscreen->family < CHIP_PALM) {
  235.                 enum pipe_video_format codec = u_reduce_video_profile(profile);
  236.                 switch (param) {
  237.                 case PIPE_VIDEO_CAP_SUPPORTED:
  238.                         /* no support for MPEG4 */
  239.                         return codec != PIPE_VIDEO_FORMAT_MPEG4 &&
  240.                                /* FIXME: VC-1 simple/main profile is broken */
  241.                                profile != PIPE_VIDEO_PROFILE_VC1_SIMPLE &&
  242.                                profile != PIPE_VIDEO_PROFILE_VC1_MAIN;
  243.                 case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
  244.                 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
  245.                         /* MPEG2 only with shaders and no support for
  246.                            interlacing on R6xx style UVD */
  247.                         return codec != PIPE_VIDEO_FORMAT_MPEG12 &&
  248.                                rscreen->family > CHIP_RV770;
  249.                 default:
  250.                         break;
  251.                 }
  252.         }
  253.  
  254.         switch (param) {
  255.         case PIPE_VIDEO_CAP_SUPPORTED:
  256.                 switch (u_reduce_video_profile(profile)) {
  257.                 case PIPE_VIDEO_FORMAT_MPEG12:
  258.                 case PIPE_VIDEO_FORMAT_MPEG4:
  259.                 case PIPE_VIDEO_FORMAT_MPEG4_AVC:
  260.                         return entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE;
  261.                 case PIPE_VIDEO_FORMAT_VC1:
  262.                         /* FIXME: VC-1 simple/main profile is broken */
  263.                         return profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED &&
  264.                                entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE;
  265.                 default:
  266.                         return false;
  267.                 }
  268.         case PIPE_VIDEO_CAP_NPOT_TEXTURES:
  269.                 return 1;
  270.         case PIPE_VIDEO_CAP_MAX_WIDTH:
  271.                 return 2048;
  272.         case PIPE_VIDEO_CAP_MAX_HEIGHT:
  273.                 return 1152;
  274.         case PIPE_VIDEO_CAP_PREFERED_FORMAT:
  275.                 return PIPE_FORMAT_NV12;
  276.         case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
  277.                 return true;
  278.         case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
  279.                 return true;
  280.         case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
  281.                 return true;
  282.         case PIPE_VIDEO_CAP_MAX_LEVEL:
  283.                 switch (profile) {
  284.                 case PIPE_VIDEO_PROFILE_MPEG1:
  285.                         return 0;
  286.                 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
  287.                 case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
  288.                         return 3;
  289.                 case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE:
  290.                         return 3;
  291.                 case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE:
  292.                         return 5;
  293.                 case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
  294.                         return 1;
  295.                 case PIPE_VIDEO_PROFILE_VC1_MAIN:
  296.                         return 2;
  297.                 case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
  298.                         return 4;
  299.                 case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
  300.                 case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
  301.                 case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
  302.                         return 41;
  303.                 default:
  304.                         return 0;
  305.                 }
  306.         default:
  307.                 return 0;
  308.         }
  309. }
  310.  
  311. boolean rvid_is_format_supported(struct pipe_screen *screen,
  312.                                  enum pipe_format format,
  313.                                  enum pipe_video_profile profile,
  314.                                  enum pipe_video_entrypoint entrypoint)
  315. {
  316.         /* we can only handle this one with UVD */
  317.         if (profile != PIPE_VIDEO_PROFILE_UNKNOWN)
  318.                 return format == PIPE_FORMAT_NV12;
  319.  
  320.         return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint);
  321. }
  322.