[Glamor] [PATCH] Add the poly line draw feature for glamor.

zhigang gong zhigang.gong at gmail.com
Sat Apr 14 08:04:47 PDT 2012


Where is the v2 patch?

On Fri, Apr 13, 2012 at 11:53 PM, He Junyan <junyan.he at linux.intel.com> wrote:
> Sorry, some err in rebase.
> V2 has been sent
>
>
>> I have two comments on this patch.
>>
>> 1. For comparison two floats/int with ">" or"<" ops, you don't need to add
>> a
>> epsilon which is only needed when you want to check whether the two floats
>> are
>> equal to each other. And I simply some of you code remove some uncessary
>> type cast.
>>
>> 2. One time draw one line segment is not efficient, you can accumulate all
>> the lines and
>> draw them all at one call toe glDrawArray.
>>
>> I fixed the comment 1 and paste the new version as below. please check it
>> out.
>> For 2, I discussed with you, and please refine them latter. Anyway,
>> this patch is already much better than original fully fallback to CPU when
>> draw diagonal poly_line.
>>
>> But just before I pushed this patch, I found regressions with XTS test.
>> xts5/Xlib9/XDrawLines/XDrawLines (32/104): FAIL
>> xts5/Xlib9/XDrawLines/XDrawLines (57/104): FAIL
>>
>> There are also two or three failures on XDrawLine, please check and fix
>> the regressions. Thanks.
>>
>>> From f5c3e62c16d88b137691e4032c17a429d26a18dd Mon Sep 17 00:00:00 2001
>>
>> From: Junyan He<junyan.he at linux.intel.com>
>> Date: Fri, 13 Apr 2012 02:29:03 +0800
>> Subject: [PATCH] Add the poly line draw feature for glamor.
>>
>>  Add the poly line draw feature for glamor. This can avoid to
>>  download the pixman to CPU and upload it to GPU after draw.
>>  Now, just solid narrow line draw is supported, other styles
>>  will still fallback.
>>
>> Signed-off-by: Junyan He<junyan.he at linux.intel.com>
>> Signed-off-by: Zhigang Gong<zhigang.gong at linux.intel.com>
>> ---
>>  src/glamor.c           |    2 +
>>  src/glamor_polylines.c |  298
>> ++++++++++++++++++++++++++++++++++++++++++++++--
>>  src/glamor_priv.h      |    7 +-
>>  3 files changed, 295 insertions(+), 12 deletions(-)
>>
>> diff --git a/src/glamor.c b/src/glamor.c
>> index 9b1d425..0b0a1be 100644
>> --- a/src/glamor.c
>> +++ b/src/glamor.c
>> @@ -399,6 +399,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
>>        glamor_init_putimage_shaders(screen);
>>        glamor_init_finish_access_shaders(screen);
>>        glamor_init_gradient_shader(screen);
>> +       glamor_init_polylines_shader(screen);
>>        glamor_pixmap_init(screen);
>>
>>        glamor_priv->flags = flags;
>> @@ -427,6 +428,7 @@ glamor_release_screen_priv(ScreenPtr screen)
>>        glamor_fini_putimage_shaders(screen);
>>        glamor_fini_finish_access_shaders(screen);
>>        glamor_fini_gradient_shader(screen);
>> +       glamor_fini_polylines_shader(screen);
>>        glamor_pixmap_fini(screen);
>>        free(glamor_priv);
>>
>> diff --git a/src/glamor_polylines.c b/src/glamor_polylines.c
>> index 70dd6c1..b1facca 100644
>> --- a/src/glamor_polylines.c
>> +++ b/src/glamor_polylines.c
>> @@ -28,11 +28,265 @@
>>
>>  #include "glamor_priv.h"
>>
>> +#define GLAMOR_LINE_SLOPE      0
>> +#define GLAMOR_LINE_SLOPE_INV  1
>> +#define GLAMOR_LINE_VER_HOR    2
>> +
>>  /** @file glamor_polylines.c
>>   *
>>   * GC PolyFillRect implementation, taken straight from fb_fill.c
>>   */
>>
>> +void
>> +glamor_init_polylines_shader(ScreenPtr screen)
>> +{
>> +       glamor_screen_private *glamor_priv;
>> +       glamor_gl_dispatch *dispatch;
>> +
>> +       const char *polylines_vs =
>> +           "attribute vec4 v_position;"
>> +           "void main()\n"
>> +           "{\n"
>> +           "    gl_Position = v_position;\n"
>> +           "}\n";
>> +
>> +       const char *polylines_fs =
>> +           GLAMOR_DEFAULT_PRECISION
>> +           "uniform vec4 color;\n"
>> +           "void main()\n"
>> +           "{\n"
>> +           "    gl_FragColor = color;\n"
>> +           "}\n";
>> +
>> +       GLint fs_prog, vs_prog;
>> +
>> +       glamor_priv = glamor_get_screen_private(screen);
>> +       dispatch =  glamor_get_dispatch(glamor_priv);
>> +
>> +       glamor_priv->polylines_prog = dispatch->glCreateProgram();
>> +
>> +       vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER,
>> polylines_vs);
>> +       fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER,
>> polylines_fs);
>> +
>> +       dispatch->glAttachShader(glamor_priv->polylines_prog, vs_prog);
>> +       dispatch->glAttachShader(glamor_priv->polylines_prog, fs_prog);
>> +
>> +       dispatch->glBindAttribLocation(glamor_priv->polylines_prog,
>> +               GLAMOR_VERTEX_POS, "v_position");
>> +       dispatch->glBindAttribLocation(glamor_priv->polylines_prog,
>> +               GLAMOR_VERTEX_SOURCE, "v_texcoord");
>> +
>> +       glamor_link_glsl_prog(dispatch, glamor_priv->polylines_prog);
>> +
>> +       glamor_put_dispatch(glamor_priv);
>> +}
>> +
>> +void
>> +glamor_fini_polylines_shader(ScreenPtr screen)
>> +{
>> +       glamor_screen_private *glamor_priv;
>> +       glamor_gl_dispatch *dispatch;
>> +
>> +       glamor_priv = glamor_get_screen_private(screen);
>> +       dispatch = glamor_get_dispatch(glamor_priv);
>> +       dispatch->glDeleteProgram(glamor_priv->polylines_prog);
>> +       glamor_put_dispatch(glamor_priv);
>> +}
>> +
>> +static Bool
>> +_glamor_draw_polylines(DrawablePtr drawable, GCPtr gc, int n_rect,
>> +                      xRectangle* rects, int* line_modes)
>> +{
>> +       glamor_screen_private *glamor_priv;
>> +       int xorg, yorg;
>> +       int xoff, yoff;
>> +       int fullX1, fullX2, fullY1, fullY2;
>> +       int n;
>> +       int region_num;
>> +       register BoxPtr pbox;
>> +       RegionPtr pClip = fbGetCompositeClip(gc);
>> +       PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable);
>> +
>> +       glamor_pixmap_private *pixmap_priv =
>> glamor_get_pixmap_private(dst_pixmap);
>> +
>> +       if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) {
>> +               glamor_fallback("dest %p has no fbo.\n", dst_pixmap);
>> +               return FALSE;
>> +       }
>> +
>> +       glamor_priv = glamor_get_screen_private(drawable->pScreen);
>> +
>> +       xorg = drawable->x;
>> +       yorg = drawable->y;
>> +
>> +       for (n = 0; n<  n_rect; n++) {
>> +               assert(line_modes[n] == GLAMOR_LINE_VER_HOR
>> +                      || line_modes[n] == GLAMOR_LINE_SLOPE
>> +                      || line_modes[n] == GLAMOR_LINE_SLOPE_INV);
>> +
>> +               if (line_modes[n] == GLAMOR_LINE_VER_HOR) {
>> +                       gc->ops->PolyFillRect(drawable, gc, 1,&rects[n]);
>>
>> +                       continue;
>> +               }
>> +
>> +               fullX1 = rects[n].x + xorg;
>> +               fullY1 = rects[n].y + yorg;
>> +               fullX2 = fullX1 + rects[n].width;
>> +               fullY2 = fullY1 + rects[n].height;
>> +
>> +               region_num = REGION_NUM_RECTS(pClip);
>> +               pbox = REGION_RECTS(pClip);
>> +
>> +               while (region_num--) {
>> +                       float x1 = fullX1;
>> +                       float x2 = fullX2;
>> +                       float y1 = fullY1;
>> +                       float y2 = fullY2;
>> +                       GLfloat color[4];
>> +                       float vertices[8];
>> +                       float line_points[4];
>> +                       GLfloat xscale, yscale;
>> +                       glamor_gl_dispatch *dispatch;
>> +                       GLint uniform_color_location;
>> +                       int tex_width;
>> +
>> +                       if (pbox->x1>  fullX1)
>> +                               x1 = pbox->x1;
>> +                       if (pbox->x2<  fullX2)
>> +                               x2 = pbox->x2;
>> +                       if (pbox->y1>  fullY1)
>> +                               y1 = pbox->y1;
>> +                       if (pbox->y2<  fullY2)
>> +                               y2 = pbox->y2;
>> +
>> +                       if (x1>= x2 || y1>= y2) {
>> +                               DebugF("rect: (%d, %d) (%d, %d)
>> \tclipbox: (%d, %d) (%d, %d)\n"
>> +                                      "--->  result:  (%f, %f) (%f, %f)
>> clip out\n",
>> +                                      fullX1, fullY1, fullX2, fullY2,
>> +                                      pbox->x1, pbox->y1, pbox->x2,
>> pbox->y2,
>> +                                      x1, y1, x2, y2);
>> +                               continue;
>> +                       }
>> +
>> +                       /* The CapNotLast mode, last pix can not draw.
>> +                          We decrease the X or Y based on the slope.*/
>> +                       if (gc->capStyle == CapNotLast&&  n == n_rect -
>> 1&&
>> +                            (rects[n].x != rects[2].x || rects[n].y !=
>> rects[1].y)) {
>> +                               if ((x2 - x1)>  (y2 - y1))
>> +                                       x2--;
>> +                               else {
>> +                                       if (line_modes[n] ==
>> GLAMOR_LINE_SLOPE)
>> +                                               y2--;
>> +                                       else
>> +                                               y1++;
>> +                               }
>> +                       }
>> +
>> +                       if (line_modes[n] == GLAMOR_LINE_SLOPE) {
>> +                               float slope;
>> +                               float new_x, new_y;
>> +
>> +                               slope = (float)(fullY2 - fullY1) / (fullX2
>> - fullX1);
>> +                               if ((x1>  fullX1) || (y1>  fullY1)) {
>> +                                       new_x = (y1 - fullY1) / slope +
>> fullX1;
>> +                                       new_y = (x1 - fullX1) * slope +
>> fullY1;
>> +                                       x1 = max(new_x, x1);
>> +                                       y1 = max(new_y, y1);
>> +                               }
>> +
>> +                               if ((fullX2>  x2) || (fullY2>  y2)) {
>> +                                       new_x = (y2 - fullY1) / slope +
>> fullX1;
>> +                                       new_y = (y2 - fullY1) * slope +
>> fullY1;
>> +                                       x2 = min(new_x, x2);
>> +                                       y2 = min(new_y, y2);
>> +                               }
>> +                       } else {//GLAMOR_LINE_SLOPE_INV
>> +                               float slope;
>> +                               float new_x, new_y;
>> +
>> +                               slope = (float)(fullY1 - fullY2) / (fullX2
>> - fullX1);
>> +                               if ((x1>  fullX1) || (fullY2>  y2)) {
>> +                                       new_x = (y2 - fullY2) / slope +
>> fullX1;
>> +                                       new_y = (x1 - fullX1) * slope
>> +fullY1;
>> +                                       x1 = max(new_x, x1);
>> +                                       y2 = min(new_y, y2);
>> +                               }
>> +
>> +                               if ((fullX2>  x2) || (y1>  fullY1)) {
>> +                                       new_x = (y1 - fullY2) / slope +
>> fullX1;
>> +                                       new_y = (x2 - fullX1) * slope +
>> fullY2;
>> +                                       x2 = min(new_x, x2);
>> +                                       y1 = max(new_y, y1);
>> +                               }
>> +                       }
>> +
>> +                       DebugF("rect: (%d, %d) (%d, %d)   \tclipbox: (%d,
>> %d) (%d, %d)\n"
>> +                              "--->  result:  (%f, %f) (%f, %f)\n",
>> +                              fullX1, fullY1, fullX2, fullY2,
>> +                              pbox->x1, pbox->y1, pbox->x2, pbox->y2,
>> +                              x1, y1, x2, y2);
>> +
>> +                       pbox++;
>> +
>> +                       /* Use shader to draw the lines. */
>> +                       glamor_get_drawable_deltas(drawable,
>> dst_pixmap,&xoff,&yoff);
>> +                       x1 += xoff;
>> +                       x2 += xoff;
>> +                       y1 += yoff;
>> +                       y2 += yoff;
>> +
>> +                       glamor_get_rgba_from_pixel(gc->fgPixel,
>> +                       &color[0],
>> +                       &color[1],
>> +                       &color[2],
>> +                       &color[3],
>> +                               format_for_pixmap(dst_pixmap));
>> +
>> +
>> glamor_set_destination_pixmap_priv_nc(pixmap_priv);
>> +                       glamor_validate_pixmap(dst_pixmap);
>> +
>> +                       dispatch = glamor_get_dispatch(glamor_priv);
>> +                       glamor_set_alu(dispatch, gc->alu);
>> +
>> +
>> dispatch->glUseProgram(glamor_priv->polylines_prog);
>> +                       uniform_color_location =
>> +
>> dispatch->glGetUniformLocation(glamor_priv->polylines_prog, "color");
>> +                       dispatch->glUniform4fv(uniform_color_location, 1,
>> color);
>> +
>> +                       dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS,
>> 2, GL_FLOAT,
>> +                               GL_FALSE, 2 * sizeof(float), line_points);
>> +
>> dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
>> +
>> +
>> pixmap_priv_get_scale(pixmap_priv,&xscale,&yscale);
>> +                       glamor_set_normalize_vcoords(xscale, yscale, x1,
>> y1, x2, y2,
>> +                               glamor_priv->yInverted, vertices);
>> +
>> +                       if (line_modes[n] == GLAMOR_LINE_SLOPE) {
>> +                               line_points[0] = vertices[0];
>> +                               line_points[1] = vertices[1];
>> +                               line_points[2] = vertices[4];
>> +                               line_points[3] = vertices[5];
>> +                       } else {//GLAMOR_LINE_SLOPE_INV
>> +                               line_points[0] = vertices[2];
>> +                               line_points[1] = vertices[3];
>> +                               line_points[2] = vertices[6];
>> +                               line_points[3] = vertices[7];
>> +                       }
>> +                       DEBUGF("Draw from: (%f, %f) to (%f, %f)\n",
>> +                              line_points[0], line_points[1],
>> +                              line_points[2], line_points[3]);
>> +
>> +                       dispatch->glDrawArrays(GL_LINES, 0, 4);
>> +
>> dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
>> +                       dispatch->glUseProgram(0);
>> +                       glamor_set_alu(dispatch, GXcopy);
>> +                       glamor_put_dispatch(glamor_priv);
>> +               }
>> +       }
>> +       return TRUE;
>> +}
>> +
>> +
>>  /**
>>   * glamor_poly_lines() checks if it can accelerate the lines as a group
>> of
>>   * horizontal or vertical lines (rectangles), and uses existing rectangle
>> fill
>> @@ -43,8 +297,10 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int
>> mode, int n,
>>                   DDXPointPtr points, Bool fallback)
>>  {
>>        xRectangle *rects;
>> +       int *line_modes;
>>        int x1, x2, y1, y2;
>>        int i;
>> +       int all_diag;
>>        glamor_screen_private *glamor_priv;
>>
>>        /* Don't try to do wide lines or non-solid fill style. */
>> @@ -54,15 +310,18 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc,
>> int mode, int n,
>>                 */
>>                goto wide_line;
>>        }
>> -       if (gc->lineStyle != LineSolid) {
>> +       if (gc->lineStyle != LineSolid || gc->fillStyle != FillSolid) {
>>                glamor_fallback
>> -                   ("non-solid fill line style %d\n",
>> -                    gc->lineStyle);
>> +               ("non-solid fill line style %d, fill style %d\n",
>> +                gc->lineStyle, gc->fillStyle);
>>                goto fail;
>>        }
>> +
>>        rects = malloc(sizeof(xRectangle) * (n - 1));
>> +       line_modes = malloc(sizeof(int) * (n - 1));
>>        x1 = points[0].x;
>>        y1 = points[0].y;
>> +       all_diag = 1;
>>        /* If we have any non-horizontal/vertical, fall back. */
>>        for (i = 0; i<  n - 1; i++) {
>>                if (mode == CoordModePrevious) {
>> @@ -72,11 +331,19 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc,
>> int mode, int n,
>>                        x2 = points[i + 1].x;
>>                        y2 = points[i + 1].y;
>>                }
>> +
>>                if (x1 != x2&&  y1 != y2) {
>>
>> -                       free(rects);
>> -                       glamor_fallback("stub diagonal poly_line\n");
>> -                       goto fail;
>> +                       if ((x2 - x1) * (y2 - y1)>  0)
>> +                               line_modes[i] = GLAMOR_LINE_SLOPE;
>> +                       else
>> +                               line_modes[i] = GLAMOR_LINE_SLOPE_INV;
>> +
>> +                       all_diag = 0;
>> +                       DEBUGF("Have diagonal poly_line\n");
>> +               } else {
>> +                       line_modes[i] = GLAMOR_LINE_VER_HOR;
>>                }
>> +
>>                if (x1<  x2) {
>>                        rects[i].x = x1;
>>                        rects[i].width = x2 - x1 + 1;
>> @@ -95,14 +362,25 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc,
>> int mode, int n,
>>                x1 = x2;
>>                y1 = y2;
>>        }
>> -       gc->ops->PolyFillRect(drawable, gc, n - 1, rects);
>> +
>> +       if (all_diag) { /* Fast path, all use the fill rect.*/
>> +               gc->ops->PolyFillRect(drawable, gc, n - 1, rects);
>> +       } else {
>> +               if (_glamor_draw_polylines(drawable, gc, n - 1,
>> +                     rects, line_modes) == FALSE)
>> +                       free(rects);
>> +                       free(line_modes);
>> +                       goto fail;
>> +       }
>> +
>>        free(rects);
>> +       free(line_modes);
>>        return TRUE;
>>
>> -      fail:
>> +fail:
>>        if (!fallback
>> -       &&  glamor_ddx_fallback_check_pixmap(drawable)
>> -       &&  glamor_ddx_fallback_check_gc(gc))
>> +       &&  glamor_ddx_fallback_check_pixmap(drawable)
>> +       &&  glamor_ddx_fallback_check_gc(gc))
>>                return FALSE;
>>
>>        glamor_priv = glamor_get_screen_private(drawable->pScreen);
>> diff --git a/src/glamor_priv.h b/src/glamor_priv.h
>> index 961af47..3403942 100644
>> --- a/src/glamor_priv.h
>> +++ b/src/glamor_priv.h
>> @@ -233,6 +233,9 @@ typedef struct glamor_screen_private {
>>        GLint tile_prog;
>>        GLint tile_wh;
>>
>> +       /* polylines */
>> +       GLint polylines_prog;
>> +
>>        /* glamor gradient */
>>        GLint gradient_prog[GRADIENT_SHADER_COUNT];
>>
>> @@ -530,13 +533,13 @@ glamor_poly_fill_rect(DrawablePtr drawable,
>>
>>  /* glamor_polylines.c */
>>  void
>> -
>>  glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
>>                  DDXPointPtr points);
>> +void glamor_init_polylines_shader(ScreenPtr screen);
>> +void glamor_fini_polylines_shader(ScreenPtr screen);
>>
>>  /* glamor_putimage.c */
>>  void
>> -
>>  glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
>>                 int w, int h, int leftPad, int format, char *bits);
>>  void glamor_init_putimage_shaders(ScreenPtr screen);
>
> _______________________________________________
> Glamor mailing list
> Glamor at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/glamor


More information about the Glamor mailing list