Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
static Bool
_glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
                                      GLenum type, int no_alpha, int revert,
                                      int swap_rb, int x, int y, int w, int h,
                                      int stride, void *bits, int pbo)
{
    ScreenPtr screen = pixmap->drawable.pScreen;
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
    glamor_screen_private *glamor_priv =
        glamor_get_screen_private(pixmap->drawable.pScreen);
    static float vertices[8];

    static float texcoords_inv[8] = { 0, 0,
        1, 0,
        1, 1,
        0, 1
    };
    float *ptexcoords;
    float dst_xscale, dst_yscale;
    GLuint tex = 0;
    int need_free_bits = 0;

    if (bits == NULL)
        goto ready_to_upload;

    if (revert > REVERT_NORMAL) {
        /* XXX if we are restoring the pixmap, then we may not need to allocate
         * new buffer */
        void *converted_bits;

        if (pixmap->drawable.depth == 1)
            stride = (((w * 8 + 7) / 8) + 3) & ~3;

        converted_bits = xallocarray(h, stride);

        if (converted_bits == NULL)
            return FALSE;
        bits = glamor_color_convert_to_bits(bits, converted_bits, w, h,
                                            stride, no_alpha, revert, swap_rb);
        if (bits == NULL) {
            free(converted_bits);
            ErrorF("Failed to convert pixmap no_alpha %d,"
                   "revert mode %d, swap mode %d\n", no_alpha, revert, swap_rb);
            return FALSE;
        }
        no_alpha = 0;
        revert = REVERT_NONE;
        swap_rb = SWAP_NONE_UPLOADING;
        need_free_bits = TRUE;
    }

 ready_to_upload:

    /* Try fast path firstly, upload the pixmap to the texture attached
     * to the fbo directly. */
    if (no_alpha == 0
        && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING
#ifdef WALKAROUND_LARGE_TEXTURE_MAP
        && glamor_pixmap_priv_is_small(pixmap_priv)
#endif
        ) {
        int fbo_x_off, fbo_y_off;

        assert(pixmap_priv->fbo->tex);
        pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off);

        assert(x + fbo_x_off >= 0 && y + fbo_y_off >= 0);
        assert(x + fbo_x_off + w <= pixmap_priv->fbo->width);
        assert(y + fbo_y_off + h <= pixmap_priv->fbo->height);
        __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->fbo->tex,
                                          format, type,
                                          x + fbo_x_off, y + fbo_y_off, w, h,
                                          bits, pbo);
    } else {
        ptexcoords = texcoords_inv;

        pixmap_priv_get_dest_scale(pixmap, pixmap_priv, &dst_xscale, &dst_yscale);
        glamor_set_normalize_vcoords(pixmap_priv, dst_xscale,
                                     dst_yscale,
                                     x, y,
                                     x + w, y + h,
                                     vertices);
        /* Slow path, we need to flip y or wire alpha to 1. */
        glamor_make_current(glamor_priv);
        glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
                              GL_FALSE, 2 * sizeof(float), vertices);
        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
        glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
                              GL_FALSE, 2 * sizeof(float), ptexcoords);
        glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);

        glamor_set_destination_pixmap_priv_nc(glamor_priv, pixmap, pixmap_priv);
        glamor_set_alu(screen, GXcopy);
        __glamor_upload_pixmap_to_texture(pixmap, &tex,
                                          format, type, 0, 0, w, h, bits, pbo);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, tex);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
        glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
        glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb);

        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

        glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
        glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
        glDeleteTextures(1, &tex);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

    if (need_free_bits)
        free(bits);
    return TRUE;
}