diff options
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | src/decoder.c | 48 | ||||
-rw-r--r-- | src/host1x-pixelbuffer.c | 20 | ||||
-rw-r--r-- | src/host1x.h | 6 | ||||
-rw-r--r-- | src/presentation_queue_target.c | 5 | ||||
-rw-r--r-- | src/surface.c | 74 | ||||
-rw-r--r-- | src/surface_shared.c | 42 | ||||
-rw-r--r-- | src/tegra_stream.c | 11 | ||||
-rw-r--r-- | src/uapi/tegra-vde.h | 4 | ||||
-rw-r--r-- | src/vdpau_tegra.h | 2 |
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') |