static void glamor_copy_bail(DrawablePtr src, DrawablePtr dst, GCPtr gc, BoxPtr box, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) && glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { if (bitplane) { if (src->bitsPerPixel > 1) fbCopyNto1(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); else fbCopy1toN(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); } else { fbCopyNtoN(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); } } glamor_finish_access(dst); glamor_finish_access(src); }
void kaaCopyNtoN (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { KdScreenPriv (pDstDrawable->pScreen); KaaScreenPriv (pDstDrawable->pScreen); PixmapPtr pSrcPixmap, pDstPixmap; int src_off_x, src_off_y; int dst_off_x, dst_off_y; /* Migrate pixmaps to same place as destination */ if (pScreenPriv->enabled && pSrcDrawable->type == DRAWABLE_PIXMAP) { if (kaaDrawableIsOffscreen (pDstDrawable)) kaaPixmapUseScreen ((PixmapPtr) pSrcDrawable); else kaaPixmapUseMemory ((PixmapPtr) pSrcDrawable); } if (pScreenPriv->enabled && (pSrcPixmap = kaaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y)) && (pDstPixmap = kaaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y)) && (*pKaaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, dx, dy, pGC ? pGC->alu : GXcopy, pGC ? pGC->planemask : FB_ALLONES)) { while (nbox--) { (*pKaaScr->info->Copy) (pbox->x1 + dx + src_off_x, pbox->y1 + dy + src_off_y, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); pbox++; } (*pKaaScr->info->DoneCopy) (); kaaMarkSync (pDstDrawable->pScreen); } else { kaaWaitSync (pDstDrawable->pScreen); fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure); } kaaDrawableDirty (pDstDrawable); }
void vivante_unaccel_CopyNtoN(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, BoxPtr pBox, int nBox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitPlane, void *closure) { vivante_prepare_drawable(pDst, ACCESS_RW); if (pDst != pSrc) vivante_prepare_drawable(pSrc, ACCESS_RO); fbCopyNtoN(pSrc, pDst, pGC, pBox, nBox, dx, dy, reverse, upsidedown, bitPlane, closure); if (pDst != pSrc) vivante_finish_drawable(pSrc, ACCESS_RO); vivante_finish_drawable(pDst, ACCESS_RW); }
static Bool _glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, GCPtr gc, BoxPtr box, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure, Bool fallback) { PixmapPtr dst_pixmap, src_pixmap; glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; glamor_screen_private *glamor_priv; glamor_gl_dispatch *dispatch; BoxPtr extent; RegionRec region; int src_x_off, src_y_off, dst_x_off, dst_y_off; Bool ok = FALSE; int force_clip = 0; if (nbox == 0) return TRUE; dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); src_pixmap = glamor_get_drawable_pixmap(src); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); glamor_priv = glamor_get_screen_private(dst->pScreen); DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n", box[0].x1, box[0].y1, box[0].x2 - box[0].x1, box[0].y2 - box[0].y1, dx, dy, src_pixmap, dst_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) goto fall_back; if (gc) { if (!glamor_set_planemask(dst_pixmap, gc->planemask)) goto fall_back; dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, gc->alu)) { glamor_put_dispatch(glamor_priv); goto fail_noregion; } glamor_put_dispatch(glamor_priv); } if (!src_pixmap_priv) { glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); } glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); RegionInitBoxes(®ion, box, nbox); extent = RegionExtents(®ion); if (!glamor_check_fbo_size(glamor_priv, extent->x2 - extent->x1, extent->y2 - extent->y1) && (src_pixmap_priv->type == GLAMOR_MEMORY || (src_pixmap_priv == dst_pixmap_priv))) { force_clip = 1; } if (force_clip || dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { glamor_pixmap_clipped_regions *clipped_dst_regions; int n_dst_region, i, j; PixmapPtr temp_source_pixmap; glamor_pixmap_private *temp_source_priv = NULL; RegionTranslate(®ion, dst_x_off, dst_y_off); if (!force_clip) clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, ®ion, &n_dst_region, 0, reverse, upsidedown); else clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv, ®ion, &n_dst_region, glamor_priv->max_fbo_size, glamor_priv->max_fbo_size, reverse, upsidedown); for(i = 0; i < n_dst_region; i++) { int n_src_region; glamor_pixmap_clipped_regions *clipped_src_regions; BoxPtr current_boxes; int n_current_boxes; SET_PIXMAP_FBO_CURRENT(dst_pixmap_priv, clipped_dst_regions[i].block_idx); temp_source_pixmap = NULL; if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { RegionTranslate(clipped_dst_regions[i].region, -dst_x_off + src_x_off + dx, -dst_y_off + src_y_off + dy); clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv, clipped_dst_regions[i].region, &n_src_region, 0, reverse, upsidedown); DEBUGF("Source is large pixmap.\n"); for (j = 0; j < n_src_region; j++) { if (src_pixmap_priv != dst_pixmap_priv) SET_PIXMAP_FBO_CURRENT(src_pixmap_priv, clipped_src_regions[j].block_idx); else if (src_pixmap_priv == dst_pixmap_priv && clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx) { /* source and the dest are the same, but need different block_idx. * we create a empty pixmap and fill the required source fbo and box to * it. It's a little hacky, but avoid extra copy. */ temp_source_pixmap = glamor_create_pixmap(src->pScreen, 0, 0, src->depth, 0); if (!temp_source_pixmap) { ok = FALSE; goto fail; } src->pScreen->ModifyPixmapHeader(temp_source_pixmap, src_pixmap->drawable.width, src_pixmap->drawable.height, 0, 0, src_pixmap->devKind, NULL); temp_source_priv = glamor_get_pixmap_private(temp_source_pixmap); *temp_source_priv = *src_pixmap_priv; temp_source_priv->large.box = src_pixmap_priv->large.box_array[clipped_src_regions[j].block_idx]; temp_source_priv->base.fbo = src_pixmap_priv->large.fbo_array[clipped_src_regions[j].block_idx]; temp_source_priv->base.pixmap = temp_source_pixmap; } assert(temp_source_pixmap || !(src_pixmap_priv == dst_pixmap_priv && (clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx))); RegionTranslate(clipped_src_regions[j].region, -src_x_off - dx, -src_y_off - dy); current_boxes = RegionRects(clipped_src_regions[j].region); n_current_boxes = RegionNumRects(clipped_src_regions[j].region); DEBUGF("dst pixmap fbo idx %d src pixmap fbo idx %d \n", clipped_dst_regions[i].block_idx, clipped_src_regions[j].block_idx); DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n", current_boxes[0].x1, current_boxes[0].y1, current_boxes[0].x2, current_boxes[0].y2, dx, dy, src_pixmap, dst_pixmap); if (!temp_source_pixmap) ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes, n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); else { ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable, dst, gc, current_boxes, n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); temp_source_priv->type = GLAMOR_MEMORY; temp_source_priv->base.fbo = NULL; glamor_destroy_pixmap(temp_source_pixmap); temp_source_pixmap = NULL; } RegionDestroy(clipped_src_regions[j].region); if (!ok) { assert(0); goto fail; } } if (n_src_region == 0) ok = TRUE; free(clipped_src_regions); } else { RegionTranslate(clipped_dst_regions[i].region, - dst_x_off, - dst_y_off); current_boxes = RegionRects(clipped_dst_regions[i].region); n_current_boxes = RegionNumRects(clipped_dst_regions[i].region); DEBUGF("dest pixmap fbo idx %d \n", clipped_dst_regions[i].block_idx); DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n", current_boxes[0].x1, current_boxes[0].y1, current_boxes[0].x2, current_boxes[0].y2, dx, dy, src_pixmap, dst_pixmap); ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes, n_current_boxes, dx, dy, reverse, upsidedown, bitplane, closure); } RegionDestroy(clipped_dst_regions[i].region); } if (n_dst_region == 0) ok = TRUE; free(clipped_dst_regions); } else { ok = __glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); } fail: RegionUninit(®ion); fail_noregion: dispatch = glamor_get_dispatch(glamor_priv); glamor_set_alu(dispatch, GXcopy); glamor_put_dispatch(glamor_priv); if (ok) return TRUE; fall_back: if (!fallback && glamor_ddx_fallback_check_pixmap(src) && glamor_ddx_fallback_check_pixmap(dst)) goto done; if (src_pixmap_priv->type == GLAMOR_DRM_ONLY || dst_pixmap_priv->type == GLAMOR_DRM_ONLY) { LogMessage(X_WARNING, "Access a DRM only pixmap is not allowed within glamor.\n"); return TRUE; } glamor_report_delayed_fallbacks(src->pScreen); glamor_report_delayed_fallbacks(dst->pScreen); glamor_fallback("from %p to %p (%c,%c)\n", src, dst, glamor_get_drawable_location(src), glamor_get_drawable_location(dst)); if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) && glamor_prepare_access(src, GLAMOR_ACCESS_RO) && glamor_prepare_access_gc(gc)) { fbCopyNtoN(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); } glamor_finish_access_gc(gc); glamor_finish_access(src); glamor_finish_access(dst); ok = TRUE; done: glamor_clear_delayed_fallbacks(src->pScreen); glamor_clear_delayed_fallbacks(dst->pScreen); return ok; }
static Bool __glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, GCPtr gc, BoxPtr box, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL; DrawablePtr temp_src = src; glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; glamor_screen_private *glamor_priv; BoxRec bound; ScreenPtr screen; int temp_dx = dx; int temp_dy = dy; int src_x_off, src_y_off, dst_x_off, dst_y_off; int i; int overlaped = 0; Bool ret = FALSE; dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); src_pixmap = glamor_get_drawable_pixmap(src); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); screen = dst_pixmap->drawable.pScreen; glamor_priv = glamor_get_screen_private(dst->pScreen); glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); if (src_pixmap_priv->base.fbo && src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) { int x_shift = abs(src_x_off - dx - dst_x_off); int y_shift = abs(src_y_off - dy - dst_y_off); for (i = 0; i < nbox; i++) { if (x_shift < abs(box[i].x2 - box[i].x1) && y_shift < abs(box[i].y2 - box[i].y1)) { overlaped = 1; break; } } } DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n", box[0].x1, box[0].y1, box[0].x2 - box[0].x1, box[0].y2 - box[0].y1, dx, dy, src_pixmap, dst_pixmap); #ifndef GLAMOR_GLES2 if (!overlaped && (glamor_priv->state != RENDER_STATE || !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex) && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { ret = TRUE; goto done; } #endif glamor_calculate_boxes_bound(&bound, box, nbox); /* Overlaped indicate the src and dst are the same pixmap. */ if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) && (((bound.x2 - bound.x1) * (bound.y2 - bound.y1) * 4 > src_pixmap->drawable.width * src_pixmap->drawable.height) || !(glamor_check_fbo_size(glamor_priv, src_pixmap->drawable.width, src_pixmap->drawable.height))))) { temp_pixmap = glamor_create_pixmap(screen, bound.x2 - bound.x1, bound.y2 - bound.y1, src_pixmap-> drawable.depth, overlaped ? 0 : GLAMOR_CREATE_PIXMAP_CPU); assert(bound.x2 - bound.x1 <= glamor_priv->max_fbo_size); assert(bound.y2 - bound.y1 <= glamor_priv->max_fbo_size); if (!temp_pixmap) goto done; glamor_translate_boxes(box, nbox, -bound.x1, -bound.y1); temp_src = &temp_pixmap->drawable; if (overlaped) glamor_copy_n_to_n_textured(src, temp_src, gc, box, nbox, temp_dx + bound.x1, temp_dy + bound.y1); else fbCopyNtoN(src, temp_src, gc, box, nbox, temp_dx + bound.x1, temp_dy + bound.y1, reverse, upsidedown, bitplane, closure); glamor_translate_boxes(box, nbox, bound.x1, bound.y1); temp_dx = -bound.x1; temp_dy = -bound.y1; } else { temp_dx = dx; temp_dy = dy; temp_src = src; } if (glamor_copy_n_to_n_textured (temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { ret = TRUE; } done: if (temp_src != src) glamor_destroy_pixmap(temp_pixmap); return ret; }
void uxa_copy_n_to_n(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { ScreenPtr screen = pDstDrawable->pScreen; uxa_screen_t *uxa_screen = uxa_get_screen(screen); int src_off_x, src_off_y; int dst_off_x, dst_off_y; PixmapPtr pSrcPixmap, pDstPixmap; if (uxa_screen->info->flags & UXA_USE_GLAMOR) { int ok = 0; if (uxa_prepare_access(pSrcDrawable, UXA_GLAMOR_ACCESS_RO)) { if (uxa_prepare_access(pDstDrawable, UXA_GLAMOR_ACCESS_RW)) { ok = glamor_copy_n_to_n_nf(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure); uxa_finish_access(pDstDrawable, UXA_GLAMOR_ACCESS_RW); } uxa_finish_access(pSrcDrawable, UXA_GLAMOR_ACCESS_RO); } if (!ok) goto fallback; return; } if (uxa_screen->force_fallback) goto fallback; pSrcPixmap = uxa_get_drawable_pixmap(pSrcDrawable); pDstPixmap = uxa_get_drawable_pixmap(pDstDrawable); if (!pSrcPixmap || !pDstPixmap) goto fallback; if (uxa_screen->info->check_copy && !uxa_screen->info->check_copy(pSrcPixmap, pDstPixmap, pGC ? pGC->alu : GXcopy, pGC ? pGC->planemask : FB_ALLONES)) goto fallback; uxa_get_drawable_deltas(pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); uxa_get_drawable_deltas(pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); /* Mixed directions must be handled specially if the card is lame */ if ((uxa_screen->info->flags & UXA_TWO_BITBLT_DIRECTIONS) && reverse != upsidedown) { if (uxa_copy_n_to_n_two_dir (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy)) return; goto fallback; } if (!uxa_pixmap_is_offscreen(pDstPixmap)) { int stride, bpp; char *dst; if (!uxa_pixmap_is_offscreen(pSrcPixmap)) goto fallback; if (!uxa_screen->info->get_image) goto fallback; /* Don't bother with under 8bpp, XYPixmaps. */ bpp = pSrcPixmap->drawable.bitsPerPixel; if (bpp != pDstDrawable->bitsPerPixel || bpp < 8) goto fallback; /* Only accelerate copies: no rop or planemask. */ if (pGC && (!UXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask) || pGC->alu != GXcopy)) goto fallback; dst = pDstPixmap->devPrivate.ptr; stride = pDstPixmap->devKind; bpp /= 8; while (nbox--) { if (!uxa_screen->info->get_image(pSrcPixmap, pbox->x1 + dx + src_off_x, pbox->y1 + dy + src_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, (char *) dst + (pbox->y1 + dst_off_y) * stride + (pbox->x1 + dst_off_x) * bpp, stride)) goto fallback; pbox++; } return; } if (uxa_pixmap_is_offscreen(pSrcPixmap)) { if (!(*uxa_screen->info->prepare_copy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, upsidedown ? -1 : 1, pGC ? pGC->alu : GXcopy, pGC ? pGC-> planemask : FB_ALLONES)) goto fallback; while (nbox--) { (*uxa_screen->info->copy) (pDstPixmap, pbox->x1 + dx + src_off_x, pbox->y1 + dy + src_off_y, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); pbox++; } (*uxa_screen->info->done_copy) (pDstPixmap); } else { int stride, bpp; char *src; if (!uxa_screen->info->put_image) goto fallback; /* Don't bother with under 8bpp, XYPixmaps. */ bpp = pSrcPixmap->drawable.bitsPerPixel; if (bpp != pDstDrawable->bitsPerPixel || bpp < 8) goto fallback; /* Only accelerate copies: no rop or planemask. */ if (pGC && (!UXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask) || pGC->alu != GXcopy)) goto fallback; src = pSrcPixmap->devPrivate.ptr; stride = pSrcPixmap->devKind; bpp /= 8; while (nbox--) { if (!uxa_screen->info->put_image(pDstPixmap, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, (char *) src + (pbox->y1 + dy + src_off_y) * stride + (pbox->x1 + dx + src_off_x) * bpp, stride)) goto fallback; pbox++; } } return; fallback: UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, uxa_drawable_location(pSrcDrawable), uxa_drawable_location(pDstDrawable))); if (uxa_prepare_access(pDstDrawable, UXA_ACCESS_RW)) { if (pSrcDrawable == pDstDrawable || uxa_prepare_access(pSrcDrawable, UXA_ACCESS_RO)) { fbCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure); if (pSrcDrawable != pDstDrawable) uxa_finish_access(pSrcDrawable, UXA_ACCESS_RO); } uxa_finish_access(pDstDrawable, UXA_ACCESS_RW); } }