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#define UVD_FW_1_66_16 ((1 << 24) | (66 << 16) | (16 << 8)) 47 48/* generate an stream handle */ 49unsigned rvid_alloc_stream_handle() 50{ 51 static unsigned counter = 0; 52 unsigned stream_handle = 0; 53 unsigned pid = getpid(); 54 int i; 55 56 for (i = 0; i < 32; ++i) 57 stream_handle |= ((pid >> i) & 1) << (31 - i); 58 59 stream_handle ^= ++counter; 60 return stream_handle; 61} 62 63/* create a buffer in the winsys */ 64bool rvid_create_buffer(struct pipe_screen *screen, struct rvid_buffer *buffer, 65 unsigned size, unsigned usage) 66{ 67 memset(buffer, 0, sizeof(*buffer)); 68 buffer->usage = usage; 69 70 /* Hardware buffer placement restrictions require the kernel to be 71 * able to move buffers around individually, so request a 72 * non-sub-allocated buffer. 73 */ 74 buffer->res = (struct r600_resource *) 75 pipe_buffer_create(screen, PIPE_BIND_SHARED, 76 usage, size); 77 78 return buffer->res != NULL; 79} 80 81/* destroy a buffer */ 82void rvid_destroy_buffer(struct rvid_buffer *buffer) 83{ 84 r600_resource_reference(&buffer->res, NULL); 85} 86 87/* reallocate a buffer, preserving its content */ 88bool rvid_resize_buffer(struct pipe_screen *screen, struct radeon_cmdbuf *cs, 89 struct rvid_buffer *new_buf, unsigned new_size) 90{ 91 struct r600_common_screen *rscreen = (struct r600_common_screen *)screen; 92 struct radeon_winsys* ws = rscreen->ws; 93 unsigned bytes = MIN2(new_buf->res->buf->size, new_size); 94 struct rvid_buffer old_buf = *new_buf; 95 void *src = NULL, *dst = NULL; 96 97 if (!rvid_create_buffer(screen, new_buf, new_size, new_buf->usage)) 98 goto error; 99 100 src = ws->buffer_map(old_buf.res->buf, cs, 101 PIPE_TRANSFER_READ | RADEON_TRANSFER_TEMPORARY); 102 if (!src) 103 goto error; 104 105 dst = ws->buffer_map(new_buf->res->buf, cs, 106 PIPE_TRANSFER_WRITE | RADEON_TRANSFER_TEMPORARY); 107 if (!dst) 108 goto error; 109 110 memcpy(dst, src, bytes); 111 if (new_size > bytes) { 112 new_size -= bytes; 113 dst += bytes; 114 memset(dst, 0, new_size); 115 } 116 ws->buffer_unmap(new_buf->res->buf); 117 ws->buffer_unmap(old_buf.res->buf); 118 rvid_destroy_buffer(&old_buf); 119 return true; 120 121error: 122 if (src) 123 ws->buffer_unmap(old_buf.res->buf); 124 rvid_destroy_buffer(new_buf); 125 *new_buf = old_buf; 126 return false; 127} 128 129/* clear the buffer with zeros */ 130void rvid_clear_buffer(struct pipe_context *context, struct rvid_buffer* buffer) 131{ 132 struct r600_common_context *rctx = (struct r600_common_context*)context; 133 134 rctx->dma_clear_buffer(context, &buffer->res->b.b, 0, 135 buffer->res->buf->size, 0); 136 context->flush(context, NULL, 0); 137} 138 139/** 140 * join surfaces into the same buffer with identical tiling params 141 * sumup their sizes and replace the backend buffers with a single bo 142 */ 143void rvid_join_surfaces(struct r600_common_context *rctx, 144 struct pb_buffer** buffers[VL_NUM_COMPONENTS], 145 struct radeon_surf *surfaces[VL_NUM_COMPONENTS]) 146{ 147 struct radeon_winsys* ws; 148 unsigned best_tiling, best_wh, off; 149 unsigned size, alignment; 150 struct pb_buffer *pb; 151 unsigned i, j; 152 153 ws = rctx->ws; 154 155 for (i = 0, best_tiling = 0, best_wh = ~0; i < VL_NUM_COMPONENTS; ++i) { 156 unsigned wh; 157 158 if (!surfaces[i]) 159 continue; 160 161 /* choose the smallest bank w/h for now */ 162 wh = surfaces[i]->u.legacy.bankw * surfaces[i]->u.legacy.bankh; 163 if (wh < best_wh) { 164 best_wh = wh; 165 best_tiling = i; 166 } 167 } 168 169 for (i = 0, off = 0; i < VL_NUM_COMPONENTS; ++i) { 170 if (!surfaces[i]) 171 continue; 172 173 /* adjust the texture layer offsets */ 174 off = align(off, surfaces[i]->surf_alignment); 175 176 /* copy the tiling parameters */ 177 surfaces[i]->u.legacy.bankw = surfaces[best_tiling]->u.legacy.bankw; 178 surfaces[i]->u.legacy.bankh = surfaces[best_tiling]->u.legacy.bankh; 179 surfaces[i]->u.legacy.mtilea = surfaces[best_tiling]->u.legacy.mtilea; 180 surfaces[i]->u.legacy.tile_split = surfaces[best_tiling]->u.legacy.tile_split; 181 182 for (j = 0; j < ARRAY_SIZE(surfaces[i]->u.legacy.level); ++j) 183 surfaces[i]->u.legacy.level[j].offset += off; 184 185 off += surfaces[i]->surf_size; 186 } 187 188 for (i = 0, size = 0, alignment = 0; i < VL_NUM_COMPONENTS; ++i) { 189 if (!buffers[i] || !*buffers[i]) 190 continue; 191 192 size = align(size, (*buffers[i])->alignment); 193 size += (*buffers[i])->size; 194 alignment = MAX2(alignment, (*buffers[i])->alignment * 1); 195 } 196 197 if (!size) 198 return; 199 200 /* TODO: 2D tiling workaround */ 201 alignment *= 2; 202 203 pb = ws->buffer_create(ws, size, alignment, RADEON_DOMAIN_VRAM, 204 RADEON_FLAG_GTT_WC); 205 if (!pb) 206 return; 207 208 for (i = 0; i < VL_NUM_COMPONENTS; ++i) { 209 if (!buffers[i] || !*buffers[i]) 210 continue; 211 212 pb_reference(buffers[i], pb); 213 } 214 215 pb_reference(&pb, NULL); 216} 217 218int rvid_get_video_param(struct pipe_screen *screen, 219 enum pipe_video_profile profile, 220 enum pipe_video_entrypoint entrypoint, 221 enum pipe_video_cap param) 222{ 223 struct r600_common_screen *rscreen = (struct r600_common_screen *)screen; 224 enum pipe_video_format codec = u_reduce_video_profile(profile); 225 struct radeon_info info; 226 227 rscreen->ws->query_info(rscreen->ws, &info); 228 229 if (entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 230 switch (param) { 231 case PIPE_VIDEO_CAP_SUPPORTED: 232 return codec == PIPE_VIDEO_FORMAT_MPEG4_AVC && 233 rvce_is_fw_version_supported(rscreen); 234 case PIPE_VIDEO_CAP_NPOT_TEXTURES: 235 return 1; 236 case PIPE_VIDEO_CAP_MAX_WIDTH: 237 return 2048; 238 case PIPE_VIDEO_CAP_MAX_HEIGHT: 239 return 1152; 240 case PIPE_VIDEO_CAP_PREFERED_FORMAT: 241 return PIPE_FORMAT_NV12; 242 case PIPE_VIDEO_CAP_PREFERS_INTERLACED: 243 return false; 244 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: 245 return false; 246 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: 247 return true; 248 case PIPE_VIDEO_CAP_STACKED_FRAMES: 249 return 1; 250 default: 251 return 0; 252 } 253 } 254 255 switch (param) { 256 case PIPE_VIDEO_CAP_SUPPORTED: 257 switch (codec) { 258 case PIPE_VIDEO_FORMAT_MPEG12: 259 return profile != PIPE_VIDEO_PROFILE_MPEG1; 260 case PIPE_VIDEO_FORMAT_MPEG4: 261 /* no support for MPEG4 on older hw */ 262 return rscreen->family >= CHIP_PALM; 263 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 264 return true; 265 case PIPE_VIDEO_FORMAT_VC1: 266 return true; 267 case PIPE_VIDEO_FORMAT_HEVC: 268 return false; 269 case PIPE_VIDEO_FORMAT_JPEG: 270 return false; 271 default: 272 return false; 273 } 274 case PIPE_VIDEO_CAP_NPOT_TEXTURES: 275 return 1; 276 case PIPE_VIDEO_CAP_MAX_WIDTH: 277 return 2048; 278 case PIPE_VIDEO_CAP_MAX_HEIGHT: 279 return 1152; 280 case PIPE_VIDEO_CAP_PREFERED_FORMAT: 281 if (profile == PIPE_VIDEO_PROFILE_HEVC_MAIN_10) 282 return PIPE_FORMAT_P016; 283 else 284 return PIPE_FORMAT_NV12; 285 286 case PIPE_VIDEO_CAP_PREFERS_INTERLACED: 287 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: 288 if (rscreen->family < CHIP_PALM) { 289 /* MPEG2 only with shaders and no support for 290 interlacing on R6xx style UVD */ 291 return codec != PIPE_VIDEO_FORMAT_MPEG12 && 292 rscreen->family > CHIP_RV770; 293 } else { 294 enum pipe_video_format format = u_reduce_video_profile(profile); 295 296 if (format == PIPE_VIDEO_FORMAT_HEVC) 297 return false; //The firmware doesn't support interlaced HEVC. 298 else if (format == PIPE_VIDEO_FORMAT_JPEG) 299 return false; 300 return true; 301 } 302 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: 303 return true; 304 case PIPE_VIDEO_CAP_MAX_LEVEL: 305 switch (profile) { 306 case PIPE_VIDEO_PROFILE_MPEG1: 307 return 0; 308 case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: 309 case PIPE_VIDEO_PROFILE_MPEG2_MAIN: 310 return 3; 311 case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE: 312 return 3; 313 case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE: 314 return 5; 315 case PIPE_VIDEO_PROFILE_VC1_SIMPLE: 316 return 1; 317 case PIPE_VIDEO_PROFILE_VC1_MAIN: 318 return 2; 319 case PIPE_VIDEO_PROFILE_VC1_ADVANCED: 320 return 4; 321 case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: 322 case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: 323 case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: 324 return 41; 325 case PIPE_VIDEO_PROFILE_HEVC_MAIN: 326 case PIPE_VIDEO_PROFILE_HEVC_MAIN_10: 327 return 186; 328 default: 329 return 0; 330 } 331 default: 332 return 0; 333 } 334} 335 336boolean rvid_is_format_supported(struct pipe_screen *screen, 337 enum pipe_format format, 338 enum pipe_video_profile profile, 339 enum pipe_video_entrypoint entrypoint) 340{ 341 /* HEVC 10 bit decoding should use P016 instead of NV12 if possible */ 342 if (profile == PIPE_VIDEO_PROFILE_HEVC_MAIN_10) 343 return (format == PIPE_FORMAT_NV12) || 344 (format == PIPE_FORMAT_P016); 345 346 /* we can only handle this one with UVD */ 347 if (profile != PIPE_VIDEO_PROFILE_UNKNOWN) 348 return format == PIPE_FORMAT_NV12; 349 350 return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint); 351} 352