[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