[PATCH 3/4] Split vertex clipping code out into vertex-clipping.c

Sam Spilsbury smspillaz at gmail.com
Fri Sep 13 19:30:02 PDT 2013


Hi Kristian,

On Sat, Sep 14, 2013 at 6:35 AM, Kristian Høgsberg <hoegsberg at gmail.com> wrote:
> On Fri, Sep 13, 2013 at 10:01:21AM +0800, Sam Spilsbury wrote:
>> ---
>>  src/Makefile.am       |   4 +-
>>  src/gl-renderer.c     | 292 +---------------------------------------------
>>  src/vertex-clipping.c | 317 ++++++++++++++++++++++++++++++++++++++++++++++++++
>>  src/vertex-clipping.h |  65 +++++++++++
>>  4 files changed, 389 insertions(+), 289 deletions(-)
>>  create mode 100644 src/vertex-clipping.c
>>  create mode 100644 src/vertex-clipping.h
>
> Wouldn't it be nicer to make calculate_edges() the entry point into
> the clipping code?  As it is, too many internal details spill into the
> header and much of the clipping logic is still in calculate_edges().
> The only problem I see is that calculate_edges() calls
> weston_surface_to_global_float(), but we can stub that out.

I thought about this, but decided against it for two reasons:

1. There's that dependency on weston_surface_to_global_float. There
are many ways to stub it out, and neither of them are really
satisfactory:
 a. You can pass weston_surface_to_global_float as a function pointer
to calculate_edges, which means that unless you pass
weston_surface_to_global_float, or something that does exactly the
same thing, tex-coord generation will be broken.
 b. You can modify weston_surface_to_global float to take as
parameters the bits of weston_surface and weston_output that it only
depends on, but that means lots of changes to those functions, which
are not in the scope of this patch.
 c. Link-seam stubbing, which is really hard to do properly and also
really fragile
2. calculate_edges has two responsibilities:
 a. First to figure out the vertices by clipping against some
arbitrary rectangle and
 b. Secondly to figure out texcoords by taking the projected vertices
and mapping them on to the texture, rotating and scaling as necessary
and then normalizing from 0<->1.

Those responsibilities are more or less independent of each other and
as such they should be tested as independent units.

I don't think that exposing clip_simple and clip_transformed exposes
too much implementation detail. They more-or-less operate on
free-standing data-sets and are utility functions to perform a
particular purpose. In fact, splitting them out from calculate_edges
makes it far clearer what calculate_edges responsibilities are, since
it operates at one level of abstraction higher.

Best Regards,

Sam.

>
> Kristian
>
>> diff --git a/src/Makefile.am b/src/Makefile.am
>> index 3710be6..92426b0 100644
>> --- a/src/Makefile.am
>> +++ b/src/Makefile.am
>> @@ -52,7 +52,9 @@ weston_SOURCES =                            \
>>
>>  if ENABLE_EGL
>>  weston_SOURCES +=                            \
>> -     gl-renderer.c
>> +     gl-renderer.c                           \
>> +     vertex-clipping.c                       \
>> +     vertex-clipping.h
>>  endif
>>
>>  git-version.h : .FORCE
>> diff --git a/src/gl-renderer.c b/src/gl-renderer.c
>> index 4381a2e..6999121 100644
>> --- a/src/gl-renderer.c
>> +++ b/src/gl-renderer.c
>> @@ -33,6 +33,7 @@
>>  #include <linux/input.h>
>>
>>  #include "gl-renderer.h"
>> +#include "vertex-clipping.h"
>>
>>  #include <EGL/eglext.h>
>>  #include "weston-egl-ext.h"
>> @@ -179,270 +180,8 @@ gl_renderer_print_egl_error_state(void)
>>               egl_error_string(code), (long)code);
>>  }
>>
>> -struct polygon8 {
>> -     GLfloat x[8];
>> -     GLfloat y[8];
>> -     int n;
>> -};
>> -
>> -struct clip_context {
>> -     struct {
>> -             GLfloat x;
>> -             GLfloat y;
>> -     } prev;
>> -
>> -     struct {
>> -             GLfloat x1, y1;
>> -             GLfloat x2, y2;
>> -     } clip;
>> -
>> -     struct {
>> -             GLfloat *x;
>> -             GLfloat *y;
>> -     } vertices;
>> -};
>> -
>> -static GLfloat
>> -float_difference(GLfloat a, GLfloat b)
>> -{
>> -     /* http://www.altdevblogaday.com/2012/02/22/comparing-floating-point-numbers-2012-edition/ */
>> -     static const GLfloat max_diff = 4.0f * FLT_MIN;
>> -     static const GLfloat max_rel_diff = 4.0e-5;
>> -     GLfloat diff = a - b;
>> -     GLfloat adiff = fabsf(diff);
>> -
>> -     if (adiff <= max_diff)
>> -             return 0.0f;
>> -
>> -     a = fabsf(a);
>> -     b = fabsf(b);
>> -     if (adiff <= (a > b ? a : b) * max_rel_diff)
>> -             return 0.0f;
>> -
>> -     return diff;
>> -}
>> -
>> -/* A line segment (p1x, p1y)-(p2x, p2y) intersects the line x = x_arg.
>> - * Compute the y coordinate of the intersection.
>> - */
>> -static GLfloat
>> -clip_intersect_y(GLfloat p1x, GLfloat p1y, GLfloat p2x, GLfloat p2y,
>> -              GLfloat x_arg)
>> -{
>> -     GLfloat a;
>> -     GLfloat diff = float_difference(p1x, p2x);
>> -
>> -     /* Practically vertical line segment, yet the end points have already
>> -      * been determined to be on different sides of the line. Therefore
>> -      * the line segment is part of the line and intersects everywhere.
>> -      * Return the end point, so we use the whole line segment.
>> -      */
>> -     if (diff == 0.0f)
>> -             return p2y;
>> -
>> -     a = (x_arg - p2x) / diff;
>> -     return p2y + (p1y - p2y) * a;
>> -}
>> -
>> -/* A line segment (p1x, p1y)-(p2x, p2y) intersects the line y = y_arg.
>> - * Compute the x coordinate of the intersection.
>> - */
>> -static GLfloat
>> -clip_intersect_x(GLfloat p1x, GLfloat p1y, GLfloat p2x, GLfloat p2y,
>> -              GLfloat y_arg)
>> -{
>> -     GLfloat a;
>> -     GLfloat diff = float_difference(p1y, p2y);
>> -
>> -     /* Practically horizontal line segment, yet the end points have already
>> -      * been determined to be on different sides of the line. Therefore
>> -      * the line segment is part of the line and intersects everywhere.
>> -      * Return the end point, so we use the whole line segment.
>> -      */
>> -     if (diff == 0.0f)
>> -             return p2x;
>> -
>> -     a = (y_arg - p2y) / diff;
>> -     return p2x + (p1x - p2x) * a;
>> -}
>> -
>> -enum path_transition {
>> -     PATH_TRANSITION_OUT_TO_OUT = 0,
>> -     PATH_TRANSITION_OUT_TO_IN = 1,
>> -     PATH_TRANSITION_IN_TO_OUT = 2,
>> -     PATH_TRANSITION_IN_TO_IN = 3,
>> -};
>> -
>> -static void
>> -clip_append_vertex(struct clip_context *ctx, GLfloat x, GLfloat y)
>> -{
>> -     *ctx->vertices.x++ = x;
>> -     *ctx->vertices.y++ = y;
>> -}
>> -
>> -static enum path_transition
>> -path_transition_left_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
>> -{
>> -     return ((ctx->prev.x >= ctx->clip.x1) << 1) | (x >= ctx->clip.x1);
>> -}
>> -
>> -static enum path_transition
>> -path_transition_right_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
>> -{
>> -     return ((ctx->prev.x < ctx->clip.x2) << 1) | (x < ctx->clip.x2);
>> -}
>> -
>> -static enum path_transition
>> -path_transition_top_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
>> -{
>> -     return ((ctx->prev.y >= ctx->clip.y1) << 1) | (y >= ctx->clip.y1);
>> -}
>> -
>> -static enum path_transition
>> -path_transition_bottom_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
>> -{
>> -     return ((ctx->prev.y < ctx->clip.y2) << 1) | (y < ctx->clip.y2);
>> -}
>> -
>> -static void
>> -clip_polygon_leftright(struct clip_context *ctx,
>> -                    enum path_transition transition,
>> -                    GLfloat x, GLfloat y, GLfloat clip_x)
>> -{
>> -     GLfloat yi;
>> -
>> -     switch (transition) {
>> -     case PATH_TRANSITION_IN_TO_IN:
>> -             clip_append_vertex(ctx, x, y);
>> -             break;
>> -     case PATH_TRANSITION_IN_TO_OUT:
>> -             yi = clip_intersect_y(ctx->prev.x, ctx->prev.y, x, y, clip_x);
>> -             clip_append_vertex(ctx, clip_x, yi);
>> -             break;
>> -     case PATH_TRANSITION_OUT_TO_IN:
>> -             yi = clip_intersect_y(ctx->prev.x, ctx->prev.y, x, y, clip_x);
>> -             clip_append_vertex(ctx, clip_x, yi);
>> -             clip_append_vertex(ctx, x, y);
>> -             break;
>> -     case PATH_TRANSITION_OUT_TO_OUT:
>> -             /* nothing */
>> -             break;
>> -     default:
>> -             assert(0 && "bad enum path_transition");
>> -     }
>> -
>> -     ctx->prev.x = x;
>> -     ctx->prev.y = y;
>> -}
>> -
>> -static void
>> -clip_polygon_topbottom(struct clip_context *ctx,
>> -                    enum path_transition transition,
>> -                    GLfloat x, GLfloat y, GLfloat clip_y)
>> -{
>> -     GLfloat xi;
>> -
>> -     switch (transition) {
>> -     case PATH_TRANSITION_IN_TO_IN:
>> -             clip_append_vertex(ctx, x, y);
>> -             break;
>> -     case PATH_TRANSITION_IN_TO_OUT:
>> -             xi = clip_intersect_x(ctx->prev.x, ctx->prev.y, x, y, clip_y);
>> -             clip_append_vertex(ctx, xi, clip_y);
>> -             break;
>> -     case PATH_TRANSITION_OUT_TO_IN:
>> -             xi = clip_intersect_x(ctx->prev.x, ctx->prev.y, x, y, clip_y);
>> -             clip_append_vertex(ctx, xi, clip_y);
>> -             clip_append_vertex(ctx, x, y);
>> -             break;
>> -     case PATH_TRANSITION_OUT_TO_OUT:
>> -             /* nothing */
>> -             break;
>> -     default:
>> -             assert(0 && "bad enum path_transition");
>> -     }
>> -
>> -     ctx->prev.x = x;
>> -     ctx->prev.y = y;
>> -}
>> -
>> -static void
>> -clip_context_prepare(struct clip_context *ctx, const struct polygon8 *src,
>> -                   GLfloat *dst_x, GLfloat *dst_y)
>> -{
>> -     ctx->prev.x = src->x[src->n - 1];
>> -     ctx->prev.y = src->y[src->n - 1];
>> -     ctx->vertices.x = dst_x;
>> -     ctx->vertices.y = dst_y;
>> -}
>> -
>> -static int
>> -clip_polygon_left(struct clip_context *ctx, const struct polygon8 *src,
>> -               GLfloat *dst_x, GLfloat *dst_y)
>> -{
>> -     enum path_transition trans;
>> -     int i;
>> -
>> -     clip_context_prepare(ctx, src, dst_x, dst_y);
>> -     for (i = 0; i < src->n; i++) {
>> -             trans = path_transition_left_edge(ctx, src->x[i], src->y[i]);
>> -             clip_polygon_leftright(ctx, trans, src->x[i], src->y[i],
>> -                                    ctx->clip.x1);
>> -     }
>> -     return ctx->vertices.x - dst_x;
>> -}
>> -
>> -static int
>> -clip_polygon_right(struct clip_context *ctx, const struct polygon8 *src,
>> -                GLfloat *dst_x, GLfloat *dst_y)
>> -{
>> -     enum path_transition trans;
>> -     int i;
>> -
>> -     clip_context_prepare(ctx, src, dst_x, dst_y);
>> -     for (i = 0; i < src->n; i++) {
>> -             trans = path_transition_right_edge(ctx, src->x[i], src->y[i]);
>> -             clip_polygon_leftright(ctx, trans, src->x[i], src->y[i],
>> -                                    ctx->clip.x2);
>> -     }
>> -     return ctx->vertices.x - dst_x;
>> -}
>> -
>> -static int
>> -clip_polygon_top(struct clip_context *ctx, const struct polygon8 *src,
>> -              GLfloat *dst_x, GLfloat *dst_y)
>> -{
>> -     enum path_transition trans;
>> -     int i;
>> -
>> -     clip_context_prepare(ctx, src, dst_x, dst_y);
>> -     for (i = 0; i < src->n; i++) {
>> -             trans = path_transition_top_edge(ctx, src->x[i], src->y[i]);
>> -             clip_polygon_topbottom(ctx, trans, src->x[i], src->y[i],
>> -                                    ctx->clip.y1);
>> -     }
>> -     return ctx->vertices.x - dst_x;
>> -}
>> -
>> -static int
>> -clip_polygon_bottom(struct clip_context *ctx, const struct polygon8 *src,
>> -                 GLfloat *dst_x, GLfloat *dst_y)
>> -{
>> -     enum path_transition trans;
>> -     int i;
>> -
>> -     clip_context_prepare(ctx, src, dst_x, dst_y);
>> -     for (i = 0; i < src->n; i++) {
>> -             trans = path_transition_bottom_edge(ctx, src->x[i], src->y[i]);
>> -             clip_polygon_topbottom(ctx, trans, src->x[i], src->y[i],
>> -                                    ctx->clip.y2);
>> -     }
>> -     return ctx->vertices.x - dst_x;
>> -}
>> -
>>  #define max(a, b) (((a) > (b)) ? (a) : (b))
>>  #define min(a, b) (((a) > (b)) ? (b) : (a))
>> -#define clip(x, a, b)  min(max(x, a), b)
>>
>>  /*
>>   * Compute the boundary vertices of the intersection of the global coordinate
>> @@ -457,7 +196,7 @@ static int
>>  calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
>>               pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
>>  {
>> -     struct polygon8 polygon;
>> +
>>       struct clip_context ctx;
>>       int i, n;
>>       GLfloat min_x, max_x, min_y, max_y;
>> @@ -500,11 +239,7 @@ calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
>>        * vertices to the clip rect bounds:
>>        */
>>       if (!es->transform.enabled) {
>> -             for (i = 0; i < surf.n; i++) {
>> -                     ex[i] = clip(surf.x[i], ctx.clip.x1, ctx.clip.x2);
>> -                     ey[i] = clip(surf.y[i], ctx.clip.y1, ctx.clip.y2);
>> -             }
>> -             return surf.n;
>> +             return clip_simple(&ctx, &surf, ex, ey);
>>       }
>>
>>       /* Transformed case: use a general polygon clipping algorithm to
>> @@ -513,26 +248,7 @@ calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
>>        * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
>>        * but without looking at any of that code.
>>        */
>> -     polygon.n = clip_polygon_left(&ctx, &surf, polygon.x, polygon.y);
>> -     surf.n = clip_polygon_right(&ctx, &polygon, surf.x, surf.y);
>> -     polygon.n = clip_polygon_top(&ctx, &surf, polygon.x, polygon.y);
>> -     surf.n = clip_polygon_bottom(&ctx, &polygon, surf.x, surf.y);
>> -
>> -     /* Get rid of duplicate vertices */
>> -     ex[0] = surf.x[0];
>> -     ey[0] = surf.y[0];
>> -     n = 1;
>> -     for (i = 1; i < surf.n; i++) {
>> -             if (float_difference(ex[n - 1], surf.x[i]) == 0.0f &&
>> -                 float_difference(ey[n - 1], surf.y[i]) == 0.0f)
>> -                     continue;
>> -             ex[n] = surf.x[i];
>> -             ey[n] = surf.y[i];
>> -             n++;
>> -     }
>> -     if (float_difference(ex[n - 1], surf.x[0]) == 0.0f &&
>> -         float_difference(ey[n - 1], surf.y[0]) == 0.0f)
>> -             n--;
>> +     n = clip_transformed(&ctx, &surf, ex, ey);
>>
>>       if (n < 3)
>>               return 0;
>> diff --git a/src/vertex-clipping.c b/src/vertex-clipping.c
>> new file mode 100644
>> index 0000000..603ce6f
>> --- /dev/null
>> +++ b/src/vertex-clipping.c
>> @@ -0,0 +1,317 @@
>> +/*
>> + * Copyright © 2012 Intel Corporation
>> + *
>> + * Permission to use, copy, modify, distribute, and sell this software and
>> + * its documentation for any purpose is hereby granted without fee, provided
>> + * that the above copyright notice appear in all copies and that both that
>> + * copyright notice and this permission notice appear in supporting
>> + * documentation, and that the name of the copyright holders not be used in
>> + * advertising or publicity pertaining to distribution of the software
>> + * without specific, written prior permission.  The copyright holders make
>> + * no representations about the suitability of this software for any
>> + * purpose.  It is provided "as is" without express or implied warranty.
>> + *
>> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
>> + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
>> + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
>> + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
>> + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
>> + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
>> + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +#include <assert.h>
>> +#include <float.h>
>> +#include <math.h>
>> +
>> +#include <GLES2/gl2.h>
>> +
>> +#include "vertex-clipping.h"
>> +
>> +GLfloat
>> +float_difference(GLfloat a, GLfloat b)
>> +{
>> +     /* http://www.altdevblogaday.com/2012/02/22/comparing-floating-point-numbers-2012-edition/ */
>> +     static const GLfloat max_diff = 4.0f * FLT_MIN;
>> +     static const GLfloat max_rel_diff = 4.0e-5;
>> +     GLfloat diff = a - b;
>> +     GLfloat adiff = fabsf(diff);
>> +
>> +     if (adiff <= max_diff)
>> +             return 0.0f;
>> +
>> +     a = fabsf(a);
>> +     b = fabsf(b);
>> +     if (adiff <= (a > b ? a : b) * max_rel_diff)
>> +             return 0.0f;
>> +
>> +     return diff;
>> +}
>> +
>> +/* A line segment (p1x, p1y)-(p2x, p2y) intersects the line x = x_arg.
>> + * Compute the y coordinate of the intersection.
>> + */
>> +static GLfloat
>> +clip_intersect_y(GLfloat p1x, GLfloat p1y, GLfloat p2x, GLfloat p2y,
>> +              GLfloat x_arg)
>> +{
>> +     GLfloat a;
>> +     GLfloat diff = float_difference(p1x, p2x);
>> +
>> +     /* Practically vertical line segment, yet the end points have already
>> +      * been determined to be on different sides of the line. Therefore
>> +      * the line segment is part of the line and intersects everywhere.
>> +      * Return the end point, so we use the whole line segment.
>> +      */
>> +     if (diff == 0.0f)
>> +             return p2y;
>> +
>> +     a = (x_arg - p2x) / diff;
>> +     return p2y + (p1y - p2y) * a;
>> +}
>> +
>> +/* A line segment (p1x, p1y)-(p2x, p2y) intersects the line y = y_arg.
>> + * Compute the x coordinate of the intersection.
>> + */
>> +static GLfloat
>> +clip_intersect_x(GLfloat p1x, GLfloat p1y, GLfloat p2x, GLfloat p2y,
>> +              GLfloat y_arg)
>> +{
>> +     GLfloat a;
>> +     GLfloat diff = float_difference(p1y, p2y);
>> +
>> +     /* Practically horizontal line segment, yet the end points have already
>> +      * been determined to be on different sides of the line. Therefore
>> +      * the line segment is part of the line and intersects everywhere.
>> +      * Return the end point, so we use the whole line segment.
>> +      */
>> +     if (diff == 0.0f)
>> +             return p2x;
>> +
>> +     a = (y_arg - p2y) / diff;
>> +     return p2x + (p1x - p2x) * a;
>> +}
>> +
>> +enum path_transition {
>> +     PATH_TRANSITION_OUT_TO_OUT = 0,
>> +     PATH_TRANSITION_OUT_TO_IN = 1,
>> +     PATH_TRANSITION_IN_TO_OUT = 2,
>> +     PATH_TRANSITION_IN_TO_IN = 3,
>> +};
>> +
>> +static void
>> +clip_append_vertex(struct clip_context *ctx, GLfloat x, GLfloat y)
>> +{
>> +     *ctx->vertices.x++ = x;
>> +     *ctx->vertices.y++ = y;
>> +}
>> +
>> +static enum path_transition
>> +path_transition_left_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
>> +{
>> +     return ((ctx->prev.x >= ctx->clip.x1) << 1) | (x >= ctx->clip.x1);
>> +}
>> +
>> +static enum path_transition
>> +path_transition_right_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
>> +{
>> +     return ((ctx->prev.x < ctx->clip.x2) << 1) | (x < ctx->clip.x2);
>> +}
>> +
>> +static enum path_transition
>> +path_transition_top_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
>> +{
>> +     return ((ctx->prev.y >= ctx->clip.y1) << 1) | (y >= ctx->clip.y1);
>> +}
>> +
>> +static enum path_transition
>> +path_transition_bottom_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
>> +{
>> +     return ((ctx->prev.y < ctx->clip.y2) << 1) | (y < ctx->clip.y2);
>> +}
>> +
>> +static void
>> +clip_polygon_leftright(struct clip_context *ctx,
>> +                    enum path_transition transition,
>> +                    GLfloat x, GLfloat y, GLfloat clip_x)
>> +{
>> +     GLfloat yi;
>> +
>> +     switch (transition) {
>> +     case PATH_TRANSITION_IN_TO_IN:
>> +             clip_append_vertex(ctx, x, y);
>> +             break;
>> +     case PATH_TRANSITION_IN_TO_OUT:
>> +             yi = clip_intersect_y(ctx->prev.x, ctx->prev.y, x, y, clip_x);
>> +             clip_append_vertex(ctx, clip_x, yi);
>> +             break;
>> +     case PATH_TRANSITION_OUT_TO_IN:
>> +             yi = clip_intersect_y(ctx->prev.x, ctx->prev.y, x, y, clip_x);
>> +             clip_append_vertex(ctx, clip_x, yi);
>> +             clip_append_vertex(ctx, x, y);
>> +             break;
>> +     case PATH_TRANSITION_OUT_TO_OUT:
>> +             /* nothing */
>> +             break;
>> +     default:
>> +             assert(0 && "bad enum path_transition");
>> +     }
>> +
>> +     ctx->prev.x = x;
>> +     ctx->prev.y = y;
>> +}
>> +
>> +static void
>> +clip_polygon_topbottom(struct clip_context *ctx,
>> +                    enum path_transition transition,
>> +                    GLfloat x, GLfloat y, GLfloat clip_y)
>> +{
>> +     GLfloat xi;
>> +
>> +     switch (transition) {
>> +     case PATH_TRANSITION_IN_TO_IN:
>> +             clip_append_vertex(ctx, x, y);
>> +             break;
>> +     case PATH_TRANSITION_IN_TO_OUT:
>> +             xi = clip_intersect_x(ctx->prev.x, ctx->prev.y, x, y, clip_y);
>> +             clip_append_vertex(ctx, xi, clip_y);
>> +             break;
>> +     case PATH_TRANSITION_OUT_TO_IN:
>> +             xi = clip_intersect_x(ctx->prev.x, ctx->prev.y, x, y, clip_y);
>> +             clip_append_vertex(ctx, xi, clip_y);
>> +             clip_append_vertex(ctx, x, y);
>> +             break;
>> +     case PATH_TRANSITION_OUT_TO_OUT:
>> +             /* nothing */
>> +             break;
>> +     default:
>> +             assert(0 && "bad enum path_transition");
>> +     }
>> +
>> +     ctx->prev.x = x;
>> +     ctx->prev.y = y;
>> +}
>> +
>> +static void
>> +clip_context_prepare(struct clip_context *ctx, const struct polygon8 *src,
>> +                   GLfloat *dst_x, GLfloat *dst_y)
>> +{
>> +     ctx->prev.x = src->x[src->n - 1];
>> +     ctx->prev.y = src->y[src->n - 1];
>> +     ctx->vertices.x = dst_x;
>> +     ctx->vertices.y = dst_y;
>> +}
>> +
>> +static int
>> +clip_polygon_left(struct clip_context *ctx, const struct polygon8 *src,
>> +               GLfloat *dst_x, GLfloat *dst_y)
>> +{
>> +     enum path_transition trans;
>> +     int i;
>> +
>> +     clip_context_prepare(ctx, src, dst_x, dst_y);
>> +     for (i = 0; i < src->n; i++) {
>> +             trans = path_transition_left_edge(ctx, src->x[i], src->y[i]);
>> +             clip_polygon_leftright(ctx, trans, src->x[i], src->y[i],
>> +                                    ctx->clip.x1);
>> +     }
>> +     return ctx->vertices.x - dst_x;
>> +}
>> +
>> +static int
>> +clip_polygon_right(struct clip_context *ctx, const struct polygon8 *src,
>> +                GLfloat *dst_x, GLfloat *dst_y)
>> +{
>> +     enum path_transition trans;
>> +     int i;
>> +
>> +     clip_context_prepare(ctx, src, dst_x, dst_y);
>> +     for (i = 0; i < src->n; i++) {
>> +             trans = path_transition_right_edge(ctx, src->x[i], src->y[i]);
>> +             clip_polygon_leftright(ctx, trans, src->x[i], src->y[i],
>> +                                    ctx->clip.x2);
>> +     }
>> +     return ctx->vertices.x - dst_x;
>> +}
>> +
>> +static int
>> +clip_polygon_top(struct clip_context *ctx, const struct polygon8 *src,
>> +              GLfloat *dst_x, GLfloat *dst_y)
>> +{
>> +     enum path_transition trans;
>> +     int i;
>> +
>> +     clip_context_prepare(ctx, src, dst_x, dst_y);
>> +     for (i = 0; i < src->n; i++) {
>> +             trans = path_transition_top_edge(ctx, src->x[i], src->y[i]);
>> +             clip_polygon_topbottom(ctx, trans, src->x[i], src->y[i],
>> +                                    ctx->clip.y1);
>> +     }
>> +     return ctx->vertices.x - dst_x;
>> +}
>> +
>> +static int
>> +clip_polygon_bottom(struct clip_context *ctx, const struct polygon8 *src,
>> +                 GLfloat *dst_x, GLfloat *dst_y)
>> +{
>> +     enum path_transition trans;
>> +     int i;
>> +
>> +     clip_context_prepare(ctx, src, dst_x, dst_y);
>> +     for (i = 0; i < src->n; i++) {
>> +             trans = path_transition_bottom_edge(ctx, src->x[i], src->y[i]);
>> +             clip_polygon_topbottom(ctx, trans, src->x[i], src->y[i],
>> +                                    ctx->clip.y2);
>> +     }
>> +     return ctx->vertices.x - dst_x;
>> +}
>> +
>> +#define max(a, b) (((a) > (b)) ? (a) : (b))
>> +#define min(a, b) (((a) > (b)) ? (b) : (a))
>> +#define clip(x, a, b)  min(max(x, a), b)
>> +
>> +int
>> +clip_simple(struct clip_context *ctx,
>> +         struct polygon8 *surf,
>> +         GLfloat *ex,
>> +         GLfloat *ey)
>> +{
>> +     int i;
>> +     for (i = 0; i < surf->n; i++) {
>> +             ex[i] = clip(surf->x[i], ctx->clip.x1, ctx->clip.x2);
>> +             ey[i] = clip(surf->y[i], ctx->clip.y1, ctx->clip.y2);
>> +     }
>> +     return surf->n;
>> +}
>> +
>> +int
>> +clip_transformed(struct clip_context *ctx,
>> +              struct polygon8 *surf,
>> +              GLfloat *ex,
>> +              GLfloat *ey)
>> +{
>> +     struct polygon8 polygon;
>> +     int i, n;
>> +
>> +     polygon.n = clip_polygon_left(ctx, surf, polygon.x, polygon.y);
>> +     surf->n = clip_polygon_right(ctx, &polygon, surf->x, surf->y);
>> +     polygon.n = clip_polygon_top(ctx, surf, polygon.x, polygon.y);
>> +     surf->n = clip_polygon_bottom(ctx, &polygon, surf->x, surf->y);
>> +
>> +     /* Get rid of duplicate vertices */
>> +     ex[0] = surf->x[0];
>> +     ey[0] = surf->y[0];
>> +     n = 1;
>> +     for (i = 1; i < surf->n; i++) {
>> +             if (float_difference(ex[n - 1], surf->x[i]) == 0.0f &&
>> +                 float_difference(ey[n - 1], surf->y[i]) == 0.0f)
>> +                     continue;
>> +             ex[n] = surf->x[i];
>> +             ey[n] = surf->y[i];
>> +             n++;
>> +     }
>> +     if (float_difference(ex[n - 1], surf->x[0]) == 0.0f &&
>> +         float_difference(ey[n - 1], surf->y[0]) == 0.0f)
>> +             n--;
>> +
>> +     return n;
>> +}
>> diff --git a/src/vertex-clipping.h b/src/vertex-clipping.h
>> new file mode 100644
>> index 0000000..a16b1df
>> --- /dev/null
>> +++ b/src/vertex-clipping.h
>> @@ -0,0 +1,65 @@
>> +/*
>> + * Copyright © 2012 Intel Corporation
>> + *
>> + * Permission to use, copy, modify, distribute, and sell this software and
>> + * its documentation for any purpose is hereby granted without fee, provided
>> + * that the above copyright notice appear in all copies and that both that
>> + * copyright notice and this permission notice appear in supporting
>> + * documentation, and that the name of the copyright holders not be used in
>> + * advertising or publicity pertaining to distribution of the software
>> + * without specific, written prior permission.  The copyright holders make
>> + * no representations about the suitability of this software for any
>> + * purpose.  It is provided "as is" without express or implied warranty.
>> + *
>> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
>> + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
>> + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
>> + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
>> + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
>> + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
>> + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +#ifndef _WESTON_VERTEX_CLIPPING_H
>> +#define _WESTON_VERTEX_CLIPPING_H
>> +
>> +#include <GLES2/gl2.h>
>> +
>> +struct polygon8 {
>> +     GLfloat x[8];
>> +     GLfloat y[8];
>> +     int n;
>> +};
>> +
>> +struct clip_context {
>> +     struct {
>> +             GLfloat x;
>> +             GLfloat y;
>> +     } prev;
>> +
>> +     struct {
>> +             GLfloat x1, y1;
>> +             GLfloat x2, y2;
>> +     } clip;
>> +
>> +     struct {
>> +             GLfloat *x;
>> +             GLfloat *y;
>> +     } vertices;
>> +};
>> +
>> +GLfloat
>> +float_difference(GLfloat a, GLfloat b);
>> +
>> +int
>> +clip_simple(struct clip_context *ctx,
>> +         struct polygon8 *surf,
>> +         GLfloat *ex,
>> +         GLfloat *ey);
>> +
>> +int
>> +clip_transformed(struct clip_context *ctx,
>> +              struct polygon8 *surf,
>> +              GLfloat *ex,
>> +              GLfloat *ey);\
>> +
>> +#endif
>> --
>> 1.8.3.2
>>
>> _______________________________________________
>> wayland-devel mailing list
>> wayland-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/wayland-devel



-- 
Sam Spilsbury


More information about the wayland-devel mailing list