예제 #1
0
static Bool
glamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h,
                    unsigned int format, unsigned long plane_mask, char *d)
{
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv;
    uint32_t    byte_stride = PixmapBytePad(w, drawable->depth);
    BoxRec      box;
    int         off_x, off_y;

    pixmap_priv = glamor_get_pixmap_private(pixmap);
    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
        goto bail;

    if (format != ZPixmap || !glamor_pm_is_solid(drawable, plane_mask))
        goto bail;

    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
    box.x1 = x;
    box.x2 = x + w;
    box.y1 = y;
    box.y2 = y + h;
    glamor_download_boxes(pixmap, &box, 1,
                          drawable->x + off_x, drawable->y + off_y,
                          -x, -y,
                          (uint8_t *) d, byte_stride);
    return TRUE;
bail:
    return FALSE;
}
예제 #2
0
/* 
 * We should already have drawable attached to it, if it has one.
 * Then set the attached pixmap to is_picture format, and set
 * the pict format.
 * */
int
glamor_create_picture(PicturePtr picture)
{
    PixmapPtr pixmap;
    glamor_pixmap_private *pixmap_priv;

    if (!picture || !picture->pDrawable)
        return 0;

    pixmap = glamor_get_drawable_pixmap(picture->pDrawable);
    pixmap_priv = glamor_get_pixmap_private(pixmap);
    if (!pixmap_priv) {
        /* We must create a pixmap priv to track the picture format even
         * if the pixmap is a pure in memory pixmap. The reason is that
         * we may need to upload this pixmap to a texture on the fly. During
         * the uploading, we need to know the picture format. */
        glamor_set_pixmap_type(pixmap, GLAMOR_MEMORY);
        pixmap_priv = glamor_get_pixmap_private(pixmap);
    }
    else {
        if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) {
            /* If the picture format is not compatible with glamor fbo format,
             * we have to mark this pixmap as a separated texture, and don't
             * fallback to DDX layer. */
            if (pixmap_priv->type == GLAMOR_TEXTURE_DRM
                && !glamor_pict_format_is_compatible(picture))
                glamor_set_pixmap_type(pixmap, GLAMOR_SEPARATE_TEXTURE);
        }
    }

    pixmap_priv->base.is_picture = 1;
    pixmap_priv->base.picture = picture;

    return miCreatePicture(picture);
}
예제 #3
0
int
glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv)
{
    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
        return -1;

    glamor_set_destination_pixmap_priv_nc(pixmap_priv);
    return 0;
}
예제 #4
0
static Bool
glamor_put_image_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
                    int w, int h, int leftPad, int format, char *bits)
{
    ScreenPtr screen = drawable->pScreen;
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv;
    uint32_t    byte_stride = PixmapBytePad(w, drawable->depth);
    RegionRec   region;
    BoxRec      box;
    int         off_x, off_y;

    pixmap_priv = glamor_get_pixmap_private(pixmap);

    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
        return FALSE;

    if (gc->alu != GXcopy)
        goto bail;

    if (!glamor_pm_is_solid(&pixmap->drawable, gc->planemask))
        goto bail;

    if (format == XYPixmap && drawable->depth == 1 && leftPad == 0)
        format = ZPixmap;

    if (format != ZPixmap)
        goto bail;

    x += drawable->x;
    y += drawable->y;
    box.x1 = x;
    box.y1 = y;
    box.x2 = box.x1 + w;
    box.y2 = box.y1 + h;
    RegionInit(&region, &box, 1);
    RegionIntersect(&region, &region, gc->pCompositeClip);

    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
    if (off_x || off_y) {
        x += off_x;
        y += off_y;
        RegionTranslate(&region, off_x, off_y);
    }

    glamor_make_current(glamor_priv);

    glamor_upload_region(pixmap, &region, x, y, (uint8_t *) bits, byte_stride);

    RegionUninit(&region);
    return TRUE;
bail:
    return FALSE;
}
예제 #5
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;
}
예제 #6
0
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(&region, box, nbox);
        clipped_regions =
            glamor_compute_clipped_regions(pixmap_priv, &region, &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(&region);
    }
    else
        _glamor_solid_boxes(pixmap, box, nbox, color);

    return TRUE;
}
예제 #7
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;
}
Bool
glamor_set_texture_pixmap(PixmapPtr texture)
{
    glamor_pixmap_private *texture_priv;

    texture_priv = glamor_get_pixmap_private(texture);

    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(texture_priv))
        return FALSE;

    if (glamor_pixmap_priv_is_large(texture_priv))
        return FALSE;

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture_priv->fbo->tex);

    /* we're not setting the sampler uniform here as we always use
     * GL_TEXTURE0, and the default value for uniforms is zero. So,
     * save a bit of CPU time by taking advantage of that.
     */
    return TRUE;
}
예제 #9
0
Bool
glamor_set_texture_pixmap(PixmapPtr texture, Bool destination_red)
{
    glamor_pixmap_private *texture_priv;

    texture_priv = glamor_get_pixmap_private(texture);

    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(texture_priv))
        return FALSE;

    if (glamor_pixmap_priv_is_large(texture_priv))
        return FALSE;

    glamor_bind_texture(glamor_get_screen_private(texture->drawable.pScreen),
                        GL_TEXTURE0,
                        texture_priv->fbo, destination_red);

    /* we're not setting the sampler uniform here as we always use
     * GL_TEXTURE0, and the default value for uniforms is zero. So,
     * save a bit of CPU time by taking advantage of that.
     */
    return TRUE;
}
예제 #10
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;
}
예제 #11
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;

}
예제 #12
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;
}
예제 #13
0
static Bool
glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
			    DrawablePtr dst,
			    GCPtr gc, BoxPtr box, int nbox, int dx, int dy)
{
	ScreenPtr screen = dst->pScreen;
	PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
	PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
	glamor_pixmap_private *src_pixmap_priv, *dst_pixmap_priv;
	glamor_screen_private *glamor_priv =
	    glamor_get_screen_private(screen);
	glamor_gl_dispatch *dispatch;
	int dst_x_off, dst_y_off, src_x_off, src_y_off, i;
	int fbo_x_off, fbo_y_off;
	int src_fbo_x_off, src_fbo_y_off;

	if (!glamor_priv->has_fbo_blit) {
		glamor_delayed_fallback(screen,
					"no EXT_framebuffer_blit\n");
		return FALSE;
	}
	src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
	dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);

	if (gc) {
		if (gc->alu != GXcopy) {
			glamor_delayed_fallback(screen, "non-copy ALU\n");
			return FALSE;
		}
	}

	if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) {
		glamor_delayed_fallback(screen, "no src fbo\n");
		return FALSE;
	}

	if (glamor_set_destination_pixmap(dst_pixmap))
		return FALSE;

	pixmap_priv_get_fbo_off(dst_pixmap_priv, &fbo_x_off, &fbo_y_off);
	pixmap_priv_get_fbo_off(src_pixmap_priv, &src_fbo_x_off, &src_fbo_y_off);

	dispatch = glamor_get_dispatch(glamor_priv);
	dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT,
				    src_pixmap_priv->base.fbo->fb);
	glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off,
				   &dst_y_off);
	glamor_get_drawable_deltas(src, src_pixmap, &src_x_off,
				   &src_y_off);
	dst_x_off += fbo_x_off;
	dst_y_off += fbo_y_off;
	src_y_off += dy + src_fbo_y_off;
	src_x_off += src_fbo_x_off;

	for (i = 0; i < nbox; i++) {
		if (glamor_priv->yInverted) {
			dispatch->glBlitFramebuffer((box[i].x1 + dx +
						     src_x_off),
						    (box[i].y1 +
						     src_y_off),
						    (box[i].x2 + dx +
						     src_x_off),
						    (box[i].y2 +
						     src_y_off),
						    (box[i].x1 +
						     dst_x_off),
						    (box[i].y1 +
						     dst_y_off),
						    (box[i].x2 +
						     dst_x_off),
						    (box[i].y2 +
						     dst_y_off),
						    GL_COLOR_BUFFER_BIT,
						    GL_NEAREST);
		} else {
			int flip_dst_y1 =
			    dst_pixmap->drawable.height - (box[i].y2 +
							   dst_y_off);
			int flip_dst_y2 =
			    dst_pixmap->drawable.height - (box[i].y1 +
							   dst_y_off);
			int flip_src_y1 =
			    src_pixmap->drawable.height - (box[i].y2 +
							   src_y_off);
			int flip_src_y2 =
			    src_pixmap->drawable.height - (box[i].y1 +
							   src_y_off);

			dispatch->glBlitFramebuffer(box[i].x1 + dx +
						    src_x_off,
						    flip_src_y1,
						    box[i].x2 + dx +
						    src_x_off,
						    flip_src_y2,
						    box[i].x1 +
						    dst_x_off,
						    flip_dst_y1,
						    box[i].x2 +
						    dst_x_off,
						    flip_dst_y2,
						    GL_COLOR_BUFFER_BIT,
						    GL_NEAREST);
		}
	}
	glamor_put_dispatch(glamor_priv);
	glamor_priv->state = BLIT_STATE;
	return TRUE;
}
예제 #14
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)
{
	PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL;
	DrawablePtr temp_src = src;
	glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
	glamor_screen_private *glamor_priv;
	BoxRec bound;
	ScreenPtr screen;
	int temp_dx = dx;
	int temp_dy = dy;
	int src_x_off, src_y_off, dst_x_off, dst_y_off;
	int i;
	int overlaped = 0;
	Bool ret = FALSE;

	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);
	screen = dst_pixmap->drawable.pScreen;
	glamor_priv = glamor_get_screen_private(dst->pScreen);
	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);

	if (src_pixmap_priv->base.fbo
		&& src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) {
		int x_shift = abs(src_x_off - dx - dst_x_off);
		int y_shift = abs(src_y_off - dy - dst_y_off);
		for (i = 0; i < nbox; i++) {
			if (x_shift < abs(box[i].x2 - box[i].x1)
			    && y_shift < abs(box[i].y2 - box[i].y1)) {
				overlaped = 1;
				break;
			}
		}
	}
	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);
#ifndef GLAMOR_GLES2
	if (!overlaped &&
	    (glamor_priv->state != RENDER_STATE
	     || !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex)
	    && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx,
					   dy)) {
		ret = TRUE;
		goto done;
	}
#endif
	glamor_calculate_boxes_bound(&bound, box, nbox);

	/*  Overlaped indicate the src and dst are the same pixmap. */
	if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)
			  && (((bound.x2 - bound.x1) * (bound.y2 - bound.y1)
			      * 4 >
			      src_pixmap->drawable.width *
			      src_pixmap->drawable.height)
				|| !(glamor_check_fbo_size(glamor_priv,
					src_pixmap->drawable.width,
					src_pixmap->drawable.height))))) {

		temp_pixmap = glamor_create_pixmap(screen,
						   bound.x2 - bound.x1,
						   bound.y2 - bound.y1,
						   src_pixmap->
						   drawable.depth,
						   overlaped ? 0 :
						   GLAMOR_CREATE_PIXMAP_CPU);
		assert(bound.x2 - bound.x1 <= glamor_priv->max_fbo_size);
		assert(bound.y2 - bound.y1 <= glamor_priv->max_fbo_size);
		if (!temp_pixmap)
			goto done;
		glamor_translate_boxes(box, nbox, -bound.x1, -bound.y1);
		temp_src = &temp_pixmap->drawable;

		if (overlaped)
			glamor_copy_n_to_n_textured(src, temp_src, gc, box,
						    nbox,
						    temp_dx + bound.x1,
						    temp_dy + bound.y1);
		else
			fbCopyNtoN(src, temp_src, gc, box, nbox,
				   temp_dx + bound.x1, temp_dy + bound.y1,
				   reverse, upsidedown, bitplane, closure);
		glamor_translate_boxes(box, nbox, bound.x1, bound.y1);
		temp_dx = -bound.x1;
		temp_dy = -bound.y1;
	} else {
		temp_dx = dx;
		temp_dy = dy;
		temp_src = src;
	}

	if (glamor_copy_n_to_n_textured
	    (temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) {
		ret = TRUE;
	}
done:
	if (temp_src != src)
		glamor_destroy_pixmap(temp_pixmap);
	return ret;
}
예제 #15
0
static Bool
glamor_fill_spans_gl(DrawablePtr drawable,
                     GCPtr gc,
                     int n, DDXPointPtr points, int *widths, int sorted)
{
    ScreenPtr screen = drawable->pScreen;
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv;
    glamor_program *prog;
    int off_x, off_y;
    GLshort *v;
    char *vbo_offset;
    int c;
    int box_x, box_y;

    pixmap_priv = glamor_get_pixmap_private(pixmap);
    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
        goto bail;

    glamor_make_current(glamor_priv);

    if (glamor_priv->glsl_version >= 130) {
        prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program,
                                       &glamor_facet_fillspans_130);

        if (!prog)
            goto bail;

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

        v = glamor_get_vbo_space(drawable->pScreen, n * (4 * sizeof (GLshort)), &vbo_offset);

        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1);
        glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE,
                              4 * sizeof (GLshort), vbo_offset);

        for (c = 0; c < n; c++) {
            v[0] = points->x;
            v[1] = points->y;
            v[2] = *widths++;
            points++;
            v += 4;
        }

        glamor_put_vbo_space(screen);
    } else {
        prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program,
                                       &glamor_facet_fillspans_120);

        if (!prog)
            goto bail;

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

        v = glamor_get_vbo_space(drawable->pScreen, n * 8 * sizeof (short), &vbo_offset);

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

        for (c = 0; c < n; c++) {
            v[0] = points->x;           v[1] = points->y;
            v[2] = points->x;           v[3] = points->y + 1;
            v[4] = points->x + *widths; v[5] = points->y + 1;
            v[6] = points->x + *widths; v[7] = points->y;

            widths++;
            points++;
            v += 8;
        }

        glamor_put_vbo_space(screen);
    }

    glEnable(GL_SCISSOR_TEST);

    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
        int nbox = RegionNumRects(gc->pCompositeClip);
        BoxPtr box = RegionRects(gc->pCompositeClip);

        glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, FALSE, prog->matrix_uniform, &off_x, &off_y);

        while (nbox--) {
            glScissor(box->x1 + off_x,
                      box->y1 + off_y,
                      box->x2 - box->x1,
                      box->y2 - box->y1);
            box++;
            if (glamor_priv->glsl_version >= 130)
                glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, n);
            else {
                glamor_glDrawArrays_GL_QUADS(glamor_priv, nbox);
            }
        }
    }
예제 #16
0
static Bool
glamor_poly_fill_rect_gl(DrawablePtr drawable,
                         GCPtr gc, int nrect, xRectangle *prect)
{
    ScreenPtr screen = drawable->pScreen;
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv;
    glamor_program *prog;
    int off_x, off_y;
    GLshort *v;
    char *vbo_offset;
    int box_x, box_y;

    pixmap_priv = glamor_get_pixmap_private(pixmap);
    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
        goto bail;

    glamor_get_context(glamor_priv);

    if (glamor_priv->glsl_version >= 130) {
        prog = glamor_use_program_fill(pixmap, gc,
                                       &glamor_priv->poly_fill_rect_program,
                                       &glamor_facet_polyfillrect_130);

        if (!prog)
            goto bail_ctx;

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

        v = glamor_get_vbo_space(drawable->pScreen, nrect * sizeof (xRectangle), &vbo_offset);

        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1);
        glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE,
                              4 * sizeof (short), vbo_offset);

        memcpy(v, prect, nrect * sizeof (xRectangle));

        glamor_put_vbo_space(screen);
    } else {
        int n;

        prog = glamor_use_program_fill(pixmap, gc,
                                       &glamor_priv->poly_fill_rect_program,
                                       &glamor_facet_polyfillrect_120);

        if (!prog)
            goto bail_ctx;

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

        v = glamor_get_vbo_space(drawable->pScreen, nrect * 8 * sizeof (short), &vbo_offset);

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

        for (n = 0; n < nrect; n++) {
            v[0] = prect->x;                v[1] = prect->y;
            v[2] = prect->x;                v[3] = prect->y + prect->height;
            v[4] = prect->x + prect->width; v[5] = prect->y + prect->height;
            v[6] = prect->x + prect->width; v[7] = prect->y;
            prect++;
            v += 8;
        }

        glamor_put_vbo_space(screen);
    }

    glEnable(GL_SCISSOR_TEST);

    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
        int nbox = RegionNumRects(gc->pCompositeClip);
        BoxPtr box = RegionRects(gc->pCompositeClip);

        glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, FALSE, prog->matrix_uniform, &off_x, &off_y);

        while (nbox--) {
            glScissor(box->x1 + off_x,
                      box->y1 + off_y,
                      box->x2 - box->x1,
                      box->y2 - box->y1);
            box++;
            if (glamor_priv->glsl_version >= 130)
                glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect);
            else {
                if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
                    glDrawArrays(GL_QUADS, 0, nrect * 4);
                } else {
                    int i;
                    for (i = 0; i < nrect; i++) {
                        glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
                    }
                }
            }
        }
    }
예제 #17
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;
}
예제 #18
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;
}
예제 #19
0
static glamor_program *
glamor_dash_setup(DrawablePtr drawable, GCPtr gc)
{
    ScreenPtr screen = drawable->pScreen;
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
    PixmapPtr dash_pixmap;
    glamor_pixmap_private *dash_priv;
    glamor_program *prog;

    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
        goto bail;

    if (gc->lineWidth != 0)
        goto bail;

    dash_pixmap = glamor_get_dash_pixmap(gc);
    dash_priv = glamor_get_pixmap_private(pixmap);

    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dash_priv))
        goto bail;

    glamor_make_current(glamor_priv);

    switch (gc->lineStyle) {
    case LineOnOffDash:
        prog = glamor_use_program_fill(pixmap, gc,
                                       &glamor_priv->on_off_dash_line_progs,
                                       &glamor_facet_on_off_dash_lines);
        if (!prog)
            goto bail;
        break;
    case LineDoubleDash:
        if (gc->fillStyle != FillSolid)
            goto bail;

        prog = &glamor_priv->double_dash_line_prog;

        if (!prog->prog) {
            if (!glamor_build_program(screen, prog,
                                      &glamor_facet_double_dash_lines,
                                      NULL, NULL, NULL))
                goto bail;
        }

        if (!glamor_use_program(pixmap, gc, prog, NULL))
            goto bail;

        glamor_set_color(pixmap, gc->fgPixel, prog->fg_uniform);
        glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform);
        break;

    default:
        goto bail;
    }


    /* Set the dash pattern as texture 1 */

    glamor_bind_texture(glamor_priv, GL_TEXTURE1, dash_priv->fbo, FALSE);
    glUniform1i(prog->dash_uniform, 1);
    glUniform1f(prog->dash_length_uniform, dash_pixmap->drawable.width);

    return prog;

bail:
    return NULL;
}
static Bool
glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc,
                         int start_x, int y, unsigned int nglyph,
                         CharInfoPtr *ppci, void *pglyph_base)
{
    ScreenPtr screen = drawable->pScreen;
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv;
    glamor_program *prog;
    RegionPtr clip = gc->pCompositeClip;
    int box_index;

    pixmap_priv = glamor_get_pixmap_private(pixmap);
    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
        goto bail;

    glamor_make_current(glamor_priv);

    prog = glamor_use_program_fill(pixmap, gc,
                                   &glamor_priv->poly_glyph_blt_progs,
                                   &glamor_facet_poly_glyph_blt);
    if (!prog)
        goto bail;

    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);

    start_x += drawable->x;
    y += drawable->y;

    glamor_pixmap_loop(pixmap_priv, box_index) {
        int x;
        int n;
        int num_points, max_points;
        INT16 *points = NULL;
        int off_x, off_y;
        char *vbo_offset;

        glamor_set_destination_drawable(drawable, box_index, FALSE, TRUE,
                                        prog->matrix_uniform, &off_x, &off_y);

        max_points = 500;
        num_points = 0;
        x = start_x;
        for (n = 0; n < nglyph; n++) {
            CharInfoPtr charinfo = ppci[n];
            int w = GLYPHWIDTHPIXELS(charinfo);
            int h = GLYPHHEIGHTPIXELS(charinfo);
            uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo);

            if (w && h) {
                int glyph_x = x + charinfo->metrics.leftSideBearing;
                int glyph_y = y - charinfo->metrics.ascent;
                int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo);
                int xx, yy;

                for (yy = 0; yy < h; yy++) {
                    uint8_t *glyph = glyphbits;
                    for (xx = 0; xx < w; glyph += ((xx&7) == 7), xx++) {
                        int pt_x_i = glyph_x + xx;
                        int pt_y_i = glyph_y + yy;

                        if (!(*glyph & (1 << (xx & 7))))
                            continue;

                        if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL))
                            continue;

                        if (!num_points) {
                            points = glamor_get_vbo_space(screen,
                                                          max_points *
                                                          (2 * sizeof (INT16)),
                                                          &vbo_offset);

                            glVertexAttribPointer(GLAMOR_VERTEX_POS,
                                                  2, GL_SHORT,
                                                  GL_FALSE, 0, vbo_offset);
                        }

                        *points++ = pt_x_i;
                        *points++ = pt_y_i;
                        num_points++;

                        if (num_points == max_points) {
                            glamor_put_vbo_space(screen);
                            glDrawArrays(GL_POINTS, 0, num_points);
                            num_points = 0;
                        }
                    }
                    glyphbits += glyph_stride;
                }
            }
            x += charinfo->metrics.characterWidth;
        }

        if (num_points) {
            glamor_put_vbo_space(screen);
            glDrawArrays(GL_POINTS, 0, num_points);
        }
    }