summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2018-05-04 17:54:45 +0200
committerThierry Reding <treding@nvidia.com>2018-05-04 17:55:19 +0200
commitde7eac113b1ea3ce5b762ec1a2a3e9a321adb0c7 (patch)
tree2ad4a12de983acec3227c302d7cc23b42bfd8033
parentfcecdf2b699f546fe563b28e277b2ccca664cafc (diff)
Update for new kernel ABIHEADmaster
This adds support for Tegra124 with the secure memory FD that's required for reference picture marking as well as tiling formats needed by the IP present in Tegra124. Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--configure.ac3
-rw-r--r--src/decoder.c48
-rw-r--r--src/host1x-pixelbuffer.c20
-rw-r--r--src/host1x.h6
-rw-r--r--src/presentation_queue_target.c5
-rw-r--r--src/surface.c74
-rw-r--r--src/surface_shared.c42
-rw-r--r--src/tegra_stream.c11
-rw-r--r--src/uapi/tegra-vde.h4
-rw-r--r--src/vdpau_tegra.h2
10 files changed, 189 insertions, 26 deletions
diff --git a/configure.ac b/configure.ac
index 03b5de6..1157598 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,6 +9,9 @@ AC_CONFIG_AUX_DIR(.)
AM_INIT_AUTOMAKE([foreign subdir-objects])
+# enable quiet compiles on automake 1.11
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
AM_DISABLE_STATIC
# Checks for programs.
diff --git a/src/decoder.c b/src/decoder.c
index 78f90a2..f27ec7e 100644
--- a/src/decoder.c
+++ b/src/decoder.c
@@ -53,7 +53,7 @@ static struct drm_tegra_bo *alloc_data(tegra_decoder *dec, void **map,
struct drm_tegra_bo *bo;
int ret;
- ret = drm_tegra_bo_new(&bo, dec->dev->drm, 0, size);
+ ret = drm_tegra_bo_new(&bo, dec->dev->drm, DRM_TEGRA_GEM_CONTIGUOUS, size);
if (ret < 0) {
return NULL;
@@ -66,13 +66,15 @@ static struct drm_tegra_bo *alloc_data(tegra_decoder *dec, void **map,
return NULL;
}
- ret = drm_tegra_bo_to_dmabuf(bo, (uint32_t *) dmabuf_fd);
+ ret = drm_tegra_bo_export(bo, 0);
if (ret < 0) {
drm_tegra_bo_unref(bo);
return NULL;
}
+ *dmabuf_fd = ret;
+
return bo;
}
@@ -174,6 +176,28 @@ static VdpStatus copy_bitstream_to_dmabuf(tegra_decoder *dec,
return VDP_STATUS_ERROR;
}
+static int setup_secure_data(tegra_decoder *dec, struct drm_tegra_bo **bop,
+ int *fdp)
+{
+ struct drm_tegra_bo *bo;
+ int err, fd;
+
+ err = drm_tegra_bo_new(&bo, dec->dev->drm, DRM_TEGRA_GEM_CONTIGUOUS, 4096);
+ if (err < 0)
+ return err;
+
+ fd = drm_tegra_bo_export(bo, 0);
+ if (fd < 0) {
+ drm_tegra_bo_unref(bo);
+ return fd;
+ }
+
+ *bop = bo;
+ *fdp = fd;
+
+ return 0;
+}
+
static int get_refs_sorted(struct tegra_vde_h264_frame *dpb_frames,
VdpReferenceFrameH264 const *referenceFrames,
int frame_num_wrap, int32_t max_frame_num,
@@ -371,7 +395,7 @@ static int get_slice_type(bitstream_reader *reader)
static VdpStatus tegra_decode_h264(tegra_decoder *dec, tegra_surface *surf,
VdpPictureInfoH264 const *info,
- int bitstream_data_fd,
+ int bitstream_data_fd, int secure_fd,
bitstream_reader *reader)
{
struct tegra_vde_h264_decoder_ctx ctx;
@@ -436,6 +460,8 @@ static VdpStatus tegra_decode_h264(tegra_decoder *dec, tegra_surface *surf,
ctx.bitstream_data_fd = bitstream_data_fd;
ctx.bitstream_data_offset = 0;
+ ctx.secure_fd = secure_fd;
+ ctx.secure_offset = 0;
ctx.dpb_frames_nb = 1 + refs_num;
ctx.dpb_frames_ptr = (uintptr_t) dpb_frames;
ctx.dpb_ref_frames_with_earlier_poc_nb = ref_frames_with_earlier_poc_num;
@@ -612,9 +638,9 @@ VdpStatus vdp_decoder_render(VdpDecoder decoder,
{
tegra_decoder *dec = get_decoder(decoder);
tegra_surface *orig, *surf = get_surface(target);
- struct drm_tegra_bo *bitstream_bo;
+ struct drm_tegra_bo *bitstream_bo, *secure_bo = NULL;
bitstream_reader bitstream_reader;
- int bitstream_data_fd;
+ int bitstream_data_fd, secure_fd = -1;
VdpStatus ret;
if (dec == NULL || surf == NULL) {
@@ -633,6 +659,14 @@ VdpStatus vdp_decoder_render(VdpDecoder decoder,
return ret;
}
+ ret = setup_secure_data(dec, &secure_bo, &secure_fd);
+ if (ret < 0) {
+ free_data(bitstream_bo, bitstream_data_fd);
+ put_surface(surf);
+ put_decoder(dec);
+ return VDP_STATUS_ERROR;
+ }
+
orig = surf;
surf = shared_surface_swap_video(surf);
@@ -642,9 +676,11 @@ VdpStatus vdp_decoder_render(VdpDecoder decoder,
}
ret = tegra_decode_h264(dec, surf, picture_info,
- bitstream_data_fd, &bitstream_reader);
+ bitstream_data_fd, secure_fd,
+ &bitstream_reader);
free_data(bitstream_bo, bitstream_data_fd);
+ free_data(secure_bo, secure_fd);
if (ret != VDP_STATUS_OK) {
put_surface(surf);
diff --git a/src/host1x-pixelbuffer.c b/src/host1x-pixelbuffer.c
index a201bd6..19bdf37 100644
--- a/src/host1x-pixelbuffer.c
+++ b/src/host1x-pixelbuffer.c
@@ -38,7 +38,7 @@ struct host1x_pixelbuffer *host1x_pixelbuffer_create(struct drm_tegra *drm,
enum layout_format layout)
{
struct host1x_pixelbuffer *pixbuf;
- uint32_t flags = 0;
+ uint32_t flags = DRM_TEGRA_GEM_CONTIGUOUS;
uint32_t y_size;
uint32_t uv_size;
uint32_t bo_size;
@@ -75,6 +75,24 @@ struct host1x_pixelbuffer *host1x_pixelbuffer_create(struct drm_tegra *drm,
if (layout == PIX_BUF_LAYOUT_TILED_16x16)
height = ALIGN(height, 16);
+ if (layout == PIX_BUF_LAYOUT_BLOCK_16BX2_ONE_GOB)
+ height = ALIGN(height, 16);
+
+ if (layout == PIX_BUF_LAYOUT_BLOCK_16BX2_TWO_GOB)
+ height = ALIGN(height, 32);
+
+ if (layout == PIX_BUF_LAYOUT_BLOCK_16BX2_FOUR_GOB)
+ height = ALIGN(height, 64);
+
+ if (layout == PIX_BUF_LAYOUT_BLOCK_16BX2_EIGHT_GOB)
+ height = ALIGN(height, 128);
+
+ if (layout == PIX_BUF_LAYOUT_BLOCK_16BX2_SIXTEEN_GOB)
+ height = ALIGN(height, 256);
+
+ if (layout == PIX_BUF_LAYOUT_BLOCK_16BX2_THIRTYTWO_GOB)
+ height = ALIGN(height, 512);
+
y_size = pitch * height;
uv_size = pitch_uv * height / 2;
diff --git a/src/host1x.h b/src/host1x.h
index 27d3839..26803f0 100644
--- a/src/host1x.h
+++ b/src/host1x.h
@@ -88,6 +88,12 @@ enum pixel_format {
enum layout_format {
PIX_BUF_LAYOUT_LINEAR,
PIX_BUF_LAYOUT_TILED_16x16,
+ PIX_BUF_LAYOUT_BLOCK_16BX2_ONE_GOB,
+ PIX_BUF_LAYOUT_BLOCK_16BX2_TWO_GOB,
+ PIX_BUF_LAYOUT_BLOCK_16BX2_FOUR_GOB,
+ PIX_BUF_LAYOUT_BLOCK_16BX2_EIGHT_GOB,
+ PIX_BUF_LAYOUT_BLOCK_16BX2_SIXTEEN_GOB,
+ PIX_BUF_LAYOUT_BLOCK_16BX2_THIRTYTWO_GOB,
};
struct host1x_csc_params {
diff --git a/src/presentation_queue_target.c b/src/presentation_queue_target.c
index 5240b6f..c946f87 100644
--- a/src/presentation_queue_target.c
+++ b/src/presentation_queue_target.c
@@ -74,16 +74,19 @@ static void pqt_update_dri_pixbuf(tegra_pqt *pqt)
DebugMsg("width %d height %d\n", width, height);
- err = drm_tegra_bo_from_name(&bo, dev->drm, buf[0].names[0], 0);
+ err = drm_tegra_bo_open(&bo, dev->drm, buf[0].names[0], 0);
if (err) {
return;
}
+ /* XXX */
+ /*
err = drm_tegra_bo_forbid_caching(bo);
if (err) {
drm_tegra_bo_unref(bo);
return;
}
+ */
pqt->dri_pixbuf = host1x_pixelbuffer_wrap(&bo, width, height,
buf[0].pitch[0], 0,
diff --git a/src/surface.c b/src/surface.c
index 69c4404..a8c6ddf 100644
--- a/src/surface.c
+++ b/src/surface.c
@@ -17,6 +17,8 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include <drm_fourcc.h>
+
#include "vdpau_tegra.h"
static uint32_t get_unused_surface_id(void)
@@ -88,6 +90,9 @@ int alloc_surface_data(tegra_surface *surf)
uint32_t stride = ALIGN(width * 4, 16);
uint32_t *bo_flinks = NULL;
uint32_t *pitches = NULL;
+ uint32_t *offsets = NULL;
+ uint64_t *modifiers = NULL;
+ uint64_t modifier = DRM_FORMAT_MOD_LINEAR;
int ret;
if (!video) {
@@ -136,8 +141,39 @@ int alloc_surface_data(tegra_surface *surf)
}
if (video) {
+ enum layout_format layout = PIX_BUF_LAYOUT_LINEAR;
+
frame = surf->frame;
+ /* anything without gr2d supports block linear layout */
+ if (!dev->gr2d) {
+ if (height % 512 == 0) {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB;
+ layout = PIX_BUF_LAYOUT_BLOCK_16BX2_THIRTYTWO_GOB;
+ frame->block_height = 5;
+ } else if (height % 256 == 0) {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB;
+ layout = PIX_BUF_LAYOUT_BLOCK_16BX2_SIXTEEN_GOB;
+ frame->block_height = 4;
+ } else if (height % 128 == 0) {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB;
+ layout = PIX_BUF_LAYOUT_BLOCK_16BX2_EIGHT_GOB;
+ frame->block_height = 3;
+ } else if (height % 64 == 0) {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB;
+ layout = PIX_BUF_LAYOUT_BLOCK_16BX2_FOUR_GOB;
+ frame->block_height = 2;
+ } else if (height % 32 == 0) {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB;
+ layout = PIX_BUF_LAYOUT_BLOCK_16BX2_TWO_GOB;
+ frame->block_height = 1;
+ } else {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB;
+ layout = PIX_BUF_LAYOUT_BLOCK_16BX2_ONE_GOB;
+ frame->block_height = 0;
+ }
+ }
+
frame->y_fd = -1;
frame->cb_fd = -1;
frame->cr_fd = -1;
@@ -148,7 +184,7 @@ int alloc_surface_data(tegra_surface *surf)
ALIGN(width, 16),
ALIGN(width, 32) / 2,
PIX_BUF_FMT_YV12,
- PIX_BUF_LAYOUT_LINEAR);
+ layout);
if (pixbuf == NULL) {
ret = -ENOMEM;
goto err_cleanup;
@@ -160,12 +196,14 @@ int alloc_surface_data(tegra_surface *surf)
/* luma plane */
- ret = drm_tegra_bo_to_dmabuf(surf->y_bo, (uint32_t *) &frame->y_fd);
+ ret = drm_tegra_bo_export(surf->y_bo, 0);
if (ret < 0) {
goto err_cleanup;
}
+ frame->y_fd = ret;
+
ret = drm_tegra_bo_map(surf->y_bo, &surf->y_data);
if (ret < 0) {
@@ -174,12 +212,14 @@ int alloc_surface_data(tegra_surface *surf)
/* blue plane */
- ret = drm_tegra_bo_to_dmabuf(surf->cb_bo, (uint32_t *) &frame->cb_fd);
+ ret = drm_tegra_bo_export(surf->cb_bo, 0);
if (ret < 0) {
goto err_cleanup;
}
+ frame->cb_fd = ret;
+
ret = drm_tegra_bo_map(surf->cb_bo, &surf->cb_data);
if (ret < 0) {
@@ -191,12 +231,14 @@ int alloc_surface_data(tegra_surface *surf)
/* red plane */
- ret = drm_tegra_bo_to_dmabuf(surf->cr_bo, (uint32_t *) &frame->cr_fd);
+ ret = drm_tegra_bo_export(surf->cr_bo, 0);
if (ret < 0) {
goto err_cleanup;
}
+ frame->cr_fd = ret;
+
ret = drm_tegra_bo_map(surf->cr_bo, &surf->cr_data);
if (ret < 0) {
@@ -208,17 +250,19 @@ int alloc_surface_data(tegra_surface *surf)
/* aux stuff */
- ret = drm_tegra_bo_new(&surf->aux_bo, dev->drm, 0,
+ ret = drm_tegra_bo_new(&surf->aux_bo, dev->drm, DRM_TEGRA_GEM_CONTIGUOUS,
ALIGN(width, 16) * ALIGN(height, 16) / 4);
if (ret < 0) {
goto err_cleanup;
}
- ret = drm_tegra_bo_to_dmabuf(surf->aux_bo, (uint32_t *) &frame->aux_fd);
+ ret = drm_tegra_bo_export(surf->aux_bo, 0);
if (ret < 0) {
goto err_cleanup;
}
+
+ frame->aux_fd = ret;
}
if (output && !tegra_vdpau_force_dri) {
@@ -263,9 +307,23 @@ int alloc_surface_data(tegra_surface *surf)
goto err_cleanup;
}
- pitches = (uint32_t *) (xv_img->data + 12);
-
+ pitches = (uint32_t *)(xv_img->data + 16);
pitches[0] = pixbuf->pitch;
+ pitches[1] = 0;
+ pitches[2] = 0;
+ pitches[3] = 0;
+
+ offsets = (uint32_t *)(xv_img->data + 32);
+ offsets[0] = pixbuf->bo_offset[0];
+ offsets[1] = 0;
+ offsets[2] = 0;
+ offsets[3] = 0;
+
+ modifiers = (uint64_t *)(xv_img->data + 48);
+ modifiers[0] = modifier;
+ modifiers[1] = 0;
+ modifiers[2] = 0;
+ modifiers[3] = 0;
}
surf->pix = pix;
diff --git a/src/surface_shared.c b/src/surface_shared.c
index adc5741..89270a7 100644
--- a/src/surface_shared.c
+++ b/src/surface_shared.c
@@ -17,16 +17,20 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include <drm_fourcc.h>
+
#include "vdpau_tegra.h"
static pthread_mutex_t shared_lock = PTHREAD_MUTEX_INITIALIZER;
static XvImage * create_video_xv(tegra_surface *video)
{
+ struct tegra_vde_h264_frame *frame = video->frame;
XvImage *xv_img;
uint32_t *bo_flinks;
uint32_t *pitches;
uint32_t *offsets;
+ uint64_t *modifiers, modifier;
if (tegra_vdpau_force_dri) {
return NULL;
@@ -39,6 +43,31 @@ static XvImage * create_video_xv(tegra_surface *video)
return NULL;
}
+ /* anything without gr2d supports block linear layout */
+ if (!video->dev->gr2d) {
+ if (video->height % 512 == 0) {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB;
+ frame->block_height = 5;
+ } else if (video->height % 256 == 0) {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB;
+ frame->block_height = 4;
+ } else if (video->height % 128 == 0) {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB;
+ frame->block_height = 3;
+ } else if (video->height % 64 == 0) {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB;
+ frame->block_height = 2;
+ } else if (video->height % 32 == 0) {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB;
+ frame->block_height = 1;
+ } else {
+ modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB;
+ frame->block_height = 0;
+ }
+ } else {
+ modifier = DRM_FORMAT_MOD_LINEAR;
+ }
+
xv_img->data = calloc(1, xv_img->data_size);
if (!xv_img->data) {
@@ -47,20 +76,29 @@ static XvImage * create_video_xv(tegra_surface *video)
}
bo_flinks = (uint32_t*) (xv_img->data + 0);
- pitches = (uint32_t*) (xv_img->data + 12);
- offsets = (uint32_t*) (xv_img->data + 24);
+ pitches = (uint32_t*) (xv_img->data + 16);
+ offsets = (uint32_t*) (xv_img->data + 32);
+ modifiers = (uint64_t*) (xv_img->data + 48);
drm_tegra_bo_get_name(video->y_bo, &bo_flinks[0]);
drm_tegra_bo_get_name(video->cb_bo, &bo_flinks[1]);
drm_tegra_bo_get_name(video->cr_bo, &bo_flinks[2]);
+ bo_flinks[3] = 0;
pitches[0] = video->pixbuf->pitch;
pitches[1] = video->pixbuf->pitch_uv;
pitches[2] = video->pixbuf->pitch_uv;
+ pitches[3] = 0;
offsets[0] = video->pixbuf->bo_offset[0];
offsets[1] = video->pixbuf->bo_offset[1];
offsets[2] = video->pixbuf->bo_offset[2];
+ offsets[3] = 0;
+
+ modifiers[0] = modifier;
+ modifiers[1] = modifier;
+ modifiers[2] = modifier;
+ modifiers[3] = 0;
return xv_img;
}
diff --git a/src/tegra_stream.c b/src/tegra_stream.c
index a623fa3..03b4f29 100644
--- a/src/tegra_stream.c
+++ b/src/tegra_stream.c
@@ -73,7 +73,6 @@ void tegra_stream_destroy(struct tegra_stream *stream)
int tegra_stream_flush(struct tegra_stream *stream)
{
- struct drm_tegra_fence *fence;
int result = 0;
if (!stream)
@@ -89,21 +88,19 @@ int tegra_stream_flush(struct tegra_stream *stream)
goto cleanup;
}
- result = drm_tegra_job_submit(stream->job, &fence);
+ result = drm_tegra_job_submit(stream->job, 1000);
if (result != 0) {
ErrorMsg("drm_tegra_job_submit() failed %d\n", result);
result = -1;
goto cleanup;
}
- result = drm_tegra_fence_wait_timeout(fence, 1000);
+ result = drm_tegra_job_wait(stream->job);
if (result != 0) {
ErrorMsg("drm_tegra_fence_wait_timeout() failed %d\n", result);
result = -1;
}
- drm_tegra_fence_free(fence);
-
cleanup:
drm_tegra_job_free(stream->job);
@@ -265,8 +262,8 @@ int tegra_stream_end(struct tegra_stream *stream)
return -1;
}
- ret = drm_tegra_pushbuf_sync(stream->buffer.pushbuf,
- DRM_TEGRA_SYNCPT_COND_OP_DONE);
+ ret = drm_tegra_pushbuf_sync(stream->buffer.pushbuf, 0, 1,
+ DRM_TEGRA_SYNC_COND_OP_DONE);
if (ret != 0) {
stream->status = TEGRADRM_STREAM_CONSTRUCTION_FAILED;
ErrorMsg("drm_tegra_pushbuf_sync() failed %d\n", ret);
diff --git a/src/uapi/tegra-vde.h b/src/uapi/tegra-vde.h
index 8502032..7ddb684 100644
--- a/src/uapi/tegra-vde.h
+++ b/src/uapi/tegra-vde.h
@@ -46,6 +46,7 @@ struct tegra_vde_h264_frame {
__u32 aux_offset;
__u32 frame_num;
__u32 flags;
+ __u32 block_height;
__u32 reserved;
} __attribute__((packed));
@@ -54,6 +55,9 @@ struct tegra_vde_h264_decoder_ctx {
__s32 bitstream_data_fd;
__u32 bitstream_data_offset;
+ __s32 secure_fd;
+ __u32 secure_offset;
+
__u64 dpb_frames_ptr;
__u8 dpb_frames_nb;
__u8 dpb_ref_frames_with_earlier_poc_nb;
diff --git a/src/vdpau_tegra.h b/src/vdpau_tegra.h
index c524eae..b0571b3 100644
--- a/src/vdpau_tegra.h
+++ b/src/vdpau_tegra.h
@@ -88,7 +88,7 @@
#define SURFACE_DATA_NEEDS_SYNC (1 << 2)
#define SURFACE_OUTPUT (1 << 3)
-#define PASSTHROUGH_DATA_SIZE 36
+#define PASSTHROUGH_DATA_SIZE 80
#define FOURCC_PASSTHROUGH_YV12 (('1' << 24) + ('2' << 16) + ('V' << 8) + 'Y')
#define FOURCC_PASSTHROUGH_XRGB565 (('1' << 24) + ('B' << 16) + ('G' << 8) + 'R')