Bool
glamor_set_solid(PixmapPtr      pixmap,
                 GCPtr          gc,
                 Bool           use_alu,
                 GLint          uniform)
{
    CARD32      pixel;
    int         alu = use_alu ? gc->alu : GXcopy;

    if (!glamor_set_planemask(gc->depth, gc->planemask))
        return FALSE;

    pixel = gc->fgPixel;

    if (!glamor_set_alu(pixmap->drawable.pScreen, alu)) {
        switch (gc->alu) {
        case GXclear:
            pixel = 0;
            break;
        case GXcopyInverted:
            pixel = ~pixel;
            break;
        case GXset:
            pixel = ~0 & gc->planemask;
            break;
        default:
            return FALSE;
        }
    }
    glamor_set_color(pixmap, gc->fgPixel, uniform);

    return TRUE;
}
Bool
glamor_set_tiled(PixmapPtr      pixmap,
                 GCPtr          gc,
                 GLint          offset_uniform,
                 GLint          size_inv_uniform)
{
    if (!glamor_set_alu(pixmap->drawable.pScreen, gc->alu))
        return FALSE;

    if (!glamor_set_planemask(gc->depth, gc->planemask))
        return FALSE;

    return glamor_set_texture(gc->tile.pixmap,
                              -gc->patOrg.x,
                              -gc->patOrg.y,
                              offset_uniform,
                              size_inv_uniform);
}
Example #3
0
Bool
glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
             unsigned char alu, unsigned long planemask, unsigned long fg_pixel)
{
    ScreenPtr screen = pixmap->drawable.pScreen;
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    glamor_pixmap_private *pixmap_priv;
    BoxRec box;

    pixmap_priv = glamor_get_pixmap_private(pixmap);

    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
        return FALSE;

    if (!glamor_set_planemask(pixmap, planemask)) {
        glamor_fallback("Failedto set planemask  in glamor_solid.\n");
        return FALSE;
    }

    glamor_get_context(glamor_priv);
    if (!glamor_set_alu(screen, alu)) {
        if (alu == GXclear)
            fg_pixel = 0;
        else {
            glamor_fallback("unsupported alu %x\n", alu);
            glamor_put_context(glamor_priv);
            return FALSE;
        }
    }
    box.x1 = x;
    box.y1 = y;
    box.x2 = x + width;
    box.y2 = y + height;
    glamor_solid_boxes(pixmap, &box, 1, fg_pixel);

    glamor_set_alu(screen, GXcopy);
    glamor_put_context(glamor_priv);

    return TRUE;
}
Example #4
0
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;
}
Example #5
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);
}
static Bool
glamor_copy_fbo_fbo_draw(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);
    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
    glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap);
    glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap);
    int src_box_index, dst_box_index;
    int dst_off_x, dst_off_y;
    int src_off_x, src_off_y;
    GLshort *v;
    char *vbo_offset;
    struct copy_args args;
    glamor_program *prog;
    const glamor_facet *copy_facet;
    int n;

    glamor_make_current(glamor_priv);

    if (gc && !glamor_set_planemask(gc->depth, gc->planemask))
        goto bail_ctx;

    if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy))
        goto bail_ctx;

    if (bitplane) {
        prog = &glamor_priv->copy_plane_prog;
        copy_facet = &glamor_facet_copyplane;
    } else {
        prog = &glamor_priv->copy_area_prog;
        copy_facet = &glamor_facet_copyarea;
    }

    if (prog->failed)
        goto bail_ctx;

    if (!prog->prog) {
        if (!glamor_build_program(screen, prog,
                                  copy_facet, NULL, NULL, NULL))
            goto bail_ctx;
    }

    args.src_pixmap = src_pixmap;
    args.bitplane = bitplane;

    /* Set up the vertex buffers for the points */

    v = glamor_get_vbo_space(dst->pScreen, nbox * 8 * sizeof (int16_t), &vbo_offset);

    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
                          2 * sizeof (GLshort), vbo_offset);

    for (n = 0; n < nbox; n++) {
        v[0] = box->x1; v[1] = box->y1;
        v[2] = box->x1; v[3] = box->y2;
        v[4] = box->x2; v[5] = box->y2;
        v[6] = box->x2; v[7] = box->y1;
        v += 8;
        box++;
    }

    glamor_put_vbo_space(screen);

    glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y);

    glEnable(GL_SCISSOR_TEST);

    glamor_pixmap_loop(src_priv, src_box_index) {
        BoxPtr src_box = glamor_pixmap_box_at(src_priv, src_box_index);

        args.dx = dx + src_off_x - src_box->x1;
        args.dy = dy + src_off_y - src_box->y1;
        args.src = glamor_pixmap_fbo_at(src_priv, src_box_index);

        if (!glamor_use_program(dst_pixmap, gc, prog, &args))
            goto bail_ctx;

        glamor_pixmap_loop(dst_priv, dst_box_index) {
            glamor_set_destination_drawable(dst, dst_box_index, FALSE, FALSE,
                                            prog->matrix_uniform,
                                            &dst_off_x, &dst_off_y);

            glScissor(dst_off_x - args.dx,
                      dst_off_y - args.dy,
                      src_box->x2 - src_box->x1,
                      src_box->y2 - src_box->y1);

            glamor_glDrawArrays_GL_QUADS(glamor_priv, nbox);
        }
Example #7
0
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(&region, &box, 1);
        clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv,
                                                             &region,
                                                             &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(&region);
    }
    else
        _glamor_tile(pixmap, tile, x, y, width, height, tile_x, tile_y);

    glamor_set_alu(screen, GXcopy);
    return TRUE;
 fail:
    return FALSE;

}
Example #8
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;
}
Example #9
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;
}