diff options
author | Thierry Reding <thierry.reding@avionic-design.de> | 2013-03-29 22:04:17 +0100 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2014-07-09 11:45:02 +0200 |
commit | 5a34d67fca3e93b3fae71501d346e45ac2775c06 (patch) | |
tree | caf1260795186112146d7954bba7755b42c7116e | |
parent | d08109dde59b0f1ed40fe76e4a5ee53029e7a574 (diff) |
Only solid fills and copies are supported, but composite paths should be
relatively easy to do as well.
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
[kwizart@gmail.com: distribute missing header files]
Signed-off-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/driver.c | 7 | ||||
-rw-r--r-- | src/driver.h | 9 | ||||
-rw-r--r-- | src/exa.c | 683 | ||||
-rw-r--r-- | src/exa.h | 42 | ||||
-rw-r--r-- | src/host1x.h | 45 |
6 files changed, 789 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 907249d..5cee747 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -36,4 +36,7 @@ opentegra_drv_la_SOURCES = \ driver.c \ driver.h \ drmmode_display.c \ - drmmode_display.h + drmmode_display.h \ + exa.c \ + exa.h \ + host1x.h diff --git a/src/driver.c b/src/driver.c index 66dc3f2..9cd2f45 100644 --- a/src/driver.c +++ b/src/driver.c @@ -455,7 +455,8 @@ TegraPreInit(ScrnInfoPtr pScrn, int flags) xf86SetDpi(pScrn, 0, 0); /* Load the required sub modules */ - if (!xf86LoadSubModule(pScrn, "fb")) + if (!xf86LoadSubModule(pScrn, "exa") || + !xf86LoadSubModule(pScrn, "fb")) return FALSE; if (tegra->drmmode.shadow_enable) { @@ -601,6 +602,8 @@ TegraCloseScreen(CLOSE_SCREEN_ARGS_DECL) if (pScrn->vtSema) TegraLeaveVT(VT_FUNC_ARGS); + TegraEXAScreenExit(pScreen); + drm_tegra_close(tegra->drm); pScreen->CreateScreenResources = tegra->createScreenResources; @@ -720,6 +723,8 @@ TegraScreenInit(SCREEN_INIT_ARGS_DECL) HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | HARDWARE_CURSOR_ARGB); + TegraEXAScreenInit(pScreen); + /* Must force it before EnterVT, so we are in control of VT and * later memory should be bound when allocating, e.g rotate_mem */ pScrn->vtSema = TRUE; diff --git a/src/driver.h b/src/driver.h index 15d4e4c..04f7393 100644 --- a/src/driver.h +++ b/src/driver.h @@ -34,6 +34,11 @@ #include "compat-api.h" #include "drmmode_display.h" +#include "exa.h" + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif typedef struct { @@ -65,8 +70,12 @@ typedef struct _TegraRec DamagePtr damage; Bool dirty_enabled; + TegraEXAPtr exa; } TegraRec, *TegraPtr; #define TegraPTR(p) ((TegraPtr)((p)->driverPrivate)) +void TegraEXAScreenInit(ScreenPtr pScreen); +void TegraEXAScreenExit(ScreenPtr pScreen); + /* vim: set et sts=4 sw=4 ts=4: */ diff --git a/src/exa.c b/src/exa.c new file mode 100644 index 0000000..150530f --- /dev/null +++ b/src/exa.c @@ -0,0 +1,683 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * 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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "xf86.h" + +#include "host1x.h" +#include "driver.h" +#include "exa.h" + +#define EXA_ALIGN(offset, align) \ + (((offset) + (align) - 1) & ~((align) - 1)) + +#define ErrorMsg(fmt, args...) \ + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s(), line %d: " fmt, __func__, \ + __LINE__, ##args) + +static const uint8_t rop3[] = { + 0x00, /* GXclear */ + 0x88, /* GXand */ + 0x44, /* GXandReverse */ + 0xcc, /* GXcopy */ + 0x22, /* GXandInverted */ + 0xaa, /* GXnoop */ + 0x66, /* GXxor */ + 0xee, /* GXor */ + 0x11, /* GXnor */ + 0x99, /* GXequiv */ + 0x55, /* GXinvert */ + 0xdd, /* GXorReverse */ + 0x33, /* GXcopyInverted */ + 0xbb, /* GXorInverted */ + 0x77, /* GXnand */ + 0xff, /* GXset */ +}; + +typedef struct { + struct drm_tegra_bo *bo; +} TegraPixmapRec, *TegraPixmapPtr; + +static inline unsigned int TegraEXAPitch(unsigned int width, unsigned int bpp) +{ + unsigned int pitch; + + /* + * Alignment to 16 bytes isn't strictly necessary for all buffers, but + * there are cases where X's software rendering fallbacks crash when a + * buffer's pitch is too small (which happens for very small, low-bpp + * pixmaps). + */ + pitch = EXA_ALIGN(width * bpp / 8, 16); + if (!pitch) + pitch = 16; + + return pitch; +} + +static int TegraEXAMarkSync(ScreenPtr pScreen) +{ + /* TODO: implement */ + + return 0; +} + +static void TegraEXAWaitMarker(ScreenPtr pScreen, int marker) +{ + /* TODO: implement */ +} + +static Bool TegraEXAPrepareAccess(PixmapPtr pPix, int index) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen); + TegraPixmapPtr priv = exaGetPixmapDriverPrivate(pPix); + int err; + + err = drm_tegra_bo_map(priv->bo, &pPix->devPrivate.ptr); + if (err < 0) { + ErrorMsg("failed to map buffer object: %d\n", err); + return FALSE; + } + + return TRUE; +} + +static void TegraEXAFinishAccess(PixmapPtr pPix, int index) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen); + TegraPixmapPtr priv = exaGetPixmapDriverPrivate(pPix); + int err; + + err = drm_tegra_bo_unmap(priv->bo); + if (err < 0) + ErrorMsg("failed to unmap buffer object: %d\n", err); +} + +static Bool TegraEXAPixmapIsOffscreen(PixmapPtr pPix) +{ + TegraPixmapPtr priv = exaGetPixmapDriverPrivate(pPix); + + return priv && priv->bo; +} + +static void *TegraEXACreatePixmap2(ScreenPtr pScreen, int width, int height, + int depth, int usage_hint, int bitsPerPixel, + int *new_fb_pitch) +{ + TegraPixmapPtr pixmap; + + pixmap = calloc(1, sizeof(*pixmap)); + if (!pixmap) + return NULL; + + /* + * Alignment to 16 bytes isn't strictly necessary for all buffers, but + * there are cases where X's software rendering fallbacks crash when a + * buffer's pitch is too small (which happens for very small, low-bpp + * pixmaps). + */ + *new_fb_pitch = TegraEXAPitch(width, bitsPerPixel); + + return pixmap; +} + +static void TegraEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) +{ + TegraPixmapPtr priv = driverPriv; + + drm_tegra_bo_put(priv->bo); + free(priv); +} + +static Bool TegraEXAModifyPixmapHeader(PixmapPtr pPixmap, int width, + int height, int depth, int bitsPerPixel, + int devKind, pointer pPixData) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen); + TegraPixmapPtr priv = exaGetPixmapDriverPrivate(pPixmap); + TegraPtr tegra = TegraPTR(pScrn); + unsigned int bpp, stride, size; + Bool ret; + int err; + + ret = miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, + devKind, pPixData); + if (!ret) + return ret; + + if (pPixData) { + void *scanout; + + scanout = drmmode_map_front_bo(&tegra->drmmode); + + if (pPixData == scanout) { + uint32_t handle = tegra->drmmode.front_bo->handle; + + size = pPixmap->drawable.width * pPixmap->drawable.height * + pPixmap->drawable.bitsPerPixel / 8; + + err = drm_tegra_bo_wrap(&priv->bo, tegra->drm, handle, 0, size); + if (err < 0) + return FALSE; + + return TRUE; + } + + /* + * The pixmap can't be used for hardware acceleration, so dispose of + * it. + */ + pPixmap->devPrivate.ptr = pPixData; + pPixmap->devKind = devKind; + + drm_tegra_bo_put(priv->bo); + priv->bo = NULL; + + return FALSE; + } + + width = pPixmap->drawable.width; + height = pPixmap->drawable.height; + depth = pPixmap->drawable.depth; + bpp = pPixmap->drawable.bitsPerPixel; + stride = TegraEXAPitch(width, bpp); + size = stride * height; + + if (!priv->bo) { + err = drm_tegra_bo_new(&priv->bo, tegra->drm, 0, size); + if (err < 0) { + ErrorMsg("failed to allocate %ux%u (%zu) buffer object: %d\n", + width, height, size, err); + return FALSE; + } + } + + return TRUE; +} + +static Bool TegraEXAPrepareSolid(PixmapPtr pPixmap, int op, Pixel planemask, + Pixel color) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen); + TegraPixmapPtr priv = exaGetPixmapDriverPrivate(pPixmap); + unsigned int bpp = pPixmap->drawable.bitsPerPixel; + TegraEXAPtr tegra = TegraPTR(pScrn)->exa; + struct drm_tegra_pushbuf *pushbuf; + uint32_t value, rop; + int err; + + if (!tegra->gr2d) + return FALSE; + + /* + * It should be possible to support all GX* raster operations given the + * mapping in the rop3 table, but none other than GXcopy have been + * validated. + */ + if (op != GXcopy) + return FALSE; + + rop = rop3[op]; + + /* + * Support only 32-bit fills for now. Adding support for 16-bit fills + * should be easy. + */ + if (bpp != 32 && bpp != 16) + return FALSE; + + err = drm_tegra_job_new(&tegra->job, tegra->gr2d); + if (err < 0) { + ErrorMsg("failed to create job: %d\n", err); + return FALSE; + } + + err = drm_tegra_pushbuf_new(&tegra->pushbuf, tegra->job); + if (err < 0) { + ErrorMsg("failed to create push buffer: %d\n", err); + goto free_job; + } + + err = drm_tegra_pushbuf_prepare(tegra->pushbuf, 16); + if (err < 0) { + ErrorMsg("failed to prepare push buffer: %d\n", err); + goto free_job; + } + + pushbuf = tegra->pushbuf; + + *pushbuf->ptr++ = HOST1X_OPCODE_SETCL(0, HOST1X_CLASS_GR2D, 0); + *pushbuf->ptr++ = HOST1X_OPCODE_MASK(0x9, 0x9); + *pushbuf->ptr++ = 0x0000003a; + *pushbuf->ptr++ = 0x00000000; + + *pushbuf->ptr++ = HOST1X_OPCODE_NONINCR(0x35, 1); + *pushbuf->ptr++ = color; + + /* 4 or 2 bytes per pixel */ + if (bpp == 32) + value = 2 << 16; + else + value = 1 << 16; + + /* fill mode, turbo-fill */ + value |= (1 << 6) | (1 << 2); + + *pushbuf->ptr++ = HOST1X_OPCODE_MASK(0x1e, 0x7); + *pushbuf->ptr++ = 0x00000000; /* controlsecond */ + *pushbuf->ptr++ = value; /* controlmain */ + *pushbuf->ptr++ = rop; /* ropfade */ + + *pushbuf->ptr++ = HOST1X_OPCODE_MASK(0x2b, 0x9); + + /* relocate destination buffer */ + err = drm_tegra_pushbuf_relocate(pushbuf, priv->bo, 0, 0); + if (err < 0) + goto free_job; + + *pushbuf->ptr++ = exaGetPixmapPitch(pPixmap); + + /* non-tiled */ + *pushbuf->ptr++ = HOST1X_OPCODE_NONINCR(0x46, 1); + *pushbuf->ptr++ = 0; + + return TRUE; + +free_job: + drm_tegra_job_free(tegra->job); + tegra->pushbuf = NULL; + tegra->job = NULL; + + return FALSE; +} + +static void TegraEXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen); + TegraEXAPtr tegra = TegraPTR(pScrn)->exa; + struct drm_tegra_pushbuf *pushbuf; + int err; + + err = drm_tegra_pushbuf_prepare(tegra->pushbuf, 8); + if (err < 0) { + ErrorMsg("failed to prepare push buffer: %d\n", err); + return; + } + + pushbuf = tegra->pushbuf; + + *pushbuf->ptr++ = HOST1X_OPCODE_MASK(0x38, 0x5); + *pushbuf->ptr++ = (y2 - y1) << 16 | (x2 - x1); + *pushbuf->ptr++ = y1 << 16 | x1; + + err = drm_tegra_pushbuf_sync(pushbuf, DRM_TEGRA_SYNCPT_COND_OP_DONE); + if (err < 0) + ErrorMsg("failed to insert syncpoint increment: %d\n", err); +} + +static void TegraEXADoneSolid(PixmapPtr pPixmap) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen); + TegraEXAPtr tegra = TegraPTR(pScrn)->exa; + struct drm_tegra_fence *fence; + int err; + + err = drm_tegra_job_submit(tegra->job, &fence); + if (err < 0) { + ErrorMsg("failed to submit job: %d\n", err); + goto free_job; + } + + err = drm_tegra_fence_wait(fence); + if (err < 0) + ErrorMsg("failed to wait for fence: %d\n", err); + + drm_tegra_fence_free(fence); + +free_job: + drm_tegra_job_free(tegra->job); + tegra->pushbuf = NULL; + tegra->job = NULL; +} + +static Bool TegraEXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, + int dx, int dy, int op, Pixel planemask) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen); + TegraPixmapPtr src = exaGetPixmapDriverPrivate(pSrcPixmap); + TegraPixmapPtr dst = exaGetPixmapDriverPrivate(pDstPixmap); + TegraEXAPtr tegra = TegraPTR(pScrn)->exa; + struct drm_tegra_pushbuf *pushbuf; + uint32_t rop; + int err; + + if (!tegra->gr2d) + return FALSE; + + /* + * It should be possible to support all GX* raster operations given the + * mapping in the rop3 table, but none other than GXcopy have been + * validated. + */ + if (op != GXcopy) + return FALSE; + + rop = rop3[op]; + + /* + * Support only 32-bit to 32-bit copies for now. The hardware should be + * able to do 32-bit to 16-bit copies as well, but some restrictions + * apply. + */ + if (pSrcPixmap->drawable.bitsPerPixel != 32 || + pDstPixmap->drawable.bitsPerPixel != 32) + return FALSE; + + err = drm_tegra_job_new(&tegra->job, tegra->gr2d); + if (err < 0) { + ErrorMsg("failed to create job: %d\n", err); + return FALSE; + } + + err = drm_tegra_pushbuf_new(&tegra->pushbuf, tegra->job); + if (err < 0) { + ErrorMsg("failed to create push buffer: %d\n", err); + goto free_job; + } + + err = drm_tegra_pushbuf_prepare(tegra->pushbuf, 16); + if (err < 0) { + ErrorMsg("failed to prepare push buffer: %d\n", err); + goto free_job; + } + + pushbuf = tegra->pushbuf; + + *pushbuf->ptr++ = HOST1X_OPCODE_SETCL(0, HOST1X_CLASS_GR2D, 0); + *pushbuf->ptr++ = HOST1X_OPCODE_MASK(0x9, 0x9); + *pushbuf->ptr++ = 0x0000003a; + *pushbuf->ptr++ = 0x00000000; + + *pushbuf->ptr++ = HOST1X_OPCODE_MASK(0x01e, 0x7); + *pushbuf->ptr++ = 0x00000000; /* controlsecond */ + /* + * [20:20] source color depth (0: mono, 1: same) + * [17:16] destination color depth (0: 8 bpp, 1: 16 bpp, 2: 32 bpp) + */ + *pushbuf->ptr++ = (1 << 20) | (2 << 16); /* controlmain */ + *pushbuf->ptr++ = rop; /* ropfade */ + + *pushbuf->ptr++ = HOST1X_OPCODE_NONINCR(0x046, 1); + /* + * [20:20] destination write tile mode (0: linear, 1: tiled) + * [ 0: 0] tile mode Y/RGB (0: linear, 1: tiled) + */ + *pushbuf->ptr++ = 0x00000000; /* tilemode */ + + *pushbuf->ptr++ = HOST1X_OPCODE_MASK(0x2b, 0x149); + + /* relocate destination buffer */ + err = drm_tegra_pushbuf_relocate(pushbuf, dst->bo, 0, 0); + if (err < 0) { + ErrorMsg("destination pixmap relocation failed: %d\n", err); + goto free_job; + } + + *pushbuf->ptr++ = exaGetPixmapPitch(pDstPixmap); /* dstst */ + + /* relocate source buffer */ + err = drm_tegra_pushbuf_relocate(pushbuf, src->bo, 0, 0); + if (err < 0) { + ErrorMsg("source pixmap relocation failed: %d\n", err); + goto free_job; + } + + *pushbuf->ptr++ = exaGetPixmapPitch(pSrcPixmap); /* srcst */ + + return TRUE; + +free_job: + drm_tegra_job_free(tegra->job); + tegra->pushbuf = NULL; + tegra->job = NULL; + + return FALSE; +} + +static void TegraEXACopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, + int dstY, int width, int height) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen); + TegraEXAPtr tegra = TegraPTR(pScrn)->exa; + struct drm_tegra_pushbuf *pushbuf; + int err; + + err = drm_tegra_pushbuf_prepare(tegra->pushbuf, 8); + if (err < 0) { + ErrorMsg("failed to prepare push buffer: %d\n", err); + return; + } + + pushbuf = tegra->pushbuf; + + *pushbuf->ptr++ = HOST1X_OPCODE_INCR(0x37, 0x4); + *pushbuf->ptr++ = height << 16 | width; /* srcsize */ + *pushbuf->ptr++ = height << 16 | width; /* dstsize */ + *pushbuf->ptr++ = srcY << 16 | srcX; /* srcps */ + *pushbuf->ptr++ = dstY << 16 | dstX; /* dstps */ + + err = drm_tegra_pushbuf_sync(pushbuf, DRM_TEGRA_SYNCPT_COND_OP_DONE); + if (err < 0) + ErrorMsg("failed to insert syncpoint increment: %d\n", err); +} + +static void TegraEXADoneCopy(PixmapPtr pDstPixmap) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen); + TegraEXAPtr tegra = TegraPTR(pScrn)->exa; + struct drm_tegra_fence *fence; + int err; + + err = drm_tegra_job_submit(tegra->job, &fence); + if (err < 0) { + ErrorMsg("failed to submit job: %d\n", err); + goto free_job; + } + + err = drm_tegra_fence_wait(fence); + if (err < 0) + ErrorMsg("failed to wait for fence: %d\n", err); + + drm_tegra_fence_free(fence); + +free_job: + drm_tegra_job_free(tegra->job); + tegra->pushbuf = NULL; + tegra->job = NULL; +} + +static Bool TegraEXACheckComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPicture->pDrawable->pScreen); + TegraEXAPtr tegra = TegraPTR(pScrn)->exa; + + if (!tegra->gr2d) + return FALSE; + + /* + * It should be possible to support all GX* raster operations given the + * mapping in the rop3 table, but none other than GXcopy have been + * validated. + */ + if (op != GXcopy) + return FALSE; + + /* TODO: implement */ + return FALSE; +} + +static Bool TegraEXAPrepareComposite(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, + PixmapPtr pMask, PixmapPtr pDst) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen); + TegraEXAPtr tegra = TegraPTR(pScrn)->exa; + + if (!tegra->gr2d) + return FALSE; + + /* + * It should be possible to support all GX* raster operations given the + * mapping in the rop3 table, but none other than GXcopy have been + * validated. + */ + if (op != GXcopy) + return FALSE; + + /* TODO: implement */ + return FALSE; +} + +static void TegraEXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, + int maskY, int dstX, int dstY, int width, + int height) +{ + /* TODO: implement */ +} + +static void TegraEXADoneComposite(PixmapPtr pDst) +{ + /* TODO: implement */ +} + +static Bool +TegraEXADownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, + char *dst, int pitch) +{ + return FALSE; +} + +void TegraEXAScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + TegraPtr tegra = TegraPTR(pScrn); + ExaDriverPtr exa; + TegraEXAPtr priv; + int err; + + exa = exaDriverAlloc(); + if (!exa) { + ErrorMsg("EXA allocation failed\n"); + return; + } + + priv = calloc(1, sizeof(*priv)); + if (!priv) { + ErrorMsg("EXA allocation failed\n"); + goto free_exa; + } + + err = drm_tegra_channel_open(&priv->gr2d, tegra->drm, DRM_TEGRA_GR2D); + if (err < 0) { + ErrorMsg("failed to open 2D channel: %d\n", err); + goto free_priv; + } + + exa->exa_major = EXA_VERSION_MAJOR; + exa->exa_minor = EXA_VERSION_MINOR; + exa->pixmapOffsetAlign = 256; + exa->pixmapPitchAlign = 64; + exa->flags = EXA_SUPPORTS_PREPARE_AUX | + EXA_OFFSCREEN_PIXMAPS | + EXA_HANDLES_PIXMAPS; + + exa->maxX = 8192; + exa->maxY = 8192; + + exa->MarkSync = TegraEXAMarkSync; + exa->WaitMarker = TegraEXAWaitMarker; + + exa->PrepareAccess = TegraEXAPrepareAccess; + exa->FinishAccess = TegraEXAFinishAccess; + exa->PixmapIsOffscreen = TegraEXAPixmapIsOffscreen; + + exa->CreatePixmap2 = TegraEXACreatePixmap2; + exa->DestroyPixmap = TegraEXADestroyPixmap; + exa->ModifyPixmapHeader = TegraEXAModifyPixmapHeader; + + exa->PrepareSolid = TegraEXAPrepareSolid; + exa->Solid = TegraEXASolid; + exa->DoneSolid = TegraEXADoneSolid; + + exa->PrepareCopy = TegraEXAPrepareCopy; + exa->Copy = TegraEXACopy; + exa->DoneCopy = TegraEXADoneCopy; + + exa->CheckComposite = TegraEXACheckComposite; + exa->PrepareComposite = TegraEXAPrepareComposite; + exa->Composite = TegraEXAComposite; + exa->DoneComposite = TegraEXADoneComposite; + + exa->DownloadFromScreen = TegraEXADownloadFromScreen; + + if (!exaDriverInit(pScreen, exa)) { + ErrorMsg("EXA initialization failed\n"); + goto close_gr2d; + } + + priv->driver = exa; + tegra->exa = priv; + + return; + +close_gr2d: + drm_tegra_channel_close(priv->gr2d); +free_priv: + free(priv); +free_exa: + free(exa); +} + +void TegraEXAScreenExit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + TegraPtr tegra = TegraPTR(pScrn); + TegraEXAPtr priv = tegra->exa; + + if (priv) { + exaDriverFini(pScreen); + free(priv->driver); + + drm_tegra_channel_close(priv->gr2d); + free(priv); + } +} + +/* vim: set et sts=4 sw=4 ts=4: */ diff --git a/src/exa.h b/src/exa.h new file mode 100644 index 0000000..50cc986 --- /dev/null +++ b/src/exa.h @@ -0,0 +1,42 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * 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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. + */ + +#ifndef __TEGRA_EXA_H +#define __TEGRA_EXA_H + +#include <xorg/exa.h> + +#include <libdrm/tegra.h> + +typedef struct _TegraEXARec{ + struct drm_tegra_pushbuf *pushbuf; + struct drm_tegra_channel *gr2d; + struct drm_tegra_job *job; + + ExaDriverPtr driver; +} *TegraEXAPtr; + +#endif + +/* vim: set et sts=4 sw=4 ts=4: */ diff --git a/src/host1x.h b/src/host1x.h new file mode 100644 index 0000000..5f9f1c2 --- /dev/null +++ b/src/host1x.h @@ -0,0 +1,45 @@ +/* + * Copyright © 2014 NVIDIA Corporation + * + * 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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. + */ + +#ifndef HOST1X_H +#define HOST1X_H + +#define HOST1X_OPCODE_SETCL(offset, classid, mask) \ + ((0x0 << 28) | (((offset) & 0xfff) << 16) | (((classid) & 0x3ff) << 6) | ((mask) & 0x3f)) +#define HOST1X_OPCODE_INCR(offset, count) \ + ((0x1 << 28) | (((offset) & 0xfff) << 16) | ((count) & 0xffff)) +#define HOST1X_OPCODE_NONINCR(offset, count) \ + ((0x2 << 28) | (((offset) & 0xfff) << 16) | ((count) & 0xffff)) +#define HOST1X_OPCODE_MASK(offset, mask) \ + ((0x3 << 28) | (((offset) & 0xfff) << 16) | ((mask) & 0xffff)) +#define HOST1X_OPCODE_IMM(offset, data) \ + ((0x4 << 28) | (((offset) & 0xfff) << 16) | ((data) & 0xffff)) +#define HOST1X_OPCODE_EXTEND(subop, value) \ + ((0xe << 28) | (((subop) & 0xf) << 24) | ((value) & 0xffffff)) + +#define HOST1X_CLASS_GR2D 0x51 + +#endif /* HOST1X_H */ + +/* vim: set et sts=4 sw=4 ts=4: */ |