diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2011-06-16 15:55:07 +0200 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2011-06-16 16:04:47 +0200 |
commit | 84166d4b457244bcc2f5ace63702d594d602d0c2 (patch) | |
tree | 892d9ee8de7a45b4d21505f9949a8424e3c81a44 /saa/saa_render.c | |
parent | 0142bb8d10edb153c9ce79a2ea3ff92a7fb15ac5 (diff) |
vmwgfx, saa: Initial import
This imports the vmwgfx driver, based on the Gallium3D Xorg state tracker,
as well as the saa library. A "Shadow Acceleration Architecture", which is
optimized for the case where transfers between system (shadow) and hw memory
is very costly.
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Diffstat (limited to 'saa/saa_render.c')
-rw-r--r-- | saa/saa_render.c | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/saa/saa_render.c b/saa/saa_render.c new file mode 100644 index 0000000..1df0dff --- /dev/null +++ b/saa/saa_render.c @@ -0,0 +1,313 @@ +/* + * Copyright © 2001 Keith Packard + * Copyright 2011 VMWare, Inc. All Rights Reserved. + * May partly be based on code that is Copyright © The XFree86 Project Inc. + * + * 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. + * + * Author: Eric Anholt <eric@anholt.net> + * Author: Michel Dänzer <michel@tungstengraphics.com> + * Author: Thomas Hellstrom <thellstrom@vmware.com> + */ +#include "saa.h" +#include "saa_priv.h" + +#ifdef RENDER +#include <mipict.h> + +/** + * Same as miCreateAlphaPicture, except it uses + * saa_check_poly_fill_rect instead + */ + +static PicturePtr +saa_create_alpha_picture(ScreenPtr pScreen, + PicturePtr pDst, + PictFormatPtr pPictFormat, CARD16 width, CARD16 height) +{ + PixmapPtr pPixmap; + PicturePtr pPicture; + GCPtr pGC; + int error; + xRectangle rect; + + if (width > 32767 || height > 32767) + return 0; + + if (!pPictFormat) { + if (pDst->polyEdge == PolyEdgeSharp) + pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1); + else + pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8); + if (!pPictFormat) + return 0; + } + + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pPictFormat->depth, 0); + if (!pPixmap) + return 0; + pGC = GetScratchGC(pPixmap->drawable.depth, pScreen); + if (!pGC) { + (*pScreen->DestroyPixmap) (pPixmap); + return 0; + } + ValidateGC(&pPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + saa_check_poly_fill_rect(&pPixmap->drawable, pGC, 1, &rect); + FreeScratchGC(pGC); + pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat, + 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + return pPicture; +} + +/** + * saa_trapezoids is essentially a copy of miTrapezoids that uses + * saa_create_alpha_picture instead of miCreateAlphaPicture. + * + * The problem with miCreateAlphaPicture is that it calls PolyFillRect + * to initialize the contents after creating the pixmap, which + * causes the pixmap to be moved in for acceleration. The subsequent + * call to RasterizeTrapezoid won't be accelerated however, which + * forces the pixmap to be moved out again. + * + */ +static void +saa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid * traps) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + BoxRec bounds; + + if (maskFormat) { + PicturePtr pPicture; + INT16 xDst, yDst; + INT16 xRel, yRel; + saa_access_t access; + + miTrapezoidBounds(ntrap, traps, &bounds); + + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + + xDst = traps[0].left.p1.x >> 16; + yDst = traps[0].left.p1.y >> 16; + + pPicture = saa_create_alpha_picture(pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + + if (saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) { + for (; ntrap; ntrap--, traps++) + (*ps->RasterizeTrapezoid) (pPicture, traps, + -bounds.x1, -bounds.y1); + saa_fad_write(pPicture->pDrawable, access); + } + + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture(op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture(pPicture, 0); + } else { + if (pDst->polyEdge == PolyEdgeSharp) + maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1); + else + maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8); + for (; ntrap; ntrap--, traps++) + saa_trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps); + } +} + +/** + * saa_triangles is essentially a copy of miTriangles that uses + * saa_create_alpha_picture instead of miCreateAlphaPicture. + * + * The problem with miCreateAlphaPicture is that it calls PolyFillRect + * to initialize the contents after creating the pixmap, which + * causes the pixmap to be moved in for acceleration. The subsequent + * call to AddTriangles won't be accelerated however, which forces the pixmap + * to be moved out again. + */ +static void +saa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntri, xTriangle * tris) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + BoxRec bounds; + + if (maskFormat) { + PicturePtr pPicture; + INT16 xDst, yDst; + INT16 xRel, yRel; + saa_access_t access; + + miTriangleBounds(ntri, tris, &bounds); + + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + + xDst = tris[0].p1.x >> 16; + yDst = tris[0].p1.y >> 16; + + pPicture = saa_create_alpha_picture(pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + + if (saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) { + (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris); + saa_fad_write(pPicture->pDrawable, access); + } + + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture(op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture(pPicture, 0); + } else { + if (pDst->polyEdge == PolyEdgeSharp) + maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1); + else + maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8); + + for (; ntri; ntri--, tris++) + saa_triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris); + } +} + +/* + * Try to turn a composite operation into an accelerated copy. + * We can do that in some special cases for PictOpSrc and PictOpOver. + */ + +static Bool +saa_copy_composite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + if (!pSrc->pDrawable || pSrc->transform || + pSrc->repeat || xSrc < 0 || ySrc < 0 || + xSrc + width > pSrc->pDrawable->width || + ySrc + height > pSrc->pDrawable->height) + return FALSE; + + if ((op == PictOpSrc && + (pSrc->format == pDst->format || + (PICT_FORMAT_COLOR(pDst->format) && + PICT_FORMAT_COLOR(pSrc->format) && + pDst->format == PICT_FORMAT(PICT_FORMAT_BPP(pSrc->format), + PICT_FORMAT_TYPE(pSrc->format), + 0, + PICT_FORMAT_R(pSrc->format), + PICT_FORMAT_G(pSrc->format), + PICT_FORMAT_B(pSrc->format))))) || + (op == PictOpOver && pSrc->format == pDst->format && + !PICT_FORMAT_A(pSrc->format))) { + + Bool ret; + RegionRec region; + + REGION_NULL(pDst->pDrawable.pScreen, ®ion); + + xDst += pDst->pDrawable->x; + yDst += pDst->pDrawable->y; + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + + if (!miComputeCompositeRegion(®ion, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, + yDst, width, height)) { + return TRUE; + } + + ret = saa_hw_copy_nton(pSrc->pDrawable, pDst->pDrawable, NULL, + RegionRects(®ion), + RegionNumRects(®ion), + xSrc - xDst, ySrc - yDst, FALSE, FALSE); + RegionUninit(®ion); + if (ret) + return TRUE; + } + return FALSE; +} + +static void +saa_composite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + if (!saa_copy_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height)) + saa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height); +} + +void +saa_render_setup(ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + struct saa_screen_priv *sscreen = saa_screen(pScreen); + + if (ps) { + saa_wrap(sscreen, ps, Trapezoids, saa_trapezoids); + saa_wrap(sscreen, ps, Triangles, saa_triangles); + saa_wrap(sscreen, ps, Composite, saa_composite); + } +} + +void +saa_render_takedown(ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + struct saa_screen_priv *sscreen = saa_screen(pScreen); + + if (ps) { + saa_unwrap(sscreen, ps, Trapezoids); + saa_unwrap(sscreen, ps, Triangles); + saa_unwrap(sscreen, ps, Composite); + } +} +#endif |