summaryrefslogtreecommitdiffstats
path: root/src/vivante_unaccel_render.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vivante_unaccel_render.c')
-rw-r--r--src/vivante_unaccel_render.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/vivante_unaccel_render.c b/src/vivante_unaccel_render.c
new file mode 100644
index 0000000..42aaa4a
--- /dev/null
+++ b/src/vivante_unaccel_render.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2012 Russell King.
+ *
+ * Based in part on code from the Intel Xorg driver.
+ *
+ * Unaccelerated drawing functions for Vivante GPU. These prepare
+ * access to the drawable prior to passing on the call to the Xorg
+ * Server's fb layer (or pixman layer.)
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "fb.h"
+#include "fbpict.h"
+#include "mipict.h"
+
+#include "vivante_unaccel.h"
+#include "vivante_utils.h"
+
+static void vivante_prepare_picture(PicturePtr pPicture, int access)
+{
+ if (pPicture->pDrawable) {
+ vivante_prepare_drawable(pPicture->pDrawable, access);
+ if (pPicture->alphaMap)
+ vivante_prepare_drawable(pPicture->alphaMap->pDrawable, access);
+ }
+}
+
+static void vivante_finish_picture(PicturePtr pPicture, int access)
+{
+ if (pPicture->pDrawable) {
+ if (pPicture->alphaMap)
+ vivante_finish_drawable(pPicture->alphaMap->pDrawable, access);
+ vivante_finish_drawable(pPicture->pDrawable, access);
+ }
+}
+
+static void GlyphExtents(int nlist, GlyphListPtr list, GlyphPtr *glyphs,
+ BoxPtr extents)
+{
+ int x1, y1, x2, y2, n, x, y;
+ GlyphPtr glyph;
+
+ x = y = 0;
+ extents->x1 = extents->y1 = MAXSHORT;
+ extents->x2 = extents->y2 = MINSHORT;
+ while (nlist--) {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ list++;
+ while (n--) {
+ glyph = *glyphs++;
+ x1 = x - glyph->info.x;
+ if (x1 < MINSHORT)
+ x1 = MINSHORT;
+ y1 = y - glyph->info.y;
+ if (y1 < MINSHORT)
+ y1 = MINSHORT;
+ x2 = x1 + glyph->info.width;
+ if (x2 > MAXSHORT)
+ x2 = MAXSHORT;
+ y2 = y1 + glyph->info.height;
+ if (y2 > MAXSHORT)
+ y2 = MAXSHORT;
+ if (x1 < extents->x1)
+ extents->x1 = x1;
+ if (x2 > extents->x2)
+ extents->x2 = x2;
+ if (y1 < extents->y1)
+ extents->y1 = y1;
+ if (y2 > extents->y2)
+ extents->y2 = y2;
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ }
+}
+
+#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
+#ifndef GLYPH_HAS_GLYPH_PICTURE_ACCESSOR
+#define GetGlyphPicture(g, s) GlyphPicture((g))[(s)->myNum]
+#define SetGlyphPicture(g, s, p) GlyphPicture((g))[(s)->myNum] = p
+#endif
+
+void vivante_unaccel_Glyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist,
+ GlyphListPtr list, GlyphPtr * glyphs)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PixmapPtr pMaskPixmap = NULL;
+ PicturePtr pMask;
+ int width = 0, height = 0, x, y, n;
+ int xDst = list->xOff, yDst = list->yOff;
+ BoxRec extents = { 0, 0, 0, 0 };
+
+ if (maskFormat) {
+ xRectangle rect;
+ CARD32 component_alpha;
+ GCPtr pGC;
+ int error;
+
+ GlyphExtents(nlist, list, glyphs, &extents);
+ if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
+ return;
+
+ width = extents.x2 - extents.x1;
+ height = extents.y2 - extents.y1;
+ pMaskPixmap = pScreen->CreatePixmap(pScreen, width, height,
+ maskFormat->depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pMaskPixmap)
+ return;
+
+ component_alpha = NeedsComponent(maskFormat->format);
+ pMask = CreatePicture(0, &pMaskPixmap->drawable, maskFormat,
+ CPComponentAlpha, &component_alpha, serverClient, &error);
+ if (!pMask) {
+ pScreen->DestroyPixmap(pMaskPixmap);
+ return;
+ }
+
+ pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen);
+ ValidateGC(&pMaskPixmap->drawable, pGC);
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = width;
+ rect.height = height;
+ pGC->ops->PolyFillRect(&pMaskPixmap->drawable, pGC, 1, &rect);
+ FreeScratchGC(pGC);
+ x = -extents.x1;
+ y = -extents.y1;
+ } else {
+ pMask = pDst;
+ x = 0;
+ y = 0;
+ }
+
+ while (nlist--) {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ while (n--) {
+ GlyphPtr glyph = *glyphs++;
+ PicturePtr g = GetGlyphPicture(glyph, pScreen);
+
+ if (g) {
+ int dstx = x - glyph->info.x;
+ int dsty = y - glyph->info.y;
+ if (maskFormat) {
+ CompositePicture(PictOpAdd, g, NULL, pMask,
+ 0, 0, 0, 0, dstx, dsty,
+ glyph->info.width, glyph->info.height);
+ } else {
+ CompositePicture(op, pSrc, g, pDst,
+ xSrc + dstx - xDst,
+ ySrc + dsty - yDst,
+ 0, 0, dstx, dsty,
+ glyph->info.width, glyph->info.height);
+ }
+ }
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ list++;
+ }
+
+ if (maskFormat) {
+ x = extents.x1;
+ y = extents.y1;
+ CompositePicture(op, pSrc, pMask, pDst,
+ xSrc + x - xDst, ySrc + y - yDst, 0, 0, x, y,
+ width, height);
+ FreePicture(pMask, 0);
+ pScreen->DestroyPixmap(pMaskPixmap);
+ }
+}
+
+void vivante_unaccel_Triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntri, xTriangle *tri)
+{
+ vivante_prepare_picture(pDst, ACCESS_RW);
+ vivante_prepare_picture(pSrc, ACCESS_RO);
+ fbTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tri);
+ vivante_finish_picture(pSrc, ACCESS_RO);
+ vivante_finish_picture(pDst, ACCESS_RW);
+}
+
+void vivante_unaccel_Trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntrap,
+ xTrapezoid * traps)
+{
+ vivante_prepare_picture(pDst, ACCESS_RW);
+ vivante_prepare_picture(pSrc, ACCESS_RO);
+ fbTrapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps);
+ vivante_finish_picture(pSrc, ACCESS_RO);
+ vivante_finish_picture(pDst, ACCESS_RW);
+}
+
+void vivante_unaccel_Composite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
+ PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst, CARD16 w, CARD16 h)
+{
+ vivante_prepare_picture(pDst, ACCESS_RW);
+ vivante_prepare_picture(pSrc, ACCESS_RO);
+ if (pMask)
+ vivante_prepare_picture(pMask, ACCESS_RO);
+ fbComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
+ xDst, yDst, w, h);
+ if (pMask)
+ vivante_finish_picture(pMask, ACCESS_RO);
+ vivante_finish_picture(pSrc, ACCESS_RO);
+ vivante_finish_picture(pDst, ACCESS_RW);
+}
+
+void vivante_unaccel_AddTriangles(PicturePtr pPicture, INT16 x_off, INT16 y_off,
+ int ntri, xTriangle *tris)
+{
+ vivante_prepare_picture(pPicture, ACCESS_RW);
+ fbAddTriangles(pPicture, x_off, y_off, ntri, tris);
+ vivante_finish_picture(pPicture, ACCESS_RW);
+}
+
+void vivante_unaccel_AddTraps(PicturePtr pPicture, INT16 x_off, INT16 y_off,
+ int ntrap, xTrap *traps)
+{
+ vivante_prepare_picture(pPicture, ACCESS_RW);
+ fbAddTraps(pPicture, x_off, y_off, ntrap, traps);
+ vivante_finish_picture(pPicture, ACCESS_RW);
+}