Пример #1
0
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);
}
Пример #3
0
/**
 * 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;
}
Пример #4
0
Bool
glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access)
{
    if (!picture || !picture->pDrawable)
        return TRUE;

    return glamor_prepare_access(picture->pDrawable, access);
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #8
0
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);
}
Пример #9
0
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(&region, box, nbox);
	extent = RegionExtents(&region);

	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(&region, dst_x_off, dst_y_off);
			if (!force_clip)
				clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv,
										     &region, &n_dst_region, 0,
										     reverse, upsidedown);
			else
				clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv,
										         &region, &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(&region);
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;
}
Пример #10
0
/** @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;
}
Пример #11
0
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;
}
Пример #12
0
/**
 * 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;
}
Пример #13
0
/**
 * 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;
}