101e04c3fSmrg/************************************************************************** 201e04c3fSmrg * 301e04c3fSmrg * Copyright 2013 Advanced Micro Devices, Inc. 401e04c3fSmrg * All Rights Reserved. 501e04c3fSmrg * 601e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 701e04c3fSmrg * copy of this software and associated documentation files (the 801e04c3fSmrg * "Software"), to deal in the Software without restriction, including 901e04c3fSmrg * without limitation the rights to use, copy, modify, merge, publish, 1001e04c3fSmrg * distribute, sub license, and/or sell copies of the Software, and to 1101e04c3fSmrg * permit persons to whom the Software is furnished to do so, subject to 1201e04c3fSmrg * the following conditions: 1301e04c3fSmrg * 1401e04c3fSmrg * The above copyright notice and this permission notice (including the 1501e04c3fSmrg * next paragraph) shall be included in all copies or substantial portions 1601e04c3fSmrg * of the Software. 1701e04c3fSmrg * 1801e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1901e04c3fSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2001e04c3fSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2101e04c3fSmrg * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR 2201e04c3fSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 2301e04c3fSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 2401e04c3fSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2501e04c3fSmrg * 2601e04c3fSmrg **************************************************************************/ 2701e04c3fSmrg 2801e04c3fSmrg/* 2901e04c3fSmrg * Authors: 3001e04c3fSmrg * Christian König <christian.koenig@amd.com> 3101e04c3fSmrg * 3201e04c3fSmrg */ 3301e04c3fSmrg 3401e04c3fSmrg#include <unistd.h> 3501e04c3fSmrg 3601e04c3fSmrg#include "util/u_memory.h" 3701e04c3fSmrg#include "util/u_video.h" 3801e04c3fSmrg 3901e04c3fSmrg#include "vl/vl_defines.h" 4001e04c3fSmrg#include "vl/vl_video_buffer.h" 4101e04c3fSmrg 4201e04c3fSmrg#include "r600_pipe_common.h" 4301e04c3fSmrg#include "radeon_video.h" 4401e04c3fSmrg#include "radeon_vce.h" 4501e04c3fSmrg 4601e04c3fSmrg#define UVD_FW_1_66_16 ((1 << 24) | (66 << 16) | (16 << 8)) 4701e04c3fSmrg 4801e04c3fSmrg/* generate an stream handle */ 4901e04c3fSmrgunsigned rvid_alloc_stream_handle() 5001e04c3fSmrg{ 5101e04c3fSmrg static unsigned counter = 0; 5201e04c3fSmrg unsigned stream_handle = 0; 5301e04c3fSmrg unsigned pid = getpid(); 5401e04c3fSmrg int i; 5501e04c3fSmrg 5601e04c3fSmrg for (i = 0; i < 32; ++i) 5701e04c3fSmrg stream_handle |= ((pid >> i) & 1) << (31 - i); 5801e04c3fSmrg 5901e04c3fSmrg stream_handle ^= ++counter; 6001e04c3fSmrg return stream_handle; 6101e04c3fSmrg} 6201e04c3fSmrg 6301e04c3fSmrg/* create a buffer in the winsys */ 6401e04c3fSmrgbool rvid_create_buffer(struct pipe_screen *screen, struct rvid_buffer *buffer, 6501e04c3fSmrg unsigned size, unsigned usage) 6601e04c3fSmrg{ 6701e04c3fSmrg memset(buffer, 0, sizeof(*buffer)); 6801e04c3fSmrg buffer->usage = usage; 6901e04c3fSmrg 7001e04c3fSmrg /* Hardware buffer placement restrictions require the kernel to be 7101e04c3fSmrg * able to move buffers around individually, so request a 7201e04c3fSmrg * non-sub-allocated buffer. 7301e04c3fSmrg */ 7401e04c3fSmrg buffer->res = (struct r600_resource *) 7501e04c3fSmrg pipe_buffer_create(screen, PIPE_BIND_SHARED, 7601e04c3fSmrg usage, size); 7701e04c3fSmrg 7801e04c3fSmrg return buffer->res != NULL; 7901e04c3fSmrg} 8001e04c3fSmrg 8101e04c3fSmrg/* destroy a buffer */ 8201e04c3fSmrgvoid rvid_destroy_buffer(struct rvid_buffer *buffer) 8301e04c3fSmrg{ 8401e04c3fSmrg r600_resource_reference(&buffer->res, NULL); 8501e04c3fSmrg} 8601e04c3fSmrg 8701e04c3fSmrg/* reallocate a buffer, preserving its content */ 8801e04c3fSmrgbool rvid_resize_buffer(struct pipe_screen *screen, struct radeon_cmdbuf *cs, 8901e04c3fSmrg struct rvid_buffer *new_buf, unsigned new_size) 9001e04c3fSmrg{ 9101e04c3fSmrg struct r600_common_screen *rscreen = (struct r600_common_screen *)screen; 9201e04c3fSmrg struct radeon_winsys* ws = rscreen->ws; 9301e04c3fSmrg unsigned bytes = MIN2(new_buf->res->buf->size, new_size); 9401e04c3fSmrg struct rvid_buffer old_buf = *new_buf; 9501e04c3fSmrg void *src = NULL, *dst = NULL; 9601e04c3fSmrg 9701e04c3fSmrg if (!rvid_create_buffer(screen, new_buf, new_size, new_buf->usage)) 9801e04c3fSmrg goto error; 9901e04c3fSmrg 1007ec681f3Smrg src = ws->buffer_map(ws, old_buf.res->buf, cs, 1017ec681f3Smrg PIPE_MAP_READ | RADEON_MAP_TEMPORARY); 10201e04c3fSmrg if (!src) 10301e04c3fSmrg goto error; 10401e04c3fSmrg 1057ec681f3Smrg dst = ws->buffer_map(ws, new_buf->res->buf, cs, 1067ec681f3Smrg PIPE_MAP_WRITE | RADEON_MAP_TEMPORARY); 10701e04c3fSmrg if (!dst) 10801e04c3fSmrg goto error; 10901e04c3fSmrg 11001e04c3fSmrg memcpy(dst, src, bytes); 11101e04c3fSmrg if (new_size > bytes) { 11201e04c3fSmrg new_size -= bytes; 11301e04c3fSmrg dst += bytes; 11401e04c3fSmrg memset(dst, 0, new_size); 11501e04c3fSmrg } 1167ec681f3Smrg ws->buffer_unmap(ws, new_buf->res->buf); 1177ec681f3Smrg ws->buffer_unmap(ws, old_buf.res->buf); 11801e04c3fSmrg rvid_destroy_buffer(&old_buf); 11901e04c3fSmrg return true; 12001e04c3fSmrg 12101e04c3fSmrgerror: 12201e04c3fSmrg if (src) 1237ec681f3Smrg ws->buffer_unmap(ws, old_buf.res->buf); 12401e04c3fSmrg rvid_destroy_buffer(new_buf); 12501e04c3fSmrg *new_buf = old_buf; 12601e04c3fSmrg return false; 12701e04c3fSmrg} 12801e04c3fSmrg 12901e04c3fSmrg/* clear the buffer with zeros */ 13001e04c3fSmrgvoid rvid_clear_buffer(struct pipe_context *context, struct rvid_buffer* buffer) 13101e04c3fSmrg{ 13201e04c3fSmrg struct r600_common_context *rctx = (struct r600_common_context*)context; 13301e04c3fSmrg 13401e04c3fSmrg rctx->dma_clear_buffer(context, &buffer->res->b.b, 0, 13501e04c3fSmrg buffer->res->buf->size, 0); 13601e04c3fSmrg context->flush(context, NULL, 0); 13701e04c3fSmrg} 13801e04c3fSmrg 13901e04c3fSmrg/** 14001e04c3fSmrg * join surfaces into the same buffer with identical tiling params 14101e04c3fSmrg * sumup their sizes and replace the backend buffers with a single bo 14201e04c3fSmrg */ 14301e04c3fSmrgvoid rvid_join_surfaces(struct r600_common_context *rctx, 14401e04c3fSmrg struct pb_buffer** buffers[VL_NUM_COMPONENTS], 14501e04c3fSmrg struct radeon_surf *surfaces[VL_NUM_COMPONENTS]) 14601e04c3fSmrg{ 14701e04c3fSmrg struct radeon_winsys* ws; 14801e04c3fSmrg unsigned best_tiling, best_wh, off; 14901e04c3fSmrg unsigned size, alignment; 15001e04c3fSmrg struct pb_buffer *pb; 15101e04c3fSmrg unsigned i, j; 15201e04c3fSmrg 15301e04c3fSmrg ws = rctx->ws; 15401e04c3fSmrg 15501e04c3fSmrg for (i = 0, best_tiling = 0, best_wh = ~0; i < VL_NUM_COMPONENTS; ++i) { 15601e04c3fSmrg unsigned wh; 15701e04c3fSmrg 15801e04c3fSmrg if (!surfaces[i]) 15901e04c3fSmrg continue; 16001e04c3fSmrg 16101e04c3fSmrg /* choose the smallest bank w/h for now */ 16201e04c3fSmrg wh = surfaces[i]->u.legacy.bankw * surfaces[i]->u.legacy.bankh; 16301e04c3fSmrg if (wh < best_wh) { 16401e04c3fSmrg best_wh = wh; 16501e04c3fSmrg best_tiling = i; 16601e04c3fSmrg } 16701e04c3fSmrg } 16801e04c3fSmrg 16901e04c3fSmrg for (i = 0, off = 0; i < VL_NUM_COMPONENTS; ++i) { 17001e04c3fSmrg if (!surfaces[i]) 17101e04c3fSmrg continue; 17201e04c3fSmrg 17301e04c3fSmrg /* adjust the texture layer offsets */ 1747ec681f3Smrg off = align(off, 1 << surfaces[i]->surf_alignment_log2); 17501e04c3fSmrg 17601e04c3fSmrg /* copy the tiling parameters */ 17701e04c3fSmrg surfaces[i]->u.legacy.bankw = surfaces[best_tiling]->u.legacy.bankw; 17801e04c3fSmrg surfaces[i]->u.legacy.bankh = surfaces[best_tiling]->u.legacy.bankh; 17901e04c3fSmrg surfaces[i]->u.legacy.mtilea = surfaces[best_tiling]->u.legacy.mtilea; 18001e04c3fSmrg surfaces[i]->u.legacy.tile_split = surfaces[best_tiling]->u.legacy.tile_split; 18101e04c3fSmrg 18201e04c3fSmrg for (j = 0; j < ARRAY_SIZE(surfaces[i]->u.legacy.level); ++j) 1837ec681f3Smrg surfaces[i]->u.legacy.level[j].offset_256B += off / 256; 18401e04c3fSmrg 18501e04c3fSmrg off += surfaces[i]->surf_size; 18601e04c3fSmrg } 18701e04c3fSmrg 18801e04c3fSmrg for (i = 0, size = 0, alignment = 0; i < VL_NUM_COMPONENTS; ++i) { 18901e04c3fSmrg if (!buffers[i] || !*buffers[i]) 19001e04c3fSmrg continue; 19101e04c3fSmrg 1927ec681f3Smrg size = align(size, 1 << (*buffers[i])->alignment_log2); 19301e04c3fSmrg size += (*buffers[i])->size; 1947ec681f3Smrg alignment = MAX2(alignment, 1 << (*buffers[i])->alignment_log2); 19501e04c3fSmrg } 19601e04c3fSmrg 19701e04c3fSmrg if (!size) 19801e04c3fSmrg return; 19901e04c3fSmrg 20001e04c3fSmrg /* TODO: 2D tiling workaround */ 20101e04c3fSmrg alignment *= 2; 20201e04c3fSmrg 20301e04c3fSmrg pb = ws->buffer_create(ws, size, alignment, RADEON_DOMAIN_VRAM, 20401e04c3fSmrg RADEON_FLAG_GTT_WC); 20501e04c3fSmrg if (!pb) 20601e04c3fSmrg return; 20701e04c3fSmrg 20801e04c3fSmrg for (i = 0; i < VL_NUM_COMPONENTS; ++i) { 20901e04c3fSmrg if (!buffers[i] || !*buffers[i]) 21001e04c3fSmrg continue; 21101e04c3fSmrg 21201e04c3fSmrg pb_reference(buffers[i], pb); 21301e04c3fSmrg } 21401e04c3fSmrg 21501e04c3fSmrg pb_reference(&pb, NULL); 21601e04c3fSmrg} 21701e04c3fSmrg 21801e04c3fSmrgint rvid_get_video_param(struct pipe_screen *screen, 21901e04c3fSmrg enum pipe_video_profile profile, 22001e04c3fSmrg enum pipe_video_entrypoint entrypoint, 22101e04c3fSmrg enum pipe_video_cap param) 22201e04c3fSmrg{ 22301e04c3fSmrg struct r600_common_screen *rscreen = (struct r600_common_screen *)screen; 22401e04c3fSmrg enum pipe_video_format codec = u_reduce_video_profile(profile); 22501e04c3fSmrg struct radeon_info info; 22601e04c3fSmrg 2277ec681f3Smrg rscreen->ws->query_info(rscreen->ws, &info, false, false); 22801e04c3fSmrg 22901e04c3fSmrg if (entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 23001e04c3fSmrg switch (param) { 23101e04c3fSmrg case PIPE_VIDEO_CAP_SUPPORTED: 23201e04c3fSmrg return codec == PIPE_VIDEO_FORMAT_MPEG4_AVC && 23301e04c3fSmrg rvce_is_fw_version_supported(rscreen); 23401e04c3fSmrg case PIPE_VIDEO_CAP_NPOT_TEXTURES: 23501e04c3fSmrg return 1; 23601e04c3fSmrg case PIPE_VIDEO_CAP_MAX_WIDTH: 23701e04c3fSmrg return 2048; 23801e04c3fSmrg case PIPE_VIDEO_CAP_MAX_HEIGHT: 23901e04c3fSmrg return 1152; 24001e04c3fSmrg case PIPE_VIDEO_CAP_PREFERED_FORMAT: 24101e04c3fSmrg return PIPE_FORMAT_NV12; 24201e04c3fSmrg case PIPE_VIDEO_CAP_PREFERS_INTERLACED: 24301e04c3fSmrg return false; 24401e04c3fSmrg case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: 24501e04c3fSmrg return false; 24601e04c3fSmrg case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: 24701e04c3fSmrg return true; 24801e04c3fSmrg case PIPE_VIDEO_CAP_STACKED_FRAMES: 24901e04c3fSmrg return 1; 25001e04c3fSmrg default: 25101e04c3fSmrg return 0; 25201e04c3fSmrg } 25301e04c3fSmrg } 25401e04c3fSmrg 25501e04c3fSmrg switch (param) { 25601e04c3fSmrg case PIPE_VIDEO_CAP_SUPPORTED: 25701e04c3fSmrg switch (codec) { 25801e04c3fSmrg case PIPE_VIDEO_FORMAT_MPEG12: 25901e04c3fSmrg return profile != PIPE_VIDEO_PROFILE_MPEG1; 26001e04c3fSmrg case PIPE_VIDEO_FORMAT_MPEG4: 26101e04c3fSmrg /* no support for MPEG4 on older hw */ 26201e04c3fSmrg return rscreen->family >= CHIP_PALM; 26301e04c3fSmrg case PIPE_VIDEO_FORMAT_MPEG4_AVC: 26401e04c3fSmrg return true; 26501e04c3fSmrg case PIPE_VIDEO_FORMAT_VC1: 26601e04c3fSmrg return true; 26701e04c3fSmrg case PIPE_VIDEO_FORMAT_HEVC: 26801e04c3fSmrg return false; 26901e04c3fSmrg case PIPE_VIDEO_FORMAT_JPEG: 27001e04c3fSmrg return false; 27101e04c3fSmrg default: 27201e04c3fSmrg return false; 27301e04c3fSmrg } 27401e04c3fSmrg case PIPE_VIDEO_CAP_NPOT_TEXTURES: 27501e04c3fSmrg return 1; 27601e04c3fSmrg case PIPE_VIDEO_CAP_MAX_WIDTH: 27701e04c3fSmrg return 2048; 27801e04c3fSmrg case PIPE_VIDEO_CAP_MAX_HEIGHT: 27901e04c3fSmrg return 1152; 28001e04c3fSmrg case PIPE_VIDEO_CAP_PREFERED_FORMAT: 2817ec681f3Smrg return PIPE_FORMAT_NV12; 28201e04c3fSmrg 28301e04c3fSmrg case PIPE_VIDEO_CAP_PREFERS_INTERLACED: 28401e04c3fSmrg case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: 28501e04c3fSmrg if (rscreen->family < CHIP_PALM) { 28601e04c3fSmrg /* MPEG2 only with shaders and no support for 28701e04c3fSmrg interlacing on R6xx style UVD */ 28801e04c3fSmrg return codec != PIPE_VIDEO_FORMAT_MPEG12 && 28901e04c3fSmrg rscreen->family > CHIP_RV770; 29001e04c3fSmrg } else { 29101e04c3fSmrg enum pipe_video_format format = u_reduce_video_profile(profile); 29201e04c3fSmrg 2937ec681f3Smrg if (format == PIPE_VIDEO_FORMAT_JPEG) 29401e04c3fSmrg return false; 29501e04c3fSmrg return true; 29601e04c3fSmrg } 29701e04c3fSmrg case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: 29801e04c3fSmrg return true; 29901e04c3fSmrg case PIPE_VIDEO_CAP_MAX_LEVEL: 30001e04c3fSmrg switch (profile) { 30101e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG1: 30201e04c3fSmrg return 0; 30301e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: 30401e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG2_MAIN: 30501e04c3fSmrg return 3; 30601e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE: 30701e04c3fSmrg return 3; 30801e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE: 30901e04c3fSmrg return 5; 31001e04c3fSmrg case PIPE_VIDEO_PROFILE_VC1_SIMPLE: 31101e04c3fSmrg return 1; 31201e04c3fSmrg case PIPE_VIDEO_PROFILE_VC1_MAIN: 31301e04c3fSmrg return 2; 31401e04c3fSmrg case PIPE_VIDEO_PROFILE_VC1_ADVANCED: 31501e04c3fSmrg return 4; 31601e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: 31701e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: 31801e04c3fSmrg case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: 31901e04c3fSmrg return 41; 32001e04c3fSmrg default: 32101e04c3fSmrg return 0; 32201e04c3fSmrg } 32301e04c3fSmrg default: 32401e04c3fSmrg return 0; 32501e04c3fSmrg } 32601e04c3fSmrg} 32701e04c3fSmrg 3287ec681f3Smrgbool rvid_is_format_supported(struct pipe_screen *screen, 3297ec681f3Smrg enum pipe_format format, 3307ec681f3Smrg enum pipe_video_profile profile, 3317ec681f3Smrg enum pipe_video_entrypoint entrypoint) 33201e04c3fSmrg{ 33301e04c3fSmrg /* we can only handle this one with UVD */ 33401e04c3fSmrg if (profile != PIPE_VIDEO_PROFILE_UNKNOWN) 33501e04c3fSmrg return format == PIPE_FORMAT_NV12; 33601e04c3fSmrg 33701e04c3fSmrg return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint); 33801e04c3fSmrg} 339