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>
This commit is contained in:
Keith Packard 2014-03-15 13:31:18 -07:00 committed by Eric Anholt
parent 0e08a79599
commit 45ebc4e3fa
13 changed files with 763 additions and 789 deletions

View File

@ -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\

View File

@ -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;

View File

@ -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,

693
glamor/glamor_copy.c Normal file
View File

@ -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;
}

View File

@ -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(&region, box, nbox);
extent = RegionExtents(&region);
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(&region, dst_x_off, dst_y_off);
if (!force_clip)
clipped_dst_regions =
glamor_compute_clipped_regions(dst_pixmap_priv, &region,
&n_dst_region, 0, reverse,
upsidedown);
else
clipped_dst_regions =
glamor_compute_clipped_regions_ext(dst_pixmap_priv, &region,
&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(&region);
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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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, &copy_box, 1, dx, dy, 0, 0, 0, NULL);
glamor_copy(&priv->base.pixmap->drawable,
&temp_pixmap->drawable,
NULL, &copy_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, &copy_box, 1, dx, dy, 0, 0, 0, NULL);
glamor_copy(&priv->base.pixmap->drawable,
&temp_pixmap->drawable,
NULL, &copy_box, 1, dx, dy, 0, 0, 0, NULL);
box++;
}
}

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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;
}