diff --git a/glamor/Makefile.am b/glamor/Makefile.am index 3664fd380..4be9f3486 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -12,18 +12,16 @@ libglamor_la_SOURCES = \ glamor_core.c \ glamor_debug.h \ glamor_fill.c \ - glamor_fillspans.c \ - glamor_getspans.c \ glamor_glx.c \ glamor_glyphs.c \ glamor_polyfillrect.c \ glamor_polylines.c \ glamor_putimage.c \ - glamor_setspans.c \ glamor_segment.c \ glamor_render.c \ glamor_gradient.c \ glamor_program.c \ + glamor_spans.c \ glamor_transfer.c \ glamor_transfer.h \ glamor_transform.c \ diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c deleted file mode 100644 index 8cbd79f6d..000000000 --- a/glamor/glamor_fillspans.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright © 1998 Keith Packard - * - * 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 Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD 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. - */ - -/** @file glamor_fillspans.c - * - * FillSpans implementation, taken from fb_fillsp.c - */ -#include "glamor_priv.h" - -static Bool -_glamor_fill_spans(DrawablePtr drawable, - GCPtr gc, - int n, DDXPointPtr points, int *widths, int sorted, - Bool fallback) -{ - DDXPointPtr ppt; - int nbox; - BoxPtr pbox; - int x1, x2, y; - RegionPtr pClip = fbGetCompositeClip(gc); - Bool ret = FALSE; - - if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) - goto fail; - - ppt = points; - while (n--) { - x1 = ppt->x; - y = ppt->y; - x2 = x1 + (int) *widths; - ppt++; - widths++; - - nbox = REGION_NUM_RECTS(pClip); - pbox = REGION_RECTS(pClip); - while (nbox--) { - int real_x1 = x1, real_x2 = x2; - - if (real_x1 < pbox->x1) - real_x1 = pbox->x1; - - if (real_x2 > pbox->x2) - real_x2 = pbox->x2; - - if (real_x2 > real_x1 && pbox->y1 <= y && pbox->y2 > y) { - if (!glamor_fill(drawable, gc, real_x1, y, - real_x2 - real_x1, 1, fallback)) - goto fail; - } - pbox++; - } - } - ret = TRUE; - goto done; - - fail: - if (!fallback && glamor_ddx_fallback_check_pixmap(drawable) - && glamor_ddx_fallback_check_gc(gc)) { - goto done; - } - glamor_fallback("to %p (%c)\n", drawable, - glamor_get_drawable_location(drawable)); - if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && - glamor_prepare_access_gc(gc)) { - fbFillSpans(drawable, gc, n, points, widths, sorted); - } - glamor_finish_access_gc(gc); - glamor_finish_access(drawable); - ret = TRUE; - - done: - return ret; -} - -void -glamor_fill_spans(DrawablePtr drawable, - GCPtr gc, int n, DDXPointPtr points, int *widths, int sorted) -{ - _glamor_fill_spans(drawable, gc, n, points, widths, sorted, TRUE); -} - -Bool -glamor_fill_spans_nf(DrawablePtr drawable, - GCPtr gc, - int n, DDXPointPtr points, int *widths, int sorted) -{ - return _glamor_fill_spans(drawable, gc, n, points, widths, sorted, FALSE); -} diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c deleted file mode 100644 index 42df87f3d..000000000 --- a/glamor/glamor_getspans.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright © 2009 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Eric Anholt - * Zhigang Gong - * - */ - -#include "glamor_priv.h" - -static Bool -_glamor_get_spans(DrawablePtr drawable, - int wmax, - DDXPointPtr points, int *widths, int count, char *dst, - Bool fallback) -{ - PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); - glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - int i; - uint8_t *readpixels_dst = (uint8_t *) dst; - void *data; - int x_off, y_off; - Bool ret = FALSE; - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) - goto fail; - - glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); - for (i = 0; i < count; i++) { - data = glamor_download_sub_pixmap_to_cpu(pixmap, points[i].x + x_off, - points[i].y + y_off, widths[i], - 1, PixmapBytePad(widths[i], - drawable-> - depth), - readpixels_dst, 0, - GLAMOR_ACCESS_RO); - (void)data; - assert(data == readpixels_dst); - readpixels_dst += PixmapBytePad(widths[i], drawable->depth); - } - - ret = TRUE; - goto done; - fail: - - if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)) - goto done; - - ret = TRUE; - if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) { - fbGetSpans(drawable, wmax, points, widths, count, dst); - } - glamor_finish_access(drawable); - done: - return ret; -} - -void -glamor_get_spans(DrawablePtr drawable, - int wmax, - DDXPointPtr points, int *widths, int count, char *dst) -{ - _glamor_get_spans(drawable, wmax, points, widths, count, dst, TRUE); -} - -Bool -glamor_get_spans_nf(DrawablePtr drawable, - int wmax, - DDXPointPtr points, int *widths, int count, char *dst) -{ - return _glamor_get_spans(drawable, wmax, points, widths, count, dst, FALSE); -} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 36f9b7108..430ca59b8 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -224,6 +224,9 @@ typedef struct glamor_screen_private { /* glamor point shader */ glamor_program point_prog; + /* glamor spans shaders */ + glamor_program_fill fill_spans_program; + /* vertext/elment_index buffer object for render */ GLuint vbo, ebo; /** Next offset within the VBO that glamor_get_vbo_space() will use. */ @@ -675,19 +678,9 @@ Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, Bool glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, unsigned long fg_pixel); -/* glamor_fillspans.c */ -void glamor_fill_spans(DrawablePtr drawable, - GCPtr gc, - int n, DDXPointPtr points, int *widths, int sorted); - void glamor_init_solid_shader(ScreenPtr screen); void glamor_fini_solid_shader(ScreenPtr screen); -/* glamor_getspans.c */ -void glamor_get_spans(DrawablePtr drawable, - int wmax, DDXPointPtr points, int *widths, - int nspans, char *dst_start); - /* glamor_glyphs.c */ Bool glamor_realize_glyph_caches(ScreenPtr screen); void glamor_glyphs_fini(ScreenPtr screen); @@ -698,10 +691,6 @@ void glamor_glyphs(CARD8 op, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs); -/* glamor_setspans.c */ -void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int n, int sorted); - /* glamor_polyfillrect.c */ void glamor_poly_fill_rect(DrawablePtr drawable, GCPtr gc, int nrect, xRectangle *prect); @@ -968,6 +957,21 @@ RegionPtr glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int dstx, int dsty, unsigned long bitPlane); +/* glamor_spans.c */ +void +glamor_fill_spans(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted); + +void +glamor_get_spans(DrawablePtr drawable, int wmax, + DDXPointPtr points, int *widths, int count, char *dst); + +void +glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int numPoints, int sorted); + +/* glamor_glyphblt.c */ void glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, void *pglyphBase); diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c deleted file mode 100644 index a51e4c5be..000000000 --- a/glamor/glamor_setspans.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright © 2009 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Eric Anholt - * Zhigang Gong - * - */ - -#include "glamor_priv.h" - -static Bool -_glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int numPoints, int sorted, - Bool fallback) -{ - PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); - glamor_pixmap_private *dest_pixmap_priv; - int i; - uint8_t *drawpixels_src = (uint8_t *) src; - RegionPtr clip = fbGetCompositeClip(gc); - BoxRec *pbox; - int x_off, y_off; - Bool ret = FALSE; - - dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { - glamor_fallback("pixmap has no fbo.\n"); - goto fail; - } - - if (gc->alu != GXcopy) { - glamor_fallback("SetSpans with non-copy ALU.\n"); - goto fail; - } - - if (!glamor_set_planemask(dest_pixmap, gc->planemask)) - goto fail; - - glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off); - for (i = 0; i < numPoints; i++) { - - int n = REGION_NUM_RECTS(clip); - - pbox = REGION_RECTS(clip); - while (n--) { - int x1 = points[i].x; - int x2 = x1 + widths[i]; - int y1 = points[i].y; - - if (pbox->y1 > points[i].y || pbox->y2 < points[i].y) - break; - x1 = x1 > pbox->x1 ? x1 : pbox->x1; - x2 = x2 < pbox->x2 ? x2 : pbox->x2; - if (x1 >= x2) - continue; - glamor_upload_sub_pixmap_to_texture(dest_pixmap, x1 + x_off, - y1 + y_off, x2 - x1, 1, - PixmapBytePad(widths[i], - drawable->depth), - drawpixels_src, 0); - } - drawpixels_src += PixmapBytePad(widths[i], drawable->depth); - } - ret = TRUE; - goto done; - - fail: - if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)) - goto done; - - glamor_fallback("to %p (%c)\n", - drawable, glamor_get_drawable_location(drawable)); - if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && - glamor_prepare_access_gc(gc)) { - fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted); - } - glamor_finish_access_gc(gc); - glamor_finish_access(drawable); - ret = TRUE; - - done: - return ret; -} - -void -glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int n, int sorted) -{ - _glamor_set_spans(drawable, gc, src, points, widths, n, sorted, TRUE); -} - -Bool -glamor_set_spans_nf(DrawablePtr drawable, GCPtr gc, char *src, - DDXPointPtr points, int *widths, int n, int sorted) -{ - return _glamor_set_spans(drawable, gc, src, points, - widths, n, sorted, FALSE); -} diff --git a/glamor/glamor_spans.c b/glamor/glamor_spans.c new file mode 100644 index 000000000..98842cdde --- /dev/null +++ b/glamor/glamor_spans.c @@ -0,0 +1,438 @@ +/* + * Copyright © 2014 Keith Packard + * + * 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 "glamor_priv.h" +#include "glamor_transform.h" +#include "glamor_transfer.h" + +glamor_program fill_spans_progs[4]; + +static const glamor_facet glamor_facet_fillspans_130 = { + .name = "fill_spans", + .version = 130, + .vs_vars = "attribute vec3 primitive;\n", + .vs_exec = (" vec2 pos = vec2(primitive.z,1) * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n" + GLAMOR_POS(gl_Position, (primitive.xy + pos))), +}; + +static const glamor_facet glamor_facet_fillspans_120 = { + .name = "fill_spans", + .vs_vars = "attribute vec2 primitive;\n", + .vs_exec = (" vec2 pos = vec2(0,0);\n" + GLAMOR_POS(gl_Position, primitive.xy)), +}; + +static Bool +glamor_fill_spans_gl(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted) +{ + ScreenPtr screen = drawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv; + glamor_program *prog; + int off_x, off_y; + GLshort *v; + char *vbo_offset; + int c; + int box_x, box_y; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + goto bail; + + glamor_get_context(glamor_priv); + + if (glamor_priv->glsl_version >= 130) { + prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program, + &glamor_facet_fillspans_130); + + if (!prog) + goto bail_ctx; + + /* Set up the vertex buffers for the points */ + + v = glamor_get_vbo_space(drawable->pScreen, n * (4 * sizeof (GLshort)), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE, + 4 * sizeof (GLshort), vbo_offset); + + for (c = 0; c < n; c++) { + v[0] = points->x; + v[1] = points->y; + v[2] = *widths++; + points++; + v += 4; + } + + glamor_put_vbo_space(screen); + } else { + prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program, + &glamor_facet_fillspans_120); + + if (!prog) + goto bail_ctx; + + /* Set up the vertex buffers for the points */ + + v = glamor_get_vbo_space(drawable->pScreen, n * 8 * sizeof (short), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, + 2 * sizeof (short), vbo_offset); + + for (c = 0; c < n; c++) { + v[0] = points->x; v[1] = points->y; + v[2] = points->x; v[3] = points->y + 1; + v[4] = points->x + *widths; v[5] = points->y + 1; + v[6] = points->x + *widths; v[7] = points->y; + + widths++; + points++; + v += 8; + } + + glamor_put_vbo_space(screen); + } + + glEnable(GL_SCISSOR_TEST); + + glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + int nbox = RegionNumRects(gc->pCompositeClip); + BoxPtr box = RegionRects(gc->pCompositeClip); + + glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, FALSE, prog->matrix_uniform, &off_x, &off_y); + + while (nbox--) { + glScissor(box->x1 + off_x, + box->y1 + off_y, + box->x2 - box->x1, + box->y2 - box->y1); + box++; + if (glamor_priv->glsl_version >= 130) + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, n); + else { + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + glDrawArrays(GL_QUADS, 0, 4 * n); + } else { + int i; + for (i = 0; i < n; i++) { + glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); + } + } + } + } + } + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_COLOR_LOGIC_OP); + if (glamor_priv->glsl_version >= 130) + glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0); + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + + glamor_put_context(glamor_priv); + return TRUE; +bail_ctx: + glDisable(GL_COLOR_LOGIC_OP); + glamor_put_context(glamor_priv); +bail: + return FALSE; +} + +static void +glamor_fill_spans_bail(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted) +{ + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && + glamor_prepare_access_gc(gc)) { + fbFillSpans(drawable, gc, n, points, widths, sorted); + } + glamor_finish_access_gc(gc); + glamor_finish_access(drawable); +} + +void +glamor_fill_spans(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted) +{ + if (glamor_fill_spans_gl(drawable, gc, n, points, widths, sorted)) + return; + glamor_fill_spans_bail(drawable, gc, n, points, widths, sorted); +} + +Bool +glamor_fill_spans_nf(DrawablePtr drawable, + GCPtr gc, + int n, DDXPointPtr points, int *widths, int sorted) +{ + if (glamor_fill_spans_gl(drawable, gc, n, points, widths, sorted)) + return TRUE; + + if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) + return FALSE; + + glamor_fill_spans_bail(drawable, gc, n, points, widths, sorted); + return TRUE; +} + +static Bool +glamor_get_spans_gl(DrawablePtr drawable, int wmax, + DDXPointPtr points, int *widths, int count, char *dst) +{ + ScreenPtr screen = drawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv; + int box_x, box_y; + int n; + char *d; + GLenum type; + GLenum format; + int off_x, off_y; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + goto bail; + + glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); + + glamor_format_for_pixmap(pixmap, &format, &type); + + glamor_get_context(glamor_priv); + + glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y); + glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->fb); + glPixelStorei(GL_PACK_ALIGNMENT, 4); + + d = dst; + for (n = 0; n < count; n++) { + int x1 = points[n].x + off_x; + int y = points[n].y + off_y; + int w = widths[n]; + int x2 = x1 + w; + char *l; + + l = d; + d += PixmapBytePad(w, drawable->depth); + + /* clip */ + if (x1 < box->x1) { + l += (box->x1 - x1) * (drawable->bitsPerPixel >> 3); + x1 = box->x1; + } + if (x2 > box->x2) + x2 = box->x2; + + if (x1 >= x2) + continue; + if (y < box->y1) + continue; + if (y >= box->y2) + continue; + + glReadPixels(x1 - box->x1, y - box->y1, x2 - x1, 1, format, type, l); + } + } + + glamor_put_context(glamor_priv); + return TRUE; +bail: + return FALSE; +} + +static void +glamor_get_spans_bail(DrawablePtr drawable, int wmax, + DDXPointPtr points, int *widths, int count, char *dst) +{ + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) + fbGetSpans(drawable, wmax, points, widths, count, dst); + glamor_finish_access(drawable); +} + +void +glamor_get_spans(DrawablePtr drawable, int wmax, + DDXPointPtr points, int *widths, int count, char *dst) +{ + if (glamor_get_spans_gl(drawable, wmax, points, widths, count, dst)) + return; + glamor_get_spans_bail(drawable, wmax, points, widths, count, dst); +} + +Bool +glamor_get_spans_nf(DrawablePtr drawable, int wmax, + DDXPointPtr points, int *widths, int count, char *dst) +{ + if (glamor_get_spans_gl(drawable, wmax, points, widths, count, dst)) + return TRUE; + + if (glamor_ddx_fallback_check_pixmap(drawable)) + return FALSE; + + glamor_get_spans_bail(drawable, wmax, points, widths, count, dst); + return TRUE; +} + +static Bool +glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int numPoints, int sorted) +{ + ScreenPtr screen = drawable->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv; + int box_x, box_y; + int n; + char *s; + GLenum type; + GLenum format; + int off_x, off_y; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + goto bail; + + if (gc->alu != GXcopy) + goto bail; + + if (!glamor_pm_is_solid(&pixmap->drawable, gc->planemask)) + goto bail; + + glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); + glamor_format_for_pixmap(pixmap, &format, &type); + + glamor_get_context(glamor_priv); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + glamor_pixmap_loop(pixmap_priv, box_x, box_y) { + BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y); + glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, fbo->tex); + + s = src; + for (n = 0; n < numPoints; n++) { + + BoxPtr clip_box = RegionRects(gc->pCompositeClip); + int nclip_box = RegionNumRects(gc->pCompositeClip); + int w = widths[n]; + int y = points[n].y; + int x = points[n].x; + + while (nclip_box--) { + int x1 = x; + int x2 = x + w; + int y1 = y; + char *l = s; + + /* clip to composite clip */ + if (x1 < clip_box->x1) { + l += (clip_box->x1 - x1) * (drawable->bitsPerPixel >> 3); + x1 = clip_box->x1; + } + if (x2 > clip_box->x2) + x2 = clip_box->x2; + + if (y < clip_box->y1) + continue; + if (y >= clip_box->y2) + continue; + + /* adjust to pixmap coordinates */ + x1 += off_x; + x2 += off_x; + y1 += off_y; + + if (x1 < box->x1) { + l += (box->x1 - x1) * (drawable->bitsPerPixel >> 3); + x1 = box->x1; + } + if (x2 > box->x2) + x2 = box->x2; + + if (x1 >= x2) + continue; + if (y1 < box->y1) + continue; + if (y1 >= box->y2) + continue; + + glTexSubImage2D(GL_TEXTURE_2D, 0, + x1 - box->x1, y1 - box->y1, x2 - x1, 1, + format, type, + l); + } + s += PixmapBytePad(w, drawable->depth); + } + } + + glamor_put_context(glamor_priv); + return TRUE; + +bail: + return FALSE; +} + +static void +glamor_set_spans_bail(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int numPoints, int sorted) +{ + if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && glamor_prepare_access_gc(gc)) + fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted); + glamor_finish_access_gc(gc); + glamor_finish_access(drawable); +} + +void +glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int numPoints, int sorted) +{ + if (glamor_set_spans_gl(drawable, gc, src, points, widths, numPoints, sorted)) + return; + glamor_set_spans_bail(drawable, gc, src, points, widths, numPoints, sorted); +} + +Bool +glamor_set_spans_nf(DrawablePtr drawable, GCPtr gc, char *src, + DDXPointPtr points, int *widths, int numPoints, int sorted) +{ + if (glamor_set_spans_gl(drawable, gc, src, points, widths, numPoints, sorted)) + return TRUE; + + if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc)) + return FALSE; + + glamor_set_spans_bail(drawable, gc, src, points, widths, numPoints, sorted); + return TRUE; +}