diff options
author | Keith Packard <keithp@keithp.com> | 2014-03-15 13:31:18 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2014-06-15 22:02:41 +0100 |
commit | 45ebc4e3fac7f1a85167d05e2833949b89f02d64 (patch) | |
tree | 516440ad47d1691481dad0655d25b489dd659ab6 /glamor | |
parent | 0e08a79599c773f77c0667d557376a5ccee3f89c (diff) |
glamor: Add glamor_program based copy acceleration
Paints with textures, using a temporary buffer for overlapping copies
Performs CPU to GPU transfers for pixmaps in memory. Accelerates copy
plane when both objects are in the GPU. Includes copy_window
acceleration too.
v2: Use NV_texture_barrier for non-overlapping copies within the same
drawable
v3: Switch to glamor_make_current
v4: Do overlap check on the bounding box of the region rather than
on individual boxes
v5: Use Eric Anholt's re-written comments which provide a more accurate
description of the code
v6: Use floating point uniform for copy plane bit multiplier. This
avoids an int to float conversion in the copy plane fragment shader.
Use round() instead of adding 0.5 in copy plane. round() and +0.5
end up generating equivalent code, and performance measurements
confirm that they are the same speed. Round() is a bit clearer
though, so we'll use it.
Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Markus Wick <markus@selfnet.de>
Diffstat (limited to 'glamor')
-rw-r--r-- | glamor/Makefile.am | 4 | ||||
-rw-r--r-- | glamor/glamor.c | 2 | ||||
-rw-r--r-- | glamor/glamor.h | 11 | ||||
-rw-r--r-- | glamor/glamor_copy.c | 693 | ||||
-rw-r--r-- | glamor/glamor_copyarea.c | 626 | ||||
-rw-r--r-- | glamor/glamor_copyplane.c | 75 | ||||
-rw-r--r-- | glamor/glamor_copywindow.c | 56 | ||||
-rw-r--r-- | glamor/glamor_glyphs.c | 6 | ||||
-rw-r--r-- | glamor/glamor_largepixmap.c | 13 | ||||
-rw-r--r-- | glamor/glamor_priv.h | 42 | ||||
-rw-r--r-- | glamor/glamor_program.c | 10 | ||||
-rw-r--r-- | glamor/glamor_program.h | 3 | ||||
-rw-r--r-- | glamor/glamor_render.c | 11 |
13 files changed, 763 insertions, 789 deletions
diff --git a/glamor/Makefile.am b/glamor/Makefile.am index cb81872b4..c0d82d67d 100644 --- a/glamor/Makefile.am +++ b/glamor/Makefile.am @@ -7,8 +7,7 @@ AM_CFLAGS = $(CWARNFLAGS) $(DIX_CFLAGS) $(GLAMOR_CFLAGS) libglamor_la_SOURCES = \ glamor.c \ glamor_context.h \ - glamor_copyarea.c \ - glamor_copywindow.c \ + glamor_copy.c \ glamor_core.c \ glamor_debug.h \ glamor_fill.c \ @@ -36,7 +35,6 @@ libglamor_la_SOURCES = \ glamor_tile.c \ glamor_triangles.c\ glamor_addtraps.c\ - glamor_copyplane.c\ glamor_glyphblt.c\ glamor_points.c\ glamor_priv.h\ diff --git a/glamor/glamor.c b/glamor/glamor.c index ac23d5216..3468b51c3 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -408,6 +408,8 @@ glamor_init(ScreenPtr screen, unsigned int flags) epoxy_has_gl_extension("GL_ARB_map_buffer_range"); glamor_priv->has_buffer_storage = epoxy_has_gl_extension("GL_ARB_buffer_storage"); + glamor_priv->has_nv_texture_barrier = + epoxy_has_gl_extension("GL_NV_texture_barrier"); glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); #ifdef MAX_FBO_SIZE glamor_priv->max_fbo_size = MAX_FBO_SIZE; diff --git a/glamor/glamor.h b/glamor/glamor.h index b0f2212d9..77fa01e8d 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -354,6 +354,17 @@ extern _X_EXPORT Bool glamor_copy_n_to_n_nf(DrawablePtr src, Bool upsidedown, Pixel bitplane, void *closure); +extern _X_EXPORT Bool glamor_copy_nf(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, + void *closure); + extern _X_EXPORT Bool glamor_composite_nf(CARD8 op, PicturePtr source, PicturePtr mask, diff --git a/glamor/glamor_copy.c b/glamor/glamor_copy.c new file mode 100644 index 000000000..bfcde43db --- /dev/null +++ b/glamor/glamor_copy.c @@ -0,0 +1,693 @@ +/* + * 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_transfer.h" +#include "glamor_prepare.h" +#include "glamor_transform.h" + +struct copy_args { + PixmapPtr src_pixmap; + glamor_pixmap_fbo *src; + uint32_t bitplane; + int dx, dy; +}; + +static Bool +use_copyarea(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg) +{ + struct copy_args *args = arg; + glamor_pixmap_fbo *src = args->src; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, src->tex); + + glUniform2f(prog->fill_offset_uniform, args->dx, args->dy); + glUniform2f(prog->fill_size_uniform, src->width, src->height); + + return TRUE; +} + +static const glamor_facet glamor_facet_copyarea = { + "copy_area", + .vs_vars = "attribute vec2 primitive;\n", + .vs_exec = (GLAMOR_POS(gl_Position, primitive.xy) + " fill_pos = (fill_offset + primitive.xy) / fill_size;\n"), + .fs_exec = " gl_FragColor = texture2D(sampler, fill_pos);\n", + .locations = glamor_program_location_fill, + .use = use_copyarea, +}; + +/* + * Configure the copy plane program for the current operation + */ + +static Bool +use_copyplane(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg) +{ + struct copy_args *args = arg; + glamor_pixmap_fbo *src = args->src; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, src->tex); + + glUniform2f(prog->fill_offset_uniform, args->dx, args->dy); + glUniform2f(prog->fill_size_uniform, src->width, src->height); + + glamor_set_color(dst, gc->fgPixel, prog->fg_uniform); + glamor_set_color(dst, gc->bgPixel, prog->bg_uniform); + + /* XXX handle 2 10 10 10 and 1555 formats; presumably the pixmap private knows this? */ + switch (args->src_pixmap->drawable.depth) { + case 24: + glUniform4ui(prog->bitplane_uniform, + (args->bitplane >> 16) & 0xff, + (args->bitplane >> 8) & 0xff, + (args->bitplane ) & 0xff, + 0); + + glUniform4f(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0); + break; + case 32: + glUniform4ui(prog->bitplane_uniform, + (args->bitplane >> 16) & 0xff, + (args->bitplane >> 8) & 0xff, + (args->bitplane ) & 0xff, + (args->bitplane >> 24) & 0xff); + + glUniform4f(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0xff); + break; + case 16: + glUniform4ui(prog->bitplane_uniform, + (args->bitplane >> 11) & 0x1f, + (args->bitplane >> 5) & 0x3f, + (args->bitplane ) & 0x1f, + 0); + + glUniform4f(prog->bitmul_uniform, 0x1f, 0x3f, 0x1f, 0); + break; + case 15: + glUniform4ui(prog->bitplane_uniform, + (args->bitplane >> 10) & 0x1f, + (args->bitplane >> 5) & 0x1f, + (args->bitplane ) & 0x1f, + 0); + + glUniform4f(prog->bitmul_uniform, 0x1f, 0x1f, 0x1f, 0); + break; + case 8: + glUniform4ui(prog->bitplane_uniform, + 0, 0, 0, args->bitplane); + glUniform4f(prog->bitmul_uniform, 0, 0, 0, 0xff); + break; + case 1: + glUniform4ui(prog->bitplane_uniform, + 0, 0, 0, args->bitplane); + glUniform4f(prog->bitmul_uniform, 0, 0, 0, 0xff); + break; + } + + return TRUE; +} + +static const glamor_facet glamor_facet_copyplane = { + "copy_plane", + .version = 130, + .vs_vars = "attribute vec2 primitive;\n", + .vs_exec = (GLAMOR_POS(gl_Position, (primitive.xy)) + " fill_pos = (fill_offset + primitive.xy) / fill_size;\n"), + .fs_exec = (" uvec4 bits = uvec4(round(texture2D(sampler, fill_pos) * bitmul));\n" + " if ((bits & bitplane) != uvec4(0,0,0,0))\n" + " gl_FragColor = fg;\n" + " else\n" + " gl_FragColor = bg;\n"), + .locations = glamor_program_location_fill|glamor_program_location_fg|glamor_program_location_bg|glamor_program_location_bitplane, + .use = use_copyplane, +}; + +/* + * When all else fails, pull the bits out of the GPU and do the + * operation with fb + */ + +static void +glamor_copy_bail(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) && glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { + if (bitplane) { + if (src->bitsPerPixel > 1) + fbCopyNto1(src, dst, gc, box, nbox, dx, dy, + reverse, upsidedown, bitplane, closure); + else + fbCopy1toN(src, dst, gc, box, nbox, dx, dy, + reverse, upsidedown, bitplane, closure); + } else { + fbCopyNtoN(src, dst, gc, box, nbox, dx, dy, + reverse, upsidedown, bitplane, closure); + } + } + glamor_finish_access(dst); + glamor_finish_access(src); +} + +/** + * Implements CopyPlane and CopyArea from the GPU to the GPU by using + * the source as a texture and painting that into the destination. + * + * This requires that source and dest are different textures, or that + * (if the copy area doesn't overlap), GL_NV_texture_barrier is used + * to ensure that the caches are flushed at the right times. + */ +static Bool +glamor_copy_cpu_fbo(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + ScreenPtr screen = dst->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + FbBits *src_bits; + FbStride src_stride; + int src_bpp; + int src_xoff, src_yoff; + int dst_xoff, dst_yoff; + + if (gc && gc->alu != GXcopy) + goto bail; + + if (gc && !glamor_pm_is_solid(dst, gc->planemask)) + goto bail; + + glamor_make_current(glamor_priv); + glamor_prepare_access(src, GLAMOR_ACCESS_RO); + + glamor_get_drawable_deltas(dst, dst_pixmap, &dst_xoff, &dst_yoff); + + fbGetDrawable(src, src_bits, src_stride, src_bpp, src_xoff, src_yoff); + + glamor_upload_boxes(dst_pixmap, box, nbox, src_xoff + dx, src_yoff + dy, + dst_xoff, dst_yoff, + (uint8_t *) src_bits, src_stride * sizeof (FbBits)); + glamor_finish_access(src); + + return TRUE; + +bail: + return FALSE; +} + +/* + * Copy from GPU to GPU by using the source + * as a texture and painting that into the destination + */ + +static Bool +glamor_copy_fbo_fbo_draw(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + ScreenPtr screen = dst->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap); + glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap); + int src_box_x, src_box_y, dst_box_x, dst_box_y; + int dst_off_x, dst_off_y; + int src_off_x, src_off_y; + GLshort *v; + char *vbo_offset; + struct copy_args args; + glamor_program *prog; + const glamor_facet *copy_facet; + Bool set_scissor; + int n; + + glamor_make_current(glamor_priv); + + if (gc && !glamor_set_planemask(dst_pixmap, gc->planemask)) + goto bail_ctx; + + if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy)) + goto bail_ctx; + + if (bitplane) { + prog = &glamor_priv->copy_plane_prog; + copy_facet = &glamor_facet_copyplane; + } else { + prog = &glamor_priv->copy_area_prog; + copy_facet = &glamor_facet_copyarea; + } + + if (prog->failed) + goto bail_ctx; + + if (!prog->prog) { + if (!glamor_build_program(screen, prog, + copy_facet, NULL)) + goto bail_ctx; + } + + args.src_pixmap = src_pixmap; + args.bitplane = bitplane; + + /* Set up the vertex buffers for the points */ + + v = glamor_get_vbo_space(dst->pScreen, nbox * 8 * sizeof (int16_t), &vbo_offset); + + glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, + 2 * sizeof (GLshort), vbo_offset); + + for (n = 0; n < nbox; n++) { + v[0] = box->x1; v[1] = box->y1; + v[2] = box->x1; v[3] = box->y2; + v[4] = box->x2; v[5] = box->y2; + v[6] = box->x2; v[7] = box->y1; + v += 8; + box++; + } + + glamor_put_vbo_space(screen); + + glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y); + + set_scissor = src_priv->type == GLAMOR_TEXTURE_LARGE; + if (set_scissor) + glEnable(GL_SCISSOR_TEST); + + glamor_pixmap_loop(src_priv, src_box_x, src_box_y) { + BoxPtr src_box = glamor_pixmap_box_at(src_priv, src_box_x, src_box_y); + + args.dx = dx + src_off_x - src_box->x1; + args.dy = dy + src_off_y - src_box->y1; + args.src = glamor_pixmap_fbo_at(src_priv, src_box_x, src_box_y); + + if (!glamor_use_program(dst_pixmap, gc, prog, &args)) + goto bail_ctx; + + glamor_pixmap_loop(dst_priv, dst_box_x, dst_box_y) { + glamor_set_destination_drawable(dst, dst_box_x, dst_box_y, FALSE, FALSE, + prog->matrix_uniform, &dst_off_x, &dst_off_y); + + if (set_scissor) + glScissor(dst_off_x - args.dx, + dst_off_y - args.dy, + src_box->x2 - src_box->x1, + src_box->y2 - src_box->y1); + + if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) + glDrawArrays(GL_QUADS, 0, nbox * 4); + else { + int i; + for (i = 0; i < nbox; i++) + glDrawArrays(GL_TRIANGLE_FAN, i*4, 4); + } + } + } + if (set_scissor) + glDisable(GL_SCISSOR_TEST); + glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + + glDisable(GL_COLOR_LOGIC_OP); + return TRUE; + +bail_ctx: + glDisable(GL_COLOR_LOGIC_OP); + return FALSE; +} + +/** + * Copies from the GPU to the GPU using a temporary pixmap in between, + * to correctly handle overlapping copies. + */ + +static Bool +glamor_copy_fbo_fbo_temp(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + ScreenPtr screen = dst->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + PixmapPtr tmp_pixmap; + BoxRec bounds; + int n; + BoxPtr tmp_box; + + if (nbox == 0) + return TRUE; + + /* Sanity check state to avoid getting halfway through and bailing + * at the last second. Might be nice to have checks that didn't + * involve setting state. + */ + glamor_make_current(glamor_priv); + + if (gc && !glamor_set_planemask(dst_pixmap, gc->planemask)) + goto bail_ctx; + + if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy)) + goto bail_ctx; + glDisable(GL_COLOR_LOGIC_OP); + + /* Find the size of the area to copy + */ + bounds = box[0]; + for (n = 1; n < nbox; n++) { + bounds.x1 = min(bounds.x1, box[n].x1); + bounds.x2 = max(bounds.x2, box[n].x2); + bounds.y1 = min(bounds.y1, box[n].y1); + bounds.y2 = max(bounds.y2, box[n].y2); + } + + /* Allocate a suitable temporary pixmap + */ + tmp_pixmap = glamor_create_pixmap(screen, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1, + src->depth, 0); + if (!tmp_pixmap) + goto bail; + + tmp_box = calloc(nbox, sizeof (BoxRec)); + if (!tmp_box) + goto bail_pixmap; + + /* Convert destination boxes into tmp pixmap boxes + */ + for (n = 0; n < nbox; n++) { + tmp_box[n].x1 = box[n].x1 - bounds.x1; + tmp_box[n].x2 = box[n].x2 - bounds.x1; + tmp_box[n].y1 = box[n].y1 - bounds.y1; + tmp_box[n].y2 = box[n].y2 - bounds.y1; + } + + if (!glamor_copy_fbo_fbo_draw(src, + &tmp_pixmap->drawable, + NULL, + tmp_box, + nbox, + dx + bounds.x1, + dy + bounds.y1, + FALSE, FALSE, + 0, NULL)) + goto bail_box; + + if (!glamor_copy_fbo_fbo_draw(&tmp_pixmap->drawable, + dst, + gc, + box, + nbox, + -bounds.x1, + -bounds.y1, + FALSE, FALSE, + bitplane, closure)) + goto bail_box; + + free(tmp_box); + + glamor_destroy_pixmap(tmp_pixmap); + + return TRUE; +bail_box: + free(tmp_box); +bail_pixmap: + glamor_destroy_pixmap(tmp_pixmap); +bail: + return FALSE; + +bail_ctx: + glDisable(GL_COLOR_LOGIC_OP); + return FALSE; +} + +/** + * Returns TRUE if the copy has to be implemented with + * glamor_copy_fbo_fbo_temp() instead of glamor_copy_fbo_fbo(). + * + * If the src and dst are in the same pixmap, then glamor_copy_fbo_fbo()'s + * sampling would give undefined results (since the same texture would be + * bound as an FBO destination and as a texture source). However, if we + * have GL_NV_texture_barrier, we can take advantage of the exception it + * added: + * + * "- If a texel has been written, then in order to safely read the result + * a texel fetch must be in a subsequent Draw separated by the command + * + * void TextureBarrierNV(void); + * + * TextureBarrierNV() will guarantee that writes have completed and caches + * have been invalidated before subsequent Draws are executed." + */ +static Bool +glamor_copy_needs_temp(DrawablePtr src, + DrawablePtr dst, + BoxPtr box, + int nbox, + int dx, + int dy) +{ + PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + ScreenPtr screen = dst->pScreen; + glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); + int n; + int dst_off_x, dst_off_y; + int src_off_x, src_off_y; + BoxRec bounds; + + if (src_pixmap != dst_pixmap) + return FALSE; + + if (nbox == 0) + return FALSE; + + if (!glamor_priv->has_nv_texture_barrier) + return TRUE; + + glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y); + glamor_get_drawable_deltas(dst, dst_pixmap, &dst_off_x, &dst_off_y); + + bounds = box[0]; + for (n = 1; n < nbox; n++) { + bounds.x1 = min(bounds.x1, box[n].x1); + bounds.y1 = min(bounds.y1, box[n].y1); + + bounds.x2 = max(bounds.x2, box[n].x2); + bounds.y2 = max(bounds.y2, box[n].y2); + } + + /* Check to see if the pixmap-relative boxes overlap in both X and Y, + * in which case we can't rely on NV_texture_barrier and must + * make a temporary copy + * + * dst.x1 < src.x2 && + * src.x1 < dst.x2 && + * + * dst.y1 < src.y2 && + * src.y1 < dst.y2 + */ + if (bounds.x1 + dst_off_x < bounds.x2 + dx + src_off_x && + bounds.x1 + dx + src_off_x < bounds.x2 + dst_off_x && + + bounds.y1 + dst_off_y < bounds.y2 + dy + src_off_y && + bounds.y1 + dy + src_off_y < bounds.y2 + dst_off_y) { + return TRUE; + } + + glTextureBarrierNV(); + + return FALSE; +} + +static Bool +glamor_copy_gl(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); + PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); + glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap); + glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap); + + if (GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_priv)) { + if (GLAMOR_PIXMAP_PRIV_HAS_FBO(src_priv)) { + if (glamor_copy_needs_temp(src, dst, box, nbox, dx, dy)) + return glamor_copy_fbo_fbo_temp(src, dst, gc, box, nbox, dx, dy, + reverse, upsidedown, bitplane, closure); + else + return glamor_copy_fbo_fbo_draw(src, dst, gc, box, nbox, dx, dy, + reverse, upsidedown, bitplane, closure); + } + if (bitplane == 0) + return glamor_copy_cpu_fbo(src, dst, gc, box, nbox, dx, dy, + reverse, upsidedown, bitplane, closure); + } + return FALSE; +} + +void +glamor_copy(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + if (glamor_copy_gl(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure)) + return; + glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); +} + +RegionPtr +glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + return miDoCopy(src, dst, gc, + srcx, srcy, width, height, + dstx, dsty, glamor_copy, 0, NULL); +} + +RegionPtr +glamor_copy_plane(DrawablePtr src, DrawablePtr dst, GCPtr gc, + int srcx, int srcy, int width, int height, int dstx, int dsty, + unsigned long bitplane) +{ + if ((bitplane & FbFullMask(src->depth)) == 0) + return miHandleExposures(src, dst, gc, + srcx, srcy, width, height, dstx, dsty, + bitplane); + return miDoCopy(src, dst, gc, + srcx, srcy, width, height, + dstx, dsty, glamor_copy, bitplane, NULL); +} + +void +glamor_copy_window(WindowPtr window, DDXPointRec old_origin, RegionPtr src_region) +{ + PixmapPtr pixmap = glamor_get_drawable_pixmap(&window->drawable); + DrawablePtr drawable = &pixmap->drawable; + RegionRec dst_region; + int dx, dy; + + dx = old_origin.x - window->drawable.x; + dy = old_origin.y - window->drawable.y; + RegionTranslate(src_region, -dx, -dy); + + RegionNull(&dst_region); + + RegionIntersect(&dst_region, &window->borderClip, src_region); + +#ifdef COMPOSITE + if (pixmap->screen_x || pixmap->screen_y) + RegionTranslate(&dst_region, -pixmap->screen_x, -pixmap->screen_y); +#endif + + miCopyRegion(drawable, drawable, + 0, &dst_region, dx, dy, glamor_copy, 0, 0); + + RegionUninit(&dst_region); +} + +Bool +glamor_copy_n_to_n_nf(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, + void *closure) +{ + if (glamor_copy_gl(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure)) + return TRUE; + if (glamor_ddx_fallback_check_pixmap(src) && glamor_ddx_fallback_check_pixmap(dst)) + return FALSE; + glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure); + return TRUE; +} + +Bool +glamor_copy_plane_nf(DrawablePtr src, DrawablePtr dst, GCPtr gc, + int srcx, int srcy, int w, int h, int dstx, int dsty, + unsigned long bitplane, RegionPtr *region) +{ + if (glamor_ddx_fallback_check_pixmap(src) && + glamor_ddx_fallback_check_pixmap(dst) && + glamor_ddx_fallback_check_gc(gc)) + return FALSE; + + *region = glamor_copy_plane(src, dst, gc, + srcx, srcy, w, h, dstx, dsty, + bitplane); + return TRUE; +} diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c deleted file mode 100644 index e1988225f..000000000 --- a/glamor/glamor_copyarea.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * Copyright © 2008 Intel Corporation - * 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. - * - * Authors: - * Eric Anholt <eric@anholt.net> - * Zhigang Gong <zhigang.gong@linux.intel.com> - */ - -#include "glamor_priv.h" - -/** @file glamor_copyarea.c - * - * GC CopyArea implementation - */ -static Bool -glamor_copy_n_to_n_fbo_blit(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, BoxPtr box, int nbox, int dx, int dy) -{ - ScreenPtr screen = dst->pScreen; - PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); - PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); - glamor_pixmap_private *src_pixmap_priv, *dst_pixmap_priv; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - int dst_x_off, dst_y_off, src_x_off, src_y_off, i; - int fbo_x_off, fbo_y_off; - int src_fbo_x_off, src_fbo_y_off; - - if (!glamor_priv->has_fbo_blit) { - glamor_delayed_fallback(screen, "no EXT_framebuffer_blit\n"); - return FALSE; - } - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); - - if (gc) { - if (gc->alu != GXcopy) { - glamor_delayed_fallback(screen, "non-copy ALU\n"); - return FALSE; - } - } - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { - glamor_delayed_fallback(screen, "no src fbo\n"); - return FALSE; - } - - if (glamor_set_destination_pixmap(dst_pixmap)) - return FALSE; - - pixmap_priv_get_fbo_off(dst_pixmap_priv, &fbo_x_off, &fbo_y_off); - pixmap_priv_get_fbo_off(src_pixmap_priv, &src_fbo_x_off, &src_fbo_y_off); - - glamor_make_current(glamor_priv); - glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->base.fbo->fb); - glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); - dst_x_off += fbo_x_off; - dst_y_off += fbo_y_off; - src_y_off += dy + src_fbo_y_off; - src_x_off += src_fbo_x_off; - - for (i = 0; i < nbox; i++) { - if (glamor_priv->yInverted) { - glBlitFramebuffer(box[i].x1 + dx + src_x_off, - box[i].y1 + src_y_off, - box[i].x2 + dx + src_x_off, - box[i].y2 + src_y_off, - box[i].x1 + dst_x_off, - box[i].y1 + dst_y_off, - box[i].x2 + dst_x_off, - box[i].y2 + dst_y_off, - GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - else { - int flip_dst_y1 = - dst_pixmap->drawable.height - (box[i].y2 + dst_y_off); - int flip_dst_y2 = - dst_pixmap->drawable.height - (box[i].y1 + dst_y_off); - int flip_src_y1 = - src_pixmap->drawable.height - (box[i].y2 + src_y_off); - int flip_src_y2 = - src_pixmap->drawable.height - (box[i].y1 + src_y_off); - - glBlitFramebuffer(box[i].x1 + dx + src_x_off, - flip_src_y1, - box[i].x2 + dx + src_x_off, - flip_src_y2, - box[i].x1 + dst_x_off, - flip_dst_y1, - box[i].x2 + dst_x_off, - flip_dst_y2, - GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - } - glamor_priv->state = BLIT_STATE; - return TRUE; -} - -static Bool -glamor_copy_n_to_n_textured(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, BoxPtr box, int nbox, int dx, int dy) -{ - glamor_screen_private *glamor_priv = - glamor_get_screen_private(dst->pScreen); - PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); - PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); - int i; - float vertices[8], texcoords[8]; - glamor_pixmap_private *src_pixmap_priv; - glamor_pixmap_private *dst_pixmap_priv; - int src_x_off, src_y_off, dst_x_off, dst_y_off; - enum glamor_pixmap_status src_status = GLAMOR_NONE; - GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; - - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); - - if (src_pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) { -#ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD - glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); - return FALSE; -#else - src_status = glamor_upload_pixmap_to_texture(src_pixmap); - if (src_status != GLAMOR_UPLOAD_DONE) - return FALSE; - - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); -#endif - } - - pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); - pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); - - glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - - glamor_make_current(glamor_priv); - - glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); - glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), vertices); - glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - - glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); - dx += src_x_off; - dy += src_y_off; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, - 2 * sizeof(float), texcoords); - glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glUseProgram(glamor_priv->finish_access_prog[0]); - glUniform1i(glamor_priv->finish_access_revert[0], REVERT_NONE); - glUniform1i(glamor_priv->finish_access_swap_rb[0], SWAP_NONE_UPLOADING); - - for (i = 0; i < nbox; i++) { - - glamor_set_normalize_vcoords(dst_pixmap_priv, - dst_xscale, dst_yscale, - box[i].x1 + dst_x_off, - box[i].y1 + dst_y_off, - box[i].x2 + dst_x_off, - box[i].y2 + dst_y_off, - glamor_priv->yInverted, vertices); - - glamor_set_normalize_tcoords(src_pixmap_priv, - src_xscale, - src_yscale, - box[i].x1 + dx, - box[i].y1 + dy, - box[i].x2 + dx, - box[i].y2 + dy, - glamor_priv->yInverted, texcoords); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - - glDisableVertexAttribArray(GLAMOR_VERTEX_POS); - glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - /* The source texture is bound to a fbo, we have to flush it here. */ - glamor_priv->state = RENDER_STATE; - glamor_priv->render_idle_cnt = 0; - return TRUE; -} - -static Bool -__glamor_copy_n_to_n(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, Pixel bitplane, void *closure) -{ - PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL; - DrawablePtr temp_src = src; - glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; - glamor_screen_private *glamor_priv; - BoxRec bound; - ScreenPtr screen; - int temp_dx = dx; - int temp_dy = dy; - int src_x_off, src_y_off, dst_x_off, dst_y_off; - int i; - int overlaped = 0; - Bool ret = FALSE; - - dst_pixmap = glamor_get_drawable_pixmap(dst); - dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); - src_pixmap = glamor_get_drawable_pixmap(src); - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - screen = dst_pixmap->drawable.pScreen; - glamor_priv = glamor_get_screen_private(dst->pScreen); - glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); - - glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - - if (src_pixmap_priv->base.fbo - && src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) { - int x_shift = abs(src_x_off - dx - dst_x_off); - int y_shift = abs(src_y_off - dy - dst_y_off); - - for (i = 0; i < nbox; i++) { - if (x_shift < abs(box[i].x2 - box[i].x1) - && y_shift < abs(box[i].y2 - box[i].y1)) { - overlaped = 1; - break; - } - } - } - DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n", - box[0].x1, box[0].y1, - box[0].x2 - box[0].x1, box[0].y2 - box[0].y1, - dx, dy, src_pixmap, dst_pixmap); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && - !overlaped && - (glamor_priv->state != RENDER_STATE - || !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex) - && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { - ret = TRUE; - goto done; - } - glamor_calculate_boxes_bound(&bound, box, nbox); - - /* Overlaped indicate the src and dst are the same pixmap. */ - if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) - && (((bound.x2 - bound.x1) * (bound.y2 - bound.y1) - * 4 > - src_pixmap->drawable.width * - src_pixmap->drawable.height) - || !(glamor_check_fbo_size(glamor_priv, - src_pixmap->drawable.width, - src_pixmap->drawable. - height))))) { - - temp_pixmap = glamor_create_pixmap(screen, - bound.x2 - bound.x1, - bound.y2 - bound.y1, - src_pixmap->drawable.depth, - overlaped ? 0 : - GLAMOR_CREATE_PIXMAP_CPU); - assert(bound.x2 - bound.x1 <= glamor_priv->max_fbo_size); - assert(bound.y2 - bound.y1 <= glamor_priv->max_fbo_size); - if (!temp_pixmap) - goto done; - glamor_translate_boxes(box, nbox, -bound.x1, -bound.y1); - temp_src = &temp_pixmap->drawable; - - if (overlaped) - glamor_copy_n_to_n_textured(src, temp_src, gc, box, - nbox, - temp_dx + bound.x1, temp_dy + bound.y1); - else - fbCopyNtoN(src, temp_src, gc, box, nbox, - temp_dx + bound.x1, temp_dy + bound.y1, - reverse, upsidedown, bitplane, closure); - glamor_translate_boxes(box, nbox, bound.x1, bound.y1); - temp_dx = -bound.x1; - temp_dy = -bound.y1; - } - else { - temp_dx = dx; - temp_dy = dy; - temp_src = src; - } - - if (glamor_copy_n_to_n_textured - (temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { - ret = TRUE; - } - done: - if (temp_src != src) - glamor_destroy_pixmap(temp_pixmap); - return ret; -} - -static Bool -_glamor_copy_n_to_n(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, Pixel bitplane, - void *closure, Bool fallback) -{ - ScreenPtr screen = dst->pScreen; - PixmapPtr dst_pixmap, src_pixmap; - glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; - glamor_screen_private *glamor_priv; - BoxPtr extent; - RegionRec region; - int src_x_off, src_y_off, dst_x_off, dst_y_off; - Bool ok = FALSE; - int force_clip = 0; - - if (nbox == 0) - return TRUE; - dst_pixmap = glamor_get_drawable_pixmap(dst); - dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); - src_pixmap = glamor_get_drawable_pixmap(src); - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - - glamor_priv = glamor_get_screen_private(screen); - - DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n", - box[0].x1, box[0].y1, - box[0].x2 - box[0].x1, box[0].y2 - box[0].y1, - dx, dy, src_pixmap, dst_pixmap); - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) - goto fall_back; - - if (gc) { - if (!glamor_set_planemask(dst_pixmap, gc->planemask)) - goto fall_back; - glamor_make_current(glamor_priv); - if (!glamor_set_alu(screen, gc->alu)) { - goto fail_noregion; - } - } - - if (!src_pixmap_priv) { - glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY); - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - } - - glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); - glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - - RegionInitBoxes(®ion, box, nbox); - extent = RegionExtents(®ion); - - if (!glamor_check_fbo_size(glamor_priv, - extent->x2 - extent->x1, extent->y2 - extent->y1) - && (src_pixmap_priv->type == GLAMOR_MEMORY - || (src_pixmap_priv == dst_pixmap_priv))) { - force_clip = 1; - } - - if (force_clip || dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE - || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - glamor_pixmap_clipped_regions *clipped_dst_regions; - int n_dst_region, i, j; - PixmapPtr temp_source_pixmap; - glamor_pixmap_private *temp_source_priv = NULL; - - RegionTranslate(®ion, dst_x_off, dst_y_off); - if (!force_clip) - clipped_dst_regions = - glamor_compute_clipped_regions(dst_pixmap_priv, ®ion, - &n_dst_region, 0, reverse, - upsidedown); - else - clipped_dst_regions = - glamor_compute_clipped_regions_ext(dst_pixmap_priv, ®ion, - &n_dst_region, - glamor_priv->max_fbo_size, - glamor_priv->max_fbo_size, - reverse, upsidedown); - for (i = 0; i < n_dst_region; i++) { - int n_src_region; - glamor_pixmap_clipped_regions *clipped_src_regions; - BoxPtr current_boxes; - int n_current_boxes; - - SET_PIXMAP_FBO_CURRENT(dst_pixmap_priv, - clipped_dst_regions[i].block_idx); - - temp_source_pixmap = NULL; - if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { - RegionTranslate(clipped_dst_regions[i].region, - -dst_x_off + src_x_off + dx, - -dst_y_off + src_y_off + dy); - clipped_src_regions = - glamor_compute_clipped_regions(src_pixmap_priv, - clipped_dst_regions[i]. - region, &n_src_region, 0, - reverse, upsidedown); - DEBUGF("Source is large pixmap.\n"); - for (j = 0; j < n_src_region; j++) { - if (src_pixmap_priv != dst_pixmap_priv) - SET_PIXMAP_FBO_CURRENT(src_pixmap_priv, - clipped_src_regions[j]. - block_idx); - else if (src_pixmap_priv == dst_pixmap_priv && - clipped_src_regions[j].block_idx != - clipped_dst_regions[i].block_idx) { - /* source and the dest are the same, but need different block_idx. - * we create a empty pixmap and fill the required source fbo and box to - * it. It's a little hacky, but avoid extra copy. */ - temp_source_pixmap = - glamor_create_pixmap(src->pScreen, 0, 0, src->depth, - 0); - if (!temp_source_pixmap) { - ok = FALSE; - goto fail; - } - src->pScreen->ModifyPixmapHeader(temp_source_pixmap, - src_pixmap->drawable. - width, - src_pixmap->drawable. - height, 0, 0, - src_pixmap->devKind, - NULL); - temp_source_priv = - glamor_get_pixmap_private(temp_source_pixmap); - *temp_source_priv = *src_pixmap_priv; - temp_source_priv->large.box = - src_pixmap_priv->large. - box_array[clipped_src_regions[j].block_idx]; - temp_source_priv->base.fbo = - src_pixmap_priv->large. - fbo_array[clipped_src_regions[j].block_idx]; - temp_source_priv->base.pixmap = temp_source_pixmap; - } - assert(temp_source_pixmap || - !(src_pixmap_priv == dst_pixmap_priv && - (clipped_src_regions[j].block_idx != - clipped_dst_regions[i].block_idx))); - - RegionTranslate(clipped_src_regions[j].region, - -src_x_off - dx, -src_y_off - dy); - current_boxes = RegionRects(clipped_src_regions[j].region); - n_current_boxes = - RegionNumRects(clipped_src_regions[j].region); - DEBUGF("dst pixmap fbo idx %d src pixmap fbo idx %d \n", - clipped_dst_regions[i].block_idx, - clipped_src_regions[j].block_idx); - DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n", - current_boxes[0].x1, current_boxes[0].y1, - current_boxes[0].x2, current_boxes[0].y2, dx, dy, - src_pixmap, dst_pixmap); - if (!temp_source_pixmap) - ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes, - n_current_boxes, dx, dy, - reverse, upsidedown, bitplane, - closure); - else { - ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable, - dst, gc, current_boxes, - n_current_boxes, dx, dy, - reverse, upsidedown, bitplane, - closure); - temp_source_priv->type = GLAMOR_MEMORY; - temp_source_priv->base.fbo = NULL; - glamor_destroy_pixmap(temp_source_pixmap); - temp_source_pixmap = NULL; - } - - RegionDestroy(clipped_src_regions[j].region); - if (!ok) { - assert(0); - goto fail; - } - } - - if (n_src_region == 0) - ok = TRUE; - free(clipped_src_regions); - } - else { - RegionTranslate(clipped_dst_regions[i].region, - -dst_x_off, -dst_y_off); - current_boxes = RegionRects(clipped_dst_regions[i].region); - n_current_boxes = RegionNumRects(clipped_dst_regions[i].region); - - DEBUGF("dest pixmap fbo idx %d \n", - clipped_dst_regions[i].block_idx); - DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n", - current_boxes[0].x1, current_boxes[0].y1, - current_boxes[0].x2, current_boxes[0].y2, - dx, dy, src_pixmap, dst_pixmap); - - ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes, - n_current_boxes, dx, dy, reverse, - upsidedown, bitplane, closure); - - } - RegionDestroy(clipped_dst_regions[i].region); - } - if (n_dst_region == 0) - ok = TRUE; - free(clipped_dst_regions); - } - else { - ok = __glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy, - reverse, upsidedown, bitplane, closure); - } - - fail: - RegionUninit(®ion); - fail_noregion: - glamor_make_current(glamor_priv); - glamor_set_alu(screen, GXcopy); - - if (ok) - return TRUE; - fall_back: - if (!fallback && glamor_ddx_fallback_check_pixmap(src) - && glamor_ddx_fallback_check_pixmap(dst)) - goto done; - - if (src_pixmap_priv->type == GLAMOR_DRM_ONLY - || dst_pixmap_priv->type == GLAMOR_DRM_ONLY) { - LogMessage(X_WARNING, - "Access a DRM only pixmap is not allowed within glamor.\n"); - return TRUE; - } - glamor_report_delayed_fallbacks(src->pScreen); - glamor_report_delayed_fallbacks(dst->pScreen); - - glamor_fallback("from %p to %p (%c,%c)\n", src, dst, - glamor_get_drawable_location(src), - glamor_get_drawable_location(dst)); - - if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) && - glamor_prepare_access(src, GLAMOR_ACCESS_RO) && - glamor_prepare_access_gc(gc)) { - fbCopyNtoN(src, dst, gc, box, nbox, - dx, dy, reverse, upsidedown, bitplane, closure); - } - glamor_finish_access_gc(gc); - glamor_finish_access(src); - glamor_finish_access(dst); - ok = TRUE; - - done: - glamor_clear_delayed_fallbacks(src->pScreen); - glamor_clear_delayed_fallbacks(dst->pScreen); - return ok; -} - -RegionPtr -glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, - int srcx, int srcy, int width, int height, int dstx, int dsty) -{ - RegionPtr region; - - region = miDoCopy(src, dst, gc, - srcx, srcy, width, height, - dstx, dsty, glamor_copy_n_to_n, 0, NULL); - - return region; -} - -void -glamor_copy_n_to_n(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) -{ - _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, - dy, reverse, upsidedown, bitplane, closure, TRUE); -} - -Bool -glamor_copy_n_to_n_nf(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, Pixel bitplane, void *closure) -{ - return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, - dy, reverse, upsidedown, bitplane, closure, - FALSE); -} diff --git a/glamor/glamor_copyplane.c b/glamor/glamor_copyplane.c deleted file mode 100644 index 2bd2de30d..000000000 --- a/glamor/glamor_copyplane.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright © 2009 Intel Corporation - * Copyright © 1998 Keith Packard - * - * 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: - * Zhigang Gong <zhigang.gong@gmail.com> - * - */ - -#include "glamor_priv.h" - -static Bool -_glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int w, int h, int dstx, int dsty, - unsigned long bitPlane, RegionPtr *pRegion, Bool fallback) -{ - if (!fallback && glamor_ddx_fallback_check_gc(pGC) - && glamor_ddx_fallback_check_pixmap(pSrc) - && glamor_ddx_fallback_check_pixmap(pDst)) - goto fail; - - if (glamor_prepare_access(pDst, GLAMOR_ACCESS_RW) && - glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO) && - glamor_prepare_access_gc(pGC)) { - *pRegion = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, - dstx, dsty, bitPlane); - } - glamor_finish_access_gc(pGC); - glamor_finish_access(pSrc); - glamor_finish_access(pDst); - return TRUE; - - fail: - return FALSE; -} - -RegionPtr -glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int w, int h, int dstx, int dsty, - unsigned long bitPlane) -{ - RegionPtr ret; - - _glamor_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h, - dstx, dsty, bitPlane, &ret, TRUE); - return ret; -} - -Bool -glamor_copy_plane_nf(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int w, int h, int dstx, int dsty, - unsigned long bitPlane, RegionPtr *pRegion) -{ - return _glamor_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h, - dstx, dsty, bitPlane, pRegion, FALSE); -} diff --git a/glamor/glamor_copywindow.c b/glamor/glamor_copywindow.c deleted file mode 100644 index 1ced4b336..000000000 --- a/glamor/glamor_copywindow.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright © 2008 Intel Corporation - * 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. - */ - -#include "glamor_priv.h" - -/** @file glamor_copywindow.c - * - * Screen CopyWindow implementation. - */ - -void -glamor_copy_window(WindowPtr win, DDXPointRec old_origin, RegionPtr src_region) -{ - RegionRec dst_region; - int dx, dy; - PixmapPtr pixmap = win->drawable.pScreen->GetWindowPixmap(win); - - dx = old_origin.x - win->drawable.x; - dy = old_origin.y - win->drawable.y; - REGION_TRANSLATE(win->drawable.pScreen, src_region, -dx, -dy); - - REGION_INIT(win->drawable.pScreen, &dst_region, NullBox, 0); - - REGION_INTERSECT(win->drawable.pScreen, &dst_region, - &win->borderClip, src_region); -#ifdef COMPOSITE - if (pixmap->screen_x || pixmap->screen_y) - REGION_TRANSLATE(win->drawable.pScreen, &dst_region, - -pixmap->screen_x, -pixmap->screen_y); -#endif - - miCopyRegion(&pixmap->drawable, &pixmap->drawable, - NULL, &dst_region, dx, dy, glamor_copy_n_to_n, 0, NULL); - - REGION_UNINIT(win->drawable.pScreen, &dst_region); -} diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c index 42f5f65f6..ba7d342b9 100644 --- a/glamor/glamor_glyphs.c +++ b/glamor/glamor_glyphs.c @@ -448,9 +448,9 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen, box.y1 = y; box.x2 = x + glyph->info.width; box.y2 = y + glyph->info.height; - glamor_copy_n_to_n_nf(&scratch->drawable, - &pCachePixmap->drawable, NULL, - &box, 1, -x, -y, FALSE, FALSE, 0, NULL); + glamor_copy(&scratch->drawable, + &pCachePixmap->drawable, NULL, + &box, 1, -x, -y, FALSE, FALSE, 0, NULL); if (scratch != pGlyphPixmap) screen->DestroyPixmap(scratch); diff --git a/glamor/glamor_largepixmap.c b/glamor/glamor_largepixmap.c index b3a8d5d20..5a4bec571 100644 --- a/glamor/glamor_largepixmap.c +++ b/glamor/glamor_largepixmap.c @@ -797,9 +797,9 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, copy_box.y2 = temp_extent->y2 - temp_extent->y1; dx = temp_extent->x1; dy = temp_extent->y1; - glamor_copy_n_to_n(&priv->base.pixmap->drawable, - &temp_pixmap->drawable, - NULL, ©_box, 1, dx, dy, 0, 0, 0, NULL); + glamor_copy(&priv->base.pixmap->drawable, + &temp_pixmap->drawable, + NULL, ©_box, 1, dx, dy, 0, 0, 0, NULL); // glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width, // temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff00); } @@ -829,9 +829,10 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv, copy_box.x1, copy_box.y1, copy_box.x2, copy_box.y2, dx, dy); - glamor_copy_n_to_n(&priv->base.pixmap->drawable, - &temp_pixmap->drawable, - NULL, ©_box, 1, dx, dy, 0, 0, 0, NULL); + glamor_copy(&priv->base.pixmap->drawable, + &temp_pixmap->drawable, + NULL, ©_box, 1, dx, dy, 0, 0, 0, NULL); + box++; } } diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 0af6092b5..1ae4e94f4 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -208,6 +208,7 @@ typedef struct glamor_screen_private { int has_map_buffer_range; int has_buffer_storage; int has_khr_debug; + int has_nv_texture_barrier; int max_fbo_size; int has_rw_pbo; @@ -236,6 +237,10 @@ typedef struct glamor_screen_private { glamor_program te_text_prog; glamor_program image_text_prog; + /* glamor copy shaders */ + glamor_program copy_area_prog; + glamor_program copy_plane_prog; + /* vertext/elment_index buffer object for render */ GLuint vbo, ebo; /** Next offset within the VBO that glamor_get_vbo_space() will use. */ @@ -619,15 +624,6 @@ glamor_pixmap_fbo *glamor_create_fbo_array(glamor_screen_private *glamor_priv, int flag, int block_w, int block_h, glamor_pixmap_private *); -/* glamor_copyarea.c */ -RegionPtr - -glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, - int srcx, int srcy, int width, int height, int dstx, int dsty); -void glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, GCPtr gc, - BoxPtr box, int nbox, int dx, int dy, Bool reverse, - Bool upsidedown, Pixel bitplane, void *closure); - /* glamor_core.c */ void glamor_init_finish_access_shaders(ScreenPtr screen); void glamor_fini_finish_access_shaders(ScreenPtr screen); @@ -931,11 +927,6 @@ void glamor_picture_format_fixup(PicturePtr picture, void glamor_add_traps(PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntrap, xTrap *traps); -RegionPtr glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int w, int h, - int dstx, int dsty, - unsigned long bitPlane); - /* glamor_text.c */ int glamor_poly_text8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars); @@ -977,6 +968,29 @@ void glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, unsigned int format, unsigned long planeMask, char *d); +/* glamor_copy.c */ +void +glamor_copy(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure); + +RegionPtr +glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, + int srcx, int srcy, int width, int height, int dstx, int dsty); + +RegionPtr +glamor_copy_plane(DrawablePtr src, DrawablePtr dst, GCPtr gc, + int srcx, int srcy, int width, int height, int dstx, int dsty, + unsigned long bitplane); + /* glamor_glyphblt.c */ void glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c index 0f4d0f06a..6ee6580ff 100644 --- a/glamor/glamor_program.c +++ b/glamor/glamor_program.c @@ -117,6 +117,11 @@ static glamor_location_var location_vars[] = { .location = glamor_program_location_font, .fs_vars = "uniform usampler2D font;\n", }, + { + .location = glamor_program_location_bitplane, + .fs_vars = ("uniform uvec4 bitplane;\n" + "uniform vec4 bitmul;\n"), + }, }; #define NUM_LOCATION_VARS (sizeof location_vars / sizeof location_vars[0]) @@ -196,6 +201,8 @@ static const glamor_facet facet_null_fill = { .name = "" }; +#define DBG 0 + static GLint glamor_get_uniform(glamor_program *prog, glamor_program_location location, @@ -281,7 +288,6 @@ glamor_build_program(ScreenPtr screen, if (!vs_prog_string || !fs_prog_string) goto fail; -#define DBG 0 #if DBG ErrorF("\nPrograms for %s %s\nVertex shader:\n\n%s\n\nFragment Shader:\n\n%s", prim->name, fill->name, vs_prog_string, fs_prog_string); @@ -318,6 +324,8 @@ glamor_build_program(ScreenPtr screen, prog->fill_offset_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_offset"); prog->fill_size_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_size"); prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font"); + prog->bitplane_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitplane"); + prog->bitmul_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitmul"); if (glGetError() != GL_NO_ERROR) goto fail; diff --git a/glamor/glamor_program.h b/glamor/glamor_program.h index 88efc3593..118f97838 100644 --- a/glamor/glamor_program.h +++ b/glamor/glamor_program.h @@ -29,6 +29,7 @@ typedef enum { glamor_program_location_bg = 2, glamor_program_location_fill = 4, glamor_program_location_font = 8, + glamor_program_location_bitplane = 16, } glamor_program_location; typedef enum { @@ -61,6 +62,8 @@ struct _glamor_program { GLint fill_size_uniform; GLint fill_offset_uniform; GLint font_uniform; + GLint bitplane_uniform; + GLint bitmul_uniform; glamor_program_location locations; glamor_program_flag flags; glamor_use prim_use; diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 8952023f1..6da38da32 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -651,11 +651,12 @@ glamor_composite_with_copy(CARD8 op, if (region->extents.y2 + y_source - y_dest > source->pDrawable->height) goto cleanup_region; } - ret = glamor_copy_n_to_n_nf(source->pDrawable, - dest->pDrawable, NULL, - RegionRects(region), RegionNumRects(region), - x_source - x_dest, y_source - y_dest, - FALSE, FALSE, 0, NULL); + glamor_copy(source->pDrawable, + dest->pDrawable, NULL, + RegionRects(region), RegionNumRects(region), + x_source - x_dest, y_source - y_dest, + FALSE, FALSE, 0, NULL); + ret = TRUE; cleanup_region: return ret; } |