1b8e80941Smrg/**************************************************************************
2b8e80941Smrg *
3b8e80941Smrg * Copyright 2013 Advanced Micro Devices, Inc.
4b8e80941Smrg * All Rights Reserved.
5b8e80941Smrg *
6b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7b8e80941Smrg * copy of this software and associated documentation files (the
8b8e80941Smrg * "Software"), to deal in the Software without restriction, including
9b8e80941Smrg * without limitation the rights to use, copy, modify, merge, publish,
10b8e80941Smrg * distribute, sub license, and/or sell copies of the Software, and to
11b8e80941Smrg * permit persons to whom the Software is furnished to do so, subject to
12b8e80941Smrg * the following conditions:
13b8e80941Smrg *
14b8e80941Smrg * The above copyright notice and this permission notice (including the
15b8e80941Smrg * next paragraph) shall be included in all copies or substantial portions
16b8e80941Smrg * of the Software.
17b8e80941Smrg *
18b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20b8e80941Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21b8e80941Smrg * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22b8e80941Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23b8e80941Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24b8e80941Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25b8e80941Smrg *
26b8e80941Smrg **************************************************************************/
27b8e80941Smrg
28b8e80941Smrg/*
29b8e80941Smrg * Authors:
30b8e80941Smrg *      Christian König <christian.koenig@amd.com>
31b8e80941Smrg *
32b8e80941Smrg */
33b8e80941Smrg
34b8e80941Smrg#include <unistd.h>
35b8e80941Smrg
36b8e80941Smrg#include "util/u_memory.h"
37b8e80941Smrg#include "util/u_video.h"
38b8e80941Smrg
39b8e80941Smrg#include "vl/vl_defines.h"
40b8e80941Smrg#include "vl/vl_video_buffer.h"
41b8e80941Smrg
42b8e80941Smrg#include "r600_pipe_common.h"
43b8e80941Smrg#include "radeon_video.h"
44b8e80941Smrg#include "radeon_vce.h"
45b8e80941Smrg
46b8e80941Smrg#define UVD_FW_1_66_16 ((1 << 24) | (66 << 16) | (16 << 8))
47b8e80941Smrg
48b8e80941Smrg/* generate an stream handle */
49b8e80941Smrgunsigned rvid_alloc_stream_handle()
50b8e80941Smrg{
51b8e80941Smrg	static unsigned counter = 0;
52b8e80941Smrg	unsigned stream_handle = 0;
53b8e80941Smrg	unsigned pid = getpid();
54b8e80941Smrg	int i;
55b8e80941Smrg
56b8e80941Smrg	for (i = 0; i < 32; ++i)
57b8e80941Smrg		stream_handle |= ((pid >> i) & 1) << (31 - i);
58b8e80941Smrg
59b8e80941Smrg	stream_handle ^= ++counter;
60b8e80941Smrg	return stream_handle;
61b8e80941Smrg}
62b8e80941Smrg
63b8e80941Smrg/* create a buffer in the winsys */
64b8e80941Smrgbool rvid_create_buffer(struct pipe_screen *screen, struct rvid_buffer *buffer,
65b8e80941Smrg			unsigned size, unsigned usage)
66b8e80941Smrg{
67b8e80941Smrg	memset(buffer, 0, sizeof(*buffer));
68b8e80941Smrg	buffer->usage = usage;
69b8e80941Smrg
70b8e80941Smrg	/* Hardware buffer placement restrictions require the kernel to be
71b8e80941Smrg	 * able to move buffers around individually, so request a
72b8e80941Smrg	 * non-sub-allocated buffer.
73b8e80941Smrg	 */
74b8e80941Smrg	buffer->res = (struct r600_resource *)
75b8e80941Smrg		pipe_buffer_create(screen, PIPE_BIND_SHARED,
76b8e80941Smrg				   usage, size);
77b8e80941Smrg
78b8e80941Smrg	return buffer->res != NULL;
79b8e80941Smrg}
80b8e80941Smrg
81b8e80941Smrg/* destroy a buffer */
82b8e80941Smrgvoid rvid_destroy_buffer(struct rvid_buffer *buffer)
83b8e80941Smrg{
84b8e80941Smrg	r600_resource_reference(&buffer->res, NULL);
85b8e80941Smrg}
86b8e80941Smrg
87b8e80941Smrg/* reallocate a buffer, preserving its content */
88b8e80941Smrgbool rvid_resize_buffer(struct pipe_screen *screen, struct radeon_cmdbuf *cs,
89b8e80941Smrg			struct rvid_buffer *new_buf, unsigned new_size)
90b8e80941Smrg{
91b8e80941Smrg	struct r600_common_screen *rscreen = (struct r600_common_screen *)screen;
92b8e80941Smrg	struct radeon_winsys* ws = rscreen->ws;
93b8e80941Smrg	unsigned bytes = MIN2(new_buf->res->buf->size, new_size);
94b8e80941Smrg	struct rvid_buffer old_buf = *new_buf;
95b8e80941Smrg	void *src = NULL, *dst = NULL;
96b8e80941Smrg
97b8e80941Smrg	if (!rvid_create_buffer(screen, new_buf, new_size, new_buf->usage))
98b8e80941Smrg		goto error;
99b8e80941Smrg
100b8e80941Smrg	src = ws->buffer_map(old_buf.res->buf, cs,
101b8e80941Smrg			     PIPE_TRANSFER_READ | RADEON_TRANSFER_TEMPORARY);
102b8e80941Smrg	if (!src)
103b8e80941Smrg		goto error;
104b8e80941Smrg
105b8e80941Smrg	dst = ws->buffer_map(new_buf->res->buf, cs,
106b8e80941Smrg			     PIPE_TRANSFER_WRITE | RADEON_TRANSFER_TEMPORARY);
107b8e80941Smrg	if (!dst)
108b8e80941Smrg		goto error;
109b8e80941Smrg
110b8e80941Smrg	memcpy(dst, src, bytes);
111b8e80941Smrg	if (new_size > bytes) {
112b8e80941Smrg		new_size -= bytes;
113b8e80941Smrg		dst += bytes;
114b8e80941Smrg		memset(dst, 0, new_size);
115b8e80941Smrg	}
116b8e80941Smrg	ws->buffer_unmap(new_buf->res->buf);
117b8e80941Smrg	ws->buffer_unmap(old_buf.res->buf);
118b8e80941Smrg	rvid_destroy_buffer(&old_buf);
119b8e80941Smrg	return true;
120b8e80941Smrg
121b8e80941Smrgerror:
122b8e80941Smrg	if (src)
123b8e80941Smrg		ws->buffer_unmap(old_buf.res->buf);
124b8e80941Smrg	rvid_destroy_buffer(new_buf);
125b8e80941Smrg	*new_buf = old_buf;
126b8e80941Smrg	return false;
127b8e80941Smrg}
128b8e80941Smrg
129b8e80941Smrg/* clear the buffer with zeros */
130b8e80941Smrgvoid rvid_clear_buffer(struct pipe_context *context, struct rvid_buffer* buffer)
131b8e80941Smrg{
132b8e80941Smrg	struct r600_common_context *rctx = (struct r600_common_context*)context;
133b8e80941Smrg
134b8e80941Smrg	rctx->dma_clear_buffer(context, &buffer->res->b.b, 0,
135b8e80941Smrg			       buffer->res->buf->size, 0);
136b8e80941Smrg	context->flush(context, NULL, 0);
137b8e80941Smrg}
138b8e80941Smrg
139b8e80941Smrg/**
140b8e80941Smrg * join surfaces into the same buffer with identical tiling params
141b8e80941Smrg * sumup their sizes and replace the backend buffers with a single bo
142b8e80941Smrg */
143b8e80941Smrgvoid rvid_join_surfaces(struct r600_common_context *rctx,
144b8e80941Smrg			struct pb_buffer** buffers[VL_NUM_COMPONENTS],
145b8e80941Smrg			struct radeon_surf *surfaces[VL_NUM_COMPONENTS])
146b8e80941Smrg{
147b8e80941Smrg	struct radeon_winsys* ws;
148b8e80941Smrg	unsigned best_tiling, best_wh, off;
149b8e80941Smrg	unsigned size, alignment;
150b8e80941Smrg	struct pb_buffer *pb;
151b8e80941Smrg	unsigned i, j;
152b8e80941Smrg
153b8e80941Smrg	ws = rctx->ws;
154b8e80941Smrg
155b8e80941Smrg	for (i = 0, best_tiling = 0, best_wh = ~0; i < VL_NUM_COMPONENTS; ++i) {
156b8e80941Smrg		unsigned wh;
157b8e80941Smrg
158b8e80941Smrg		if (!surfaces[i])
159b8e80941Smrg			continue;
160b8e80941Smrg
161b8e80941Smrg		/* choose the smallest bank w/h for now */
162b8e80941Smrg		wh = surfaces[i]->u.legacy.bankw * surfaces[i]->u.legacy.bankh;
163b8e80941Smrg		if (wh < best_wh) {
164b8e80941Smrg			best_wh = wh;
165b8e80941Smrg			best_tiling = i;
166b8e80941Smrg		}
167b8e80941Smrg	}
168b8e80941Smrg
169b8e80941Smrg	for (i = 0, off = 0; i < VL_NUM_COMPONENTS; ++i) {
170b8e80941Smrg		if (!surfaces[i])
171b8e80941Smrg			continue;
172b8e80941Smrg
173b8e80941Smrg		/* adjust the texture layer offsets */
174b8e80941Smrg		off = align(off, surfaces[i]->surf_alignment);
175b8e80941Smrg
176b8e80941Smrg		/* copy the tiling parameters */
177b8e80941Smrg		surfaces[i]->u.legacy.bankw = surfaces[best_tiling]->u.legacy.bankw;
178b8e80941Smrg		surfaces[i]->u.legacy.bankh = surfaces[best_tiling]->u.legacy.bankh;
179b8e80941Smrg		surfaces[i]->u.legacy.mtilea = surfaces[best_tiling]->u.legacy.mtilea;
180b8e80941Smrg		surfaces[i]->u.legacy.tile_split = surfaces[best_tiling]->u.legacy.tile_split;
181b8e80941Smrg
182b8e80941Smrg		for (j = 0; j < ARRAY_SIZE(surfaces[i]->u.legacy.level); ++j)
183b8e80941Smrg			surfaces[i]->u.legacy.level[j].offset += off;
184b8e80941Smrg
185b8e80941Smrg		off += surfaces[i]->surf_size;
186b8e80941Smrg	}
187b8e80941Smrg
188b8e80941Smrg	for (i = 0, size = 0, alignment = 0; i < VL_NUM_COMPONENTS; ++i) {
189b8e80941Smrg		if (!buffers[i] || !*buffers[i])
190b8e80941Smrg			continue;
191b8e80941Smrg
192b8e80941Smrg		size = align(size, (*buffers[i])->alignment);
193b8e80941Smrg		size += (*buffers[i])->size;
194b8e80941Smrg		alignment = MAX2(alignment, (*buffers[i])->alignment * 1);
195b8e80941Smrg	}
196b8e80941Smrg
197b8e80941Smrg	if (!size)
198b8e80941Smrg		return;
199b8e80941Smrg
200b8e80941Smrg	/* TODO: 2D tiling workaround */
201b8e80941Smrg	alignment *= 2;
202b8e80941Smrg
203b8e80941Smrg	pb = ws->buffer_create(ws, size, alignment, RADEON_DOMAIN_VRAM,
204b8e80941Smrg			       RADEON_FLAG_GTT_WC);
205b8e80941Smrg	if (!pb)
206b8e80941Smrg		return;
207b8e80941Smrg
208b8e80941Smrg	for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
209b8e80941Smrg		if (!buffers[i] || !*buffers[i])
210b8e80941Smrg			continue;
211b8e80941Smrg
212b8e80941Smrg		pb_reference(buffers[i], pb);
213b8e80941Smrg	}
214b8e80941Smrg
215b8e80941Smrg	pb_reference(&pb, NULL);
216b8e80941Smrg}
217b8e80941Smrg
218b8e80941Smrgint rvid_get_video_param(struct pipe_screen *screen,
219b8e80941Smrg			 enum pipe_video_profile profile,
220b8e80941Smrg			 enum pipe_video_entrypoint entrypoint,
221b8e80941Smrg			 enum pipe_video_cap param)
222b8e80941Smrg{
223b8e80941Smrg	struct r600_common_screen *rscreen = (struct r600_common_screen *)screen;
224b8e80941Smrg	enum pipe_video_format codec = u_reduce_video_profile(profile);
225b8e80941Smrg	struct radeon_info info;
226b8e80941Smrg
227b8e80941Smrg	rscreen->ws->query_info(rscreen->ws, &info);
228b8e80941Smrg
229b8e80941Smrg	if (entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
230b8e80941Smrg		switch (param) {
231b8e80941Smrg		case PIPE_VIDEO_CAP_SUPPORTED:
232b8e80941Smrg			return codec == PIPE_VIDEO_FORMAT_MPEG4_AVC &&
233b8e80941Smrg				rvce_is_fw_version_supported(rscreen);
234b8e80941Smrg		case PIPE_VIDEO_CAP_NPOT_TEXTURES:
235b8e80941Smrg			return 1;
236b8e80941Smrg		case PIPE_VIDEO_CAP_MAX_WIDTH:
237b8e80941Smrg			return 2048;
238b8e80941Smrg		case PIPE_VIDEO_CAP_MAX_HEIGHT:
239b8e80941Smrg			return 1152;
240b8e80941Smrg		case PIPE_VIDEO_CAP_PREFERED_FORMAT:
241b8e80941Smrg			return PIPE_FORMAT_NV12;
242b8e80941Smrg		case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
243b8e80941Smrg			return false;
244b8e80941Smrg		case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
245b8e80941Smrg			return false;
246b8e80941Smrg		case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
247b8e80941Smrg			return true;
248b8e80941Smrg		case PIPE_VIDEO_CAP_STACKED_FRAMES:
249b8e80941Smrg			return 1;
250b8e80941Smrg		default:
251b8e80941Smrg			return 0;
252b8e80941Smrg		}
253b8e80941Smrg	}
254b8e80941Smrg
255b8e80941Smrg	switch (param) {
256b8e80941Smrg	case PIPE_VIDEO_CAP_SUPPORTED:
257b8e80941Smrg		switch (codec) {
258b8e80941Smrg		case PIPE_VIDEO_FORMAT_MPEG12:
259b8e80941Smrg			return profile != PIPE_VIDEO_PROFILE_MPEG1;
260b8e80941Smrg		case PIPE_VIDEO_FORMAT_MPEG4:
261b8e80941Smrg			/* no support for MPEG4 on older hw */
262b8e80941Smrg			return rscreen->family >= CHIP_PALM;
263b8e80941Smrg		case PIPE_VIDEO_FORMAT_MPEG4_AVC:
264b8e80941Smrg			return true;
265b8e80941Smrg		case PIPE_VIDEO_FORMAT_VC1:
266b8e80941Smrg			return true;
267b8e80941Smrg		case PIPE_VIDEO_FORMAT_HEVC:
268b8e80941Smrg			return false;
269b8e80941Smrg		case PIPE_VIDEO_FORMAT_JPEG:
270b8e80941Smrg			return false;
271b8e80941Smrg		default:
272b8e80941Smrg			return false;
273b8e80941Smrg		}
274b8e80941Smrg	case PIPE_VIDEO_CAP_NPOT_TEXTURES:
275b8e80941Smrg		return 1;
276b8e80941Smrg	case PIPE_VIDEO_CAP_MAX_WIDTH:
277b8e80941Smrg		return 2048;
278b8e80941Smrg	case PIPE_VIDEO_CAP_MAX_HEIGHT:
279b8e80941Smrg		return 1152;
280b8e80941Smrg	case PIPE_VIDEO_CAP_PREFERED_FORMAT:
281b8e80941Smrg		if (profile == PIPE_VIDEO_PROFILE_HEVC_MAIN_10)
282b8e80941Smrg			return PIPE_FORMAT_P016;
283b8e80941Smrg		else
284b8e80941Smrg			return PIPE_FORMAT_NV12;
285b8e80941Smrg
286b8e80941Smrg	case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
287b8e80941Smrg	case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
288b8e80941Smrg		if (rscreen->family < CHIP_PALM) {
289b8e80941Smrg			/* MPEG2 only with shaders and no support for
290b8e80941Smrg			   interlacing on R6xx style UVD */
291b8e80941Smrg			return codec != PIPE_VIDEO_FORMAT_MPEG12 &&
292b8e80941Smrg			       rscreen->family > CHIP_RV770;
293b8e80941Smrg		} else {
294b8e80941Smrg			enum pipe_video_format format = u_reduce_video_profile(profile);
295b8e80941Smrg
296b8e80941Smrg			if (format == PIPE_VIDEO_FORMAT_HEVC)
297b8e80941Smrg				return false; //The firmware doesn't support interlaced HEVC.
298b8e80941Smrg			else if (format == PIPE_VIDEO_FORMAT_JPEG)
299b8e80941Smrg				return false;
300b8e80941Smrg			return true;
301b8e80941Smrg		}
302b8e80941Smrg	case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
303b8e80941Smrg		return true;
304b8e80941Smrg	case PIPE_VIDEO_CAP_MAX_LEVEL:
305b8e80941Smrg		switch (profile) {
306b8e80941Smrg		case PIPE_VIDEO_PROFILE_MPEG1:
307b8e80941Smrg			return 0;
308b8e80941Smrg		case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
309b8e80941Smrg		case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
310b8e80941Smrg			return 3;
311b8e80941Smrg		case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE:
312b8e80941Smrg			return 3;
313b8e80941Smrg		case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE:
314b8e80941Smrg			return 5;
315b8e80941Smrg		case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
316b8e80941Smrg			return 1;
317b8e80941Smrg		case PIPE_VIDEO_PROFILE_VC1_MAIN:
318b8e80941Smrg			return 2;
319b8e80941Smrg		case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
320b8e80941Smrg			return 4;
321b8e80941Smrg		case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
322b8e80941Smrg		case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
323b8e80941Smrg		case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
324b8e80941Smrg			return 41;
325b8e80941Smrg		case PIPE_VIDEO_PROFILE_HEVC_MAIN:
326b8e80941Smrg		case PIPE_VIDEO_PROFILE_HEVC_MAIN_10:
327b8e80941Smrg			return 186;
328b8e80941Smrg		default:
329b8e80941Smrg			return 0;
330b8e80941Smrg		}
331b8e80941Smrg	default:
332b8e80941Smrg		return 0;
333b8e80941Smrg	}
334b8e80941Smrg}
335b8e80941Smrg
336b8e80941Smrgboolean rvid_is_format_supported(struct pipe_screen *screen,
337b8e80941Smrg				 enum pipe_format format,
338b8e80941Smrg				 enum pipe_video_profile profile,
339b8e80941Smrg				 enum pipe_video_entrypoint entrypoint)
340b8e80941Smrg{
341b8e80941Smrg	/* HEVC 10 bit decoding should use P016 instead of NV12 if possible */
342b8e80941Smrg	if (profile == PIPE_VIDEO_PROFILE_HEVC_MAIN_10)
343b8e80941Smrg		return (format == PIPE_FORMAT_NV12) ||
344b8e80941Smrg			(format == PIPE_FORMAT_P016);
345b8e80941Smrg
346b8e80941Smrg	/* we can only handle this one with UVD */
347b8e80941Smrg	if (profile != PIPE_VIDEO_PROFILE_UNKNOWN)
348b8e80941Smrg		return format == PIPE_FORMAT_NV12;
349b8e80941Smrg
350b8e80941Smrg	return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint);
351b8e80941Smrg}
352