Beispiel #1
0
static cairo_int_status_t
_cairo_gl_surface_fill_alpha_channel (cairo_gl_surface_t *dst,
				      cairo_gl_context_t *ctx,
				      int x, int y,
				      int width, int height)
{
    cairo_gl_composite_t setup;
    cairo_status_t status;

    _cairo_gl_composite_flush (ctx);
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);

    status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE, dst,
                                       FALSE, NULL);
    if (unlikely (status))
        goto CLEANUP;

    _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_BLACK);

    status = _cairo_gl_composite_begin (&setup, &ctx);
    if (unlikely (status))
        goto CLEANUP;

    _cairo_gl_composite_emit_rect (ctx, x, y, x + width, y + height, 0);

    status = _cairo_gl_context_release (ctx, status);

  CLEANUP:
    _cairo_gl_composite_fini (&setup);

    _cairo_gl_composite_flush (ctx);
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

    return status;
}
Beispiel #2
0
static void
_cairo_gl_composite_prepare_buffer (cairo_gl_context_t *ctx,
				    unsigned int n_vertices,
				    cairo_gl_primitive_type_t primitive_type)
{
    if (ctx->primitive_type != primitive_type) {
	_cairo_gl_composite_flush (ctx);
	ctx->primitive_type = primitive_type;
    }

    if (ctx->vb_offset + n_vertices * ctx->vertex_size > CAIRO_GL_VBO_SIZE)
	_cairo_gl_composite_flush (ctx);
}
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);
}
static void
_cairo_gl_composite_prepare_buffer (cairo_gl_context_t *ctx,
				    unsigned int n_vertices,
				    cairo_gl_primitive_type_t primitive_type)
{
    if (ctx->primitive_type != primitive_type) {
	_cairo_gl_composite_flush (ctx);
	ctx->primitive_type = primitive_type;
    }

    assert(ctx->vbo_size > 0);
    if (ctx->vb_offset + n_vertices * ctx->vertex_size > ctx->vbo_size)
	_cairo_gl_composite_flush (ctx);
}
static cairo_int_status_t
_prevent_overlapping_drawing (cairo_gl_context_t 		*ctx,
			      cairo_gl_composite_t 		*setup,
			      cairo_composite_rectangles_t 	*composite,
			      const cairo_path_fixed_t		*path,
			      const cairo_stroke_style_t	*style,
			      const cairo_matrix_t		*ctm)
{
    cairo_rectangle_int_t stroke_extents;
    const cairo_pattern_t *pattern = composite->original_source_pattern;
    cairo_pattern_type_t type = cairo_pattern_get_type ((cairo_pattern_t *) pattern);

    if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
	return CAIRO_INT_STATUS_UNSUPPORTED;


    /* XXX: improve me - since we have lazy init, we cannot use sample
       area */
    if (type == CAIRO_PATTERN_TYPE_SOLID &&
	_cairo_pattern_is_opaque_solid (pattern))
	return CAIRO_INT_STATUS_SUCCESS;

   if (glIsEnabled (GL_STENCIL_TEST) == FALSE) {
       /* In case we have pending operations we have to flush before
	  adding the stencil buffer. */
       _cairo_gl_composite_flush (ctx);

	/* Enable the stencil buffer, even if we are not using it for clipping,
	   so we can use it below to prevent overlapping shapes. We initialize
	   it all to one here which represents infinite clip. */
	if (! ctx->states_cache.depth_mask) {
	    glDepthMask (GL_TRUE);
	    ctx->states_cache.depth_mask = TRUE;
	}
	glEnable (GL_STENCIL_TEST);

	/* If we don't have clip, then we will setup clip extents based on
	   approximate stroke extent. */
	if (! setup->clip) {
	    _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
							  &stroke_extents);
	    _cairo_gl_scissor_to_extents (setup->dst, &stroke_extents);
	}

	glClearStencil (1);
	glClear (GL_STENCIL_BUFFER_BIT);
	glStencilFunc (GL_EQUAL, 1, 1);
    }

    /* This means that once we draw to a particular pixel nothing else can
       be drawn there until the stencil buffer is reset or the stencil test
       is disabled. */
    glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);

    /* we need to clean up clip cache */
    _cairo_clip_destroy (ctx->clip);
    ctx->clip = NULL;

    return CAIRO_INT_STATUS_SUCCESS;
}
Beispiel #6
0
void
_cairo_gl_activate_surface_as_nonmultisampling (cairo_gl_context_t *ctx,
						cairo_gl_surface_t *surface)
{
    assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP);
    _cairo_gl_ensure_framebuffer (ctx, surface);

#if CAIRO_HAS_GL_SURFACE
    if (! surface->msaa_active) {
	glDisable (GL_MULTISAMPLE);
	ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
	return;
    }

    _cairo_gl_composite_flush (ctx);
    glDisable (GL_MULTISAMPLE);

    /* The last time we drew to the surface, we were using multisampling,
       so we need to blit from the multisampling framebuffer into the
       non-multisampling framebuffer. */
    ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->fb);
    ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->msaa_fb);
    ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height,
				   0, 0, surface->width, surface->height,
				   GL_COLOR_BUFFER_BIT, GL_NEAREST);
    ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
    surface->msaa_active = FALSE;
#endif
}
Beispiel #7
0
void
_cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx,
                                GLfloat x1,
                                GLfloat y1,
                                GLfloat x2,
                                GLfloat y2,
                                GLfloat glyph_x1,
                                GLfloat glyph_y1,
                                GLfloat glyph_x2,
                                GLfloat glyph_y2)
{
    if (ctx->draw_mode != CAIRO_GL_VERTEX) {
	_cairo_gl_composite_flush (ctx);
	ctx->draw_mode = CAIRO_GL_VERTEX;
    }

    _cairo_gl_composite_prepare_buffer (ctx, 6,
					CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);

    _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y1, glyph_x1, glyph_y1);
    _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
    _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);

    _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
    _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y2, glyph_x2, glyph_y2);
    _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);
}
Beispiel #8
0
static void
_cairo_gl_activate_surface_as_multisampling (cairo_gl_context_t *ctx,
					     cairo_gl_surface_t *surface)
{
    assert (surface->supports_msaa);
    assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP);

    _cairo_gl_ensure_framebuffer (ctx, surface);
    _cairo_gl_ensure_multisampling (ctx, surface);


    if (surface->msaa_active) {
	glEnable (GL_MULTISAMPLE);
	ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
	return;
    }

    _cairo_gl_composite_flush (ctx);
    glEnable (GL_MULTISAMPLE);

    _disable_scissor_buffer ();

    /* The last time we drew to the surface, we were not using multisampling,
       so we need to blit from the non-multisampling framebuffer into the
       multisampling framebuffer. */
    ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->msaa_fb);
    ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->fb);
    ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height,
				   0, 0, surface->width, surface->height,
				   GL_COLOR_BUFFER_BIT, GL_NEAREST);
    ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
    surface->msaa_active = TRUE;
}
Beispiel #9
0
void
_cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx,
                                   cairo_gl_tex_t tex_unit)
{
    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;

    if  (!_cairo_gl_context_is_flushed (ctx))
	_cairo_gl_composite_flush (ctx);

    switch (ctx->operands[tex_unit].type) {
    default:
    case CAIRO_GL_OPERAND_COUNT:
        ASSERT_NOT_REACHED;
    case CAIRO_GL_OPERAND_NONE:
        break;
        /* fall through */
    case CAIRO_GL_OPERAND_CONSTANT:
        break;
    case CAIRO_GL_OPERAND_TEXTURE:
        dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
        break;
    case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
    case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
    case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
    case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
        dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
        break;
    }

    memset (&ctx->operands[tex_unit], 0, sizeof (cairo_gl_operand_t));
}
Beispiel #10
0
static cairo_status_t
_gl_flush (void *device)
{
    cairo_gl_context_t *ctx;
    cairo_status_t status;

    status = _cairo_gl_context_acquire (device, &ctx);
    if (unlikely (status))
        return status;

    _cairo_gl_composite_flush (ctx);

    _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE);
    _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK);

    if (ctx->clip_region) {
        cairo_region_destroy (ctx->clip_region);
        ctx->clip_region = NULL;
    }

    ctx->current_target = NULL;
    ctx->current_operator = -1;
    ctx->vertex_size = 0;
    ctx->pre_shader = NULL;
    _cairo_gl_set_shader (ctx, NULL);

    ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, 0);

    glDisable (GL_SCISSOR_TEST);
    glDisable (GL_BLEND);

    return _cairo_gl_context_release (ctx, status);
}
static cairo_int_status_t
_cairo_gl_composite_setup_clipping (cairo_gl_composite_t *setup,
				    cairo_gl_context_t *ctx,
				    int vertex_size)
{

    if (! _cairo_gl_context_is_flushed (ctx) &&
	(! cairo_region_equal (ctx->clip_region, setup->clip_region) ||
	 ! _cairo_clip_equal (ctx->clip, setup->clip)))
	_cairo_gl_composite_flush (ctx);

    cairo_region_destroy (ctx->clip_region);
    ctx->clip_region = cairo_region_reference (setup->clip_region);
    _cairo_clip_destroy (ctx->clip);
    ctx->clip = _cairo_clip_copy (setup->clip);

    assert (!setup->clip_region || !setup->clip);

    if (ctx->clip_region) {
	_disable_stencil_buffer ();
	glEnable (GL_SCISSOR_TEST);
	return CAIRO_INT_STATUS_SUCCESS;
    }

    if (ctx->clip)
	return _cairo_gl_composite_setup_painted_clipping (setup, ctx,
							   vertex_size);

    _disable_stencil_buffer ();
    glDisable (GL_SCISSOR_TEST);
    return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_int_status_t
_prevent_overlapping_strokes (cairo_gl_context_t 		*ctx,
			      cairo_gl_composite_t 		*setup,
			      cairo_composite_rectangles_t 	*composite,
			      const cairo_path_fixed_t		*path,
			      const cairo_stroke_style_t	*style,
			      const cairo_matrix_t		*ctm)
{
    cairo_rectangle_int_t stroke_extents;

    if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (_cairo_pattern_is_opaque (&composite->source_pattern.base,
				  &composite->source_sample_area))
	return CAIRO_INT_STATUS_SUCCESS;

   if (glIsEnabled (GL_STENCIL_TEST) == FALSE) {
	cairo_bool_t scissor_was_enabled;

       /* In case we have pending operations we have to flush before
	  adding the stencil buffer. */
       _cairo_gl_composite_flush (ctx);

	/* Enable the stencil buffer, even if we are not using it for clipping,
	   so we can use it below to prevent overlapping shapes. We initialize
	   it all to one here which represents infinite clip. */
	glDepthMask (GL_TRUE);
	glEnable (GL_STENCIL_TEST);

	/* We scissor here so that we don't have to clear the entire stencil
	 * buffer. If the scissor test is already enabled, it was enabled
	 * for clipping. In that case, instead of calculating an intersection,
	 * we just reuse it, and risk clearing too much. */
	scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST);
	if (! scissor_was_enabled) {
	    _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
							  FALSE, /* is_vector */
							  &stroke_extents);
	    _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents);
	}
	glClearStencil (1);
	glClear (GL_STENCIL_BUFFER_BIT);
	if (! scissor_was_enabled)
	    glDisable (GL_SCISSOR_TEST);

	glStencilFunc (GL_EQUAL, 1, 1);
    }

    /* This means that once we draw to a particular pixel nothing else can
       be drawn there until the stencil buffer is reset or the stencil test
       is disabled. */
    glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);

    _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
    setup->dst->clip_on_stencil_buffer = NULL;

    return CAIRO_INT_STATUS_SUCCESS;
}
Beispiel #13
0
cairo_status_t
_cairo_gl_composite_begin_tristrip (cairo_gl_composite_t	*setup,
				    cairo_gl_context_t		**ctx_out)
{
    cairo_gl_context_t *ctx;
    cairo_status_t status;
    cairo_gl_shader_t *shader;
    int src_size, dst_size;

    cairo_gl_operand_t default_mask;
    memset (&default_mask, 0, sizeof (cairo_gl_operand_t));

    assert (setup->dst);

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

    /* Finish any pending operations from other GL compositors. */
    if (! _cairo_gl_context_is_flushed (ctx))
	_cairo_gl_composite_flush (ctx);

    glEnable (GL_BLEND);

    status = _cairo_gl_get_shader_by_type (ctx,
					   &setup->src,
					   &default_mask,
					   setup->spans,
					   CAIRO_GL_SHADER_IN_NORMAL,
                                           &shader);
    if (unlikely (status)) {
	status = _cairo_gl_context_release (ctx, status);
	return status;
    }

    _cairo_gl_context_set_destination (ctx, setup->dst);

    _cairo_gl_set_operator (ctx, setup->op, FALSE);
    _cairo_gl_set_shader (ctx, shader);
    _cairo_gl_composite_bind_to_shader (ctx, setup);

    dst_size  = 2 * sizeof (GLfloat);
    src_size  = _cairo_gl_operand_get_vertex_size (setup->src.type);

    ctx->vertex_size = dst_size + src_size;

    ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, ctx->vbo);
    ctx->dispatch.VertexAttribPointer (CAIRO_GL_VERTEX_ATTRIB_INDEX, 2,
				       GL_FLOAT, GL_FALSE, ctx->vertex_size, NULL);
    ctx->dispatch.EnableVertexAttribArray (CAIRO_GL_VERTEX_ATTRIB_INDEX);

    _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_SOURCE, &setup->src,
				     ctx->vertex_size, dst_size);

    return status;
}
Beispiel #14
0
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);
}
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 we cannot reduce the clip to a rectangular region,
       we clip using the stencil buffer. */
    glDisable (GL_SCISSOR_TEST);

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

    glDepthMask (GL_TRUE);
    glEnable (GL_STENCIL_TEST);
    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);

    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;
}
Beispiel #16
0
void
_cairo_gl_context_activate (cairo_gl_context_t *ctx,
                            cairo_gl_tex_t      tex_unit)
{
    if (ctx->max_textures <= (GLint) tex_unit) {
        if (tex_unit < 2) {
            _cairo_gl_composite_flush (ctx);
            _cairo_gl_context_destroy_operand (ctx, ctx->max_textures - 1);
        }
        glActiveTexture (ctx->max_textures - 1);
    } else {
        glActiveTexture (GL_TEXTURE0 + tex_unit);
    }
}
Beispiel #17
0
static void
_cairo_gl_composite_setup_vbo (cairo_gl_context_t *ctx,
			       unsigned int size_per_vertex)
{
    if (ctx->vertex_size != size_per_vertex)
        _cairo_gl_composite_flush (ctx);

    if (_cairo_gl_context_is_flushed (ctx)) {
	ctx->dispatch.VertexAttribPointer (CAIRO_GL_VERTEX_ATTRIB_INDEX, 2,
					   GL_FLOAT, GL_FALSE, size_per_vertex,
					   ctx->vb);
	ctx->dispatch.EnableVertexAttribArray (CAIRO_GL_VERTEX_ATTRIB_INDEX);
    }
    ctx->vertex_size = size_per_vertex;
}
Beispiel #18
0
cairo_int_status_t
_cairo_gl_composite_emit_point_as_single_line (cairo_gl_context_t  *ctx,
					       const cairo_point_t point[2])
{
    int num_indices = 2;
    if (ctx->draw_mode != CAIRO_GL_LINES)
	_cairo_gl_composite_flush (ctx);

    ctx->draw_mode = CAIRO_GL_LINES;

    _cairo_gl_composite_prepare_buffer (ctx, 2,
					CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS);

    _cairo_gl_composite_emit_point (ctx, &point[0], 0);
    _cairo_gl_composite_emit_point (ctx, &point[1], 0);
    return _cairo_gl_composite_append_vertex_indices (ctx, num_indices, FALSE);
}
Beispiel #19
0
cairo_int_status_t
_cairo_gl_composite_emit_triangle_as_tristrip (cairo_gl_context_t	*ctx,
					       cairo_gl_composite_t	*setup,
					       const cairo_point_t	 triangle[3])
{
    if (ctx->draw_mode != CAIRO_GL_VERTEX) {
	_cairo_gl_composite_flush (ctx);
	ctx->draw_mode = CAIRO_GL_VERTEX;
    }

    _cairo_gl_composite_prepare_buffer (ctx, 3,
					CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS);

    _cairo_gl_composite_emit_point (ctx, &triangle[0], 0);
    _cairo_gl_composite_emit_point (ctx, &triangle[1], 0);
    _cairo_gl_composite_emit_point (ctx, &triangle[2], 0);
    return _cairo_gl_composite_append_vertex_indices (ctx, 3, TRUE);
}
static cairo_int_status_t
_cairo_gl_composite_setup_clipping (cairo_gl_composite_t *setup,
				    cairo_gl_context_t *ctx,
				    int vertex_size)
{
    cairo_bool_t clip_changing = TRUE;
    cairo_bool_t clip_region_changing = TRUE;

    if (! ctx->clip && ! setup->clip && ! setup->clip_region && ! ctx->clip_region)
	goto disable_all_clipping;

    clip_changing = ! _cairo_clip_equal (ctx->clip, setup->clip);
    clip_region_changing = ! cairo_region_equal (ctx->clip_region, setup->clip_region);
    if (! _cairo_gl_context_is_flushed (ctx) &&
	(clip_region_changing || clip_changing))
	_cairo_gl_composite_flush (ctx);

    assert (!setup->clip_region || !setup->clip);

    /* setup->clip is only used by the msaa compositor and setup->clip_region
     * only by the other compositors, so it's safe to wait to clean up obsolete
     * clips. */
    if (clip_region_changing) {
	cairo_region_destroy (ctx->clip_region);
	ctx->clip_region = cairo_region_reference (setup->clip_region);
    }
    if (clip_changing) {
	_cairo_clip_destroy (ctx->clip);
	ctx->clip = _cairo_clip_copy (setup->clip);
    }

    /* For clip regions, we scissor right before drawing. */
    if (setup->clip_region)
	goto disable_all_clipping;

    if (setup->clip)
	return _cairo_gl_composite_setup_painted_clipping (setup, ctx,
                                                           vertex_size);
disable_all_clipping:
    _disable_stencil_buffer ();
    glDisable (GL_SCISSOR_TEST);
    return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_bool_t
_cairo_gl_composite_setup_vbo (cairo_gl_context_t *ctx,
			       unsigned int size_per_vertex)
{
    cairo_bool_t vertex_size_changed = ctx->vertex_size != size_per_vertex;
    if (vertex_size_changed) {
	ctx->vertex_size = size_per_vertex;
	_cairo_gl_composite_flush (ctx);
    }

    if (_cairo_gl_context_is_flushed (ctx)) {
	ctx->dispatch.VertexAttribPointer (CAIRO_GL_VERTEX_ATTRIB_INDEX, 2,
					   GL_FLOAT, GL_FALSE, size_per_vertex,
					   ctx->vb);
	ctx->dispatch.EnableVertexAttribArray (CAIRO_GL_VERTEX_ATTRIB_INDEX);
    }

    return vertex_size_changed;
}
Beispiel #22
0
static void
_cairo_gl_composite_prepare_buffer (cairo_gl_context_t *ctx,
                                    unsigned int n_vertices)
{
    cairo_gl_dispatch_t *dispatch = &ctx->dispatch;

    if (ctx->vb_offset + n_vertices * ctx->vertex_size > CAIRO_GL_VBO_SIZE)
	_cairo_gl_composite_flush (ctx);

    if (ctx->vb == NULL) {
	if (ctx->has_map_buffer) {
	    dispatch->BufferData (GL_ARRAY_BUFFER, CAIRO_GL_VBO_SIZE,
				  NULL, GL_DYNAMIC_DRAW);
	    ctx->vb = dispatch->MapBuffer (GL_ARRAY_BUFFER, GL_WRITE_ONLY);
	}
	else {
	    ctx->vb = ctx->vb_mem;
	}
    }
}
Beispiel #23
0
void
_cairo_gl_context_activate (cairo_gl_context_t *ctx,
                            cairo_gl_tex_t      tex_unit)
{
    if (ctx->max_textures <= (GLint) tex_unit) {
        if (tex_unit < 2) {
            _cairo_gl_composite_flush (ctx);
            _cairo_gl_context_destroy_operand (ctx, ctx->max_textures - 1);
        }
        if (ctx->states_cache.active_texture != ctx->max_textures - 1) {
	    glActiveTexture (ctx->max_textures - 1);
	    ctx->states_cache.active_texture = ctx->max_textures - 1;
        }
    } else {
        if (ctx->states_cache.active_texture != GL_TEXTURE0 + tex_unit) {
	    glActiveTexture (GL_TEXTURE0 + tex_unit);
	    ctx->states_cache.active_texture = GL_TEXTURE0 + tex_unit;
        }
    }
}
Beispiel #24
0
void
_cairo_gl_gradient_destroy (cairo_gl_gradient_t *gradient)
{
    cairo_gl_context_t *ctx;
    cairo_status_t ignore;

    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&gradient->ref_count));

    if (! _cairo_reference_count_dec_and_test (&gradient->ref_count))
	return;

    if (_cairo_gl_context_acquire (gradient->device, &ctx) == CAIRO_STATUS_SUCCESS) {
	/* The gradient my still be active in the last operation, so flush */
	_cairo_gl_composite_flush (ctx);
	glDeleteTextures (1, &gradient->tex);
	ignore = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);
    }

    free (gradient);
}
Beispiel #25
0
static cairo_status_t
_cairo_gl_surface_flush (void *abstract_surface)
{
    cairo_gl_surface_t *surface = abstract_surface;
    cairo_status_t status;
    cairo_gl_context_t *ctx;

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

    if ((ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE &&
         ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) ||
        (ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE &&
         ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) ||
        (ctx->current_target == surface))
      _cairo_gl_composite_flush (ctx);

    return _cairo_gl_context_release (ctx, status);
}
static void
bind_singlesample_framebuffer (cairo_gl_context_t *ctx,
			       cairo_gl_surface_t *surface)
{
    cairo_bool_t stencil_test_enabled;
    cairo_bool_t scissor_test_enabled;

    assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP);
    _cairo_gl_ensure_framebuffer (ctx, surface);

    if (! surface->msaa_active) {
	glDisable (GL_MULTISAMPLE);
	ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
	return;
    }

    _cairo_gl_composite_flush (ctx);

    stencil_test_enabled = glIsEnabled (GL_STENCIL_TEST);
    scissor_test_enabled = glIsEnabled (GL_SCISSOR_TEST);
    glDisable (GL_STENCIL_TEST);
    glDisable (GL_SCISSOR_TEST);

    glDisable (GL_MULTISAMPLE);

    /* The last time we drew to the surface, we were using multisampling,
       so we need to blit from the multisampling framebuffer into the
       non-multisampling framebuffer. */
    ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->fb);
    ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->msaa_fb);
    ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height,
				   0, 0, surface->width, surface->height,
				   GL_COLOR_BUFFER_BIT, GL_NEAREST);
    ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);

    if (stencil_test_enabled)
	glEnable (GL_STENCIL_TEST);
    if (scissor_test_enabled)
	glEnable (GL_SCISSOR_TEST);
}
Beispiel #27
0
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);
    }
}
static cairo_int_status_t
_draw_clip_to_stencil_buffer (cairo_gl_context_t	*ctx,
			      cairo_gl_composite_t	*setup,
			      cairo_clip_t		*clip)
{
    cairo_int_status_t status;

    assert (! _cairo_clip_is_all_clipped (clip));

    if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
	return CAIRO_INT_STATUS_UNSUPPORTED;

    glDepthMask (GL_TRUE);
    glEnable (GL_STENCIL_TEST);
    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 = _draw_clip (ctx, setup, clip);
    if (unlikely (status)) {
	glColorMask (1, 1, 1, 1);
	_disable_stencil_buffer ();
	return status;
    }

    /* We want to only render to the stencil buffer, so draw everything now. */
    _cairo_gl_composite_flush (ctx);

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

    return status;;
}
Beispiel #29
0
cairo_int_status_t
_cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t	*ctx,
					   cairo_gl_composite_t	*setup,
					   const cairo_point_t	quad[4])
{
    if (ctx->draw_mode != CAIRO_GL_VERTEX) {
	_cairo_gl_composite_flush (ctx);
	ctx->draw_mode = CAIRO_GL_VERTEX;
    }

    _cairo_gl_composite_prepare_buffer (ctx, 4,
					CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS);

    _cairo_gl_composite_emit_point (ctx, &quad[0], 0);
    _cairo_gl_composite_emit_point (ctx, &quad[1], 0);

    /* Cairo stores quad vertices in counter-clockwise order, but we need to
       emit them from top to bottom in the triangle strip, so we need to reverse
       the order of the last two vertices. */
    _cairo_gl_composite_emit_point (ctx, &quad[3], 0);
    _cairo_gl_composite_emit_point (ctx, &quad[2], 0);

    return _cairo_gl_composite_append_vertex_indices (ctx, 4, TRUE);
}
Beispiel #30
0
void
_cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
                               GLfloat x1,
                               GLfloat y1,
                               GLfloat x2,
                               GLfloat y2,
                               uint8_t alpha)
{
    if (ctx->draw_mode != CAIRO_GL_VERTEX) {
	_cairo_gl_composite_flush (ctx);
	ctx->draw_mode = CAIRO_GL_VERTEX;
    }

    _cairo_gl_composite_prepare_buffer (ctx, 6,
					CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);

    _cairo_gl_composite_emit_vertex (ctx, x1, y1, alpha);
    _cairo_gl_composite_emit_vertex (ctx, x2, y1, alpha);
    _cairo_gl_composite_emit_vertex (ctx, x1, y2, alpha);

    _cairo_gl_composite_emit_vertex (ctx, x2, y1, alpha);
    _cairo_gl_composite_emit_vertex (ctx, x2, y2, alpha);
    _cairo_gl_composite_emit_vertex (ctx, x1, y2, alpha);
}