/**
 * Implements CopyPlane and CopyArea from the GPU to the GPU by using
 * the source as a texture and painting that into the destination.
 *
 * This requires that source and dest are different textures, or that
 * (if the copy area doesn't overlap), GL_NV_texture_barrier is used
 * to ensure that the caches are flushed at the right times.
 */
static Bool
glamor_copy_cpu_fbo(DrawablePtr src,
                    DrawablePtr dst,
                    GCPtr gc,
                    BoxPtr box,
                    int nbox,
                    int dx,
                    int dy,
                    Bool reverse,
                    Bool upsidedown,
                    Pixel bitplane,
                    void *closure)
{
    ScreenPtr screen = dst->pScreen;
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
    FbBits *src_bits;
    FbStride src_stride;
    int src_bpp;
    int src_xoff, src_yoff;
    int dst_xoff, dst_yoff;

    if (gc && gc->alu != GXcopy)
        goto bail;

    if (gc && !glamor_pm_is_solid(gc->depth, gc->planemask))
        goto bail;

    glamor_make_current(glamor_priv);
    glamor_prepare_access(src, GLAMOR_ACCESS_RO);

    glamor_get_drawable_deltas(dst, dst_pixmap, &dst_xoff, &dst_yoff);

    fbGetDrawable(src, src_bits, src_stride, src_bpp, src_xoff, src_yoff);

    glamor_upload_boxes(dst_pixmap, box, nbox, src_xoff + dx, src_yoff + dy,
                        dst_xoff, dst_yoff,
                        (uint8_t *) src_bits, src_stride * sizeof (FbBits));
    glamor_finish_access(src);

    return TRUE;

bail:
    return FALSE;
}
static inline void
glamor_copy_glyph(PixmapPtr     glyph_pixmap,
                  DrawablePtr   atlas_draw,
                  int16_t x,
                  int16_t y)
{
    DrawablePtr glyph_draw = &glyph_pixmap->drawable;
    BoxRec      box = {
        .x1 = 0,
        .y1 = 0,
        .x2 = glyph_draw->width,
        .y2 = glyph_draw->height,
    };
    PixmapPtr upload_pixmap = glyph_pixmap;

    if (glyph_pixmap->drawable.bitsPerPixel != atlas_draw->bitsPerPixel) {

        /* If we're dealing with 1-bit glyphs, we copy them to a
         * temporary 8-bit pixmap and upload them from there, since
         * that's what GL can handle.
         */
        ScreenPtr       screen = atlas_draw->pScreen;
        GCPtr           scratch_gc;
        ChangeGCVal     changes[2];

        upload_pixmap = glamor_create_pixmap(screen,
                                             glyph_draw->width,
                                             glyph_draw->height,
                                             atlas_draw->depth,
                                             GLAMOR_CREATE_PIXMAP_CPU);
        if (!upload_pixmap)
            return;

        scratch_gc = GetScratchGC(upload_pixmap->drawable.depth, screen);
        if (!scratch_gc) {
            glamor_destroy_pixmap(upload_pixmap);
            return;
        }
        changes[0].val = 0xff;
        changes[1].val = 0x00;
        if (ChangeGC(NullClient, scratch_gc,
                     GCForeground|GCBackground, changes) != Success) {
            glamor_destroy_pixmap(upload_pixmap);
            FreeScratchGC(scratch_gc);
            return;
        }
        ValidateGC(&upload_pixmap->drawable, scratch_gc);

        (*scratch_gc->ops->CopyPlane)(glyph_draw,
                                      &upload_pixmap->drawable,
                                      scratch_gc,
                                      0, 0,
                                      glyph_draw->width,
                                      glyph_draw->height,
                                      0, 0, 0x1);
    }
    glamor_upload_boxes((PixmapPtr) atlas_draw,
                        &box, 1,
                        0, 0,
                        x, y,
                        upload_pixmap->devPrivate.ptr,
                        upload_pixmap->devKind);

    if (upload_pixmap != glyph_pixmap)
        glamor_destroy_pixmap(upload_pixmap);
}

static Bool
glamor_glyph_atlas_init(ScreenPtr screen, struct glamor_glyph_atlas *atlas)
{
    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
    PictFormatPtr               format = atlas->format;

    atlas->atlas = glamor_create_pixmap(screen, glamor_priv->glyph_atlas_dim,
                                        glamor_priv->glyph_atlas_dim, format->depth,
                                        GLAMOR_CREATE_FBO_NO_FBO);
    if (!glamor_pixmap_has_fbo(atlas->atlas)) {
        glamor_destroy_pixmap(atlas->atlas);
        atlas->atlas = NULL;
    }
    atlas->x = 0;
    atlas->y = 0;
    atlas->row_height = 0;
    atlas->serial++;
    atlas->nglyph = 0;
    return TRUE;
}
Example #3
0
/**
 * Implements CopyPlane and CopyArea from the GPU to the GPU by using
 * the source as a texture and painting that into the destination.
 *
 * This requires that source and dest are different textures, or that
 * (if the copy area doesn't overlap), GL_NV_texture_barrier is used
 * to ensure that the caches are flushed at the right times.
 */
static Bool
glamor_copy_cpu_fbo(DrawablePtr src,
                    DrawablePtr dst,
                    GCPtr gc,
                    BoxPtr box,
                    int nbox,
                    int dx,
                    int dy,
                    Bool reverse,
                    Bool upsidedown,
                    Pixel bitplane,
                    void *closure)
{
    ScreenPtr screen = dst->pScreen;
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
    FbBits *src_bits;
    FbStride src_stride;
    int src_bpp;
    int src_xoff, src_yoff;
    int dst_xoff, dst_yoff;

    if (gc && gc->alu != GXcopy)
        goto bail;

    if (gc && !glamor_pm_is_solid(gc->depth, gc->planemask))
        goto bail;

    glamor_make_current(glamor_priv);
    glamor_prepare_access(src, GLAMOR_ACCESS_RO);

    glamor_get_drawable_deltas(dst, dst_pixmap, &dst_xoff, &dst_yoff);

    if (bitplane) {
        PixmapPtr src_pix = fbCreatePixmap(screen, dst_pixmap->drawable.width,
                                           dst_pixmap->drawable.height,
                                           dst->depth, 0);

        if (!src_pix) {
            glamor_finish_access(src);
            goto bail;
        }

        src_pix->drawable.x = -dst->x;
        src_pix->drawable.y = -dst->y;

        fbGetDrawable(&src_pix->drawable, src_bits, src_stride, src_bpp, src_xoff,
                      src_yoff);

        if (src->bitsPerPixel > 1)
            fbCopyNto1(src, &src_pix->drawable, gc, box, nbox, dx, dy,
                       reverse, upsidedown, bitplane, closure);
        else
            fbCopy1toN(src, &src_pix->drawable, gc, box, nbox, dx, dy,
                       reverse, upsidedown, bitplane, closure);

        glamor_upload_boxes(dst_pixmap, box, nbox, src_xoff, src_yoff,
                            dst_xoff, dst_yoff, (uint8_t *) src_bits,
                            src_stride * sizeof(FbBits));
        fbDestroyPixmap(src_pix);
    } else {
        fbGetDrawable(src, src_bits, src_stride, src_bpp, src_xoff, src_yoff);
        glamor_upload_boxes(dst_pixmap, box, nbox, src_xoff + dx, src_yoff + dy,
                            dst_xoff, dst_yoff,
                            (uint8_t *) src_bits, src_stride * sizeof (FbBits));
    }
    glamor_finish_access(src);

    return TRUE;

bail:
    return FALSE;
}