/** * 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; }
/** * 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; }