Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
  2. /* cairo - a vector graphics library with display and print output
  3.  *
  4.  * Copyright © 2002 University of Southern California
  5.  * Copyright © 2005 Red Hat, Inc.
  6.  * Copyright © 2011 Intel Corporation
  7.  * Copyright © 2011 Samsung Electronics
  8.  *
  9.  * This library is free software; you can redistribute it and/or
  10.  * modify it either under the terms of the GNU Lesser General Public
  11.  * License version 2.1 as published by the Free Software Foundation
  12.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  13.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  14.  * notice, a recipient may use your version of this file under either
  15.  * the MPL or the LGPL.
  16.  *
  17.  * You should have received a copy of the LGPL along with this library
  18.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  20.  * You should have received a copy of the MPL along with this library
  21.  * in the file COPYING-MPL-1.1
  22.  *
  23.  * The contents of this file are subject to the Mozilla Public License
  24.  * Version 1.1 (the "License"); you may not use this file except in
  25.  * compliance with the License. You may obtain a copy of the License at
  26.  * http://www.mozilla.org/MPL/
  27.  *
  28.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  29.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  30.  * the specific language governing rights and limitations.
  31.  *
  32.  * The Original Code is the cairo graphics library.
  33.  *
  34.  * The Initial Developer of the Original Code is University of Southern
  35.  * California.
  36.  *
  37.  * Contributor(s):
  38.  *      Henry Song <hsong@sisa.samsung.com>
  39.  *      Martin Robinson <mrobinson@igalia.com>
  40.  */
  41.  
  42. #include "cairoint.h"
  43.  
  44. #include "cairo-clip-inline.h"
  45. #include "cairo-composite-rectangles-private.h"
  46. #include "cairo-compositor-private.h"
  47. #include "cairo-gl-private.h"
  48. #include "cairo-path-private.h"
  49. #include "cairo-traps-private.h"
  50.  
  51. static cairo_bool_t
  52. can_use_msaa_compositor (cairo_gl_surface_t *surface,
  53.                          cairo_antialias_t antialias);
  54.  
  55. static void
  56. query_surface_capabilities (cairo_gl_surface_t *surface);
  57.  
  58. struct _tristrip_composite_info {
  59.     cairo_gl_composite_t        setup;
  60.     cairo_gl_context_t          *ctx;
  61. };
  62.  
  63. static cairo_int_status_t
  64. _draw_trap (cairo_gl_context_t          *ctx,
  65.             cairo_gl_composite_t        *setup,
  66.             cairo_trapezoid_t           *trap)
  67. {
  68.     cairo_point_t quad[4];
  69.  
  70.     quad[0].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
  71.                                                           &trap->left.p2,
  72.                                                           trap->top);
  73.     quad[0].y = trap->top;
  74.  
  75.     quad[1].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
  76.                                                       &trap->left.p2,
  77.                                                       trap->bottom);
  78.     quad[1].y = trap->bottom;
  79.  
  80.     quad[2].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
  81.                                                       &trap->right.p2,
  82.                                                       trap->bottom);
  83.     quad[2].y = trap->bottom;
  84.  
  85.     quad[3].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
  86.                                                       &trap->right.p2,
  87.                                                       trap->top);
  88.     quad[3].y = trap->top;
  89.     return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
  90. }
  91.  
  92. static cairo_int_status_t
  93. _draw_traps (cairo_gl_context_t         *ctx,
  94.              cairo_gl_composite_t       *setup,
  95.              cairo_traps_t              *traps)
  96. {
  97.     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
  98.     int i;
  99.  
  100.     for (i = 0; i < traps->num_traps; i++) {
  101.         cairo_trapezoid_t *trap = traps->traps + i;
  102.         if (unlikely ((status = _draw_trap (ctx, setup, trap))))
  103.             return status;
  104.     }
  105.  
  106.    return status;
  107. }
  108.  
  109. static cairo_int_status_t
  110. _draw_int_rect (cairo_gl_context_t      *ctx,
  111.                 cairo_gl_composite_t    *setup,
  112.                 cairo_rectangle_int_t   *rect)
  113. {
  114.     cairo_box_t box;
  115.     cairo_point_t quad[4];
  116.  
  117.     _cairo_box_from_rectangle (&box, rect);
  118.     quad[0].x = box.p1.x;
  119.     quad[0].y = box.p1.y;
  120.     quad[1].x = box.p1.x;
  121.     quad[1].y = box.p2.y;
  122.     quad[2].x = box.p2.x;
  123.     quad[2].y = box.p2.y;
  124.     quad[3].x = box.p2.x;
  125.     quad[3].y = box.p1.y;
  126.  
  127.     return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
  128. }
  129.  
  130. static cairo_int_status_t
  131. _draw_triangle_fan (cairo_gl_context_t          *ctx,
  132.                     cairo_gl_composite_t        *setup,
  133.                     const cairo_point_t         *midpt,
  134.                     const cairo_point_t         *points,
  135.                     int                          npoints)
  136. {
  137.     int i;
  138.  
  139.     /* Our strategy here is to not even try to build a triangle fan, but to
  140.        draw each triangle as if it was an unconnected member of a triangle strip. */
  141.     for (i = 1; i < npoints; i++) {
  142.         cairo_int_status_t status;
  143.         cairo_point_t triangle[3];
  144.  
  145.         triangle[0] = *midpt;
  146.         triangle[1] = points[i - 1];
  147.         triangle[2] = points[i];
  148.  
  149.         status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
  150.         if (unlikely (status))
  151.             return status;
  152.     }
  153.  
  154.     return CAIRO_STATUS_SUCCESS;
  155. }
  156.  
  157. static cairo_int_status_t
  158. _clip_to_traps (cairo_clip_t *clip,
  159.                 cairo_traps_t *traps)
  160. {
  161.     cairo_int_status_t status;
  162.     cairo_polygon_t polygon;
  163.     cairo_antialias_t antialias;
  164.     cairo_fill_rule_t fill_rule;
  165.  
  166.     _cairo_traps_init (traps);
  167.  
  168.     if (clip->num_boxes == 1 && clip->path == NULL) {
  169.         cairo_boxes_t boxes;
  170.         _cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes);
  171.         return _cairo_traps_init_boxes (traps, &boxes);
  172.     }
  173.  
  174.     status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias);
  175.     if (unlikely (status))
  176.         return status;
  177.  
  178.     /* We ignore the antialias mode of the clip here, since the user requested
  179.      * unantialiased rendering of their path and we expect that this stencil
  180.      * based rendering of the clip to be a reasonable approximation to
  181.      * the intersection between that clip and the path.
  182.      *
  183.      * In other words, what the user expects when they try to perform
  184.      * a geometric intersection between an unantialiased polygon and an
  185.      * antialiased polygon is open to interpretation. And we choose the fast
  186.      * option.
  187.      */
  188.  
  189.     _cairo_traps_init (traps);
  190.     status = _cairo_bentley_ottmann_tessellate_polygon (traps,
  191.                                                         &polygon,
  192.                                                         fill_rule);
  193.     _cairo_polygon_fini (&polygon);
  194.  
  195.     return status;
  196. }
  197.  
  198. cairo_int_status_t
  199. _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
  200.                                      cairo_gl_composite_t *setup,
  201.                                      cairo_clip_t *clip)
  202. {
  203.     cairo_int_status_t status;
  204.     cairo_traps_t traps;
  205.  
  206.     status = _clip_to_traps (clip, &traps);
  207.     if (unlikely (status))
  208.         return status;
  209.     status = _draw_traps (ctx, setup, &traps);
  210.  
  211.     _cairo_traps_fini (&traps);
  212.     return status;
  213. }
  214.  
  215. static cairo_bool_t
  216. _should_use_unbounded_surface (cairo_composite_rectangles_t *composite)
  217. {
  218.     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
  219.     cairo_rectangle_int_t *source = &composite->source;
  220.  
  221.     if (composite->is_bounded)
  222.         return FALSE;
  223.  
  224.     /* This isn't just an optimization. It also detects when painting is used
  225.        to paint back the unbounded surface, preventing infinite recursion. */
  226.     return ! (source->x <= 0 && source->y <= 0 &&
  227.               source->height + source->y >= dst->height &&
  228.               source->width + source->x >= dst->width);
  229. }
  230.  
  231. static cairo_surface_t*
  232. _prepare_unbounded_surface (cairo_gl_surface_t *dst)
  233. {
  234.  
  235.     cairo_surface_t* surface = cairo_gl_surface_create (dst->base.device,
  236.                                                         dst->base.content,
  237.                                                         dst->width,
  238.                                                         dst->height);
  239.     if (surface == NULL)
  240.         return NULL;
  241.     if (unlikely (surface->status)) {
  242.         cairo_surface_destroy (surface);
  243.         return NULL;
  244.     }
  245.     return surface;
  246. }
  247.  
  248. static cairo_int_status_t
  249. _paint_back_unbounded_surface (const cairo_compositor_t         *compositor,
  250.                                cairo_composite_rectangles_t     *composite,
  251.                                cairo_surface_t                  *surface)
  252. {
  253.     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
  254.     cairo_int_status_t status;
  255.  
  256.     cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
  257.     if (unlikely (pattern->status)) {
  258.         status = pattern->status;
  259.         goto finish;
  260.     }
  261.  
  262.     status = _cairo_compositor_paint (compositor, &dst->base,
  263.                                       composite->op, pattern,
  264.                                       composite->clip);
  265.  
  266. finish:
  267.     cairo_pattern_destroy (pattern);
  268.     cairo_surface_destroy (surface);
  269.     return status;
  270. }
  271.  
  272. static cairo_bool_t
  273. can_use_msaa_compositor (cairo_gl_surface_t *surface,
  274.                          cairo_antialias_t antialias)
  275. {
  276.     query_surface_capabilities (surface);
  277.     if (! surface->supports_stencil)
  278.         return FALSE;
  279.  
  280.     /* Multisampling OpenGL ES surfaces only maintain one multisampling
  281.        framebuffer and thus must use the spans compositor to do non-antialiased
  282.        rendering. */
  283.     if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES
  284.          && surface->supports_msaa
  285.          && antialias == CAIRO_ANTIALIAS_NONE)
  286.         return FALSE;
  287.  
  288.     /* The MSAA compositor has a single-sample mode, so we can
  289.        support non-antialiased rendering. */
  290.     if (antialias == CAIRO_ANTIALIAS_NONE)
  291.         return TRUE;
  292.  
  293.     if (antialias == CAIRO_ANTIALIAS_FAST || antialias == CAIRO_ANTIALIAS_DEFAULT)
  294.         return surface->supports_msaa;
  295.     return FALSE;
  296. }
  297.  
  298. static void
  299. _cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t *composite,
  300.                                     cairo_gl_composite_t *setup)
  301. {
  302.     if (_cairo_composite_rectangles_can_reduce_clip (composite, composite->clip))
  303.         return;
  304.     _cairo_gl_composite_set_clip (setup, composite->clip);
  305. }
  306.  
  307. /* Masking with the SOURCE operator requires two passes. In the first
  308.  * pass we use the mask as the source to get:
  309.  * result = (1 - ma) * dst
  310.  * In the second pass we use the add operator to achieve:
  311.  * result = (src * ma) + dst
  312.  * Combined this produces:
  313.  * result = (src * ma) + (1 - ma) * dst
  314.  */
  315. static cairo_int_status_t
  316. _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compositor,
  317.                                                 cairo_composite_rectangles_t *composite)
  318. {
  319.     cairo_gl_composite_t setup;
  320.     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
  321.     cairo_gl_context_t *ctx = NULL;
  322.     cairo_int_status_t status;
  323.  
  324.     cairo_clip_t *clip = composite->clip;
  325.     cairo_traps_t traps;
  326.  
  327.     /* If we have a non-rectangular clip, we can avoid using the stencil buffer
  328.      * for clipping and just draw the clip polygon. */
  329.     if (clip) {
  330.         status = _clip_to_traps (clip, &traps);
  331.         if (unlikely (status)) {
  332.             _cairo_traps_fini (&traps);
  333.             return status;
  334.         }
  335.     }
  336.  
  337.     status = _cairo_gl_composite_init (&setup,
  338.                                        CAIRO_OPERATOR_DEST_OUT,
  339.                                        dst,
  340.                                        FALSE /* assume_component_alpha */);
  341.     if (unlikely (status))
  342.         return status;
  343.     status = _cairo_gl_composite_set_source (&setup,
  344.                                              &composite->mask_pattern.base,
  345.                                              &composite->mask_sample_area,
  346.                                              &composite->bounded,
  347.                                              FALSE);
  348.     if (unlikely (status))
  349.         goto finish;
  350.     _cairo_gl_composite_set_multisample (&setup);
  351.     status = _cairo_gl_composite_begin (&setup, &ctx);
  352.     if (unlikely (status))
  353.         goto finish;
  354.  
  355.     if (! clip)
  356.         status = _draw_int_rect (ctx, &setup, &composite->bounded);
  357.     else
  358.         status = _draw_traps (ctx, &setup, &traps);
  359.     if (unlikely (status))
  360.         goto finish;
  361.  
  362.     /* Now draw the second pass. */
  363.     status = _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD,
  364.                                                FALSE /* assume_component_alpha */);
  365.     if (unlikely (status))
  366.         goto finish;
  367.     status = _cairo_gl_composite_set_source (&setup,
  368.                                              &composite->source_pattern.base,
  369.                                              &composite->source_sample_area,
  370.                                              &composite->bounded,
  371.                                              FALSE);
  372.     if (unlikely (status))
  373.         goto finish;
  374.     status = _cairo_gl_composite_set_mask (&setup,
  375.                                            &composite->mask_pattern.base,
  376.                                            &composite->source_sample_area,
  377.                                            &composite->bounded,
  378.                                            FALSE);
  379.     if (unlikely (status))
  380.         goto finish;
  381.     status = _cairo_gl_set_operands_and_operator (&setup, ctx);
  382.     if (unlikely (status))
  383.         goto finish;
  384.  
  385.     if (! clip)
  386.         status = _draw_int_rect (ctx, &setup, &composite->bounded);
  387.     else
  388.         status = _draw_traps (ctx, &setup, &traps);
  389.  
  390. finish:
  391.     _cairo_gl_composite_fini (&setup);
  392.     if (ctx)
  393.         status = _cairo_gl_context_release (ctx, status);
  394.     if (clip)
  395.         _cairo_traps_fini (&traps);
  396.  
  397.     return status;
  398. }
  399.  
  400. static cairo_int_status_t
  401. _cairo_gl_msaa_compositor_mask (const cairo_compositor_t        *compositor,
  402.                                 cairo_composite_rectangles_t    *composite)
  403. {
  404.     cairo_gl_composite_t setup;
  405.     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
  406.     cairo_gl_context_t *ctx = NULL;
  407.     cairo_int_status_t status;
  408.     cairo_operator_t op = composite->op;
  409.     cairo_clip_t *clip = composite->clip;
  410.  
  411.     if (! can_use_msaa_compositor (dst, CAIRO_ANTIALIAS_DEFAULT))
  412.         return CAIRO_INT_STATUS_UNSUPPORTED;
  413.  
  414.     if (composite->op == CAIRO_OPERATOR_CLEAR &&
  415.         composite->original_mask_pattern != NULL)
  416.         return CAIRO_INT_STATUS_UNSUPPORTED;
  417.  
  418.     /* GL compositing operators cannot properly represent a mask operation
  419.        using the SOURCE compositing operator in one pass. This only matters if
  420.        there actually is a mask (there isn't in a paint operation) and if the
  421.        mask isn't totally opaque. */
  422.     if (op == CAIRO_OPERATOR_SOURCE &&
  423.          composite->original_mask_pattern != NULL &&
  424.         ! _cairo_pattern_is_opaque (&composite->mask_pattern.base,
  425.                                     &composite->mask_sample_area)) {
  426.  
  427.         if (! _cairo_pattern_is_opaque (&composite->source_pattern.base,
  428.                                       &composite->source_sample_area)) {
  429.             return _cairo_gl_msaa_compositor_mask_source_operator (compositor, composite);
  430.         }
  431.  
  432.         /* If the source is opaque the operation reduces to OVER. */
  433.         op = CAIRO_OPERATOR_OVER;
  434.     }
  435.  
  436.     if (_should_use_unbounded_surface (composite)) {
  437.         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
  438.  
  439.         if (unlikely (surface == NULL))
  440.             return CAIRO_INT_STATUS_UNSUPPORTED;
  441.  
  442.         /* This may be a paint operation. */
  443.         if (composite->original_mask_pattern == NULL) {
  444.             status = _cairo_compositor_paint (compositor, surface,
  445.                                               CAIRO_OPERATOR_SOURCE,
  446.                                               &composite->source_pattern.base,
  447.                                               NULL);
  448.         } else {
  449.             status = _cairo_compositor_mask (compositor, surface,
  450.                                              CAIRO_OPERATOR_SOURCE,
  451.                                              &composite->source_pattern.base,
  452.                                              &composite->mask_pattern.base,
  453.                                              NULL);
  454.         }
  455.  
  456.         if (unlikely (status)) {
  457.             cairo_surface_destroy (surface);
  458.             return status;
  459.         }
  460.  
  461.         return _paint_back_unbounded_surface (compositor, composite, surface);
  462.     }
  463.  
  464.     status = _cairo_gl_composite_init (&setup,
  465.                                        op,
  466.                                        dst,
  467.                                        FALSE /* assume_component_alpha */);
  468.     if (unlikely (status))
  469.         return status;
  470.  
  471.     status = _cairo_gl_composite_set_source (&setup,
  472.                                              &composite->source_pattern.base,
  473.                                              &composite->source_sample_area,
  474.                                              &composite->bounded,
  475.                                              FALSE);
  476.     if (unlikely (status))
  477.         goto finish;
  478.  
  479.     if (composite->original_mask_pattern != NULL) {
  480.         status = _cairo_gl_composite_set_mask (&setup,
  481.                                                &composite->mask_pattern.base,
  482.                                                &composite->mask_sample_area,
  483.                                                &composite->bounded,
  484.                                                FALSE);
  485.     }
  486.     if (unlikely (status))
  487.         goto finish;
  488.  
  489.     /* We always use multisampling here, because we do not yet have the smarts
  490.        to calculate when the clip or the source requires it. */
  491.      _cairo_gl_composite_set_multisample (&setup);
  492.  
  493.     status = _cairo_gl_composite_begin (&setup, &ctx);
  494.     if (unlikely (status))
  495.         goto finish;
  496.  
  497.     if (! clip)
  498.         status = _draw_int_rect (ctx, &setup, &composite->bounded);
  499.     else
  500.         status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, clip);
  501.  
  502. finish:
  503.     _cairo_gl_composite_fini (&setup);
  504.  
  505.     if (ctx)
  506.         status = _cairo_gl_context_release (ctx, status);
  507.  
  508.     return status;
  509. }
  510.  
  511. static cairo_int_status_t
  512. _cairo_gl_msaa_compositor_paint (const cairo_compositor_t       *compositor,
  513.                                  cairo_composite_rectangles_t   *composite)
  514. {
  515.     return _cairo_gl_msaa_compositor_mask (compositor, composite);
  516. }
  517.  
  518. static cairo_status_t
  519. _stroke_shaper_add_triangle (void                       *closure,
  520.                              const cairo_point_t         triangle[3])
  521. {
  522.     struct _tristrip_composite_info *info = closure;
  523.     return _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx,
  524.                                                           &info->setup,
  525.                                                           triangle);
  526. }
  527.  
  528. static cairo_status_t
  529. _stroke_shaper_add_triangle_fan (void                   *closure,
  530.                                  const cairo_point_t    *midpoint,
  531.                                  const cairo_point_t    *points,
  532.                                  int                     npoints)
  533. {
  534.     struct _tristrip_composite_info *info = closure;
  535.     return _draw_triangle_fan (info->ctx, &info->setup,
  536.                                midpoint, points, npoints);
  537. }
  538.  
  539. static cairo_status_t
  540. _stroke_shaper_add_quad (void                   *closure,
  541.                          const cairo_point_t     quad[4])
  542. {
  543.     struct _tristrip_composite_info *info = closure;
  544.     return _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup,
  545.                                                       quad);
  546. }
  547.  
  548. static cairo_int_status_t
  549. _prevent_overlapping_strokes (cairo_gl_context_t                *ctx,
  550.                               cairo_gl_composite_t              *setup,
  551.                               cairo_composite_rectangles_t      *composite,
  552.                               const cairo_path_fixed_t          *path,
  553.                               const cairo_stroke_style_t        *style,
  554.                               const cairo_matrix_t              *ctm)
  555. {
  556.     cairo_rectangle_int_t stroke_extents;
  557.  
  558.     if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
  559.         return CAIRO_INT_STATUS_UNSUPPORTED;
  560.  
  561.     if (_cairo_pattern_is_opaque (&composite->source_pattern.base,
  562.                                   &composite->source_sample_area))
  563.         return CAIRO_INT_STATUS_SUCCESS;
  564.  
  565.    if (glIsEnabled (GL_STENCIL_TEST) == FALSE) {
  566.         cairo_bool_t scissor_was_enabled;
  567.  
  568.        /* In case we have pending operations we have to flush before
  569.           adding the stencil buffer. */
  570.        _cairo_gl_composite_flush (ctx);
  571.  
  572.         /* Enable the stencil buffer, even if we are not using it for clipping,
  573.            so we can use it below to prevent overlapping shapes. We initialize
  574.            it all to one here which represents infinite clip. */
  575.         glDepthMask (GL_TRUE);
  576.         glEnable (GL_STENCIL_TEST);
  577.  
  578.         /* We scissor here so that we don't have to clear the entire stencil
  579.          * buffer. If the scissor test is already enabled, it was enabled
  580.          * for clipping. In that case, instead of calculating an intersection,
  581.          * we just reuse it, and risk clearing too much. */
  582.         scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST);
  583.         if (! scissor_was_enabled) {
  584.             _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
  585.                                                           &stroke_extents);
  586.             _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents);
  587.         }
  588.         glClearStencil (1);
  589.         glClear (GL_STENCIL_BUFFER_BIT);
  590.         if (! scissor_was_enabled)
  591.             glDisable (GL_SCISSOR_TEST);
  592.  
  593.         glStencilFunc (GL_EQUAL, 1, 1);
  594.     }
  595.  
  596.     /* This means that once we draw to a particular pixel nothing else can
  597.        be drawn there until the stencil buffer is reset or the stencil test
  598.        is disabled. */
  599.     glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);
  600.  
  601.     _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
  602.     setup->dst->clip_on_stencil_buffer = NULL;
  603.  
  604.     return CAIRO_INT_STATUS_SUCCESS;
  605. }
  606.  
  607. static void
  608. query_surface_capabilities (cairo_gl_surface_t *surface)
  609. {
  610.     GLint samples, stencil_bits;
  611.     cairo_gl_context_t *ctx;
  612.     cairo_int_status_t status;
  613.  
  614.     /* Texture surfaces are create in such a way that they always
  615.        have stencil and multisample bits if possible, so we don't
  616.        need to query their capabilities lazily. */
  617.     if (_cairo_gl_surface_is_texture (surface))
  618.         return;
  619.     if (surface->stencil_and_msaa_caps_initialized)
  620.         return;
  621.  
  622.     surface->stencil_and_msaa_caps_initialized = TRUE;
  623.     surface->supports_stencil = FALSE;
  624.     surface->supports_msaa = FALSE;
  625.  
  626.     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
  627.     if (unlikely (status))
  628.         return;
  629.  
  630.     _cairo_gl_context_set_destination (ctx, surface, FALSE);
  631.  
  632.     glGetIntegerv(GL_SAMPLES, &samples);
  633.     glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
  634.     surface->supports_stencil = stencil_bits > 0;
  635.     surface->supports_msaa = samples > 1;
  636.  
  637.     status = _cairo_gl_context_release (ctx, status);
  638. }
  639.  
  640. static cairo_int_status_t
  641. _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t      *compositor,
  642.                                   cairo_composite_rectangles_t  *composite,
  643.                                   const cairo_path_fixed_t      *path,
  644.                                   const cairo_stroke_style_t    *style,
  645.                                   const cairo_matrix_t          *ctm,
  646.                                   const cairo_matrix_t          *ctm_inverse,
  647.                                   double                         tolerance,
  648.                                   cairo_antialias_t              antialias)
  649. {
  650.     cairo_int_status_t status;
  651.     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
  652.     struct _tristrip_composite_info info;
  653.  
  654.     if (! can_use_msaa_compositor (dst, antialias))
  655.         return CAIRO_INT_STATUS_UNSUPPORTED;
  656.  
  657.     if (composite->is_bounded == FALSE) {
  658.         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
  659.  
  660.         if (unlikely (surface == NULL))
  661.             return CAIRO_INT_STATUS_UNSUPPORTED;
  662.  
  663.         status = _cairo_compositor_stroke (compositor, surface,
  664.                                            CAIRO_OPERATOR_SOURCE,
  665.                                            &composite->source_pattern.base,
  666.                                            path, style, ctm, ctm_inverse,
  667.                                            tolerance, antialias, NULL);
  668.         if (unlikely (status)) {
  669.             cairo_surface_destroy (surface);
  670.             return status;
  671.         }
  672.  
  673.         return _paint_back_unbounded_surface (compositor, composite, surface);
  674.     }
  675.  
  676.     status = _cairo_gl_composite_init (&info.setup,
  677.                                        composite->op,
  678.                                        dst,
  679.                                        FALSE /* assume_component_alpha */);
  680.     if (unlikely (status))
  681.         return status;
  682.  
  683.     info.ctx = NULL;
  684.  
  685.     status = _cairo_gl_composite_set_source (&info.setup,
  686.                                              &composite->source_pattern.base,
  687.                                              &composite->source_sample_area,
  688.                                              &composite->bounded,
  689.                                              FALSE);
  690.     if (unlikely (status))
  691.         goto finish;
  692.  
  693.     _cairo_gl_msaa_compositor_set_clip (composite, &info.setup);
  694.     if (antialias != CAIRO_ANTIALIAS_NONE)
  695.         _cairo_gl_composite_set_multisample (&info.setup);
  696.  
  697.     status = _cairo_gl_composite_begin (&info.setup, &info.ctx);
  698.     if (unlikely (status))
  699.         goto finish;
  700.  
  701.     status = _prevent_overlapping_strokes (info.ctx, &info.setup,
  702.                                            composite, path, style, ctm);
  703.     if (unlikely (status))
  704.         goto finish;
  705.  
  706.     status = _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path,
  707.                                                  style,
  708.                                                  ctm,
  709.                                                  ctm_inverse,
  710.                                                  tolerance,
  711.                                                  _stroke_shaper_add_triangle,
  712.                                                  _stroke_shaper_add_triangle_fan,
  713.                                                  _stroke_shaper_add_quad,
  714.                                                  &info);
  715.     if (unlikely (status))
  716.         goto finish;
  717.  
  718. finish:
  719.     _cairo_gl_composite_fini (&info.setup);
  720.  
  721.     if (info.ctx)
  722.         status = _cairo_gl_context_release (info.ctx, status);
  723.  
  724.     return status;
  725. }
  726.  
  727. static cairo_int_status_t
  728. _draw_simple_quad_path (cairo_gl_context_t *ctx,
  729.                         cairo_gl_composite_t *setup,
  730.                         const cairo_path_fixed_t *path)
  731. {
  732.     cairo_point_t triangle[3];
  733.     cairo_int_status_t status;
  734.     const cairo_point_t *points;
  735.  
  736.     points = cairo_path_head (path)->points;
  737.     triangle[0] = points[0];
  738.     triangle[1] = points[1];
  739.     triangle[2] = points[2];
  740.     status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
  741.     if (status)
  742.         return status;
  743.  
  744.     triangle[0] = points[2];
  745.     triangle[1] = points[3];
  746.     triangle[2] = points[0];
  747.     return _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
  748. }
  749.  
  750. static cairo_int_status_t
  751. _cairo_gl_msaa_compositor_fill (const cairo_compositor_t        *compositor,
  752.                                 cairo_composite_rectangles_t    *composite,
  753.                                 const cairo_path_fixed_t        *path,
  754.                                 cairo_fill_rule_t                fill_rule,
  755.                                 double                           tolerance,
  756.                                 cairo_antialias_t                antialias)
  757. {
  758.     cairo_gl_composite_t setup;
  759.     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
  760.     cairo_gl_context_t *ctx = NULL;
  761.     cairo_int_status_t status;
  762.     cairo_traps_t traps;
  763.     cairo_bool_t draw_path_with_traps;
  764.  
  765.     if (! can_use_msaa_compositor (dst, antialias))
  766.         return CAIRO_INT_STATUS_UNSUPPORTED;
  767.  
  768.     if (composite->is_bounded == FALSE) {
  769.         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
  770.  
  771.         if (unlikely (surface == NULL))
  772.             return CAIRO_INT_STATUS_UNSUPPORTED;
  773.  
  774.  
  775.         status = _cairo_compositor_fill (compositor, surface,
  776.                                          CAIRO_OPERATOR_SOURCE,
  777.                                          &composite->source_pattern.base,
  778.                                          path, fill_rule, tolerance,
  779.                                          antialias, NULL);
  780.  
  781.         if (unlikely (status)) {
  782.             cairo_surface_destroy (surface);
  783.             return status;
  784.         }
  785.  
  786.         return _paint_back_unbounded_surface (compositor, composite, surface);
  787.     }
  788.  
  789.     draw_path_with_traps = ! _cairo_path_fixed_is_simple_quad (path);
  790.  
  791.     if (draw_path_with_traps) {
  792.         _cairo_traps_init (&traps);
  793.         status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
  794.         if (unlikely (status))
  795.             goto cleanup_traps;
  796.     }
  797.  
  798.     status = _cairo_gl_composite_init (&setup,
  799.                                        composite->op,
  800.                                        dst,
  801.                                        FALSE /* assume_component_alpha */);
  802.     if (unlikely (status))
  803.         goto cleanup_traps;
  804.  
  805.     status = _cairo_gl_composite_set_source (&setup,
  806.                                              &composite->source_pattern.base,
  807.                                              &composite->source_sample_area,
  808.                                              &composite->bounded,
  809.                                              FALSE);
  810.     if (unlikely (status))
  811.         goto cleanup_setup;
  812.  
  813.     _cairo_gl_msaa_compositor_set_clip (composite, &setup);
  814.     if (antialias != CAIRO_ANTIALIAS_NONE)
  815.         _cairo_gl_composite_set_multisample (&setup);
  816.  
  817.     status = _cairo_gl_composite_begin (&setup, &ctx);
  818.     if (unlikely (status))
  819.         goto cleanup_setup;
  820.  
  821.     if (! draw_path_with_traps)
  822.         status = _draw_simple_quad_path (ctx, &setup, path);
  823.     else
  824.         status = _draw_traps (ctx, &setup, &traps);
  825.     if (unlikely (status))
  826.         goto cleanup_setup;
  827.  
  828. cleanup_setup:
  829.     _cairo_gl_composite_fini (&setup);
  830.  
  831.     if (ctx)
  832.         status = _cairo_gl_context_release (ctx, status);
  833.  
  834. cleanup_traps:
  835.     if (draw_path_with_traps)
  836.         _cairo_traps_fini (&traps);
  837.  
  838.     return status;
  839. }
  840.  
  841. static cairo_int_status_t
  842. _cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t      *compositor,
  843.                                   cairo_composite_rectangles_t  *composite,
  844.                                   cairo_scaled_font_t           *scaled_font,
  845.                                   cairo_glyph_t                 *glyphs,
  846.                                   int                            num_glyphs,
  847.                                   cairo_bool_t                   overlap)
  848. {
  849.     cairo_int_status_t status;
  850.     cairo_surface_t *src = NULL;
  851.     int src_x, src_y;
  852.     cairo_composite_glyphs_info_t info;
  853.  
  854.     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
  855.  
  856.     query_surface_capabilities (dst);
  857.     if (! dst->supports_stencil)
  858.         return CAIRO_INT_STATUS_UNSUPPORTED;
  859.  
  860.     if (composite->op == CAIRO_OPERATOR_CLEAR)
  861.         return CAIRO_INT_STATUS_UNSUPPORTED;
  862.  
  863.     if (composite->is_bounded == FALSE) {
  864.         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
  865.  
  866.         if (unlikely (surface == NULL))
  867.             return CAIRO_INT_STATUS_UNSUPPORTED;
  868.  
  869.         status = _cairo_compositor_glyphs (compositor, surface,
  870.                                            CAIRO_OPERATOR_SOURCE,
  871.                                            &composite->source_pattern.base,
  872.                                            glyphs, num_glyphs,
  873.                                            scaled_font, composite->clip);
  874.  
  875.         if (unlikely (status)) {
  876.             cairo_surface_destroy (surface);
  877.             return status;
  878.         }
  879.  
  880.         return _paint_back_unbounded_surface (compositor, composite, surface);
  881.     }
  882.  
  883.     src = _cairo_gl_pattern_to_source (&dst->base,
  884.                                        &composite->source_pattern.base,
  885.                                        FALSE,
  886.                                        &composite->bounded,
  887.                                        &composite->source_sample_area,
  888.                                        &src_x, &src_y);
  889.     if (unlikely (src->status)) {
  890.         status = src->status;
  891.         goto finish;
  892.     }
  893.  
  894.     status = _cairo_gl_check_composite_glyphs (composite,
  895.                                                scaled_font, glyphs,
  896.                                                &num_glyphs);
  897.     if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
  898.         goto finish;
  899.  
  900.     info.font = scaled_font;
  901.     info.glyphs = glyphs;
  902.     info.num_glyphs = num_glyphs;
  903.     info.use_mask = overlap || ! composite->is_bounded ||
  904.                     composite->op == CAIRO_OPERATOR_SOURCE;
  905.     info.extents = composite->bounded;
  906.  
  907.     _cairo_scaled_font_freeze_cache (scaled_font);
  908.     status = _cairo_gl_composite_glyphs_with_clip (dst, composite->op,
  909.                                                    src, src_x, src_y,
  910.                                                    0, 0, &info,
  911.                                                    composite->clip);
  912.  
  913.     _cairo_scaled_font_thaw_cache (scaled_font);
  914.  
  915. finish:
  916.     if (src)
  917.         cairo_surface_destroy (src);
  918.  
  919.     return status;
  920. }
  921.  
  922. static void
  923. _cairo_gl_msaa_compositor_init (cairo_compositor_t       *compositor,
  924.                                 const cairo_compositor_t *delegate)
  925. {
  926.     compositor->delegate = delegate;
  927.  
  928.     compositor->paint = _cairo_gl_msaa_compositor_paint;
  929.     compositor->mask = _cairo_gl_msaa_compositor_mask;
  930.     compositor->fill = _cairo_gl_msaa_compositor_fill;
  931.     compositor->stroke = _cairo_gl_msaa_compositor_stroke;
  932.     compositor->glyphs = _cairo_gl_msaa_compositor_glyphs;
  933. }
  934.  
  935. const cairo_compositor_t *
  936. _cairo_gl_msaa_compositor_get (void)
  937. {
  938.     static cairo_compositor_t compositor;
  939.     if (compositor.delegate == NULL)
  940.         _cairo_gl_msaa_compositor_init (&compositor,
  941.                                         _cairo_gl_span_compositor_get ());
  942.  
  943.     return &compositor;
  944. }
  945.