Example #1
0
Bool
glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
{
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);

    return glamor_download_pixmap_to_cpu(pixmap, access);
}
Example #2
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;
}
Example #3
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);
}
Example #4
0
static void
glamor_dash_loop(DrawablePtr drawable, GCPtr gc, glamor_program *prog,
                 int n, GLenum mode)
{
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
    int box_index;
    int off_x, off_y;

    glEnable(GL_SCISSOR_TEST);

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

        glamor_set_destination_drawable(drawable, box_index, TRUE, TRUE,
                                        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++;
            glDrawArrays(mode, 0, n);
        }
    }
Example #5
0
/* Upload picture to texture.  We may need to flip the y axis or
 * wire alpha to 1. So we may conditional create fbo for the picture.
 * */
enum glamor_pixmap_status
glamor_upload_picture_to_texture(PicturePtr picture)
{
    PixmapPtr pixmap;

    assert(picture->pDrawable);
    pixmap = glamor_get_drawable_pixmap(picture->pDrawable);

    return glamor_upload_pixmap_to_texture(pixmap);
}
Example #6
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;
}
static void
glamor_glyphs_flush(CARD8 op, PicturePtr src, PicturePtr dst,
                   glamor_program *prog,
                   struct glamor_glyph_atlas *atlas, int nglyph)
{
    DrawablePtr drawable = dst->pDrawable;
    glamor_screen_private *glamor_priv = glamor_get_screen_private(drawable->pScreen);
    PixmapPtr atlas_pixmap = atlas->atlas;
    glamor_pixmap_private *atlas_priv = glamor_get_pixmap_private(atlas_pixmap);
    glamor_pixmap_fbo *atlas_fbo = glamor_pixmap_fbo_at(atlas_priv, 0, 0);
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
    int box_x, box_y;
    int off_x, off_y;

    glamor_put_vbo_space(drawable->pScreen);

    glEnable(GL_SCISSOR_TEST);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, atlas_fbo->tex);

    for (;;) {
        if (!glamor_use_program_render(prog, op, src, dst))
            break;

        glUniform1i(prog->atlas_uniform, 1);

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

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

            /* Run over the clip list, drawing the glyphs
             * in each box
             */

            while (nbox--) {
                glScissor(box->x1 + off_x,
                          box->y1 + off_y,
                          box->x2 - box->x1,
                          box->y2 - box->y1);
                box++;

                if (glamor_glyph_use_130(glamor_priv))
                    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph);
                else
                    glamor_glDrawArrays_GL_QUADS(glamor_priv, nglyph);
            }
        }
        if (prog->alpha != glamor_program_alpha_ca_first)
            break;
        prog++;
    }
Example #8
0
const Bool
glamor_get_drawable_location(const DrawablePtr drawable)
{
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
    glamor_screen_private *glamor_priv =
        glamor_get_screen_private(drawable->pScreen);
    if (pixmap_priv == NULL || pixmap_priv->base.gl_fbo == 0)
        return 'm';
    if (pixmap_priv->base.fbo->fb == glamor_priv->screen_fbo)
        return 's';
    else
        return 'f';
}
Example #9
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;
}
Example #11
0
/* Upload picture to texture.  We may need to flip the y axis or
 * wire alpha to 1. So we may conditional create fbo for the picture.
 * */
enum glamor_pixmap_status
glamor_upload_picture_to_texture(PicturePtr picture)
{
    PixmapPtr pixmap;

    assert(picture->pDrawable);
    pixmap = glamor_get_drawable_pixmap(picture->pDrawable);

    if (glamor_upload_sub_pixmap_to_texture(pixmap, 0, 0,
                                            pixmap->drawable.width,
                                            pixmap->drawable.height,
                                            pixmap->devKind,
                                            pixmap->devPrivate.ptr, 0,
                                            picture->format))
        return GLAMOR_UPLOAD_DONE;
    else
        return GLAMOR_UPLOAD_FAILED;
}
Example #12
0
void
glamor_destroy_picture(PicturePtr picture)
{
    PixmapPtr pixmap;
    glamor_pixmap_private *pixmap_priv;

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

    pixmap = glamor_get_drawable_pixmap(picture->pDrawable);
    pixmap_priv = glamor_get_pixmap_private(pixmap);

    if (pixmap_priv) {
        pixmap_priv->base.is_picture = 0;
        pixmap_priv->base.picture = NULL;
    }
    miDestroyPicture(picture);
}
Example #13
0
void
glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode)
{
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
    glamor_screen_private *glamor_priv =
        glamor_get_screen_private(drawable->pScreen);

    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv))
        return;

    if (access_mode != GLAMOR_ACCESS_RO) {
        glamor_restore_pixmap_to_texture(pixmap);
    }

    if (pixmap_priv->base.fbo->pbo != 0 && pixmap_priv->base.fbo->pbo_valid) {
        assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);

        glamor_get_context(glamor_priv);
        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
        glDeleteBuffers(1, &pixmap_priv->base.fbo->pbo);
        glamor_put_context(glamor_priv);

        pixmap_priv->base.fbo->pbo_valid = FALSE;
        pixmap_priv->base.fbo->pbo = 0;
    }
    else {
        free(pixmap->devPrivate.ptr);
    }

    if (pixmap_priv->type == GLAMOR_TEXTURE_DRM)
        pixmap->devKind = pixmap_priv->base.drm_stride;

    if (pixmap_priv->base.gl_fbo == GLAMOR_FBO_DOWNLOADED)
        pixmap_priv->base.gl_fbo = GLAMOR_FBO_NORMAL;

    pixmap->devPrivate.ptr = NULL;
}
/**
 * glamor_trapezoids will generate trapezoid mask accumulating in
 * system memory.
 */
void
glamor_trapezoids(CARD8 op,
                  PicturePtr src, PicturePtr dst,
                  PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
                  int ntrap, xTrapezoid *traps)
{
    ScreenPtr screen = dst->pDrawable->pScreen;
    BoxRec bounds;
    PicturePtr picture;
    INT16 x_dst, y_dst;
    INT16 x_rel, y_rel;
    int width, height, stride;
    PixmapPtr pixmap;
    pixman_image_t *image = NULL;

    /* If a mask format wasn't provided, we get to choose, but behavior should
     * be as if there was no temporary mask the traps were accumulated into.
     */
    if (!mask_format) {
        if (dst->polyEdge == PolyEdgeSharp)
            mask_format = PictureMatchFormat(screen, 1, PICT_a1);
        else
            mask_format = PictureMatchFormat(screen, 8, PICT_a8);
        for (; ntrap; ntrap--, traps++)
            glamor_trapezoids(op, src, dst, mask_format, x_src,
                              y_src, 1, traps);
        return;
    }

    miTrapezoidBounds(ntrap, traps, &bounds);

    if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
        return;

    x_dst = traps[0].left.p1.x >> 16;
    y_dst = traps[0].left.p1.y >> 16;

    width = bounds.x2 - bounds.x1;
    height = bounds.y2 - bounds.y1;
    stride = PixmapBytePad(width, mask_format->depth);

    picture = glamor_create_mask_picture(screen, dst, mask_format,
                                         width, height);
    if (!picture)
        return;

    image = pixman_image_create_bits(picture->format,
                                     width, height, NULL, stride);
    if (!image) {
        FreePicture(picture, 0);
        return;
    }

    for (; ntrap; ntrap--, traps++)
        pixman_rasterize_trapezoid(image,
                                   (pixman_trapezoid_t *) traps,
                                   -bounds.x1, -bounds.y1);

    pixmap = glamor_get_drawable_pixmap(picture->pDrawable);

    screen->ModifyPixmapHeader(pixmap, width, height,
                               mask_format->depth,
                               BitsPerPixel(mask_format->depth),
                               PixmapBytePad(width,
                                             mask_format->depth),
                               pixman_image_get_data(image));

    x_rel = bounds.x1 + x_src - x_dst;
    y_rel = bounds.y1 + y_src - y_dst;

    CompositePicture(op, src, picture, dst,
                     x_rel, y_rel,
                     0, 0,
                     bounds.x1, bounds.y1,
                     bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);

    if (image)
        pixman_image_unref(image);

    FreePicture(picture, 0);
}
Example #15
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 #16
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;
}
Example #17
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;
}
Example #18
0
static Bool
glamor_copy_n_to_n_textured(DrawablePtr src,
			    DrawablePtr dst,
			    GCPtr gc, BoxPtr box, int nbox, int dx, int dy)
{
	glamor_screen_private *glamor_priv =
	    glamor_get_screen_private(dst->pScreen);
	glamor_gl_dispatch *dispatch;
	PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
	PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
	int i;
	float vertices[8], texcoords[8];
	glamor_pixmap_private *src_pixmap_priv;
	glamor_pixmap_private *dst_pixmap_priv;
	int src_x_off, src_y_off, dst_x_off, dst_y_off;
	GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale;

	src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
	dst_pixmap_priv = glamor_get_pixmap_private(dst_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);

	if (!src_pixmap_priv->base.gl_fbo) {
		/* Optimize when the source doesn't have an FBO, just upload
		   the data directly to the dest FBO */
		int src_stride = src_pixmap->devKind;
		int bpp = src_pixmap->drawable.bitsPerPixel;
		void *src_data = NULL;
		if (src->bitsPerPixel != dst->bitsPerPixel) {
			DEBUGF("Non-matching bpp\n");
			return FALSE;
		}
		if (src->bitsPerPixel < 8) {
			DEBUGF("bpp < 8\n");
			return FALSE;
		}
		if (gc && !(gc->alu == GXcopy && glamor_pm_is_solid(src, gc->planemask))) {
			DEBUGF("non gxcopy and solid\n");
			return FALSE;
		}
		for (i = 0; i < nbox; i++) {
			int x = box[i].x1 + dst_x_off;
			int y = box[i].y1 + dst_y_off;
			int w = box[i].x2 - box[i].x1;
			int h = box[i].y2 - box[i].y1;
			src_data = (char *)src_pixmap->devPrivate.ptr + (box[i].y1 + dy +
								src_y_off) * src_stride +
								(box[i].x1 + dx + src_x_off) * (bpp / 8);
			if (!glamor_upload_sub_pixmap_to_texture(dst_pixmap,
					x, y, w, h,
					src_stride, src_data, 0)) {
				ErrorF("Failed to upload the sub pixmap to dst\n");
				return FALSE;
			}
		}
		return TRUE;
	}


	pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale);
	pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale);


	dispatch = glamor_get_dispatch(glamor_priv);


	glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
	dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
					GL_FALSE, 2 * sizeof(float),
					vertices);
	dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);


	dx += src_x_off;
	dy += src_y_off;


	dispatch->glActiveTexture(GL_TEXTURE0);
	dispatch->glBindTexture(GL_TEXTURE_2D,
				src_pixmap_priv->base.fbo->tex);
#ifndef GLAMOR_GLES2
	dispatch->glTexParameteri(GL_TEXTURE_2D,
				  GL_TEXTURE_WRAP_S,
				  GL_CLAMP_TO_BORDER);
	dispatch->glTexParameteri(GL_TEXTURE_2D,
				  GL_TEXTURE_WRAP_T,
				  GL_CLAMP_TO_BORDER);
#endif
	dispatch->glTexParameteri(GL_TEXTURE_2D,
				  GL_TEXTURE_MIN_FILTER,
				  GL_NEAREST);
	dispatch->glTexParameteri(GL_TEXTURE_2D,
				  GL_TEXTURE_MAG_FILTER,
				  GL_NEAREST);

	dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
					GL_FLOAT, GL_FALSE,
					2 * sizeof(float),
					texcoords);
	dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
	dispatch->glUseProgram(glamor_priv->finish_access_prog[0]);
	dispatch->glUniform1i(glamor_priv->finish_access_revert[0],
			      REVERT_NONE);
	dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0],
			      SWAP_NONE_UPLOADING);

	for (i = 0; i < nbox; i++) {

		glamor_set_normalize_vcoords(dst_pixmap_priv,
					     dst_xscale, dst_yscale,
					     box[i].x1 + dst_x_off,
					     box[i].y1 + dst_y_off,
					     box[i].x2 + dst_x_off,
					     box[i].y2 + dst_y_off,
					     glamor_priv->yInverted,
					     vertices);

		glamor_set_normalize_tcoords(src_pixmap_priv,
					     src_xscale,
					     src_yscale,
					     box[i].x1 + dx,
					     box[i].y1 + dy,
					     box[i].x2 + dx,
					     box[i].y2 + dy,
					     glamor_priv->yInverted,
					     texcoords);
		dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
	}

	dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
	dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
	/* The source texture is bound to a fbo, we have to flush it here. */
	glamor_put_dispatch(glamor_priv);
	glamor_priv->state = RENDER_STATE;
	glamor_priv->render_idle_cnt = 0;
	return TRUE;
}
Example #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;
}
Example #20
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);
            }
        }
    }
Example #21
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);
                    }
                }
            }
        }
    }
void
glamor_set_destination_drawable(DrawablePtr     drawable,
                                int             box_index,
                                Bool            do_drawable_translate,
                                Bool            center_offset,
                                GLint           matrix_uniform_location,
                                int             *p_off_x,
                                int             *p_off_y)
{
    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);
    int off_x, off_y;
    BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_index);
    int w = box->x2 - box->x1;
    int h = box->y2 - box->y1;
    float scale_x = 2.0f / (float) w;
    float scale_y = 2.0f / (float) h;
    float center_adjust = 0.0f;

    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);

    off_x -= box->x1;
    off_y -= box->y1;

    if (p_off_x) {
        *p_off_x = off_x;
        *p_off_y = off_y;
    }

    /* A tricky computation to find the right value for the two linear functions
     * that transform rendering coordinates to pixmap coordinates
     *
     *  pixmap_x = render_x + drawable->x + off_x
     *  pixmap_y = render_y + drawable->y + off_y
     *
     *  gl_x = pixmap_x * 2 / width - 1
     *  gl_y = pixmap_y * 2 / height - 1
     *
     *  gl_x = (render_x + drawable->x + off_x) * 2 / width - 1
     *
     *  gl_x = (render_x) * 2 / width + (drawable->x + off_x) * 2 / width - 1
     */

    if (do_drawable_translate) {
        off_x += drawable->x;
        off_y += drawable->y;
    }

    /*
     * To get GL_POINTS drawn in the right spot, we need to adjust the
     * coordinates by 1/2 a pixel.
     */
    if (center_offset)
        center_adjust = 0.5f;

    glUniform4f(matrix_uniform_location,
                scale_x, (off_x + center_adjust) * scale_x - 1.0f,
                scale_y, (off_y + center_adjust) * scale_y - 1.0f);

    glamor_set_destination_pixmap_fbo(glamor_priv, glamor_pixmap_fbo_at(pixmap_priv, box_index),
                                      0, 0, w, h);
}
Example #23
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);
}
Example #24
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;
}
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 #26
0
static int
glamor_text(DrawablePtr drawable, GCPtr gc,
            glamor_font_t *glamor_font,
            glamor_program *prog,
            int x, int y,
            int count, char *s_chars, CharInfoPtr *charinfo,
            Bool sixteen)
{
    unsigned char *chars = (unsigned char *) s_chars;
    FontPtr font = gc->font;
    int off_x, off_y;
    int c;
    int nglyph;
    GLshort *v;
    char *vbo_offset;
    CharInfoPtr ci;
    int firstRow = font->info.firstRow;
    int firstCol = font->info.firstCol;
    int glyph_spacing_x = glamor_font->glyph_width_bytes * 8;
    int glyph_spacing_y = glamor_font->glyph_height;
    int box_x, box_y;
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);

    /* Set the font as texture 1 */

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id);
    glUniform1i(prog->font_uniform, 1);

    /* Set up the vertex buffers for the font and destination */

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

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

    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
    glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 1);
    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_SHORT, GL_FALSE,
                          6 * sizeof (GLshort), vbo_offset + 4 * sizeof (GLshort));

    /* Set the vertex coordinates */
    nglyph = 0;

    for (c = 0; c < count; c++) {
        if ((ci = *charinfo++)) {
            int     x1 = x + ci->metrics.leftSideBearing;
            int     y1 = y - ci->metrics.ascent;
            int     width = GLYPHWIDTHPIXELS(ci);
            int     height = GLYPHHEIGHTPIXELS(ci);
            int     tx, ty = 0;
            int     row = 0, col;

            x += ci->metrics.characterWidth;

            if (sixteen) {
                if (ci == glamor_font->default_char) {
                    row = glamor_font->default_row;
                    col = glamor_font->default_col;
                } else {
                    row = chars[0];
                    col = chars[1];
                }
                if (FONTLASTROW(font) != 0)
                    ty = (row - firstRow) * glyph_spacing_y;
                else
                    col += row << 8;
            } else {
                if (ci == glamor_font->default_char)
                    col = glamor_font->default_col;
                else
                    col = chars[0];
            }

            tx = (col - firstCol) * glyph_spacing_x;

            v[ 0] = x1;
            v[ 1] = y1;
            v[ 2] = width;
            v[ 3] = height;
            v[ 4] = tx;
            v[ 5] = ty;

            v += 6;
            nglyph++;
        }
        chars += 1 + sixteen;
    }
    glamor_put_vbo_space(drawable->pScreen);

    if (nglyph != 0) {

        glEnable(GL_SCISSOR_TEST);

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

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

            /* Run over the clip list, drawing the glyphs
             * in each box
             */

            while (nbox--) {
                glScissor(box->x1 + off_x,
                          box->y1 + off_y,
                          box->x2 - box->x1,
                          box->y2 - box->y1);
                box++;
                glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph);
            }
        }
Example #27
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;
}
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);
        }
    }
Example #29
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 #30
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;
}