Bool glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, unsigned long fg_pixel) { glamor_pixmap_private *pixmap_priv; GLfloat color[4]; pixmap_priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return FALSE; glamor_get_rgba_from_pixel(fg_pixel, &color[0], &color[1], &color[2], &color[3], format_for_pixmap(pixmap)); if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { RegionRec region; int n_region; glamor_pixmap_clipped_regions *clipped_regions; int i; RegionInitBoxes(®ion, box, nbox); clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &n_region, 0, 0, 0); for (i = 0; i < n_region; i++) { BoxPtr inner_box; int inner_nbox; SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx); inner_box = RegionRects(clipped_regions[i].region); inner_nbox = RegionNumRects(clipped_regions[i].region); _glamor_solid_boxes(pixmap, inner_box, inner_nbox, color); RegionDestroy(clipped_regions[i].region); } free(clipped_regions); RegionUninit(®ion); } else _glamor_solid_boxes(pixmap, box, nbox, color); return TRUE; }
Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int x, int y, int width, int height, unsigned char alu, unsigned long planemask, int tile_x, int tile_y) { ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_pixmap_private *dst_pixmap_priv; glamor_pixmap_private *src_pixmap_priv; dst_pixmap_priv = glamor_get_pixmap_private(pixmap); src_pixmap_priv = glamor_get_pixmap_private(tile); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) return FALSE; if (glamor_priv->tile_prog == 0) { glamor_fallback("Tiling unsupported\n"); goto fail; } if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { /* XXX dynamic uploading candidate. */ glamor_fallback("Non-texture tile pixmap\n"); goto fail; } if (!glamor_set_planemask(pixmap, planemask)) { glamor_fallback("unsupported planemask %lx\n", planemask); goto fail; } glamor_make_current(glamor_priv); if (!glamor_set_alu(screen, alu)) { glamor_fallback("unsupported alu %x\n", alu); goto fail; } if (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, k; BoxRec box; RegionRec region; box.x1 = x; box.y1 = y; box.x2 = x + width; box.y2 = y + height; RegionInitBoxes(®ion, &box, 1); clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv, ®ion, &n_dst_region, 0, 0, 0); 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); if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { RegionTranslate(clipped_dst_regions[i].region, tile_x - x, tile_y - y); DEBUGF("tiled a large src pixmap. %dx%d \n", tile->drawable.width, tile->drawable.height); clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv, clipped_dst_regions[i]. region, &n_src_region, 1, 0, 0); DEBUGF("got %d src regions %d \n", n_src_region); for (j = 0; j < n_src_region; j++) { SET_PIXMAP_FBO_CURRENT(src_pixmap_priv, clipped_src_regions[j].block_idx); RegionTranslate(clipped_src_regions[j].region, x - tile_x, y - tile_y); current_boxes = RegionRects(clipped_src_regions[j].region); n_current_boxes = RegionNumRects(clipped_src_regions[j].region); for (k = 0; k < n_current_boxes; k++) { DEBUGF ("Tile on %d %d %d %d dst block id %d tile block id %d tilex %d tiley %d\n", current_boxes[k].x1, current_boxes[k].y1, current_boxes[k].x2 - current_boxes[k].x1, current_boxes[k].y2 - current_boxes[k].y1, clipped_dst_regions[i].block_idx, clipped_src_regions[j].block_idx, (tile_x + (current_boxes[k].x1 - x)), tile_y + (current_boxes[k].y1 - y)); _glamor_tile(pixmap, tile, current_boxes[k].x1, current_boxes[k].y1, current_boxes[k].x2 - current_boxes[k].x1, current_boxes[k].y2 - current_boxes[k].y1, (tile_x + (current_boxes[k].x1 - x)), (tile_y + (current_boxes[k].y1 - y))); } RegionDestroy(clipped_src_regions[j].region); } free(clipped_src_regions); } else { current_boxes = RegionRects(clipped_dst_regions[i].region); n_current_boxes = RegionNumRects(clipped_dst_regions[i].region); for (k = 0; k < n_current_boxes; k++) { _glamor_tile(pixmap, tile, current_boxes[k].x1, current_boxes[k].y1, current_boxes[k].x2 - current_boxes[k].x1, current_boxes[k].y2 - current_boxes[k].y1, (tile_x + (current_boxes[k].x1 - x)), (tile_y + (current_boxes[k].y1 - y))); } } RegionDestroy(clipped_dst_regions[i].region); } free(clipped_dst_regions); RegionUninit(®ion); } else _glamor_tile(pixmap, tile, x, y, width, height, tile_x, tile_y); glamor_set_alu(screen, GXcopy); return TRUE; fail: return FALSE; }
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; }