コード例 #1
0
ファイル: cairo-gl-device.c プロジェクト: NicoK78/Colory
void
_cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
                                   cairo_gl_surface_t *surface,
                                   cairo_bool_t multisampling)
{
    /* OpenGL ES surfaces are always in MSAA mode once it's been turned on,
     * so we don't need to check whether we are switching modes for that
     * surface type. */
    if (ctx->current_target == surface && ! surface->needs_update &&
	(ctx->gl_flavor == CAIRO_GL_FLAVOR_ES ||
	 surface->msaa_active == multisampling))
	return;

    _cairo_gl_composite_flush (ctx);

    ctx->current_target = surface;
    surface->needs_update = FALSE;

    if (_cairo_gl_surface_is_texture (surface)) {
	if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) {
	    _cairo_gl_ensure_framebuffer (ctx, surface);
	    ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
#if CAIRO_HAS_GL_SURFACE
	} else if (multisampling)
	    _cairo_gl_activate_surface_as_multisampling (ctx, surface);
	else {
	    _cairo_gl_activate_surface_as_nonmultisampling (ctx, surface);
#endif
	}
    } else {
        ctx->make_current (ctx, surface);

#if CAIRO_HAS_GL_SURFACE
	if (multisampling)
	    glEnable(GL_MULTISAMPLE);
	else
	    glDisable(GL_MULTISAMPLE);
#endif

        ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, 0);

#if CAIRO_HAS_GL_SURFACE
        glDrawBuffer (GL_BACK_LEFT);
        glReadBuffer (GL_BACK_LEFT);
#endif
    }

    glViewport (0, 0, surface->width, surface->height);

    if (_cairo_gl_surface_is_texture (surface))
	_gl_identity_ortho (ctx->modelviewprojection_matrix,
			    0, surface->width, 0, surface->height);
    else
	_gl_identity_ortho (ctx->modelviewprojection_matrix,
			    0, surface->width, surface->height, 0);
}
コード例 #2
0
void
_cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
                                   cairo_gl_surface_t *surface,
                                   cairo_bool_t multisampling)
{
    cairo_bool_t changing_surface, changing_sampling;

    /* The decision whether or not to use multisampling happens when
     * we create an OpenGL ES surface, so we can never switch modes. */
    if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES)
	multisampling = surface->msaa_active;

    changing_surface = ctx->current_target != surface || surface->needs_update;
    changing_sampling = surface->msaa_active != multisampling;
    if (! changing_surface && ! changing_sampling)
	return;

    if (! changing_surface) {
	_cairo_gl_composite_flush (ctx);
	_cairo_gl_context_bind_framebuffer (ctx, surface, multisampling);
	return;
    }

    _cairo_gl_composite_flush (ctx);

    ctx->current_target = surface;
    surface->needs_update = FALSE;

    if (! _cairo_gl_surface_is_texture (surface)) {
	ctx->make_current (ctx, surface);
    }

    _cairo_gl_context_bind_framebuffer (ctx, surface, multisampling);

    if (! _cairo_gl_surface_is_texture (surface)) {
#if CAIRO_HAS_GL_SURFACE
	glDrawBuffer (GL_BACK_LEFT);
	glReadBuffer (GL_BACK_LEFT);
#endif
    }

    glDisable (GL_DITHER);
    glViewport (0, 0, surface->width, surface->height);

    if (_cairo_gl_surface_is_texture (surface))
	_gl_identity_ortho (ctx->modelviewprojection_matrix,
			    0, surface->width, 0, surface->height);
    else
	_gl_identity_ortho (ctx->modelviewprojection_matrix,
			    0, surface->width, surface->height, 0);
}
コード例 #3
0
ファイル: cairo-gl-surface.c プロジェクト: mrobinson/cairo
void
cairo_gl_surface_set_size (cairo_surface_t *abstract_surface,
			   int              width,
			   int              height)
{
    cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;

    if (unlikely (abstract_surface->status))
	return;
    if (unlikely (abstract_surface->finished)) {
	_cairo_surface_set_error (abstract_surface,
				  _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
        return;
    }

    if (! _cairo_surface_is_gl (abstract_surface) ||
        _cairo_gl_surface_is_texture (surface)) {
	_cairo_surface_set_error (abstract_surface,
				  _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
	return;
    }

    if (surface->width != width || surface->height != height) {
	surface->needs_update = TRUE;
	surface->width = width;
	surface->height = height;
    }
}
コード例 #4
0
static void
_wgl_acquire (void *abstract_ctx)
{
    cairo_wgl_context_t *ctx = abstract_ctx;

    HDC current_dc;

    ctx->prev_dc = wglGetCurrentDC ();
    ctx->prev_rc = wglGetCurrentContext ();

    if (ctx->base.current_target == NULL ||
        _cairo_gl_surface_is_texture (ctx->base.current_target))
    {
        current_dc = ctx->dummy_dc;
    }
    else
    {
        cairo_wgl_surface_t *surface = (cairo_wgl_surface_t *) ctx->base.current_target;
        current_dc = surface->dc;
    }

    if (ctx->prev_dc != current_dc ||
	(ctx->prev_rc != ctx->rc &&
	 current_dc != ctx->dummy_dc))
    {
        wglMakeCurrent (current_dc, ctx->rc);
    }
}
コード例 #5
0
void
_cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx,
				    cairo_gl_surface_t *surface,
				    cairo_bool_t multisampling)
{
    if (_cairo_gl_surface_is_texture (surface)) {
	/* OpenGL ES surfaces only have either a multisample framebuffer or a
	 * singlesample framebuffer, so we cannot switch back and forth. */
	if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) {
	    _cairo_gl_ensure_framebuffer (ctx, surface);
	    ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
	    return;
	}

#if CAIRO_HAS_GL_SURFACE
	if (multisampling)
	    bind_multisample_framebuffer (ctx, surface);
	else
	    bind_singlesample_framebuffer (ctx, surface);
#endif
    } else {
	ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, 0);

#if CAIRO_HAS_GL_SURFACE
	if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) {
	    if (multisampling)
		glEnable (GL_MULTISAMPLE);
	    else
		glDisable (GL_MULTISAMPLE);
	}
#endif
    }

    surface->msaa_active = multisampling;
}
コード例 #6
0
static void
query_surface_capabilities (cairo_gl_surface_t *surface)
{
    GLint samples, stencil_bits;
    cairo_gl_context_t *ctx;
    cairo_int_status_t status;

    /* Texture surfaces are create in such a way that they always
       have stencil and multisample bits if possible, so we don't
       need to query their capabilities lazily. */
    if (_cairo_gl_surface_is_texture (surface))
	return;
    if (surface->stencil_and_msaa_caps_initialized)
	return;

    surface->stencil_and_msaa_caps_initialized = TRUE;
    surface->supports_stencil = FALSE;
    surface->supports_msaa = FALSE;

    status = _cairo_gl_context_acquire (surface->base.device, &ctx);
    if (unlikely (status))
	return;

    _cairo_gl_context_set_destination (ctx, surface, FALSE);

    glGetIntegerv(GL_SAMPLES, &samples);
    glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
    surface->supports_stencil = stencil_bits > 0;
    surface->supports_msaa = samples > 1;

    status = _cairo_gl_context_release (ctx, status);
}
コード例 #7
0
ファイル: cairo-gl-operand.c プロジェクト: zwcloud/CairoSharp
static cairo_status_t
_cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
				   const cairo_pattern_t *_src,
				   cairo_gl_surface_t *dst,
				   const cairo_rectangle_int_t *sample,
				   const cairo_rectangle_int_t *extents,
				   cairo_bool_t use_texgen)
{
    const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
    cairo_surface_subsurface_t *sub;
    cairo_gl_surface_t *surface;
    cairo_surface_attributes_t *attributes;
    cairo_int_status_t status;

    sub = (cairo_surface_subsurface_t *) src->surface;

    if (sample->x < 0 || sample->y < 0 ||
	sample->x + sample->width  > sub->extents.width ||
	sample->y + sample->height > sub->extents.height)
    {
	return _cairo_gl_subsurface_clone_operand_init (operand, _src,
							dst, sample, extents,
							use_texgen);
    }

    surface = (cairo_gl_surface_t *) sub->target;
    if (surface->base.device && surface->base.device != dst->base.device)
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (! _cairo_gl_surface_is_texture (surface))
	return CAIRO_INT_STATUS_UNSUPPORTED;

    status = _cairo_gl_surface_resolve_multisampling (surface);
    if (unlikely (status))
	return status;

    /* Translate the matrix from
     * (unnormalized src -> unnormalized src) to
     * (unnormalized dst -> unnormalized src)
     */
    _cairo_gl_operand_copy(operand, &surface->operand);

    attributes = &operand->texture.attributes;
    attributes->matrix = src->base.matrix;
    attributes->matrix.x0 += sub->extents.x;
    attributes->matrix.y0 += sub->extents.y;
    cairo_matrix_multiply (&attributes->matrix,
			   &attributes->matrix,
			   &surface->operand.texture.attributes.matrix);

    attributes->extend = src->base.extend;
    attributes->filter = src->base.filter;
    attributes->has_component_alpha = src->base.has_component_alpha;

    operand->texture.texgen = use_texgen;
    return CAIRO_STATUS_SUCCESS;
}
コード例 #8
0
cairo_status_t
_cairo_gl_surface_clone_similar (void		     *abstract_surface,
				 cairo_surface_t     *src,
				 int                  src_x,
				 int                  src_y,
				 int                  width,
				 int                  height,
				 int                 *clone_offset_x,
				 int                 *clone_offset_y,
				 cairo_surface_t    **clone_out)
{
    cairo_gl_surface_t *surface = abstract_surface;
    cairo_int_status_t status;

    /* XXX: Use GLCopyTexImage2D to clone non-texture-surfaces */
    if (src->device == surface->base.device &&
        _cairo_gl_surface_is_texture ((cairo_gl_surface_t *) src)) {
	status = _cairo_gl_surface_deferred_clear ((cairo_gl_surface_t *)src);
	if (unlikely (status))
	    return status;

	*clone_offset_x = 0;
	*clone_offset_y = 0;
	*clone_out = cairo_surface_reference (src);

	return CAIRO_STATUS_SUCCESS;
    } else if (_cairo_surface_is_image (src)) {
	cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
	cairo_gl_surface_t *clone;

	clone = (cairo_gl_surface_t *)
		_cairo_gl_surface_create_similar (&surface->base,
						  src->content,
						  width, height);
	if (clone == NULL)
	    return UNSUPPORTED ("create_similar failed");
	if (clone->base.status)
	    return clone->base.status;

	status = _cairo_gl_surface_draw_image (clone, image_src,
					       src_x, src_y,
					       width, height,
					       0, 0);
	if (status) {
	    cairo_surface_destroy (&clone->base);
	    return status;
	}

	*clone_out = &clone->base;
	*clone_offset_x = src_x;
	*clone_offset_y = src_y;

	return CAIRO_STATUS_SUCCESS;
    }

    return UNSUPPORTED ("unknown src surface type in clone_similar");
}
コード例 #9
0
static GLXDrawable
_glx_get_current_drawable (cairo_glx_context_t *ctx)
{
    if (ctx->base.current_target == NULL ||
	_cairo_gl_surface_is_texture (ctx->base.current_target)) {
	return ctx->dummy_window;
    }

    return ((cairo_glx_surface_t *) ctx->base.current_target)->win;
}
コード例 #10
0
static void
_scissor_to_rectangle (cairo_gl_surface_t *surface,
		       const cairo_rectangle_int_t *r)
{
    int y = r->y;
    if (_cairo_gl_surface_is_texture (surface) == FALSE)
	y = surface->height - (r->y + r->height);
    glScissor (r->x, y, r->width, r->height);
    glEnable (GL_SCISSOR_TEST);
}
コード例 #11
0
static EGLSurface
_egl_get_current_surface (cairo_egl_context_t *ctx)
{
    if (ctx->base.current_target == NULL ||
        _cairo_gl_surface_is_texture (ctx->base.current_target)) {
	return  ctx->dummy_surface;
    }

    return ((cairo_egl_surface_t *) ctx->base.current_target)->egl;
}
コード例 #12
0
ファイル: cairo-gl-composite.c プロジェクト: csyuschmjuh/apl
static void
_scissor_to_doubles (cairo_gl_surface_t	*surface,
		     double x1, double y1,
		     double x2, double y2)
{
    double height;

    height = y2 - y1;
    if (_cairo_gl_surface_is_texture (surface) == FALSE)
	y1 = surface->height - (y1 + height);
    glScissor (x1, y1, x2 - x1, height);
    glEnable (GL_SCISSOR_TEST);
}
コード例 #13
0
ファイル: cairo-gl-operand.c プロジェクト: zwcloud/CairoSharp
static cairo_status_t
_cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
				const cairo_pattern_t *_src,
				cairo_gl_surface_t *dst,
				const cairo_rectangle_int_t *sample,
				const cairo_rectangle_int_t *extents,
				cairo_bool_t use_texgen)
{
    const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
    cairo_gl_surface_t *surface;
    cairo_surface_attributes_t *attributes;
    cairo_int_status_t status;

    surface = (cairo_gl_surface_t *) src->surface;
    if (surface->base.type != CAIRO_SURFACE_TYPE_GL)
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (surface->base.backend->type != CAIRO_SURFACE_TYPE_GL) {
	if (_cairo_surface_is_subsurface (&surface->base))
	    return _cairo_gl_subsurface_operand_init (operand, _src, dst,
						      sample, extents,
						      use_texgen);

	return CAIRO_INT_STATUS_UNSUPPORTED;
    }

    if (surface->base.device && surface->base.device != dst->base.device)
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (surface->base.device && ! _cairo_gl_surface_is_texture (surface))
	return CAIRO_INT_STATUS_UNSUPPORTED;

    status = _cairo_gl_surface_resolve_multisampling (surface);
    if (unlikely (status))
	return status;

    _cairo_gl_operand_copy(operand, &surface->operand);

    attributes = &operand->texture.attributes;
    cairo_matrix_multiply (&attributes->matrix,
			   &src->base.matrix,
			   &attributes->matrix);

    attributes->extend = src->base.extend;
    attributes->filter = src->base.filter;
    attributes->has_component_alpha = src->base.has_component_alpha;

    operand->texture.texgen = use_texgen;
    return CAIRO_STATUS_SUCCESS;
}
コード例 #14
0
ファイル: cairo-gl-device.c プロジェクト: NicoK78/Colory
cairo_bool_t
_cairo_gl_ensure_stencil (cairo_gl_context_t *ctx,
			  cairo_gl_surface_t *surface)
{
    if (! _cairo_gl_surface_is_texture (surface))
	return TRUE; /* best guess for now, will check later */
    if (! ctx->has_packed_depth_stencil)
	return FALSE;

    if (surface->msaa_active)
	return _cairo_gl_ensure_msaa_depth_stencil_buffer (ctx, surface);
    else
	return _cairo_gl_ensure_depth_stencil_buffer (ctx, surface);
}
コード例 #15
0
ファイル: cairo-gl-composite.c プロジェクト: csyuschmjuh/apl
void
_cairo_gl_scissor_to_extents (cairo_gl_surface_t	*surface,
			      const cairo_rectangle_int_t	*extents)
{
    int x1, y1, height;

    x1 = extents->x;
    y1 = extents->y;
    height = extents->height;

    if (_cairo_gl_surface_is_texture (surface) == FALSE)
	y1 = surface->height - (y1 + height);
    glScissor (x1, y1, extents->width, height);
    glEnable (GL_SCISSOR_TEST);
}
コード例 #16
0
ファイル: cairo-gl-surface.c プロジェクト: mrobinson/cairo
void
cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface)
{
    cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;

    if (unlikely (abstract_surface->status))
	return;
    if (unlikely (abstract_surface->finished)) {
	_cairo_surface_set_error (abstract_surface,
				  _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
        return;
    }

    if (! _cairo_surface_is_gl (abstract_surface)) {
	_cairo_surface_set_error (abstract_surface,
				  CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
	return;
    }

    if (! _cairo_gl_surface_is_texture (surface)) {
	cairo_gl_context_t *ctx;
        cairo_status_t status;

        status = _cairo_gl_context_acquire (surface->base.device, &ctx);
        if (unlikely (status))
            return;

	/* For swapping on EGL, at least, we need a valid context/target. */
	_cairo_gl_context_set_destination (ctx, surface);
	/* And in any case we should flush any pending operations. */
	_cairo_gl_composite_flush (ctx);

	ctx->swap_buffers (ctx, surface);

        status = _cairo_gl_context_release (ctx, status);
        if (status)
            status = _cairo_surface_set_error (abstract_surface, status);
    }
}
コード例 #17
0
ファイル: cairo-gl-surface.c プロジェクト: mrobinson/cairo
static cairo_surface_t *
_cairo_gl_surface_map_to_image (void      *abstract_surface,
				const cairo_rectangle_int_t   *extents)
{
    cairo_gl_surface_t *surface = abstract_surface;
    cairo_image_surface_t *image;
    cairo_gl_context_t *ctx;
    GLenum format, type;
    pixman_format_code_t pixman_format;
    unsigned int cpp;
    cairo_bool_t invert;
    cairo_status_t status;

    /* Want to use a switch statement here but the compiler gets whiny. */
    if (surface->base.content == CAIRO_CONTENT_COLOR_ALPHA) {
	format = GL_BGRA;
	pixman_format = PIXMAN_a8r8g8b8;
	type = GL_UNSIGNED_INT_8_8_8_8_REV;
	cpp = 4;
    } else if (surface->base.content == CAIRO_CONTENT_COLOR) {
	format = GL_BGRA;
	pixman_format = PIXMAN_x8r8g8b8;
	type = GL_UNSIGNED_INT_8_8_8_8_REV;
	cpp = 4;
    } else if (surface->base.content == CAIRO_CONTENT_ALPHA) {
	format = GL_ALPHA;
	pixman_format = PIXMAN_a8;
	type = GL_UNSIGNED_BYTE;
	cpp = 1;
    } else {
	ASSERT_NOT_REACHED;
	return NULL;
    }

    /*
     * GLES2 supports only RGBA, UNSIGNED_BYTE so use that.
     * We are also using this format for ALPHA as GLES2 does not
     * support GL_PACK_ROW_LENGTH anyway, and this makes sure that the
     * pixman image that is created has row_stride = row_width * bpp.
     */
    if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES) {
	format = GL_RGBA;
	if (! _cairo_is_little_endian ()) {
	    if (surface->base.content == CAIRO_CONTENT_COLOR)
		pixman_format = PIXMAN_r8g8b8x8;
	    else
		pixman_format = PIXMAN_r8g8b8a8;
	} else {
	    if (surface->base.content == CAIRO_CONTENT_COLOR)
		pixman_format = PIXMAN_x8b8g8r8;
	    else
		pixman_format = PIXMAN_a8b8g8r8;
	}
	type = GL_UNSIGNED_BYTE;
	cpp = 4;
    }

    image = (cairo_image_surface_t*)
	_cairo_image_surface_create_with_pixman_format (NULL,
							pixman_format,
							extents->width,
							extents->height,
							-1);
    if (unlikely (image->base.status))
	return &image->base;

    if (surface->base.serial == 0)
	return &image->base;

    status = _cairo_gl_context_acquire (surface->base.device, &ctx);
    if (unlikely (status)) {
	cairo_surface_destroy (&image->base);
	return _cairo_surface_create_in_error (status);
    }

    cairo_surface_set_device_offset (&image->base, -extents->x, -extents->y);

    /* This is inefficient, as we'd rather just read the thing without making
     * it the destination.  But then, this is the fallback path, so let's not
     * fall back instead.
     */
    _cairo_gl_composite_flush (ctx);
    _cairo_gl_context_set_destination (ctx, surface);

    invert = ! _cairo_gl_surface_is_texture (surface) &&
	    ctx->has_mesa_pack_invert;

    glPixelStorei (GL_PACK_ALIGNMENT, 4);
    if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
	glPixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp);
    if (invert)
	glPixelStorei (GL_PACK_INVERT_MESA, 1);
    glReadPixels (extents->x, extents->y,
		  extents->width, extents->height,
		  format, type, image->data);
    if (invert)
	glPixelStorei (GL_PACK_INVERT_MESA, 0);

    status = _cairo_gl_context_release (ctx, status);
    if (unlikely (status)) {
	cairo_surface_destroy (&image->base);
	image = (cairo_image_surface_t *)
	    _cairo_surface_create_in_error (status);
    }

    return &image->base;
}
コード例 #18
0
ファイル: cairo-gl-surface.c プロジェクト: mrobinson/cairo
cairo_status_t
_cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
			      cairo_image_surface_t *src,
			      int src_x, int src_y,
			      int width, int height,
			      int dst_x, int dst_y)
{
    GLenum internal_format, format, type;
    cairo_bool_t has_alpha, needs_swap;
    cairo_image_surface_t *clone = NULL;
    cairo_gl_context_t *ctx;
    int cpp;
    cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;

    status = _cairo_gl_context_acquire (dst->base.device, &ctx);
    if (unlikely (status))
	return status;

    if (! _cairo_gl_get_image_format_and_type (ctx->gl_flavor,
					       src->pixman_format,
					       &internal_format,
					       &format,
					       &type,
					       &has_alpha,
					       &needs_swap))
    {
	cairo_bool_t is_supported;

	clone = _cairo_image_surface_coerce (src);
	if (unlikely (status = clone->base.status))
	    goto FAIL;

	is_supported =
	    _cairo_gl_get_image_format_and_type (ctx->gl_flavor,
						 clone->pixman_format,
		                                 &internal_format,
						 &format,
						 &type,
						 &has_alpha,
						 &needs_swap);
	assert (is_supported);
	assert (!needs_swap);
	src = clone;
    }

    cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8;

    status = _cairo_gl_surface_flush (&dst->base);
    if (unlikely (status))
	goto FAIL;

    if (_cairo_gl_surface_is_texture (dst)) {
	void *data_start = src->data + src_y * src->stride + src_x * cpp;
	void *data_start_gles2 = NULL;

	/*
	 * Due to GL_UNPACK_ROW_LENGTH missing in GLES2 we have to extract the
	 * image data ourselves in some cases. In particular, we must extract
	 * the pixels if:
	 * a. we don't want full-length lines or
	 * b. the row stride cannot be handled by GL itself using a 4 byte
	 *     alignment constraint
	 */
	if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES &&
	    (src->width * cpp < src->stride - 3 ||
	     width != src->width))
	{
	    glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
	    status = _cairo_gl_surface_extract_image_data (src, src_x, src_y,
							   width, height,
							   &data_start_gles2);
	    if (unlikely (status))
		goto FAIL;

	    data_start = data_start_gles2;
	}
	else
	{
	    glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
	    if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
		glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp);
	}

        _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
	glBindTexture (ctx->tex_target, dst->tex);
	glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexSubImage2D (ctx->tex_target, 0,
			 dst_x, dst_y, width, height,
			 format, type, data_start);

	free (data_start_gles2);

	/* If we just treated some rgb-only data as rgba, then we have to
	 * go back and fix up the alpha channel where we filled in this
	 * texture data.
	 */
	if (!has_alpha) {
	    _cairo_gl_surface_fill_alpha_channel (dst, ctx,
						  dst_x, dst_y,
						  width, height);
	}
    } else {
        cairo_surface_t *tmp;

        tmp = _cairo_gl_surface_create_scratch (ctx,
                                                dst->base.content,
                                                width, height);
        if (unlikely (tmp->status))
            goto FAIL;

        status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp,
                                               src,
                                               src_x, src_y,
                                               width, height,
                                               0, 0);
        if (status == CAIRO_INT_STATUS_SUCCESS) {
            cairo_surface_pattern_t tmp_pattern;
	    cairo_rectangle_int_t r;
	    cairo_clip_t *clip;

            _cairo_pattern_init_for_surface (&tmp_pattern, tmp);
	    cairo_matrix_init_translate (&tmp_pattern.base.matrix,
					 -dst_x, -dst_y);
	    tmp_pattern.base.filter = CAIRO_FILTER_NEAREST;
	    tmp_pattern.base.extend = CAIRO_EXTEND_NONE;

	    r.x = dst_x;
	    r.y = dst_y;
	    r.width = width;
	    r.height = height;
	    clip = _cairo_clip_intersect_rectangle (NULL, &r);
	    status = _cairo_surface_paint (&dst->base,
					   CAIRO_OPERATOR_SOURCE,
					   &tmp_pattern.base,
					   clip);
	    _cairo_clip_destroy (clip);
            _cairo_pattern_fini (&tmp_pattern.base);
        }

        cairo_surface_destroy (tmp);
    }

FAIL:
    status = _cairo_gl_context_release (ctx, status);

    if (clone)
        cairo_surface_destroy (&clone->base);

    return status;
}
コード例 #19
0
static cairo_int_status_t
_cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup,
					    cairo_gl_context_t *ctx,
					    int vertex_size)
{
    cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;

    cairo_gl_surface_t *dst = setup->dst;
    cairo_clip_t *clip = setup->clip;

    if (clip->num_boxes == 1 && clip->path == NULL) {
	_scissor_to_box (dst, &clip->boxes[0]);
	goto disable_stencil_buffer_and_return;
    }

    if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) {
	status = CAIRO_INT_STATUS_UNSUPPORTED;
	goto disable_stencil_buffer_and_return;
    }

    /* We only want to clear the part of the stencil buffer
     * that we are about to use. It also does not hurt to
     * scissor around the painted clip. */
    _cairo_gl_scissor_to_rectangle (dst, _cairo_clip_get_extents (clip));

    /* The clip is not rectangular, so use the stencil buffer. */
    glDepthMask (GL_TRUE);
    glEnable (GL_STENCIL_TEST);

    /* Texture surfaces have private depth/stencil buffers, so we can
     * rely on any previous clip being cached there. */
    if (_cairo_gl_surface_is_texture (setup->dst)) {
	cairo_clip_t *old_clip = setup->dst->clip_on_stencil_buffer;
	if (_cairo_clip_equal (old_clip, setup->clip))
	    goto activate_stencil_buffer_and_return;

	if (old_clip) {
	    _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
	}

	setup->dst->clip_on_stencil_buffer = _cairo_clip_copy (setup->clip);
    }

    glClearStencil (0);
    glClear (GL_STENCIL_BUFFER_BIT);

    glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);
    glStencilFunc (GL_EQUAL, 1, 0xffffffff);
    glColorMask (0, 0, 0, 0);

    status = _cairo_gl_msaa_compositor_draw_clip (ctx, setup, clip);

    if (unlikely (status)) {
	glColorMask (1, 1, 1, 1);
	goto disable_stencil_buffer_and_return;
    }

    /* We want to only render to the stencil buffer, so draw everything now.
       Flushing also unbinds the VBO, which we want to rebind for regular
       drawing. */
    _cairo_gl_composite_flush (ctx);
    _cairo_gl_composite_setup_vbo (ctx, vertex_size);

activate_stencil_buffer_and_return:
    glColorMask (1, 1, 1, 1);
    glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
    glStencilFunc (GL_EQUAL, 1, 0xffffffff);
    return CAIRO_INT_STATUS_SUCCESS;

disable_stencil_buffer_and_return:
    _disable_stencil_buffer ();
    return status;
}