135c4bbdfSmrg/*
235c4bbdfSmrg * Copyright © 2014 Keith Packard
335c4bbdfSmrg *
435c4bbdfSmrg * Permission to use, copy, modify, distribute, and sell this software and its
535c4bbdfSmrg * documentation for any purpose is hereby granted without fee, provided that
635c4bbdfSmrg * the above copyright notice appear in all copies and that both that copyright
735c4bbdfSmrg * notice and this permission notice appear in supporting documentation, and
835c4bbdfSmrg * that the name of the copyright holders not be used in advertising or
935c4bbdfSmrg * publicity pertaining to distribution of the software without specific,
1035c4bbdfSmrg * written prior permission.  The copyright holders make no representations
1135c4bbdfSmrg * about the suitability of this software for any purpose.  It is provided "as
1235c4bbdfSmrg * is" without express or implied warranty.
1335c4bbdfSmrg *
1435c4bbdfSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1535c4bbdfSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1635c4bbdfSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1735c4bbdfSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1835c4bbdfSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1935c4bbdfSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2035c4bbdfSmrg * OF THIS SOFTWARE.
2135c4bbdfSmrg */
2235c4bbdfSmrg
2335c4bbdfSmrg#include "glamor_priv.h"
2435c4bbdfSmrg#include "glamor_transfer.h"
2535c4bbdfSmrg#include "glamor_transform.h"
2635c4bbdfSmrg
2735c4bbdfSmrg/*
2835c4bbdfSmrg * PutImage. Only does ZPixmap right now as other formats are quite a bit harder
2935c4bbdfSmrg */
3035c4bbdfSmrg
3135c4bbdfSmrgstatic Bool
3235c4bbdfSmrgglamor_put_image_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
3335c4bbdfSmrg                    int w, int h, int leftPad, int format, char *bits)
3435c4bbdfSmrg{
3535c4bbdfSmrg    ScreenPtr screen = drawable->pScreen;
3635c4bbdfSmrg    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
3735c4bbdfSmrg    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
3835c4bbdfSmrg    glamor_pixmap_private *pixmap_priv;
3935c4bbdfSmrg    uint32_t    byte_stride = PixmapBytePad(w, drawable->depth);
4035c4bbdfSmrg    RegionRec   region;
4135c4bbdfSmrg    BoxRec      box;
4235c4bbdfSmrg    int         off_x, off_y;
4335c4bbdfSmrg
4435c4bbdfSmrg    pixmap_priv = glamor_get_pixmap_private(pixmap);
4535c4bbdfSmrg
4635c4bbdfSmrg    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
4735c4bbdfSmrg        return FALSE;
4835c4bbdfSmrg
4935c4bbdfSmrg    if (gc->alu != GXcopy)
5035c4bbdfSmrg        goto bail;
5135c4bbdfSmrg
5235c4bbdfSmrg    if (!glamor_pm_is_solid(gc->depth, gc->planemask))
5335c4bbdfSmrg        goto bail;
5435c4bbdfSmrg
5535c4bbdfSmrg    if (format == XYPixmap && drawable->depth == 1 && leftPad == 0)
5635c4bbdfSmrg        format = ZPixmap;
5735c4bbdfSmrg
5835c4bbdfSmrg    if (format != ZPixmap)
5935c4bbdfSmrg        goto bail;
6035c4bbdfSmrg
6135c4bbdfSmrg    x += drawable->x;
6235c4bbdfSmrg    y += drawable->y;
6335c4bbdfSmrg    box.x1 = x;
6435c4bbdfSmrg    box.y1 = y;
6535c4bbdfSmrg    box.x2 = box.x1 + w;
6635c4bbdfSmrg    box.y2 = box.y1 + h;
6735c4bbdfSmrg    RegionInit(&region, &box, 1);
6835c4bbdfSmrg    RegionIntersect(&region, &region, gc->pCompositeClip);
6935c4bbdfSmrg
7035c4bbdfSmrg    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
7135c4bbdfSmrg    if (off_x || off_y) {
7235c4bbdfSmrg        x += off_x;
7335c4bbdfSmrg        y += off_y;
7435c4bbdfSmrg        RegionTranslate(&region, off_x, off_y);
7535c4bbdfSmrg    }
7635c4bbdfSmrg
7735c4bbdfSmrg    glamor_make_current(glamor_priv);
7835c4bbdfSmrg
7935c4bbdfSmrg    glamor_upload_region(pixmap, &region, x, y, (uint8_t *) bits, byte_stride);
8035c4bbdfSmrg
8135c4bbdfSmrg    RegionUninit(&region);
8235c4bbdfSmrg    return TRUE;
8335c4bbdfSmrgbail:
8435c4bbdfSmrg    return FALSE;
8535c4bbdfSmrg}
8635c4bbdfSmrg
8735c4bbdfSmrgstatic void
8835c4bbdfSmrgglamor_put_image_bail(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
8935c4bbdfSmrg                      int w, int h, int leftPad, int format, char *bits)
9035c4bbdfSmrg{
9135c4bbdfSmrg    if (glamor_prepare_access_box(drawable, GLAMOR_ACCESS_RW, x, y, w, h))
9235c4bbdfSmrg        fbPutImage(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
9335c4bbdfSmrg    glamor_finish_access(drawable);
9435c4bbdfSmrg}
9535c4bbdfSmrg
9635c4bbdfSmrgvoid
9735c4bbdfSmrgglamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
9835c4bbdfSmrg                 int w, int h, int leftPad, int format, char *bits)
9935c4bbdfSmrg{
10035c4bbdfSmrg    if (glamor_put_image_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits))
10135c4bbdfSmrg        return;
10235c4bbdfSmrg    glamor_put_image_bail(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
10335c4bbdfSmrg}
10435c4bbdfSmrg
10535c4bbdfSmrgstatic Bool
10635c4bbdfSmrgglamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h,
10735c4bbdfSmrg                    unsigned int format, unsigned long plane_mask, char *d)
10835c4bbdfSmrg{
10935c4bbdfSmrg    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
11035c4bbdfSmrg    glamor_pixmap_private *pixmap_priv;
11135c4bbdfSmrg    uint32_t    byte_stride = PixmapBytePad(w, drawable->depth);
11235c4bbdfSmrg    BoxRec      box;
11335c4bbdfSmrg    int         off_x, off_y;
11435c4bbdfSmrg
11535c4bbdfSmrg    pixmap_priv = glamor_get_pixmap_private(pixmap);
11635c4bbdfSmrg    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
11735c4bbdfSmrg        goto bail;
11835c4bbdfSmrg
1191b5d61b8Smrg    if (format != ZPixmap)
12035c4bbdfSmrg        goto bail;
12135c4bbdfSmrg
12235c4bbdfSmrg    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
12335c4bbdfSmrg    box.x1 = x;
12435c4bbdfSmrg    box.x2 = x + w;
12535c4bbdfSmrg    box.y1 = y;
12635c4bbdfSmrg    box.y2 = y + h;
12735c4bbdfSmrg    glamor_download_boxes(pixmap, &box, 1,
12835c4bbdfSmrg                          drawable->x + off_x, drawable->y + off_y,
12935c4bbdfSmrg                          -x, -y,
13035c4bbdfSmrg                          (uint8_t *) d, byte_stride);
1311b5d61b8Smrg
1321b5d61b8Smrg    if (!glamor_pm_is_solid(drawable->depth, plane_mask)) {
1331b5d61b8Smrg        FbStip pm = fbReplicatePixel(plane_mask, drawable->bitsPerPixel);
1341b5d61b8Smrg        FbStip *dst = (void *)d;
1351b5d61b8Smrg        uint32_t dstStride = byte_stride / sizeof(FbStip);
1361b5d61b8Smrg
1371b5d61b8Smrg        for (int i = 0; i < dstStride * h; i++)
1381b5d61b8Smrg            dst[i] &= pm;
1391b5d61b8Smrg    }
1401b5d61b8Smrg
14135c4bbdfSmrg    return TRUE;
14235c4bbdfSmrgbail:
14335c4bbdfSmrg    return FALSE;
14435c4bbdfSmrg}
14535c4bbdfSmrg
14635c4bbdfSmrgstatic void
14735c4bbdfSmrgglamor_get_image_bail(DrawablePtr drawable, int x, int y, int w, int h,
14835c4bbdfSmrg                      unsigned int format, unsigned long plane_mask, char *d)
14935c4bbdfSmrg{
15035c4bbdfSmrg    if (glamor_prepare_access_box(drawable, GLAMOR_ACCESS_RO, x, y, w, h))
15135c4bbdfSmrg        fbGetImage(drawable, x, y, w, h, format, plane_mask, d);
15235c4bbdfSmrg    glamor_finish_access(drawable);
15335c4bbdfSmrg}
15435c4bbdfSmrg
15535c4bbdfSmrgvoid
15635c4bbdfSmrgglamor_get_image(DrawablePtr drawable, int x, int y, int w, int h,
15735c4bbdfSmrg                 unsigned int format, unsigned long plane_mask, char *d)
15835c4bbdfSmrg{
15935c4bbdfSmrg    if (glamor_get_image_gl(drawable, x, y, w, h, format, plane_mask, d))
16035c4bbdfSmrg        return;
16135c4bbdfSmrg    glamor_get_image_bail(drawable, x, y, w, h, format, plane_mask, d);
16235c4bbdfSmrg}
163