/* XXX LARGE pixmap? */ Bool glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) { glamor_pixmap_fbo *old_fbo; glamor_pixmap_fbo *new_fbo = NULL; PixmapPtr scratch = NULL; glamor_pixmap_private *scratch_priv; DrawablePtr drawable; GCPtr gc = NULL; int ret = FALSE; drawable = &pixmap_priv->base.pixmap->drawable; if (!GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(pixmap_priv)) return TRUE; old_fbo = pixmap_priv->base.fbo; if (!old_fbo) return FALSE; gc = GetScratchGC(drawable->depth, screen); if (!gc) goto fail; scratch = glamor_create_pixmap(screen, drawable->width, drawable->height, drawable->depth, GLAMOR_CREATE_PIXMAP_FIXUP); scratch_priv = glamor_get_pixmap_private(scratch); if (!scratch_priv->base.fbo) goto fail; ValidateGC(&scratch->drawable, gc); glamor_copy_area(drawable, &scratch->drawable, gc, 0, 0, drawable->width, drawable->height, 0, 0); old_fbo = glamor_pixmap_detach_fbo(pixmap_priv); new_fbo = glamor_pixmap_detach_fbo(scratch_priv); glamor_pixmap_attach_fbo(pixmap_priv->base.pixmap, new_fbo); glamor_pixmap_attach_fbo(scratch, old_fbo); DEBUGF("old %dx%d type %d\n", drawable->width, drawable->height, pixmap_priv->type); DEBUGF("copy tex %d %dx%d to tex %d %dx%d \n", old_fbo->tex, old_fbo->width, old_fbo->height, new_fbo->tex, new_fbo->width, new_fbo->height); ret = TRUE; fail: if (gc) FreeScratchGC(gc); if (scratch) glamor_destroy_pixmap(scratch); return ret; }
static Bool _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, int w, int h, int left_pad, int image_format, char *bits, Bool fallback) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); RegionPtr clip; int x_off, y_off; Bool ret = FALSE; PixmapPtr temp_pixmap, sub_pixmap; glamor_pixmap_private *temp_pixmap_priv; BoxRec box; int stride; glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); clip = fbGetCompositeClip(gc); if (image_format == XYBitmap) { assert(depth == 1); goto fail; } if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_fallback("has no fbo.\n"); goto fail; } if (image_format != ZPixmap) { glamor_fallback("non-ZPixmap\n"); goto fail; } if (!glamor_set_planemask(pixmap, gc->planemask)) { goto fail; } /* create a temporary pixmap and upload the bits to that * pixmap, then apply clip copy it to the destination pixmap.*/ stride = PixmapBytePad(w, depth); box.x1 = x + drawable->x; box.y1 = y + drawable->y; box.x2 = x + w + drawable->x; box.y2 = y + h + drawable->y; if ((clip != NULL && RegionContainsRect(clip, &box) != rgnIN) || gc->alu != GXcopy) { temp_pixmap = glamor_create_pixmap(drawable->pScreen, w, h, depth, 0); if (temp_pixmap == NULL) goto fail; temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap); if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) { temp_pixmap_priv->base.picture = pixmap_priv->base.picture; temp_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture; } glamor_upload_sub_pixmap_to_texture(temp_pixmap, 0, 0, w, h, stride, bits, 0); glamor_copy_area(&temp_pixmap->drawable, drawable, gc, 0, 0, w, h, x, y); glamor_destroy_pixmap(temp_pixmap); } else { glamor_upload_sub_pixmap_to_texture(pixmap, x + drawable->x + x_off, y + drawable->y + y_off, w, h, stride, bits, 0); } ret = TRUE; goto done; fail: glamor_set_planemask(pixmap, ~0); if (!fallback && glamor_ddx_fallback_check_pixmap(&pixmap->drawable)) goto done; glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); sub_pixmap = glamor_get_sub_pixmap(pixmap, x + x_off + drawable->x, y + y_off + drawable->y, w, h, GLAMOR_ACCESS_RW); if (sub_pixmap) { if (clip != NULL) pixman_region_translate (clip, -x - drawable->x, -y - drawable->y); fbPutImage(&sub_pixmap->drawable, gc, depth, 0, 0, w, h, left_pad, image_format, bits); glamor_put_sub_pixmap(sub_pixmap, pixmap, x + x_off + drawable->x, y + y_off + drawable->y, w, h, GLAMOR_ACCESS_RW); if (clip != NULL) pixman_region_translate (clip, x + drawable->x, y + drawable->y); } else fbPutImage(drawable, gc, depth, x, y, w, h, left_pad, image_format, bits); ret = TRUE; done: return ret; }