From 09b01bee078e4ac287c673dfa2b365d3de158213 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 4 May 2018 17:58:42 +0200 Subject: Add support for Tegra124 Signed-off-by: Thierry Reding --- src/dri2.c | 2 ++ src/drm_plane.c | 81 +++++++++++++++++++++++++-------------------- src/drm_plane.h | 3 +- src/drmmode_display.h | 4 +++ src/exa.c | 54 +++++++++++++++--------------- src/gr3d.c | 4 +-- src/tegra_stream.c | 91 +++++++++++++++++++++++++++++++++------------------ src/tegra_stream.h | 16 +++++---- src/xv.c | 28 +++++++++++----- src/xv.h | 2 +- 10 files changed, 174 insertions(+), 111 deletions(-) diff --git a/src/dri2.c b/src/dri2.c index c734dc7..b2f3dc6 100644 --- a/src/dri2.c +++ b/src/dri2.c @@ -183,7 +183,9 @@ tegra_dri2_create_buffer(DrawablePtr drawable, unsigned int attachment, return NULL; } + /* drm_tegra_bo_forbid_caching(tegra->bo); + */ buffer->pitch = pixmap->devKind; buffer->driverPrivate = private; diff --git a/src/drm_plane.c b/src/drm_plane.c index 0e57853..9de5214 100644 --- a/src/drm_plane.c +++ b/src/drm_plane.c @@ -24,8 +24,6 @@ #include "driver.h" -#define FD_INVALID UINT32_MAX - #define MUNMAP_VERBOSE(PTR, SIZE) \ if (PTR && munmap(PTR, page_align(SIZE)) != 0) \ FatalError("%s: " #PTR " munmap failed: %s\n", \ @@ -158,7 +156,7 @@ static uint32_t create_gem(int drm_fd, uint32_t size) if (ret) { ErrorMsg("Failed to create GEM[0]: %s\n", strerror(-ret)); - return FD_INVALID; + return 0; } return gem.handle; @@ -178,70 +176,84 @@ static void close_gem(int drm_fd, uint32_t handle) static drm_overlay_fb * drm_create_fb_internal(int drm_fd, uint32_t drm_format, uint32_t width, uint32_t height, - uint32_t *bo_handles, + uint32_t *handles, uint32_t *pitches, - uint32_t *offsets) + uint32_t *offsets, + uint64_t *modifiers) { drm_overlay_fb *fb = NULL; - uint32_t fb_id = FD_INVALID; + uint32_t fb_id = 0; Bool from_handle; + unsigned int i; int ret; if (width == 0 || height == 0) return NULL; - from_handle = !!(bo_handles); + from_handle = !!handles; if (from_handle) goto create_framebuffer; - bo_handles = alloca(sizeof(uint32_t) * 3); - if (!bo_handles) + handles = alloca(sizeof(uint32_t) * 4); + if (!handles) return NULL; - pitches = alloca(sizeof(uint32_t) * 3); + pitches = alloca(sizeof(uint32_t) * 4); if (!pitches) return NULL; - offsets = alloca(sizeof(uint32_t) * 3); + offsets = alloca(sizeof(uint32_t) * 4); if (!offsets) return NULL; pitches[0] = fb_pitch(drm_format, width); pitches[1] = fb_pitch_c(drm_format, width); pitches[2] = fb_pitch_c(drm_format, width); + pitches[3] = 0; offsets[0] = 0; offsets[1] = 0; offsets[2] = 0; + offsets[3] = 0; - bo_handles[1] = FD_INVALID; - bo_handles[2] = FD_INVALID; + handles[0] = 0; + handles[1] = 0; + handles[2] = 0; + handles[3] = 0; /* Allocate PLANE[0] */ - bo_handles[0] = create_gem(drm_fd, fb_size(drm_format, width, height)); + handles[0] = create_gem(drm_fd, fb_size(drm_format, width, height)); - if (bo_handles[0] == FD_INVALID) + if (!handles[0]) goto error_cleanup; if (!format_planar(drm_format)) goto create_framebuffer; /* Allocate PLANE[1] */ - bo_handles[1] = create_gem(drm_fd, fb_size_c(drm_format, width, height)); + handles[1] = create_gem(drm_fd, fb_size_c(drm_format, width, height)); - if (bo_handles[1] == FD_INVALID) + if (!handles[1]) goto error_cleanup; /* Allocate PLANE[2] */ - bo_handles[2] = create_gem(drm_fd, fb_size_c(drm_format, width, height)); + handles[2] = create_gem(drm_fd, fb_size_c(drm_format, width, height)); - if (bo_handles[2] == FD_INVALID) + if (!handles[2]) goto error_cleanup; create_framebuffer: - ret = drmModeAddFB2(drm_fd, width, height, drm_format, - bo_handles, pitches, offsets, &fb_id, 0); + if (modifiers) { + ret = drmModeAddFB2WithModifiers(drm_fd, width, height, drm_format, + handles, pitches, offsets, + modifiers, &fb_id, + DRM_MODE_FB_MODIFIERS); + } else { + ret = drmModeAddFB2(drm_fd, width, height, drm_format, handles, + pitches, offsets, &fb_id, 0); + } + if (ret) { ErrorMsg("Failed to create DRM framebuffer: %s\n", strerror(-ret)); goto error_cleanup; @@ -253,9 +265,9 @@ create_framebuffer: fb->format = drm_format; fb->width = width; fb->height = height; - fb->bo_y_id = bo_handles[0]; - fb->bo_cb_id = bo_handles[1]; - fb->bo_cr_id = bo_handles[2]; + fb->bo_y_id = handles[0]; + fb->bo_cb_id = handles[1]; + fb->bo_cr_id = handles[2]; if (from_handle) return fb; @@ -318,17 +330,13 @@ error_cleanup: free(fb); } - if (fb_id != FD_INVALID) + if (fb_id) drmModeRmFB(drm_fd, fb_id); - if (bo_handles[2] != FD_INVALID) - close_gem(drm_fd, bo_handles[2]); - - if (bo_handles[1] != FD_INVALID) - close_gem(drm_fd, bo_handles[1]); - - if (bo_handles[0] != FD_INVALID) - close_gem(drm_fd, bo_handles[0]); + for (i = 0; i < 3; i++) { + if (handles[2 - i]) + close_gem(drm_fd, handles[i]); + } return NULL; } @@ -337,17 +345,18 @@ drm_overlay_fb * drm_create_fb(int drm_fd, uint32_t drm_format, uint32_t width, uint32_t height) { return drm_create_fb_internal(drm_fd, drm_format, width, height, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); } drm_overlay_fb * drm_create_fb_from_handle(int drm_fd, uint32_t drm_format, uint32_t width, uint32_t height, uint32_t *bo_handles, uint32_t *pitches, - uint32_t *offsets) + uint32_t *offsets, + uint64_t *modifiers) { return drm_create_fb_internal(drm_fd, drm_format, width, height, - bo_handles, pitches, offsets); + bo_handles, pitches, offsets, modifiers); } void drm_free_overlay_fb(int drm_fd, drm_overlay_fb *fb) diff --git a/src/drm_plane.h b/src/drm_plane.h index 1d61c53..35b345f 100644 --- a/src/drm_plane.h +++ b/src/drm_plane.h @@ -51,7 +51,8 @@ drm_overlay_fb * drm_create_fb_from_handle(int drm_fd, uint32_t drm_format, uint32_t width, uint32_t height, uint32_t *bo_handles, uint32_t *pitches, - uint32_t *offsets); + uint32_t *offsets, + uint64_t *modifiers); void drm_free_overlay_fb(int drm_fd, drm_overlay_fb *fb); diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 2aca7f6..2c552e5 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -37,6 +37,10 @@ # endif #endif +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0) +# define DamageUnregister(d, dd) DamageUnregister(dd) +#endif + struct dumb_bo { struct drm_tegra_bo *bo; uint32_t handle; diff --git a/src/exa.c b/src/exa.c index be22404..85a4b63 100644 --- a/src/exa.c +++ b/src/exa.c @@ -354,9 +354,9 @@ unsigned int TegraEXAPitch(unsigned int width, unsigned int height, return TEGRA_PITCH_ALIGN(width, bpp, alignment); } -static void TegraEXAWaitFence(struct tegra_fence *fence) +static void TegraEXAWaitFence(TegraEXAPtr tegra, struct tegra_fence *fence) { - if (tegra_stream_wait_fence(fence) && !fence->gr2d) { + if (tegra_stream_wait_fence(&tegra->cmds, fence) && !fence->gr2d) { /* * XXX: A bit more optimal would be to release buffers * right after submitting the job, but then BO reservation @@ -384,7 +384,7 @@ static int TegraEXAMarkSync(ScreenPtr pScreen) * EXA may take marker multiple times, but it waits only for the * lastly taken marker, so we release the previous marker-fence here. */ - tegra_stream_put_fence(tegra->scratch.marker); + tegra_stream_put_fence(&tegra->cmds, tegra->scratch.marker); tegra->scratch.marker = data.fence; return data.marker; @@ -401,8 +401,8 @@ static void TegraEXAWaitMarker(ScreenPtr pScreen, int marker) data.marker = marker; - TegraEXAWaitFence(data.fence); - tegra_stream_put_fence(data.fence); + TegraEXAWaitFence(tegra, data.fence); + tegra_stream_put_fence(&tegra->cmds, data.fence); /* if it was a lastly-taken marker, then we've just released it */ if (data.fence == tegra->scratch.marker) @@ -489,7 +489,7 @@ static Bool TegraEXAAllocateMem(TegraPixmapPtr pixmap, unsigned int size) return pixmap->fallback != NULL; } -static void TegraEXAReleasePixmapData(TegraPixmapPtr priv) +static void TegraEXAReleasePixmapData(TegraEXAPtr tegra, TegraPixmapPtr priv) { /* * We have to await the fence to avoid BO re-use while job is in progress, @@ -497,8 +497,8 @@ static void TegraEXAReleasePixmapData(TegraPixmapPtr priv) * by kernel driver. */ if (priv->fence) { - TegraEXAWaitFence(priv->fence); - tegra_stream_put_fence(priv->fence); + TegraEXAWaitFence(tegra, priv->fence); + tegra_stream_put_fence(&tegra->cmds, priv->fence); priv->fence = NULL; } @@ -568,9 +568,11 @@ static void *TegraEXACreatePixmap2(ScreenPtr pScreen, int width, int height, static void TegraEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) { + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + TegraEXAPtr tegra = TegraPTR(pScrn)->exa; TegraPixmapPtr priv = driverPriv; - TegraEXAReleasePixmapData(priv); + TegraEXAReleasePixmapData(tegra, priv); free(priv); } @@ -590,7 +592,7 @@ static Bool TegraEXAModifyPixmapHeader(PixmapPtr pPixmap, int width, return FALSE; if (pPixData) { - TegraEXAReleasePixmapData(priv); + TegraEXAReleasePixmapData(tegra->exa, priv); if (pPixData == drmmode_map_front_bo(&tegra->drmmode)) { scanout = drmmode_get_front_bo(&tegra->drmmode); @@ -674,7 +676,7 @@ static void TegraEXASolid(PixmapPtr pPixmap, tegra_stream_push(&tegra->cmds, HOST1X_OPCODE_MASK(0x38, 0x5)); tegra_stream_push(&tegra->cmds, (py2 - py1) << 16 | (px2 - px1)); tegra_stream_push(&tegra->cmds, py1 << 16 | px1); - tegra_stream_sync(&tegra->cmds, DRM_TEGRA_SYNCPT_COND_OP_DONE); + tegra_stream_sync(&tegra->cmds, DRM_TEGRA_SYNC_COND_OP_DONE); tegra->scratch.ops++; } @@ -688,13 +690,13 @@ static void TegraEXADoneSolid(PixmapPtr pPixmap) if (tegra->scratch.ops && tegra->cmds.status == TEGRADRM_STREAM_CONSTRUCT) { if (priv->fence && !priv->fence->gr2d) - TegraEXAWaitFence(priv->fence); + TegraEXAWaitFence(tegra, priv->fence); tegra_stream_end(&tegra->cmds); fence = tegra_stream_submit(&tegra->cmds, true); if (priv->fence != fence) { - tegra_stream_put_fence(priv->fence); + tegra_stream_put_fence(&tegra->cmds, priv->fence); priv->fence = tegra_stream_ref_fence(fence, &tegra->scratch); } } else { @@ -808,7 +810,7 @@ static void TegraEXACopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, tegra_stream_push(&tegra->cmds, height << 16 | width); /* dstsize */ tegra_stream_push(&tegra->cmds, srcY << 16 | srcX); /* srcps */ tegra_stream_push(&tegra->cmds, dstY << 16 | dstX); /* dstps */ - tegra_stream_sync(&tegra->cmds, DRM_TEGRA_SYNCPT_COND_OP_DONE); + tegra_stream_sync(&tegra->cmds, DRM_TEGRA_SYNC_COND_OP_DONE); tegra->scratch.ops++; } @@ -825,22 +827,22 @@ static void TegraEXADoneCopy(PixmapPtr pDstPixmap) priv = exaGetPixmapDriverPrivate(tegra->scratch.pSrc); if (priv->fence && !priv->fence->gr2d) { - TegraEXAWaitFence(priv->fence); + TegraEXAWaitFence(tegra, priv->fence); - tegra_stream_put_fence(priv->fence); + tegra_stream_put_fence(&tegra->cmds, priv->fence); priv->fence = NULL; } } priv = exaGetPixmapDriverPrivate(pDstPixmap); if (priv->fence && !priv->fence->gr2d) - TegraEXAWaitFence(priv->fence); + TegraEXAWaitFence(tegra, priv->fence); tegra_stream_end(&tegra->cmds); fence = tegra_stream_submit(&tegra->cmds, true); if (priv->fence != fence) { - tegra_stream_put_fence(priv->fence); + tegra_stream_put_fence(&tegra->cmds, priv->fence); priv->fence = tegra_stream_ref_fence(fence, &tegra->scratch); } } else { @@ -1443,9 +1445,9 @@ static void TegraEXADoneComposite(PixmapPtr pDst) priv = exaGetPixmapDriverPrivate(tegra->scratch.pSrc); if (priv->fence && priv->fence->gr2d) { - TegraEXAWaitFence(priv->fence); + TegraEXAWaitFence(tegra, priv->fence); - tegra_stream_put_fence(priv->fence); + tegra_stream_put_fence(&tegra->cmds, priv->fence); priv->fence = NULL; } } @@ -1454,16 +1456,16 @@ static void TegraEXADoneComposite(PixmapPtr pDst) priv = exaGetPixmapDriverPrivate(tegra->scratch.pMask); if (priv->fence && priv->fence->gr2d) { - TegraEXAWaitFence(priv->fence); + TegraEXAWaitFence(tegra, priv->fence); - tegra_stream_put_fence(priv->fence); + tegra_stream_put_fence(&tegra->cmds, priv->fence); priv->fence = NULL; } } priv = exaGetPixmapDriverPrivate(pDst); if (priv->fence && priv->fence->gr2d) - TegraEXAWaitFence(priv->fence); + TegraEXAWaitFence(tegra, priv->fence); tegra_stream_end(&tegra->cmds); fence = tegra_stream_submit(&tegra->cmds, false); @@ -1480,7 +1482,7 @@ static void TegraEXADoneComposite(PixmapPtr pDst) * See TegraGR3D_DrawPrimitives() in gr3d.c */ if (priv->fence != fence) { - tegra_stream_put_fence(priv->fence); + tegra_stream_put_fence(&tegra->cmds, priv->fence); priv->fence = tegra_stream_ref_fence(fence, &tegra->scratch); } } else { @@ -1489,7 +1491,7 @@ static void TegraEXADoneComposite(PixmapPtr pDst) /* buffer reallocation could fail, cleanup it now */ if (tegra->scratch.attribs_alloc_err) { - tegra_stream_wait_fence(fence); + tegra_stream_wait_fence(&tegra->cmds, fence); TegraCompositeReleaseAttribBuffers(&tegra->scratch); tegra->scratch.attribs_alloc_err = FALSE; } @@ -1542,7 +1544,7 @@ void TegraEXAScreenInit(ScreenPtr pScreen) goto close_gr2d; } - err = tegra_stream_create(&priv->cmds); + err = tegra_stream_create(&priv->cmds, tegra->drm); if (err < 0) { ErrorMsg("failed to create command stream: %d\n", err); goto close_gr3d; diff --git a/src/gr3d.c b/src/gr3d.c index 9e8912d..29f2157 100644 --- a/src/gr3d.c +++ b/src/gr3d.c @@ -501,7 +501,7 @@ void TegraGR3D_DrawPrimitives(struct tegra_stream *cmds, * XXX: This requires proper waitcheck barrier, expect graphical * glitches due to not properly prefetched vertex / tex data. */ - tegra_stream_sync(cmds, DRM_TEGRA_SYNCPT_COND_RD_DONE); + tegra_stream_sync(cmds, DRM_TEGRA_SYNC_COND_RD_DONE); tegra_stream_prep(cmds, 2); @@ -511,7 +511,7 @@ void TegraGR3D_DrawPrimitives(struct tegra_stream *cmds, tegra_stream_push(cmds, HOST1X_OPCODE_INCR(TGR3D_DRAW_PRIMITIVES, 1)); tegra_stream_push(cmds, value); - tegra_stream_sync(cmds, DRM_TEGRA_SYNCPT_COND_OP_DONE); + tegra_stream_sync(cmds, DRM_TEGRA_SYNC_COND_OP_DONE); } static void TegraGR3D_UploadProgram(struct tegra_stream *cmds, diff --git a/src/tegra_stream.c b/src/tegra_stream.c index 92e5e6f..7f9b58f 100644 --- a/src/tegra_stream.c +++ b/src/tegra_stream.c @@ -25,6 +25,11 @@ * Arto Merilainen */ +#include +#include + +#include + #include "xorg-server.h" #include "xf86.h" @@ -44,9 +49,10 @@ * tegra_stream_push(). */ -int tegra_stream_create(struct tegra_stream *stream) +int tegra_stream_create(struct tegra_stream *stream, struct drm_tegra *drm) { stream->status = TEGRADRM_STREAM_FREE; + stream->drm = drm; return 0; } @@ -62,8 +68,8 @@ void tegra_stream_destroy(struct tegra_stream *stream) if (!stream) return; - tegra_stream_wait_fence(stream->last_fence); - tegra_stream_put_fence(stream->last_fence); + tegra_stream_wait_fence(stream, stream->last_fence); + tegra_stream_put_fence(stream, stream->last_fence); drm_tegra_job_free(stream->job); } @@ -91,14 +97,13 @@ int tegra_stream_cleanup(struct tegra_stream *stream) int tegra_stream_flush(struct tegra_stream *stream) { - struct drm_tegra_fence *fence; int result = 0; if (!stream) return -1; - tegra_stream_wait_fence(stream->last_fence); - tegra_stream_put_fence(stream->last_fence); + tegra_stream_wait_fence(stream, stream->last_fence); + tegra_stream_put_fence(stream, stream->last_fence); stream->last_fence = NULL; /* Reflushing is fine */ @@ -111,21 +116,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); + ErrorMsg("drm_tegra_job_wait() failed %d\n", result); result = -1; } - drm_tegra_fence_free(fence); - cleanup: tegra_stream_cleanup(stream); @@ -134,7 +137,6 @@ cleanup: struct tegra_fence * tegra_stream_submit(struct tegra_stream *stream, bool gr2d) { - struct drm_tegra_fence *fence; struct tegra_fence *f; int result; @@ -153,13 +155,39 @@ struct tegra_fence * tegra_stream_submit(struct tegra_stream *stream, bool gr2d) 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; } else { - f = tegra_stream_create_fence(fence, gr2d); - tegra_stream_put_fence(stream->last_fence); + unsigned int num_fences, count; + struct drm_fence *fences; + + num_fences = drm_tegra_job_get_fences(stream->job, NULL, 0); + if (num_fences == 0) { + result = -1; + goto cleanup; + } + + fences = calloc(num_fences, sizeof(*fences)); + if (!fences) { + result = -1; + goto cleanup; + } + + count = drm_tegra_job_get_fences(stream->job, fences, num_fences); + if (count != num_fences) { + result = -1; + goto cleanup; + } + + f = tegra_stream_create_fence(fences, num_fences, gr2d); + if (!f) { + result = -1; + goto cleanup; + } + + tegra_stream_put_fence(stream, stream->last_fence); stream->last_fence = f; } @@ -191,42 +219,43 @@ struct tegra_fence * tegra_stream_get_last_fence(struct tegra_stream *stream) return NULL; } -struct tegra_fence * tegra_stream_create_fence(struct drm_tegra_fence *fence, +struct tegra_fence * tegra_stream_create_fence(struct drm_fence *fences, + unsigned int num_fences, bool gr2d) { struct tegra_fence *f = calloc(1, sizeof(*f)); if (f) { - f->fence = fence; + f->num_fences = num_fences; + f->fences = fences; f->gr2d = gr2d; } return f; } -bool tegra_stream_wait_fence(struct tegra_fence *f) +bool tegra_stream_wait_fence(struct tegra_stream *stream, struct tegra_fence *f) { int result; - if (f && f->fence) { - result = drm_tegra_fence_wait_timeout(f->fence, 1000); + if (f && f->num_fences > 0) { + result = drm_tegra_wait_fences(stream->drm, f->fences, f->num_fences); if (result != 0) { - ErrorMsg("drm_tegra_fence_wait_timeout() failed %d\n", result); + ErrorMsg("drm_tegra_wait_fences() failed: %d\n", result); + return false; } - drm_tegra_fence_free(f->fence); - f->fence = NULL; - return true; } return false; } -void tegra_stream_put_fence(struct tegra_fence *f) +void tegra_stream_put_fence(struct tegra_stream *stream, struct tegra_fence *f) { if (f && --f->refcnt < 0) { - drm_tegra_fence_free(f->fence); + drm_tegra_put_fences(stream->drm, f->fences, f->num_fences); + free(f->fences); free(f); } } @@ -369,8 +398,8 @@ int tegra_stream_end(struct tegra_stream *stream) if (stream->op_done_synced) goto ready; - 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); @@ -480,7 +509,7 @@ int tegra_stream_prep(struct tegra_stream *stream, uint32_t words) } int tegra_stream_sync(struct tegra_stream *stream, - enum drm_tegra_syncpt_cond cond) + enum drm_tegra_sync_cond cond) { int ret; @@ -489,14 +518,14 @@ int tegra_stream_sync(struct tegra_stream *stream, return -1; } - ret = drm_tegra_pushbuf_sync(stream->buffer.pushbuf, cond); + ret = drm_tegra_pushbuf_sync(stream->buffer.pushbuf, 0, 1, cond); if (ret != 0) { stream->status = TEGRADRM_STREAM_CONSTRUCTION_FAILED; ErrorMsg("drm_tegra_pushbuf_sync() failed %d\n", ret); return -1; } - if (cond == DRM_TEGRA_SYNCPT_COND_OP_DONE) + if (cond == DRM_TEGRA_SYNC_COND_OP_DONE) stream->op_done_synced = true; return 0; diff --git a/src/tegra_stream.h b/src/tegra_stream.h index dc16b2c..0b60c5d 100644 --- a/src/tegra_stream.h +++ b/src/tegra_stream.h @@ -44,13 +44,16 @@ struct tegra_command_buffer { }; struct tegra_fence { - struct drm_tegra_fence *fence; + struct drm_fence *fences; + unsigned int num_fences; void *opaque; int refcnt; bool gr2d; }; struct tegra_stream { + struct drm_tegra *drm; + enum tegra_stream_status status; struct drm_tegra_job *job; @@ -70,7 +73,7 @@ struct tegra_reloc { }; /* Stream operations */ -int tegra_stream_create(struct tegra_stream *stream); +int tegra_stream_create(struct tegra_stream *stream, struct drm_tegra *drm); void tegra_stream_destroy(struct tegra_stream *stream); int tegra_stream_begin(struct tegra_stream *stream, struct drm_tegra_channel *channel); @@ -80,10 +83,11 @@ int tegra_stream_flush(struct tegra_stream *stream); struct tegra_fence * tegra_stream_submit(struct tegra_stream *stream, bool gr2d); struct tegra_fence * tegra_stream_ref_fence(struct tegra_fence *f, void *opaque); struct tegra_fence * tegra_stream_get_last_fence(struct tegra_stream *stream); -struct tegra_fence * tegra_stream_create_fence(struct drm_tegra_fence *fence, +struct tegra_fence * tegra_stream_create_fence(struct drm_fence *fences, + unsigned int num_fences, bool gr2d); -bool tegra_stream_wait_fence(struct tegra_fence *f); -void tegra_stream_put_fence(struct tegra_fence *f); +bool tegra_stream_wait_fence(struct tegra_stream *stream, struct tegra_fence *f); +void tegra_stream_put_fence(struct tegra_stream *stream, struct tegra_fence *f); int tegra_stream_push(struct tegra_stream *stream, uint32_t word); int tegra_stream_push_setclass(struct tegra_stream *stream, unsigned class_id); int tegra_stream_push_reloc(struct tegra_stream *stream, @@ -94,7 +98,7 @@ int tegra_stream_push_words(struct tegra_stream *stream, const void *addr, unsigned words, int num_relocs, ...); int tegra_stream_prep(struct tegra_stream *stream, uint32_t words); int tegra_stream_sync(struct tegra_stream *stream, - enum drm_tegra_syncpt_cond cond); + enum drm_tegra_sync_cond cond); int tegra_stream_pushf(struct tegra_stream *stream, float f); #endif diff --git a/src/xv.c b/src/xv.c index 725f445..3bc93b5 100644 --- a/src/xv.c +++ b/src/xv.c @@ -283,11 +283,12 @@ static Bool TegraVideoOverlayCreateFB(TegraVideoPtr priv, ScrnInfoPtr scrn, { TegraPtr tegra = TegraPTR(scrn); uint32_t *flinks = (uint32_t*) (passthrough_data + 0); - uint32_t *pitches = (uint32_t*) (passthrough_data + 12); - uint32_t *offsets = (uint32_t*) (passthrough_data + 24); - uint32_t bo_handles[3]; + uint32_t pitches[4]; + uint32_t offsets[4]; + uint32_t handles[4]; + uint64_t modifiers[4]; drm_overlay_fb *fb; - int i = 0; + unsigned int i; if (priv->fb && priv->fb->format == drm_format && @@ -304,21 +305,32 @@ static Bool TegraVideoOverlayCreateFB(TegraVideoPtr priv, ScrnInfoPtr scrn, } if (passthrough) { + for (i = 0; i < 3; i++) { + pitches[i] = ((uint32_t *)(passthrough_data + 16))[i]; + offsets[i] = ((uint32_t *)(passthrough_data + 32))[i]; + modifiers[i] = ((uint64_t *)(passthrough_data + 48))[i]; + } + + pitches[3] = offsets[3] = modifiers[3] = 0; + switch (drm_format) { case DRM_FORMAT_YUV420: i = 3; break; default: i = 1; + break; } for (; i > 0; i--) { - if (!TegraImportBo(scrn, flinks[i - 1], &bo_handles[i - 1])) + if (!TegraImportBo(scrn, flinks[i - 1], &handles[i - 1])) goto fail; } + handles[3] = 0; + fb = drm_create_fb_from_handle(tegra->fd, drm_format, width, height, - bo_handles, pitches, offsets); + handles, pitches, offsets, modifiers); } else { fb = drm_create_fb(tegra->fd, drm_format, width, height); } @@ -341,8 +353,8 @@ static Bool TegraVideoOverlayCreateFB(TegraVideoPtr priv, ScrnInfoPtr scrn, fail: ErrorMsg("Failed to create framebuffer\n"); - for (; i < TEGRA_ARRAY_SIZE(bo_handles) && i > 0; i--) { - TegraCloseBo(scrn, bo_handles[i - 1]); + for (; i < TEGRA_ARRAY_SIZE(handles) && i > 0; i--) { + TegraCloseBo(scrn, handles[i - 1]); } return FALSE; diff --git a/src/xv.h b/src/xv.h index 02af31e..347a479 100644 --- a/src/xv.h +++ b/src/xv.h @@ -28,7 +28,7 @@ #define TEGRA_VIDEO_OVERLAY_MAX_WIDTH 4096 #define TEGRA_VIDEO_OVERLAY_MAX_HEIGHT 4096 -#define PASSTHROUGH_DATA_SIZE 36 +#define PASSTHROUGH_DATA_SIZE 80 #define FOURCC_PASSTHROUGH_YV12 (('1' << 24) + ('2' << 16) + ('V' << 8) + 'Y') #define FOURCC_PASSTHROUGH_RGB565 (('1' << 24) + ('B' << 16) + ('G' << 8) + 'R') -- cgit v1.2.3