radeon/uvd: add UVD implementation v5

Just everything you need for UVD with r600g and radeonsi.

v2: move UVD code to radeon subdir, clean up build system additions,
    remove an unused SI function, disable tiling on SI for now.
v3: some minor indentation fix and rebased
v4: dpb size calculation fixed
v5: implement proper fall-back in case the kernel doesn't support UVD,
    based on patches from Andreas Boll but cleaned up a bit more.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Christian König
2013-04-03 10:18:35 +02:00
parent f91e4d2c9d
commit 5b2855bfe7
17 changed files with 1939 additions and 24 deletions

View File

@@ -1780,6 +1780,7 @@ radeon_llvm_check() {
configure flag])
fi
LLVM_COMPONENTS="${LLVM_COMPONENTS} r600 bitreader"
NEED_RADEON_LLVM=yes
}
dnl Gallium drivers
@@ -1817,7 +1818,6 @@ if test "x$with_gallium_drivers" != x; then
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r600"
if test "x$enable_r600_llvm" = xyes -o "x$enable_opencl" = xyes; then
radeon_llvm_check
NEED_RADEON_GALLIUM=yes;
R600_NEED_RADEON_GALLIUM=yes;
LLVM_COMPONENTS="${LLVM_COMPONENTS} ipo bitreader asmparser"
fi
@@ -1835,7 +1835,6 @@ if test "x$with_gallium_drivers" != x; then
gallium_require_drm_loader
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS radeonsi"
radeon_llvm_check
NEED_RADEON_GALLIUM=yes;
gallium_check_st "radeon/drm" "dri-radeonsi" "xorg-radeonsi" "" "" "vdpau-radeonsi" ""
;;
xnouveau)
@@ -1990,7 +1989,7 @@ AM_CONDITIONAL(HAVE_COMMON_DRI, test x$HAVE_COMMON_DRI = xyes)
AM_CONDITIONAL(HAVE_GALAHAD_GALLIUM, test x$HAVE_GALAHAD_GALLIUM = xyes)
AM_CONDITIONAL(HAVE_IDENTITY_GALLIUM, test x$HAVE_IDENTITY_GALLIUM = xyes)
AM_CONDITIONAL(HAVE_NOOP_GALLIUM, test x$HAVE_NOOP_GALLIUM = xyes)
AM_CONDITIONAL(NEED_RADEON_GALLIUM, test x$NEED_RADEON_GALLIUM = xyes)
AM_CONDITIONAL(NEED_RADEON_LLVM, test x$NEED_RADEON_LLVM = xyes)
AM_CONDITIONAL(R600_NEED_RADEON_GALLIUM, test x$R600_NEED_RADEON_GALLIUM = xyes)
AM_CONDITIONAL(USE_R600_LLVM_COMPILER, test x$USE_R600_LLVM_COMPILER = xyes)
AM_CONDITIONAL(HAVE_LOADER_GALLIUM, test x$enable_gallium_loader = xyes)

13
docs/README.UVD Normal file
View File

@@ -0,0 +1,13 @@
The software may implement third party technologies (e.g. third party
libraries) that are not licensed to you by AMD and for which you may need
to obtain licenses from other parties. Unless explicitly stated otherwise,
these third party technologies are not licensed hereunder. Such third
party technologies include, but are not limited, to H.264, MPEG-2, MPEG-4,
AVC, and VC-1.
For MPEG-2 Encoding Products ANY USE OF THIS PRODUCT IN ANY MANNER OTHER
THAN PERSONAL USE THAT COMPLIES WITH THE MPEG-2 STANDARD FOR ENCODING VIDEO
INFORMATION FOR PACKAGED MEDIA IS EXPRESSLY PROHIBITED WITHOUT A LICENSE
UNDER APPLICABLE PATENTS IN THE MPEG-2 PATENT PORTFOLIO, WHICH LICENSES IS
AVAILABLE FROM MPEG LA, LLC, 6312 S. Fiddlers Green Circle, Suite 400E,
Greenwood Village, Colorado 80111 U.S.A.

View File

@@ -56,10 +56,18 @@ endif
################################################################################
if NEED_RADEON_GALLIUM
if HAVE_GALLIUM_R600
SUBDIRS += radeon
else
if HAVE_GALLIUM_RADEONSI
SUBDIRS += radeon
endif
endif
################################################################################

View File

@@ -13,12 +13,14 @@ AM_CFLAGS = \
libr600_la_SOURCES = \
$(C_SOURCES)
libr600_la_LIBADD = ../radeon/libradeon.la
if R600_NEED_RADEON_GALLIUM
libr600_la_SOURCES += \
$(LLVM_C_SOURCES)
libr600_la_LIBADD = ../radeon/libllvmradeon@VERSION@.la
libr600_la_LIBADD += ../radeon/libllvmradeon@VERSION@.la
AM_CFLAGS += \
$(LLVM_CFLAGS) \

View File

@@ -17,6 +17,7 @@ C_SOURCES = \
r600_state_common.c \
evergreen_compute.c \
evergreen_compute_internal.c \
compute_memory_pool.c
compute_memory_pool.c \
r600_uvd.c
LLVM_C_SOURCES = r600_llvm.c

View File

@@ -37,6 +37,7 @@
#include "util/u_math.h"
#include "vl/vl_decoder.h"
#include "vl/vl_video_buffer.h"
#include "radeon/radeon_uvd.h"
#include "os/os_time.h"
static const struct debug_named_value debug_options[] = {
@@ -379,8 +380,13 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
r600_init_context_resource_functions(rctx);
r600_init_surface_functions(rctx);
rctx->context.create_video_decoder = vl_create_decoder;
rctx->context.create_video_buffer = vl_video_buffer_create;
if (rscreen->info.has_uvd) {
rctx->context.create_video_decoder = r600_uvd_create_decoder;
rctx->context.create_video_buffer = r600_video_buffer_create;
} else {
rctx->context.create_video_decoder = vl_create_decoder;
rctx->context.create_video_buffer = vl_video_buffer_create;
}
r600_init_common_state_functions(rctx);
@@ -1257,7 +1263,6 @@ struct pipe_screen *r600_screen_create(struct radeon_winsys *ws)
rscreen->screen.get_param = r600_get_param;
rscreen->screen.get_shader_param = r600_get_shader_param;
rscreen->screen.get_paramf = r600_get_paramf;
rscreen->screen.get_video_param = r600_get_video_param;
rscreen->screen.get_compute_param = r600_get_compute_param;
rscreen->screen.get_timestamp = r600_get_timestamp;
@@ -1268,12 +1273,20 @@ struct pipe_screen *r600_screen_create(struct radeon_winsys *ws)
rscreen->screen.is_format_supported = r600_is_format_supported;
rscreen->dma_blit = &r600_dma_blit;
}
rscreen->screen.is_video_format_supported = vl_video_buffer_is_format_supported;
rscreen->screen.context_create = r600_create_context;
rscreen->screen.fence_reference = r600_fence_reference;
rscreen->screen.fence_signalled = r600_fence_signalled;
rscreen->screen.fence_finish = r600_fence_finish;
rscreen->screen.get_driver_query_info = r600_get_driver_query_info;
if (rscreen->info.has_uvd) {
rscreen->screen.get_video_param = ruvd_get_video_param;
rscreen->screen.is_video_format_supported = ruvd_is_format_supported;
} else {
rscreen->screen.get_video_param = r600_get_video_param;
rscreen->screen.is_video_format_supported = vl_video_buffer_is_format_supported;
}
r600_init_screen_resource_functions(&rscreen->screen);
util_format_s3tc_init();

View File

@@ -885,6 +885,18 @@ unsigned r600_tex_mipfilter(unsigned filter);
unsigned r600_tex_compare(unsigned compare);
bool sampler_state_needs_border_color(const struct pipe_sampler_state *state);
/* r600_uvd.c */
struct pipe_video_decoder *r600_uvd_create_decoder(struct pipe_context *context,
enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height,
unsigned max_references, bool expect_chunked_decode);
struct pipe_video_buffer *r600_video_buffer_create(struct pipe_context *pipe,
const struct pipe_video_buffer *tmpl);
/*
* Helpers for building command buffers
*/

View File

@@ -0,0 +1,178 @@
/**************************************************************************
*
* Copyright 2011 Advanced Micro Devices, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Christian König <christian.koenig@amd.com>
*
*/
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include "pipe/p_video_decoder.h"
#include "util/u_memory.h"
#include "util/u_video.h"
#include "vl/vl_defines.h"
#include "vl/vl_mpeg12_decoder.h"
#include "r600_pipe.h"
#include "radeon/radeon_uvd.h"
#include "r600d.h"
/**
* creates an video buffer with an UVD compatible memory layout
*/
struct pipe_video_buffer *r600_video_buffer_create(struct pipe_context *pipe,
const struct pipe_video_buffer *tmpl)
{
struct r600_context *ctx = (struct r600_context *)pipe;
struct r600_texture *resources[VL_NUM_COMPONENTS] = {};
struct radeon_surface* surfaces[VL_NUM_COMPONENTS] = {};
struct pb_buffer **pbs[VL_NUM_COMPONENTS] = {};
const enum pipe_format *resource_formats;
struct pipe_video_buffer template;
struct pipe_resource templ;
unsigned i, depth;
assert(pipe);
/* first create the needed resources as "normal" textures */
resource_formats = vl_video_buffer_formats(pipe->screen, tmpl->buffer_format);
if (!resource_formats)
return NULL;
depth = tmpl->interlaced ? 2 : 1;
template = *tmpl;
template.width = align(tmpl->width, VL_MACROBLOCK_WIDTH);
template.height = align(tmpl->height / depth, VL_MACROBLOCK_HEIGHT);
vl_vide_buffer_template(&templ, &template, resource_formats[0], depth, PIPE_USAGE_STATIC, 0);
resources[0] = (struct r600_texture *)
pipe->screen->resource_create(pipe->screen, &templ);
if (!resources[0])
goto error;
if (resource_formats[1] != PIPE_FORMAT_NONE) {
vl_vide_buffer_template(&templ, &template, resource_formats[1], depth, PIPE_USAGE_STATIC, 1);
resources[1] = (struct r600_texture *)
pipe->screen->resource_create(pipe->screen, &templ);
if (!resources[1])
goto error;
}
if (resource_formats[2] != PIPE_FORMAT_NONE) {
vl_vide_buffer_template(&templ, &template, resource_formats[2], depth, PIPE_USAGE_STATIC, 2);
resources[2] = (struct r600_texture *)
pipe->screen->resource_create(pipe->screen, &templ);
if (!resources[2])
goto error;
}
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
if (!resources[i])
continue;
pbs[i] = &resources[i]->resource.buf;
surfaces[i] = &resources[i]->surface;
if (ctx->chip_class < EVERGREEN) {
resources[i]->array_mode[0] = V_038000_ARRAY_LINEAR_ALIGNED;
resources[i]->surface.level[0].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
}
}
ruvd_join_surfaces(ctx->ws, templ.bind, pbs, surfaces);
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
if (!resources[i])
continue;
/* recreate the CS handle */
resources[i]->resource.cs_buf = ctx->ws->buffer_get_cs_handle(
resources[i]->resource.buf);
}
template.height *= depth;
return vl_video_buffer_create_ex2(pipe, &template, (struct pipe_resource **)resources);
error:
for (i = 0; i < VL_NUM_COMPONENTS; ++i)
pipe_resource_reference((struct pipe_resource **)&resources[i], NULL);
return NULL;
}
/* hw encode the number of memory banks */
static uint32_t eg_num_banks(uint32_t nbanks)
{
switch (nbanks) {
case 2:
return 0;
case 4:
return 1;
case 8:
default:
return 2;
case 16:
return 3;
}
}
/* set the decoding target buffer offsets */
static struct radeon_winsys_cs_handle* r600_uvd_set_dtb(struct ruvd_msg *msg, struct vl_video_buffer *buf)
{
struct r600_screen *rscreen = (struct r600_screen*)buf->base.context->screen;
struct r600_texture *luma = (struct r600_texture *)buf->resources[0];
struct r600_texture *chroma = (struct r600_texture *)buf->resources[1];
msg->decode.dt_field_mode = buf->base.interlaced;
msg->decode.dt_surf_tile_config |= RUVD_NUM_BANKS(eg_num_banks(rscreen->tiling_info.num_banks));
ruvd_set_dt_surfaces(msg, &luma->surface, &chroma->surface);
return luma->resource.cs_buf;
}
/* create decoder */
struct pipe_video_decoder *r600_uvd_create_decoder(struct pipe_context *context,
enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height,
unsigned max_references, bool expect_chunked_decode)
{
struct r600_context *ctx = (struct r600_context *)context;
return ruvd_create_decoder(context, profile, entrypoint, chroma_format,
width, height, max_references, expect_chunked_decode,
ctx->ws, r600_uvd_set_dtb);
}

View File

@@ -3,6 +3,15 @@ include $(top_srcdir)/src/gallium/Automake.inc
LIBGALLIUM_LIBS=
noinst_LTLIBRARIES = libradeon.la
AM_CFLAGS = $(GALLIUM_CFLAGS)
libradeon_la_SOURCES = \
$(C_SOURCES)
if NEED_RADEON_LLVM
if HAVE_GALLIUM_R600
if HAVE_GALLIUM_RADEONSI
lib_LTLIBRARIES = libllvmradeon@VERSION@.la
@@ -10,26 +19,28 @@ libllvmradeon@VERSION@_la_LDFLAGS = -Wl, -shared -avoid-version \
$(LLVM_LDFLAGS)
LIBGALLIUM_LIBS += $(top_builddir)/src/gallium/auxiliary/libgallium.la
else
noinst_LTLIBRARIES = libllvmradeon@VERSION@.la
noinst_LTLIBRARIES += libllvmradeon@VERSION@.la
endif
else
noinst_LTLIBRARIES = libllvmradeon@VERSION@.la
noinst_LTLIBRARIES += libllvmradeon@VERSION@.la
endif
AM_CXXFLAGS = \
libllvmradeon@VERSION@_la_CXXFLAGS = \
$(GALLIUM_CFLAGS) \
$(filter-out -DDEBUG, $(LLVM_CXXFLAGS)) \
$(DEFINES)
AM_CFLAGS = \
libllvmradeon@VERSION@_la_CFLAGS = \
$(GALLIUM_CFLAGS) \
$(LLVM_CFLAGS)
libllvmradeon@VERSION@_la_SOURCES = \
$(CPP_FILES) \
$(C_FILES)
$(LLVM_CPP_FILES) \
$(LLVM_C_FILES)
libllvmradeon@VERSION@_la_LIBADD = \
$(LIBGALLIUM_LIBS) \
$(CLOCK_LIB) \
$(LLVM_LIBS)
endif

View File

@@ -1,6 +1,9 @@
CPP_FILES := \
C_SOURCES := \
radeon_uvd.c
LLVM_CPP_FILES := \
radeon_llvm_emit.cpp
C_FILES := \
LLVM_C_FILES := \
radeon_setup_tgsi_llvm.c \
radeon_llvm_util.c

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,377 @@
/**************************************************************************
*
* Copyright 2011 Advanced Micro Devices, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Christian König <christian.koenig@amd.com>
*
*/
#ifndef RADEON_UVD_H
#define RADEON_UVD_H
/* UVD uses PM4 packet type 0 and 2 */
#define RUVD_PKT_TYPE_S(x) (((x) & 0x3) << 30)
#define RUVD_PKT_TYPE_G(x) (((x) >> 30) & 0x3)
#define RUVD_PKT_TYPE_C 0x3FFFFFFF
#define RUVD_PKT_COUNT_S(x) (((x) & 0x3FFF) << 16)
#define RUVD_PKT_COUNT_G(x) (((x) >> 16) & 0x3FFF)
#define RUVD_PKT_COUNT_C 0xC000FFFF
#define RUVD_PKT0_BASE_INDEX_S(x) (((x) & 0xFFFF) << 0)
#define RUVD_PKT0_BASE_INDEX_G(x) (((x) >> 0) & 0xFFFF)
#define RUVD_PKT0_BASE_INDEX_C 0xFFFF0000
#define RUVD_PKT0(index, count) (RUVD_PKT_TYPE_S(0) | RUVD_PKT0_BASE_INDEX_S(index) | RUVD_PKT_COUNT_S(count))
#define RUVD_PKT2() (RUVD_PKT_TYPE_S(2))
/* registers involved with UVD */
#define RUVD_GPCOM_VCPU_CMD 0xEF0C
#define RUVD_GPCOM_VCPU_DATA0 0xEF10
#define RUVD_GPCOM_VCPU_DATA1 0xEF14
#define RUVD_ENGINE_CNTL 0xEF18
/* UVD commands to VCPU */
#define RUVD_CMD_MSG_BUFFER 0x00000000
#define RUVD_CMD_DPB_BUFFER 0x00000001
#define RUVD_CMD_DECODING_TARGET_BUFFER 0x00000002
#define RUVD_CMD_FEEDBACK_BUFFER 0x00000003
#define RUVD_CMD_BITSTREAM_BUFFER 0x00000100
/* UVD message types */
#define RUVD_MSG_CREATE 0
#define RUVD_MSG_DECODE 1
#define RUVD_MSG_DESTROY 2
/* UVD stream types */
#define RUVD_CODEC_H264 0x00000000
#define RUVD_CODEC_VC1 0x00000001
#define RUVD_CODEC_MPEG2 0x00000003
#define RUVD_CODEC_MPEG4 0x00000004
/* UVD decode target buffer tiling mode */
#define RUVD_TILE_LINEAR 0x00000000
#define RUVD_TILE_8X4 0x00000001
#define RUVD_TILE_8X8 0x00000002
#define RUVD_TILE_32AS8 0x00000003
/* UVD decode target buffer array mode */
#define RUVD_ARRAY_MODE_LINEAR 0x00000000
#define RUVD_ARRAY_MODE_MACRO_LINEAR_MICRO_TILED 0x00000001
#define RUVD_ARRAY_MODE_1D_THIN 0x00000002
#define RUVD_ARRAY_MODE_2D_THIN 0x00000004
#define RUVD_ARRAY_MODE_MACRO_TILED_MICRO_LINEAR 0x00000004
#define RUVD_ARRAY_MODE_MACRO_TILED_MICRO_TILED 0x00000005
/* UVD tile config */
#define RUVD_BANK_WIDTH(x) ((x) << 0)
#define RUVD_BANK_HEIGHT(x) ((x) << 3)
#define RUVD_MACRO_TILE_ASPECT_RATIO(x) ((x) << 6)
#define RUVD_NUM_BANKS(x) ((x) << 9)
/* H.264 profile definitions */
#define RUVD_H264_PROFILE_BASELINE 0x00000000
#define RUVD_H264_PROFILE_MAIN 0x00000001
#define RUVD_H264_PROFILE_HIGH 0x00000002
#define RUVD_H264_PROFILE_STEREO_HIGH 0x00000003
#define RUVD_H264_PROFILE_MVC 0x00000004
/* VC-1 profile definitions */
#define RUVD_VC1_PROFILE_SIMPLE 0x00000000
#define RUVD_VC1_PROFILE_MAIN 0x00000001
#define RUVD_VC1_PROFILE_ADVANCED 0x00000002
struct ruvd_mvc_element {
uint16_t viewOrderIndex;
uint16_t viewId;
uint16_t numOfAnchorRefsInL0;
uint16_t viewIdOfAnchorRefsInL0[15];
uint16_t numOfAnchorRefsInL1;
uint16_t viewIdOfAnchorRefsInL1[15];
uint16_t numOfNonAnchorRefsInL0;
uint16_t viewIdOfNonAnchorRefsInL0[15];
uint16_t numOfNonAnchorRefsInL1;
uint16_t viewIdOfNonAnchorRefsInL1[15];
};
struct ruvd_h264 {
uint32_t profile;
uint32_t level;
uint32_t sps_info_flags;
uint32_t pps_info_flags;
uint8_t chroma_format;
uint8_t bit_depth_luma_minus8;
uint8_t bit_depth_chroma_minus8;
uint8_t log2_max_frame_num_minus4;
uint8_t pic_order_cnt_type;
uint8_t log2_max_pic_order_cnt_lsb_minus4;
uint8_t num_ref_frames;
uint8_t reserved_8bit;
int8_t pic_init_qp_minus26;
int8_t pic_init_qs_minus26;
int8_t chroma_qp_index_offset;
int8_t second_chroma_qp_index_offset;
uint8_t num_slice_groups_minus1;
uint8_t slice_group_map_type;
uint8_t num_ref_idx_l0_active_minus1;
uint8_t num_ref_idx_l1_active_minus1;
uint16_t slice_group_change_rate_minus1;
uint16_t reserved_16bit_1;
uint8_t scaling_list_4x4[6][16];
uint8_t scaling_list_8x8[2][64];
uint32_t frame_num;
uint32_t frame_num_list[16];
int32_t curr_field_order_cnt_list[2];
int32_t field_order_cnt_list[16][2];
uint32_t decoded_pic_idx;
uint32_t curr_pic_ref_frame_num;
uint8_t ref_frame_list[16];
uint32_t reserved[122];
struct {
uint32_t numViews;
uint32_t viewId0;
struct ruvd_mvc_element mvcElements[1];
} mvc;
};
struct ruvd_vc1 {
uint32_t profile;
uint32_t level;
uint32_t sps_info_flags;
uint32_t pps_info_flags;
uint32_t pic_structure;
uint32_t chroma_format;
};
struct ruvd_mpeg2 {
uint32_t decoded_pic_idx;
uint32_t ref_pic_idx[2];
uint8_t load_intra_quantiser_matrix;
uint8_t load_nonintra_quantiser_matrix;
uint8_t reserved_quantiser_alignement[2];
uint8_t intra_quantiser_matrix[64];
uint8_t nonintra_quantiser_matrix[64];
uint8_t profile_and_level_indication;
uint8_t chroma_format;
uint8_t picture_coding_type;
uint8_t reserved_1;
uint8_t f_code[2][2];
uint8_t intra_dc_precision;
uint8_t pic_structure;
uint8_t top_field_first;
uint8_t frame_pred_frame_dct;
uint8_t concealment_motion_vectors;
uint8_t q_scale_type;
uint8_t intra_vlc_format;
uint8_t alternate_scan;
};
struct ruvd_mpeg4
{
uint32_t decoded_pic_idx;
uint32_t ref_pic_idx[2];
uint32_t variant_type;
uint8_t profile_and_level_indication;
uint8_t video_object_layer_verid;
uint8_t video_object_layer_shape;
uint8_t reserved_1;
uint16_t video_object_layer_width;
uint16_t video_object_layer_height;
uint16_t vop_time_increment_resolution;
uint16_t reserved_2;
uint32_t flags;
uint8_t quant_type;
uint8_t reserved_3[3];
uint8_t intra_quant_mat[64];
uint8_t nonintra_quant_mat[64];
struct {
uint8_t sprite_enable;
uint8_t reserved_4[3];
uint16_t sprite_width;
uint16_t sprite_height;
int16_t sprite_left_coordinate;
int16_t sprite_top_coordinate;
uint8_t no_of_sprite_warping_points;
uint8_t sprite_warping_accuracy;
uint8_t sprite_brightness_change;
uint8_t low_latency_sprite_enable;
} sprite_config;
struct {
uint32_t flags;
uint8_t vol_mode;
uint8_t reserved_5[3];
} divx_311_config;
};
/* message between driver and hardware */
struct ruvd_msg {
uint32_t size;
uint32_t msg_type;
uint32_t stream_handle;
uint32_t status_report_feedback_number;
union {
struct {
uint32_t stream_type;
uint32_t session_flags;
uint32_t asic_id;
uint32_t width_in_samples;
uint32_t height_in_samples;
uint32_t dpb_buffer;
uint32_t dpb_size;
uint32_t dpb_model;
uint32_t version_info;
} create;
struct {
uint32_t stream_type;
uint32_t decode_flags;
uint32_t width_in_samples;
uint32_t height_in_samples;
uint32_t dpb_buffer;
uint32_t dpb_size;
uint32_t dpb_model;
uint32_t dpb_reserved;
uint32_t db_offset_alignment;
uint32_t db_pitch;
uint32_t db_tiling_mode;
uint32_t db_array_mode;
uint32_t db_field_mode;
uint32_t db_surf_tile_config;
uint32_t db_aligned_height;
uint32_t db_reserved;
uint32_t use_addr_macro;
uint32_t bsd_buffer;
uint32_t bsd_size;
uint32_t pic_param_buffer;
uint32_t pic_param_size;
uint32_t mb_cntl_buffer;
uint32_t mb_cntl_size;
uint32_t dt_buffer;
uint32_t dt_pitch;
uint32_t dt_tiling_mode;
uint32_t dt_array_mode;
uint32_t dt_field_mode;
uint32_t dt_luma_top_offset;
uint32_t dt_luma_bottom_offset;
uint32_t dt_chroma_top_offset;
uint32_t dt_chroma_bottom_offset;
uint32_t dt_surf_tile_config;
uint32_t dt_reserved[3];
uint32_t reserved[16];
union {
struct ruvd_h264 h264;
struct ruvd_vc1 vc1;
struct ruvd_mpeg2 mpeg2;
struct ruvd_mpeg4 mpeg4;
uint32_t codec_info[768];
} ;
uint8_t extension_support;
uint8_t reserved_8bit_1;
uint8_t reserved_8bit_2;
uint8_t reserved_8bit_3;
uint32_t extension_reserved[64];
} decode;
};
};
/* driver dependent callback */
typedef struct radeon_winsys_cs_handle* (*ruvd_set_dtb)
(struct ruvd_msg* msg, struct vl_video_buffer *vb);
/* create an UVD decode */
struct pipe_video_decoder *ruvd_create_decoder(struct pipe_context *context,
enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height,
unsigned max_references, bool expect_chunked_decode,
struct radeon_winsys* ws,
ruvd_set_dtb set_dtb);
/* join surfaces into the same buffer with identical tiling params
sumup their sizes and replace the backend buffers with a single bo */
void ruvd_join_surfaces(struct radeon_winsys* ws, unsigned bind,
struct pb_buffer** buffers[VL_NUM_COMPONENTS],
struct radeon_surface *surfaces[VL_NUM_COMPONENTS]);
/* fill decoding target field from the luma and chroma surfaces */
void ruvd_set_dt_surfaces(struct ruvd_msg *msg, struct radeon_surface *luma,
struct radeon_surface *chroma);
/* returns supported codecs and other parameters */
int ruvd_get_video_param(struct pipe_screen *screen,
enum pipe_video_profile profile,
enum pipe_video_cap param);
/* the hardware only supports NV12 */
boolean ruvd_is_format_supported(struct pipe_screen *screen,
enum pipe_format format,
enum pipe_video_profile profile);
#endif

View File

@@ -33,4 +33,6 @@ AM_CPPFLAGS = \
AM_CFLAGS = $(LLVM_CFLAGS)
libradeonsi_la_SOURCES = $(C_SOURCES)
libradeonsi_la_LIBADD = ../radeon/libllvmradeon@VERSION@.la
libradeonsi_la_LIBADD = \
../radeon/libradeon.la \
../radeon/libllvmradeon@VERSION@.la

View File

@@ -13,4 +13,5 @@ C_SOURCES := \
si_state.c \
si_state_streamout.c \
si_state_draw.c \
si_commands.c
si_commands.c \
radeonsi_uvd.c

View File

@@ -43,6 +43,8 @@
#include "vl/vl_video_buffer.h"
#include "os/os_time.h"
#include "pipebuffer/pb_buffer.h"
#include "radeonsi_pipe.h"
#include "radeon/radeon_uvd.h"
#include "r600.h"
#include "sid.h"
#include "r600_resource.h"
@@ -219,8 +221,13 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
si_init_surface_functions(rctx);
si_init_compute_functions(rctx);
rctx->context.create_video_decoder = vl_create_decoder;
rctx->context.create_video_buffer = vl_video_buffer_create;
if (rscreen->info.has_uvd) {
rctx->context.create_video_decoder = radeonsi_uvd_create_decoder;
rctx->context.create_video_buffer = radeonsi_video_buffer_create;
} else {
rctx->context.create_video_decoder = vl_create_decoder;
rctx->context.create_video_buffer = vl_video_buffer_create;
}
switch (rctx->chip_class) {
case TAHITI:
@@ -784,16 +791,22 @@ struct pipe_screen *radeonsi_screen_create(struct radeon_winsys *ws)
rscreen->screen.get_param = r600_get_param;
rscreen->screen.get_shader_param = r600_get_shader_param;
rscreen->screen.get_paramf = r600_get_paramf;
rscreen->screen.get_video_param = r600_get_video_param;
rscreen->screen.get_compute_param = r600_get_compute_param;
rscreen->screen.is_format_supported = si_is_format_supported;
rscreen->screen.is_video_format_supported = vl_video_buffer_is_format_supported;
rscreen->screen.context_create = r600_create_context;
rscreen->screen.fence_reference = r600_fence_reference;
rscreen->screen.fence_signalled = r600_fence_signalled;
rscreen->screen.fence_finish = r600_fence_finish;
r600_init_screen_resource_functions(&rscreen->screen);
if (rscreen->info.has_uvd) {
rscreen->screen.get_video_param = ruvd_get_video_param;
rscreen->screen.is_video_format_supported = ruvd_is_format_supported;
} else {
rscreen->screen.get_video_param = r600_get_video_param;
rscreen->screen.is_video_format_supported = vl_video_buffer_is_format_supported;
}
util_format_s3tc_init();
rscreen->fences.bo = NULL;

View File

@@ -249,6 +249,17 @@ void r600_trace_emit(struct r600_context *rctx);
/* radeonsi_compute.c */
void si_init_compute_functions(struct r600_context *rctx);
/* radeonsi_uvd.c */
struct pipe_video_decoder *radeonsi_uvd_create_decoder(struct pipe_context *context,
enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height,
unsigned max_references, bool expect_chunked_decode);
struct pipe_video_buffer *radeonsi_video_buffer_create(struct pipe_context *pipe,
const struct pipe_video_buffer *tmpl);
/*
* common helpers
*/

View File

@@ -0,0 +1,160 @@
/**************************************************************************
*
* Copyright 2011 Advanced Micro Devices, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Christian König <christian.koenig@amd.com>
*
*/
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include "pipe/p_video_decoder.h"
#include "util/u_memory.h"
#include "util/u_video.h"
#include "vl/vl_defines.h"
#include "vl/vl_mpeg12_decoder.h"
#include "radeonsi_pipe.h"
#include "radeon/radeon_uvd.h"
#include "sid.h"
/**
* creates an video buffer with an UVD compatible memory layout
*/
struct pipe_video_buffer *radeonsi_video_buffer_create(struct pipe_context *pipe,
const struct pipe_video_buffer *tmpl)
{
struct r600_context *ctx = (struct r600_context *)pipe;
struct r600_resource_texture *resources[VL_NUM_COMPONENTS] = {};
struct radeon_surface *surfaces[VL_NUM_COMPONENTS] = {};
struct pb_buffer **pbs[VL_NUM_COMPONENTS] = {};
const enum pipe_format *resource_formats;
struct pipe_video_buffer template;
struct pipe_resource templ;
unsigned i, depth;
assert(pipe);
/* first create the needed resources as "normal" textures */
resource_formats = vl_video_buffer_formats(pipe->screen, tmpl->buffer_format);
if (!resource_formats)
return NULL;
depth = tmpl->interlaced ? 2 : 1;
template = *tmpl;
template.width = align(tmpl->width, VL_MACROBLOCK_WIDTH);
template.height = align(tmpl->height / depth, VL_MACROBLOCK_HEIGHT);
vl_vide_buffer_template(&templ, &template, resource_formats[0], depth, PIPE_USAGE_STATIC, 0);
resources[0] = (struct r600_resource_texture *)
pipe->screen->resource_create(pipe->screen, &templ);
if (!resources[0])
goto error;
if (resource_formats[1] != PIPE_FORMAT_NONE) {
vl_vide_buffer_template(&templ, &template, resource_formats[1], depth, PIPE_USAGE_STATIC, 1);
resources[1] = (struct r600_resource_texture *)
pipe->screen->resource_create(pipe->screen, &templ);
if (!resources[1])
goto error;
}
if (resource_formats[2] != PIPE_FORMAT_NONE) {
vl_vide_buffer_template(&templ, &template, resource_formats[2], depth, PIPE_USAGE_STATIC, 2);
resources[2] = (struct r600_resource_texture *)
pipe->screen->resource_create(pipe->screen, &templ);
if (!resources[2])
goto error;
}
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
if (!resources[i])
continue;
surfaces[i] = & resources[i]->surface;
pbs[i] = &resources[i]->resource.buf;
}
ruvd_join_surfaces(ctx->ws, templ.bind, pbs, surfaces);
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
if (!resources[i])
continue;
/* recreate the CS handle */
resources[i]->resource.cs_buf = ctx->ws->buffer_get_cs_handle(
resources[i]->resource.buf);
/* TODO: tiling used to work with UVD on SI */
resources[i]->surface.level[0].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
}
template.height *= depth;
return vl_video_buffer_create_ex2(pipe, &template, (struct pipe_resource **)resources);
error:
for (i = 0; i < VL_NUM_COMPONENTS; ++i)
pipe_resource_reference((struct pipe_resource **)&resources[i], NULL);
return NULL;
}
/* set the decoding target buffer offsets */
static struct radeon_winsys_cs_handle* radeonsi_uvd_set_dtb(struct ruvd_msg *msg, struct vl_video_buffer *buf)
{
struct r600_resource_texture *luma = (struct r600_resource_texture *)buf->resources[0];
struct r600_resource_texture *chroma = (struct r600_resource_texture *)buf->resources[1];
msg->decode.dt_field_mode = buf->base.interlaced;
ruvd_set_dt_surfaces(msg, &luma->surface, &chroma->surface);
return luma->resource.cs_buf;
}
/**
* creates an UVD compatible decoder
*/
struct pipe_video_decoder *radeonsi_uvd_create_decoder(struct pipe_context *context,
enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height,
unsigned max_references, bool expect_chunked_decode)
{
struct r600_context *ctx = (struct r600_context *)context;
return ruvd_create_decoder(context, profile, entrypoint, chroma_format,
width, height, max_references, expect_chunked_decode,
ctx->ws, radeonsi_uvd_set_dtb);
}