static Bool _glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane, RegionPtr *pRegion, Bool fallback) { if (!fallback && glamor_ddx_fallback_check_gc(pGC) && glamor_ddx_fallback_check_pixmap(pSrc) && glamor_ddx_fallback_check_pixmap(pDst)) goto fail; if (glamor_prepare_access(pDst, GLAMOR_ACCESS_RW) && glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO) && glamor_prepare_access_gc(pGC)) { *pRegion = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane); } glamor_finish_access_gc(pGC); glamor_finish_access(pSrc); glamor_finish_access(pDst); return TRUE; fail: return FALSE; }
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); }
/** * Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the * current fill style. * * Solid doesn't use an extra pixmap source, so we don't worry about them. * Stippled/OpaqueStippled are 1bpp and can be in fb, so we should worry * about them. */ Bool glamor_prepare_access_gc(GCPtr gc) { if (gc->stipple) { if (!glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO)) return FALSE; } if (gc->fillStyle == FillTiled) { if (!glamor_prepare_access(&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RO)) { if (gc->stipple) glamor_finish_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO); return FALSE; } } return TRUE; }
Bool glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access) { if (!picture || !picture->pDrawable) return TRUE; return glamor_prepare_access(picture->pDrawable, access); }
RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap) { RegionPtr ret; glamor_fallback("pixmap %p \n", pixmap); if (!glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO)) return NULL; ret = fbPixmapToRegion(pixmap); glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RO); return ret; }
static Bool _glamor_get_spans(DrawablePtr drawable, int wmax, DDXPointPtr points, int *widths, int count, char *dst, Bool fallback) { PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); int i; uint8_t *readpixels_dst = (uint8_t *) dst; int x_off, y_off; Bool ret = FALSE; if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) goto fail; glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); for (i = 0; i < count; i++) { #ifdef DEBUG void *data = #endif glamor_download_sub_pixmap_to_cpu(pixmap, points[i].x + x_off, points[i].y + y_off, widths[i], 1, PixmapBytePad(widths[i], drawable->depth), readpixels_dst, 0, GLAMOR_ACCESS_RO); assert(data == readpixels_dst); readpixels_dst += PixmapBytePad(widths[i], drawable->depth); } ret = TRUE; goto done; fail: if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)) goto done; ret = TRUE; if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) { fbGetSpans(drawable, wmax, points, widths, count, dst); } glamor_finish_access(drawable); done: return ret; }
/** * Implements CopyArea from the GPU to the CPU using glReadPixels from the * source FBO. */ static Bool glamor_copy_fbo_cpu(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 src_pixmap = glamor_get_drawable_pixmap(src); FbBits *dst_bits; FbStride dst_stride; int dst_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(dst, GLAMOR_ACCESS_RW); glamor_get_drawable_deltas(src, src_pixmap, &src_xoff, &src_yoff); fbGetDrawable(dst, dst_bits, dst_stride, dst_bpp, dst_xoff, dst_yoff); glamor_download_boxes(src_pixmap, box, nbox, src_xoff + dx, src_yoff + dy, dst_xoff, dst_yoff, (uint8_t *) dst_bits, dst_stride * sizeof (FbBits)); glamor_finish_access(dst); return TRUE; bail: return FALSE; }
static void glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, int x, int y, int w, int h, int left_pad, int image_format, char *bits) { ScreenPtr screen = drawable->pScreen; PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); float fg[4], bg[4]; GLuint tex; unsigned int stride = PixmapBytePad(1, w + left_pad); RegionPtr clip; BoxPtr box; int nbox; float dest_coords[8]; const float bitmap_coords[8] = { 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, }; GLfloat xscale, yscale; glamor_pixmap_private *pixmap_priv; pixmap_priv = glamor_get_pixmap_private(pixmap); pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); glamor_set_normalize_vcoords(xscale, yscale, x, y, x + w, y + h, glamor_priv->yInverted, dest_coords); glamor_fallback("glamor_put_image_xybitmap: disabled\n"); goto fail; if (glamor_priv->put_image_xybitmap_prog == 0) { ErrorF("no program for xybitmap putimage\n"); goto fail; } glamor_set_alu(gc->alu); if (!glamor_set_planemask(pixmap, gc->planemask)) goto fail; dispatch->glUseProgram(glamor_priv->put_image_xybitmap_prog); glamor_get_color_4f_from_pixel(pixmap, gc->fgPixel, fg); dispatch->glUniform4fv (glamor_priv->put_image_xybitmap_fg_uniform_location, 1, fg); glamor_get_color_4f_from_pixel(pixmap, gc->bgPixel, bg); dispatch->glUniform4fv (glamor_priv->put_image_xybitmap_bg_uniform_location, 1, bg); dispatch->glGenTextures(1, &tex); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8); dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad); dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_COLOR_INDEX, GL_BITMAP, bits); dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); /* Now that we've set up our bitmap texture and the shader, shove * the destination rectangle through the cliprects and run the * shader on the resulting fragments. */ dispatch->glVertexPointer(2, GL_FLOAT, 0, dest_coords); dispatch->glEnableClientState(GL_VERTEX_ARRAY); dispatch->glClientActiveTexture(GL_TEXTURE0); dispatch->glTexCoordPointer(2, GL_FLOAT, 0, bitmap_coords); dispatch->glEnableClientState(GL_TEXTURE_COORD_ARRAY); dispatch->glEnable(GL_SCISSOR_TEST); clip = fbGetCompositeClip(gc); for (nbox = REGION_NUM_RECTS(clip), box = REGION_RECTS(clip); nbox--; box++) { int x1 = x; int y1 = y; int x2 = x + w; int y2 = y + h; if (x1 < box->x1) x1 = box->x1; if (y1 < box->y1) y1 = box->y1; if (x2 > box->x2) x2 = box->x2; if (y2 > box->y2) y2 = box->y2; if (x1 >= x2 || y1 >= y2) continue; dispatch->glScissor(box->x1, y_flip(pixmap, box->y1), box->x2 - box->x1, box->y2 - box->y1); dispatch->glDrawArrays(GL_QUADS, 0, 4); } dispatch->glDisable(GL_SCISSOR_TEST); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); dispatch->glDeleteTextures(1, &tex); dispatch->glDisableClientState(GL_VERTEX_ARRAY); dispatch->glDisableClientState(GL_TEXTURE_COORD_ARRAY); return; glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); glamor_fallback(": to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); fail: if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && glamor_prepare_access_gc(gc)) { fbPutImage(drawable, gc, 1, x, y, w, h, left_pad, XYBitmap, bits); } glamor_finish_access_gc(gc); glamor_finish_access(drawable); }
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; }
/** @file glamor_fillspans.c * * GC fill implementation, based loosely on fb_fill.c */ Bool glamor_fill(DrawablePtr drawable, GCPtr gc, int x, int y, int width, int height, Bool fallback) { PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable); int off_x, off_y; PixmapPtr sub_pixmap = NULL; glamor_access_t sub_pixmap_access; DrawablePtr saved_drawable = NULL; int saved_x = x, saved_y = y; glamor_get_drawable_deltas(drawable, dst_pixmap, &off_x, &off_y); switch (gc->fillStyle) { case FillSolid: if (!glamor_solid(dst_pixmap, x + off_x, y + off_y, width, height, gc->alu, gc->planemask, gc->fgPixel)) goto fail; break; case FillStippled: case FillOpaqueStippled: if (!glamor_stipple(dst_pixmap, gc->stipple, x + off_x, y + off_y, width, height, gc->alu, gc->planemask, gc->fgPixel, gc->bgPixel, gc->patOrg.x, gc->patOrg.y)) goto fail; break; case FillTiled: if (!glamor_tile(dst_pixmap, gc->tile.pixmap, x + off_x, y + off_y, width, height, gc->alu, gc->planemask, x - drawable->x - gc->patOrg.x, y - drawable->y - gc->patOrg.y)) goto fail; break; } return TRUE; fail: if (!fallback) { if (glamor_ddx_fallback_check_pixmap(&dst_pixmap->drawable) && glamor_ddx_fallback_check_gc(gc)) return FALSE; } /* Is it possible to set the access as WO? */ sub_pixmap_access = GLAMOR_ACCESS_RW; sub_pixmap = glamor_get_sub_pixmap(dst_pixmap, x + off_x, y + off_y, width, height, sub_pixmap_access); if (sub_pixmap != NULL) { if (gc->fillStyle != FillSolid) { gc->patOrg.x += (drawable->x - x); gc->patOrg.y += (drawable->y - y); } saved_drawable = drawable; drawable = &sub_pixmap->drawable; saved_x = x; saved_y = y; x = 0; y = 0; } if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_gc(gc)) { fbFill(drawable, gc, x, y, width, height); glamor_finish_access_gc(gc); } glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } if (sub_pixmap != NULL) { if (gc->fillStyle != FillSolid) { gc->patOrg.x -= (saved_drawable->x - saved_x); gc->patOrg.y -= (saved_drawable->y - saved_y); } x = saved_x; y = saved_y; glamor_put_sub_pixmap(sub_pixmap, dst_pixmap, x + off_x, y + off_y, width, height, sub_pixmap_access); } return TRUE; }
static Bool _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, DDXPointPtr points, int *widths, int numPoints, int sorted, Bool fallback) { PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); glamor_pixmap_private *dest_pixmap_priv; int i; uint8_t *drawpixels_src = (uint8_t *) src; RegionPtr clip = fbGetCompositeClip(gc); BoxRec *pbox; int x_off, y_off; Bool ret = FALSE; dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { glamor_fallback("pixmap has no fbo.\n"); goto fail; } /* XXX Shall we set alu here? */ if (!glamor_set_planemask(dest_pixmap, gc->planemask)) goto fail; glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off); for (i = 0; i < numPoints; i++) { int n = REGION_NUM_RECTS(clip); pbox = REGION_RECTS(clip); while (n--) { int x1 = points[i].x; int x2 = x1 + widths[i]; int y1 = points[i].y; if (pbox->y1 > points[i].y || pbox->y2 < points[i].y) break; x1 = x1 > pbox->x1 ? x1 : pbox->x1; x2 = x2 < pbox->x2 ? x2 : pbox->x2; if (x1 >= x2) continue; glamor_upload_sub_pixmap_to_texture(dest_pixmap, x1 + x_off, y1 + y_off, x2 - x1, 1, PixmapBytePad(widths[i], drawable->depth), drawpixels_src, 0); } drawpixels_src += PixmapBytePad(widths[i], drawable->depth); } ret = TRUE; goto done; fail: if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)) goto done; glamor_fallback("to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) { fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted); glamor_finish_access(drawable, GLAMOR_ACCESS_RW); } ret = TRUE; done: return ret; }
/** * uxa_validate_gc() sets the ops to glamor's implementations, which may be * accelerated or may sync the card and fall back to fb. */ void glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) { /* fbValidateGC will do direct access to pixmaps if the tiling has changed. * Preempt fbValidateGC by doing its work and masking the change out, so * that we can do the Prepare/finish_access. */ #ifdef FB_24_32BIT if ((changes & GCTile) && fbGetRotatedPixmap(gc)) { gc->pScreen->DestroyPixmap(fbGetRotatedPixmap(gc)); fbGetRotatedPixmap(gc) = 0; } if (gc->fillStyle == FillTiled) { PixmapPtr old_tile, new_tile; old_tile = gc->tile.pixmap; if (old_tile->drawable.bitsPerPixel != drawable->bitsPerPixel) { new_tile = fbGetRotatedPixmap(gc); if (!new_tile || new_tile->drawable.bitsPerPixel != drawable->bitsPerPixel) { if (new_tile) gc->pScreen->DestroyPixmap(new_tile); /* fb24_32ReformatTile will do direct access of a newly- * allocated pixmap. */ glamor_fallback ("GC %p tile FB_24_32 transformat %p.\n", gc, old_tile); if (glamor_prepare_access (&old_tile->drawable, GLAMOR_ACCESS_RO)) { new_tile = fb24_32ReformatTile(old_tile, drawable->bitsPerPixel); glamor_finish_access(&old_tile->drawable, GLAMOR_ACCESS_RO); } } if (new_tile) { fbGetRotatedPixmap(gc) = old_tile; gc->tile.pixmap = new_tile; changes |= GCTile; } } } #endif if (changes & GCTile) { if (!gc->tileIsPixel) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(gc->tile.pixmap); if ((!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) && FbEvenTile(gc->tile.pixmap->drawable.width * drawable->bitsPerPixel)) { glamor_fallback ("GC %p tile changed %p.\n", gc, gc->tile.pixmap); if (glamor_prepare_access (&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RW)) { fbPadPixmap(gc->tile.pixmap); glamor_finish_access (&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RW); } } } /* Mask out the GCTile change notification, now that we've done FB's * job for it. */ changes &= ~GCTile; } if (changes & GCStipple && gc->stipple) { /* We can't inline stipple handling like we do for GCTile because * it sets fbgc privates. */ if (glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW)) { fbValidateGC(gc, changes, drawable); glamor_finish_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW); } } else { fbValidateGC(gc, changes, drawable); } gc->ops = &glamor_gc_ops; }
/** * 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; }