largepixmap: Implement infrastructure for large pixmap.

Added infrastructure for largepixmap, this commit implemented:
1. Create/Destroy large pixmap.
2. Upload/Download large pixmap.
3. Implement basic repeat normal support.
3. tile/fill/copyarea large pixmap get supported.

The most complicated part glamor_composite still not implemented.

Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
This commit is contained in:
Zhigang Gong 2012-06-11 01:52:14 +08:00 committed by Eric Anholt
parent ace35e408c
commit e96ea02010
11 changed files with 1711 additions and 453 deletions

View File

@ -42,6 +42,7 @@ libglamor_la_SOURCES = \
glamor_glyphblt.c\
glamor_polyops.c\
glamor_pixmap.c\
glamor_largepixmap.c\
glamor_picture.c\
glamor_window.c\
glamor_gl_dispatch.c\

View File

@ -141,9 +141,11 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
if (w > 32767 || h > 32767)
return NullPixmap;
if (usage == GLAMOR_CREATE_PIXMAP_CPU
|| (w == 0 && h == 0)
|| !glamor_check_pixmap_fbo_depth(depth))
if ((usage == GLAMOR_CREATE_PIXMAP_CPU
|| (w == 0 && h == 0)
|| !glamor_check_pixmap_fbo_depth(depth))
|| (!GLAMOR_TEXTURED_LARGE_PIXMAP &&
!glamor_check_fbo_size(glamor_priv, w, h)))
return fbCreatePixmap(screen, w, h, depth, usage);
else
pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
@ -161,10 +163,24 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
pixmap_priv->base.pixmap = pixmap;
pixmap_priv->base.glamor_priv = glamor_priv;
pixmap_priv->type = type;
gl_iformat_for_depth(depth, &format);
fbo = glamor_create_fbo(glamor_priv, w, h, format, usage);
pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);
if (type == GLAMOR_MEMORY_MAP || glamor_check_fbo_size(glamor_priv, w, h)) {
pixmap_priv->type = type;
fbo = glamor_create_fbo(glamor_priv, w, h, format, usage);
}
else {
DEBUGF("Create LARGE pixmap %p width %d height %d\n", pixmap, w, h);
pixmap_priv->type = GLAMOR_TEXTURE_LARGE;
fbo = glamor_create_fbo_array(glamor_priv, w, h, format, usage,
glamor_priv->max_fbo_size,
glamor_priv->max_fbo_size,
pixmap_priv);
}
if (fbo == NULL) {
fbDestroyPixmap(pixmap);
@ -174,8 +190,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
glamor_pixmap_attach_fbo(pixmap, fbo);
pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);
return pixmap;
}
@ -186,13 +200,8 @@ glamor_destroy_textured_pixmap(PixmapPtr pixmap)
glamor_pixmap_private *pixmap_priv;
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (pixmap_priv != NULL) {
glamor_pixmap_fbo *fbo;
fbo = glamor_pixmap_detach_fbo(pixmap_priv);
if (fbo)
glamor_destroy_fbo(fbo);
free(pixmap_priv);
}
if (pixmap_priv != NULL)
glamor_pixmap_destroy_fbo(pixmap_priv);
}
}
@ -315,6 +324,9 @@ glamor_init(ScreenPtr screen, unsigned int flags)
glamor_gl_has_extension("GL_EXT_framebuffer_blit");
glamor_priv->_dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE,
&glamor_priv->max_fbo_size);
#ifdef MAX_FBO_SIZE
glamor_priv->max_fbo_size = MAX_FBO_SIZE;
#endif
glamor_set_debug_level(&glamor_debug_level);

View File

@ -40,11 +40,13 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
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;
glamor_pixmap_private *src_pixmap_priv, *dst_pixmap_priv;
glamor_screen_private *glamor_priv =
glamor_get_screen_private(screen);
glamor_gl_dispatch *dispatch;
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,
@ -52,17 +54,13 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
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_pm_is_solid(dst, gc->planemask)) {
glamor_delayed_fallback(screen,
"non-solid planemask\n");
return FALSE;
}
}
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) {
@ -73,6 +71,9 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
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);
dispatch = glamor_get_dispatch(glamor_priv);
dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT,
src_pixmap_priv->base.fbo->fb);
@ -80,7 +81,10 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
&dst_y_off);
glamor_get_drawable_deltas(src, src_pixmap, &src_x_off,
&src_y_off);
src_y_off += dy;
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) {
@ -154,17 +158,11 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
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;
int alu = GXcopy;
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) {
glamor_delayed_fallback(dst->pScreen, "dst has no fbo.\n");
return FALSE;
}
if (!src_pixmap_priv || !src_pixmap_priv->base.gl_fbo) {
if (!src_pixmap_priv->base.gl_fbo) {
#ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n");
return FALSE;
@ -177,11 +175,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
#endif
}
if (gc) {
if (!glamor_set_planemask(dst_pixmap, gc->planemask))
return FALSE;
alu = gc->alu;
}
pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale);
pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale);
@ -191,10 +184,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
dispatch = glamor_get_dispatch(glamor_priv);
if (!glamor_set_alu(dispatch, alu)) {
glamor_put_dispatch(glamor_priv);
return FALSE;
}
glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
@ -239,8 +228,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
for (i = 0; i < nbox; i++) {
glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale,
dst_yscale,
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,
@ -248,7 +237,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
glamor_priv->yInverted,
vertices);
glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale,
glamor_set_normalize_tcoords(src_pixmap_priv,
src_xscale,
src_yscale,
box[i].x1 + dx,
box[i].y1 + dy,
@ -270,19 +260,18 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
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, Bool fallback)
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)
{
glamor_access_t dst_access;
PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL;
DrawablePtr temp_src = src;
glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
@ -296,32 +285,20 @@ _glamor_copy_n_to_n(DrawablePtr src,
int overlaped = 0;
Bool ret = FALSE;
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);
screen = dst_pixmap->drawable.pScreen;
glamor_priv = glamor_get_screen_private(dst->pScreen);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) {
glamor_fallback("dest pixmap %p has no fbo. \n",
dst_pixmap);
goto fail;
}
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);
if (src_pixmap_priv->base.fbo && src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) {
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++) {
@ -332,6 +309,11 @@ _glamor_copy_n_to_n(DrawablePtr src,
}
}
}
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);
#ifndef GLAMOR_GLES2
if ((overlaped
|| !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex)
@ -345,10 +327,13 @@ _glamor_copy_n_to_n(DrawablePtr src,
/* 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)
&& (((bound.x2 - bound.x1) * (bound.y2 - bound.y1)
* 4 >
src_pixmap->drawable.width *
src_pixmap->drawable.height))) {
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,
@ -357,9 +342,11 @@ _glamor_copy_n_to_n(DrawablePtr src,
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 fail;
glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1);
goto done;
glamor_translate_boxes(box, nbox, -bound.x1, -bound.y1);
temp_src = &temp_pixmap->drawable;
if (overlaped)
@ -371,7 +358,7 @@ _glamor_copy_n_to_n(DrawablePtr src,
fbCopyNtoN(src, temp_src, gc, box, nbox,
temp_dx + bound.x1, temp_dy + bound.y1,
reverse, upsidedown, bitplane, closure);
glamor_transform_boxes(box, nbox, bound.x1, bound.y1);
glamor_translate_boxes(box, nbox, bound.x1, bound.y1);
temp_dx = -bound.x1;
temp_dy = -bound.y1;
} else {
@ -383,13 +370,221 @@ _glamor_copy_n_to_n(DrawablePtr src,
if (glamor_copy_n_to_n_textured
(temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) {
ret = TRUE;
goto done;
}
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)
{
glamor_access_t dst_access;
PixmapPtr dst_pixmap, src_pixmap;
glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
glamor_screen_private *glamor_priv;
glamor_gl_dispatch *dispatch;
BoxPtr extent;
RegionRec region;
ScreenPtr screen;
int src_x_off, src_y_off, dst_x_off, dst_y_off;
Bool ret = FALSE;
int ok = TRUE;
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);
screen = dst_pixmap->drawable.pScreen;
glamor_priv = glamor_get_screen_private(dst->pScreen);
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 fail;
dispatch = glamor_get_dispatch(glamor_priv);
if (!glamor_set_alu(dispatch, gc->alu)) {
glamor_put_dispatch(glamor_priv);
goto fail;
}
glamor_put_dispatch(glamor_priv);
}
if (!src_pixmap_priv) {
glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY);
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
}
fail:
if (!fallback
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;
int temp_dx = 0, temp_dy = 0;
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);
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);
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);
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)
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];
/* XXX need revisit here. */
temp_dx = dx/* - src_x_off*/;
temp_dy = dy/* - src_y_off*/;
}
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, temp_dx, temp_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;
}
}
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);
}
free(clipped_dst_regions);
RegionUninit(&region);
} else {
ok = __glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy,
reverse, upsidedown, bitplane,
closure);
}
fail:
dispatch = glamor_get_dispatch(glamor_priv);
glamor_set_alu(dispatch, GXcopy);
glamor_put_dispatch(glamor_priv);
if (ok)
return TRUE;
fall_back:
if (!fallback
&& glamor_ddx_fallback_check_pixmap(src)
&& glamor_ddx_fallback_check_pixmap(dst))
goto done;
@ -428,8 +623,6 @@ _glamor_copy_n_to_n(DrawablePtr src,
done:
glamor_clear_delayed_fallbacks(src->pScreen);
glamor_clear_delayed_fallbacks(dst->pScreen);
if (temp_src != src)
glamor_destroy_pixmap(temp_pixmap);
return ret;
}
@ -455,10 +648,10 @@ glamor_copy_n_to_n(DrawablePtr src,
int dx,
int dy,
Bool reverse,
Bool upsidedown, Pixel bitplane,
Bool upsidedown, Pixel bitplane,
void *closure)
{
_glamor_copy_n_to_n(src, dst, gc, box, nbox, dx,
_glamor_copy_n_to_n(src, dst, gc, box, nbox, dx,
dy, reverse, upsidedown, bitplane, closure, TRUE);
}
@ -471,10 +664,10 @@ glamor_copy_n_to_n_nf(DrawablePtr src,
int dx,
int dy,
Bool reverse,
Bool upsidedown, Pixel bitplane,
Bool upsidedown, Pixel bitplane,
void *closure)
{
return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx,
return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx,
dy, reverse, upsidedown, bitplane, closure, FALSE);
}

View File

@ -175,7 +175,8 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo)
if (fbo->fb == 0 || n_format == -1
|| fbo->glamor_priv->fbo_cache_watermark >= FBO_CACHE_THRESHOLD) {
fbo->glamor_priv->tick ++;
fbo->glamor_priv->tick += GLAMOR_CACHE_EXPIRE_MAX;
glamor_fbo_expire(fbo->glamor_priv);
glamor_purge_fbo(fbo);
return;
}
@ -404,6 +405,92 @@ no_tex:
return fbo;
}
static glamor_pixmap_fbo *
_glamor_create_fbo_array(glamor_screen_private *glamor_priv,
int w, int h, GLenum format, int flag,
int block_w, int block_h,
glamor_pixmap_private *pixmap_priv,
int has_fbo)
{
int block_wcnt;
int block_hcnt;
glamor_pixmap_fbo **fbo_array;
BoxPtr box_array;
int i,j;
glamor_pixmap_private_large_t *priv;
priv = &pixmap_priv->large;
block_wcnt = (w + block_w - 1) / block_w;
block_hcnt = (h + block_h - 1) / block_h;
box_array = calloc(block_wcnt * block_hcnt, sizeof(box_array[0]));
if (box_array == NULL)
return NULL;
fbo_array = calloc(block_wcnt * block_hcnt, sizeof(glamor_pixmap_fbo*));
if (fbo_array == NULL) {
free(box_array);
return FALSE;
}
for(i = 0; i < block_hcnt; i++)
{
int block_y1, block_y2;
int fbo_w, fbo_h;
block_y1 = i * block_h;
block_y2 = (block_y1 + block_h) > h ? h : (block_y1 + block_h);
fbo_h = block_y2 - block_y1;
for (j = 0; j < block_wcnt; j++)
{
box_array[i * block_wcnt + j].x1 = j * block_w;
box_array[i * block_wcnt + j].y1 = block_y1;
box_array[i * block_wcnt + j].x2 = (j + 1) * block_w > w ? w : (j + 1) * block_w;
box_array[i * block_wcnt + j].y2 = block_y2;
fbo_w = box_array[i * block_wcnt + j].x2 - box_array[i * block_wcnt + j].x1;
if (!has_fbo)
fbo_array[i * block_wcnt + j] = glamor_create_fbo(glamor_priv,
fbo_w, fbo_h, format,
GLAMOR_CREATE_PIXMAP_FIXUP);
else
fbo_array[i * block_wcnt + j] = priv->base.fbo;
if (fbo_array[i * block_wcnt + j] == NULL)
goto cleanup;
}
}
priv->box = box_array[0];
priv->box_array = box_array;
priv->fbo_array = fbo_array;
priv->block_wcnt = block_wcnt;
priv->block_hcnt = block_hcnt;
return fbo_array[0];
cleanup:
for(i = 0; i < block_wcnt * block_hcnt; i++)
if ((fbo_array)[i])
glamor_destroy_fbo((fbo_array)[i]);
free(box_array);
free(fbo_array);
return NULL;
}
/* Create a fbo array to cover the w*h region, by using block_w*block_h
* block.*/
glamor_pixmap_fbo *
glamor_create_fbo_array(glamor_screen_private *glamor_priv,
int w, int h, GLenum format, int flag,
int block_w, int block_h,
glamor_pixmap_private *pixmap_priv)
{
pixmap_priv->large.block_w = block_w;
pixmap_priv->large.block_h = block_h;
return _glamor_create_fbo_array(glamor_priv, w, h, format, flag,
block_w, block_h, pixmap_priv, 0);
}
glamor_pixmap_fbo *
glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv)
{
@ -428,23 +515,13 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo)
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (pixmap_priv == NULL) {
glamor_screen_private *glamor_priv;
glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
pixmap_priv = calloc(1, sizeof(*pixmap_priv));
dixSetPrivate(&pixmap->devPrivates,
glamor_pixmap_private_key, pixmap_priv);
pixmap_priv->base.pixmap = pixmap;
pixmap_priv->base.glamor_priv = glamor_priv;
pixmap_priv->type = GLAMOR_MEMORY;
}
if (pixmap_priv->base.fbo)
return;
pixmap_priv->base.fbo = fbo;
switch (pixmap_priv->type) {
case GLAMOR_TEXTURE_LARGE:
case GLAMOR_TEXTURE_ONLY:
case GLAMOR_TEXTURE_DRM:
pixmap_priv->base.gl_fbo = 1;
@ -462,6 +539,23 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo)
}
}
void
glamor_pixmap_destroy_fbo(glamor_pixmap_private *priv)
{
glamor_pixmap_fbo *fbo;
if (priv->type == GLAMOR_TEXTURE_LARGE) {
int i;
glamor_pixmap_private_large_t *large = &priv->large;
for(i = 0; i < large->block_wcnt * large->block_hcnt; i++)
glamor_destroy_fbo(large->fbo_array[i]);
free(large->fbo_array);
} else {
fbo = glamor_pixmap_detach_fbo(priv);
if (fbo)
glamor_destroy_fbo(fbo);
free(priv);
}
}
Bool
glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag)
@ -472,7 +566,7 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag)
glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) {
if (pixmap_priv->base.fbo == NULL) {
fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
pixmap->drawable.height,
@ -492,7 +586,6 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag)
glamor_pixmap_ensure_fb(pixmap_priv->base.fbo);
}
pixmap_priv = glamor_get_pixmap_private(pixmap);
return TRUE;
}

View File

@ -180,10 +180,9 @@ glamor_fini_solid_shader(ScreenPtr screen)
glamor_put_dispatch(glamor_priv);
}
Bool
glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
unsigned char alu, unsigned long planemask,
unsigned long fg_pixel)
static void
_glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
float *color)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv =
@ -195,14 +194,49 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
int x2 = x + width;
int y1 = y;
int y2 = y + height;
GLfloat color[4];
float vertices[8];
GLfloat xscale, yscale;
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) {
glamor_fallback("dest %p has no fbo.\n", pixmap);
glamor_set_destination_pixmap_priv_nc(pixmap_priv);
dispatch = glamor_get_dispatch(glamor_priv);
dispatch->glUseProgram(glamor_priv->solid_prog);
dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location,
1, color);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
GL_FALSE, 2 * sizeof(float),
vertices);
dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale,
x1, y1,
x2, y2,
glamor_priv->yInverted, vertices);
dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
dispatch->glUseProgram(0);
glamor_put_dispatch(glamor_priv);
}
Bool
glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
unsigned char alu, unsigned long planemask,
unsigned long fg_pixel)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv =
glamor_get_screen_private(screen);
glamor_pixmap_private *pixmap_priv;
glamor_gl_dispatch *dispatch;
GLfloat color[4];
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return FALSE;
}
if (!glamor_set_planemask(pixmap, planemask)) {
glamor_fallback
@ -216,8 +250,6 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
&color[2],
&color[3], format_for_pixmap(pixmap));
glamor_set_destination_pixmap_priv_nc(pixmap_priv);
dispatch = glamor_get_dispatch(glamor_priv);
if (!glamor_set_alu(dispatch, alu)) {
if (alu == GXclear)
@ -228,23 +260,47 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
return FALSE;
}
}
dispatch->glUseProgram(glamor_priv->solid_prog);
dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location,
1, color);
if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
RegionRec region;
BoxRec box;
int n_region;
glamor_pixmap_clipped_regions *clipped_regions;
int i,j;
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
GL_FALSE, 2 * sizeof(float),
vertices);
dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
box.x1 = x;
box.y1 = y;
box.x2 = x + width;
box.y2 = y + height;
RegionInitBoxes(&region, &box, 1);
clipped_regions = glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0);
for(i = 0; i < n_region; i++)
{
BoxPtr boxes;
int nbox;
SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx);
boxes = RegionRects(clipped_regions[i].region);
nbox = RegionNumRects(clipped_regions[i].region);
for(j = 0; j < nbox; j++)
{
_glamor_solid(pixmap, boxes[j].x1, boxes[j].y1,
boxes[j].x2 - boxes[j].x1,
boxes[j].y2 - boxes[j].y1, color);
}
RegionDestroy(clipped_regions[i].region);
}
free(clipped_regions);
RegionUninit(&region);
} else
_glamor_solid(pixmap,
x,
y,
width, height,
color);
glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale, x1, y1, x2, y2,
glamor_priv->yInverted, vertices);
dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
dispatch->glUseProgram(0);
glamor_set_alu(dispatch, GXcopy);
glamor_put_dispatch(glamor_priv);
return TRUE;
}

412
glamor/glamor_largepixmap.c Normal file
View File

@ -0,0 +1,412 @@
#include <stdlib.h>
#include "glamor_priv.h"
/**
* Clip the boxes regards to each pixmap's block array.
*
* Should translate the region to relative coords to the pixmap,
* start at (0,0).
*/
#if 0
//#define DEBUGF(str, ...) do {} while(0)
#define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__)
//#define DEBUGRegionPrint(x) do {} while (0)
#define DEBUGRegionPrint RegionPrint
#endif
static glamor_pixmap_clipped_regions *
__glamor_compute_clipped_regions(int block_w,
int block_h,
int block_stride,
int x, int y,
int w, int h,
RegionPtr region,
int *n_region,
int repeat)
{
glamor_pixmap_clipped_regions * clipped_regions;
BoxPtr extent;
int start_x, start_y, end_x, end_y;
int start_block_x, start_block_y;
int end_block_x, end_block_y;
int i, j;
int width, height;
RegionRec temp_region;
RegionPtr current_region;
int block_idx;
int k = 0;
int temp_block_idx;
extent = RegionExtents(region);
start_x = MAX(x, extent->x1);
start_y = MAX(y, extent->y1);
end_x = MIN(x + w, extent->x2);
end_y = MIN(y + h, extent->y2);
DEBUGF("start compute clipped regions:\n");
DEBUGF("block w %d h %d x %d y %d w %d h %d, block_stride %d \n",
block_w, block_h, x, y, w, h, block_stride);
DEBUGRegionPrint(region);
DEBUGF("start_x %d start_y %d end_x %d end_y %d \n", start_x, start_y, end_x, end_y);
if (start_x >= end_x || start_y >= end_y) {
*n_region = 0;
return NULL;
}
width = end_x - start_x;
height = end_y - start_y;
start_block_x = (start_x - x)/ block_w;
start_block_y = (start_y - y)/ block_h;
end_block_x = (end_x - x)/ block_w;
end_block_y = (end_y - y)/ block_h;
clipped_regions = calloc((end_block_x - start_block_x + 1)
* (end_block_y - start_block_y + 1),
sizeof(*clipped_regions));
block_idx = (start_block_y - 1) * block_stride;
DEBUGF("startx %d starty %d endx %d endy %d \n",
start_x, start_y, end_x, end_y);
DEBUGF("start_block_x %d end_block_x %d \n", start_block_x, end_block_x);
DEBUGF("start_block_y %d end_block_y %d \n", start_block_y, end_block_y);
for(j = start_block_y; j <= end_block_y; j++)
{
block_idx += block_stride;
temp_block_idx = block_idx + start_block_x;
for(i = start_block_x;
i <= end_block_x; i++, temp_block_idx++)
{
BoxRec temp_box;
temp_box.x1 = x + i * block_w;
temp_box.y1 = y + j * block_h;
temp_box.x2 = MIN(temp_box.x1 + block_w, end_x);
temp_box.y2 = MIN(temp_box.y1 + block_h, end_y);
RegionInitBoxes(&temp_region, &temp_box, 1);
DEBUGF("block idx %d \n",temp_block_idx);
DEBUGRegionPrint(&temp_region);
current_region = RegionCreate(NULL, 4);
RegionIntersect(current_region, &temp_region, region);
DEBUGF("i %d j %d region: \n",i ,j);
DEBUGRegionPrint(current_region);
if (RegionNumRects(current_region)) {
clipped_regions[k].region = current_region;
clipped_regions[k].block_idx = temp_block_idx;
k++;
} else
RegionDestroy(current_region);
RegionUninit(&temp_region);
}
}
*n_region = k;
return clipped_regions;
}
/**
* Do a two round clipping,
* first is to clip the region regard to current pixmap's
* block array. Then for each clipped region, do a inner
* block clipping. This is to make sure the final result
* will be shapped by inner_block_w and inner_block_h, and
* the final region also will not cross the pixmap's block
* boundary.
*
* This is mainly used by transformation support when do
* compositing.
*/
glamor_pixmap_clipped_regions *
glamor_compute_clipped_regions_ext(glamor_pixmap_private *pixmap_priv,
RegionPtr region,
int *n_region,
int inner_block_w, int inner_block_h)
{
glamor_pixmap_clipped_regions * clipped_regions, *inner_regions, *result_regions;
int i, j, x, y, k, inner_n_regions;
int width, height;
glamor_pixmap_private_large_t *priv;
priv = &pixmap_priv->large;
DEBUGF("ext called \n");
if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) {
clipped_regions = calloc(1, sizeof(*clipped_regions));
if (clipped_regions == NULL) {
*n_region = 0;
return NULL;
}
clipped_regions[0].region = RegionCreate(NULL, 1);
clipped_regions[0].block_idx = 0;
RegionCopy(clipped_regions[0].region, region);
*n_region = 1;
priv->block_w = priv->base.pixmap->drawable.width;
priv->block_h = priv->base.pixmap->drawable.height;
priv->box_array = &priv->box;
priv->box.x1 = priv->box.y1 = 0;
priv->box.x2 = priv->block_w;
priv->box.y2 = priv->block_h;
} else {
clipped_regions = __glamor_compute_clipped_regions(priv->block_w,
priv->block_h,
priv->block_wcnt,
0, 0,
priv->base.pixmap->drawable.width,
priv->base.pixmap->drawable.height,
region, n_region, 0
);
if (clipped_regions == NULL) {
*n_region = 0;
return NULL;
}
}
if (inner_block_w >= priv->block_w
&& inner_block_h >= priv->block_h)
return clipped_regions;
result_regions = calloc(*n_region
* ((priv->block_w + inner_block_w - 1)/inner_block_w)
* ((priv->block_h + inner_block_h - 1)/ inner_block_h),
sizeof(*result_regions));
k = 0;
for(i = 0; i < *n_region; i++)
{
x = priv->box_array[clipped_regions[i].block_idx].x1;
y = priv->box_array[clipped_regions[i].block_idx].y1;
width = priv->box_array[clipped_regions[i].block_idx].x2 - x;
height = priv->box_array[clipped_regions[i].block_idx].y2 - y;
inner_regions = __glamor_compute_clipped_regions(inner_block_w,
inner_block_h,
0, x, y,
width,
height,
clipped_regions[i].region,
&inner_n_regions, 0);
for(j = 0; j < inner_n_regions; j++)
{
result_regions[k].region = inner_regions[j].region;
result_regions[k].block_idx = clipped_regions[i].block_idx;
k++;
}
free(inner_regions);
}
*n_region = k;
free(clipped_regions);
return result_regions;
}
/**
* Clip the boxes regards to each pixmap's block array.
*
* Should translate the region to relative coords to the pixmap,
* start at (0,0).
*
* @is_transform: if it is set, it has a transform matrix.
*
* XXX Not support repeatPad currently.
*/
static glamor_pixmap_clipped_regions *
_glamor_compute_clipped_regions(glamor_pixmap_private *pixmap_priv,
RegionPtr region, int *n_region,
int repeat_type, int is_transform)
{
glamor_pixmap_clipped_regions * clipped_regions;
BoxPtr extent;
int i, j;
int width, height;
RegionPtr current_region;
int pixmap_width, pixmap_height;
int m;
BoxRec repeat_box;
RegionRec repeat_region;
int right_shift = 0;
int down_shift = 0;
int x_center_shift = 0, y_center_shift = 0;
glamor_pixmap_private_large_t *priv;
priv = &pixmap_priv->large;
DEBUGRegionPrint(region);
if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE) {
clipped_regions = calloc(1, sizeof(*clipped_regions));
clipped_regions[0].region = RegionCreate(NULL, 1);
clipped_regions[0].block_idx = 0;
RegionCopy(clipped_regions[0].region, region);
*n_region = 1;
return clipped_regions;
}
pixmap_width = priv->base.pixmap->drawable.width;
pixmap_height = priv->base.pixmap->drawable.height;
if (repeat_type == 0) {
clipped_regions = __glamor_compute_clipped_regions(priv->block_w,
priv->block_h,
priv->block_wcnt,
0, 0,
priv->base.pixmap->drawable.width,
priv->base.pixmap->drawable.height,
region, n_region, 0
);
return clipped_regions;
} else if (repeat_type != RepeatNormal) {
*n_region = 0;
return NULL;
}
extent = RegionExtents(region);
x_center_shift = extent->x1 / pixmap_width;
if (x_center_shift < 0)
x_center_shift--;
if (abs(x_center_shift) & 1)
x_center_shift++;
y_center_shift = extent->y1 / pixmap_height;
if (y_center_shift < 0)
y_center_shift--;
if (abs(y_center_shift) & 1)
y_center_shift++;
if (extent->x1 < 0)
right_shift = ((-extent->x1 + pixmap_width - 1) / pixmap_width );
if (extent->y1 < 0)
down_shift = ((-extent->y1 + pixmap_height - 1) / pixmap_height );
if (right_shift != 0 || down_shift != 0) {
if (repeat_type == RepeatReflect) {
right_shift = (right_shift + 1)&~1;
down_shift = (down_shift + 1)&~1;
}
RegionTranslate(region, right_shift * pixmap_width, down_shift * pixmap_height);
}
extent = RegionExtents(region);
width = extent->x2 - extent->x1;
height = extent->y2 - extent->y1;
/* Tile a large pixmap to another large pixmap.
* We can't use the target large pixmap as the
* loop variable, instead we need to loop for all
* the blocks in the tile pixmap.
*
* simulate repeat each single block to cover the
* target's blocks. Two special case:
* a block_wcnt == 1 or block_hcnt ==1, then we
* only need to loop one direction as the other
* direction is fully included in the first block.
*
* For the other cases, just need to start
* from a proper shiftx/shifty, and then increase
* y by tile_height each time to walk trhough the
* target block and then walk trhough the target
* at x direction by increate tile_width each time.
*
* This way, we can consolidate all the sub blocks
* of the target boxes into one tile source's block.
*
* */
m = 0;
clipped_regions = calloc(priv->block_wcnt * priv->block_hcnt,
sizeof(*clipped_regions));
if (clipped_regions == NULL) {
*n_region = 0;
return NULL;
}
if (right_shift != 0 || down_shift != 0) {
DEBUGF("region to be repeated shifted \n");
DEBUGRegionPrint(region);
}
DEBUGF("repeat pixmap width %d height %d \n", pixmap_width, pixmap_height);
DEBUGF("extent x1 %d y1 %d x2 %d y2 %d \n", extent->x1, extent->y1, extent->x2, extent->y2);
for(j = 0; j < priv->block_hcnt; j++)
{
for(i = 0; i < priv->block_wcnt; i++)
{
int dx = pixmap_width;
int dy = pixmap_height;
int idx;
int shift_x;
int shift_y;
int saved_y1, saved_y2;
int x_idx = 0, y_idx = 0;
RegionRec temp_region;
shift_x = (extent->x1 / pixmap_width) * pixmap_width;
shift_y = (extent->y1 / pixmap_height) * pixmap_height;
idx = j * priv->block_wcnt + i;
if (repeat_type == RepeatReflect) {
x_idx = (extent->x1 / pixmap_width);
y_idx = (extent->y1 / pixmap_height);
}
/* Construct a rect to clip the target region. */
repeat_box.x1 = shift_x + priv->box_array[idx].x1;
repeat_box.y1 = shift_y + priv->box_array[idx].y1;
if (priv->block_wcnt == 1)
repeat_box.x2 = extent->x2;
else
repeat_box.x2 = shift_x + priv->box_array[idx].x2;
if (priv->block_hcnt == 1)
repeat_box.y2 = extent->y2;
else
repeat_box.y2 = shift_y + priv->box_array[idx].y2;
current_region = RegionCreate(NULL, 4);
RegionInit(&temp_region, NULL, 4);
DEBUGF("init repeat box %d %d %d %d \n",
repeat_box.x1, repeat_box.y1, repeat_box.x2, repeat_box.y2);
if (repeat_type == RepeatNormal) {
saved_y1 = repeat_box.y1;
saved_y2 = repeat_box.y2;
for(; repeat_box.x1 < extent->x2;
repeat_box.x1 += dx, repeat_box.x2 += dx)
{
repeat_box.y1 = saved_y1;
repeat_box.y2 = saved_y2;
for( repeat_box.y1 = saved_y1, repeat_box.y2 = saved_y2;
repeat_box.y1 < extent->y2;
repeat_box.y1 += dy, repeat_box.y2 += dy)
{
RegionInitBoxes(&repeat_region, &repeat_box, 1);
DEBUGF("Start to clip repeat region: \n");
DEBUGRegionPrint(&repeat_region);
RegionIntersect(&temp_region, &repeat_region, region);
DEBUGF("clip result:\n");
DEBUGRegionPrint(&temp_region);
RegionAppend(current_region, &temp_region);
RegionUninit(&repeat_region);
}
}
}
DEBUGF("dx %d dy %d \n", dx, dy);
if (RegionNumRects(current_region)) {
if ((right_shift != 0 || down_shift != 0))
RegionTranslate(current_region,
-right_shift * pixmap_width,
-down_shift * pixmap_height);
clipped_regions[m].region = current_region;
clipped_regions[m].block_idx = idx;
m++;
} else
RegionDestroy(current_region);
RegionUninit(&temp_region);
}
}
if (right_shift != 0 || down_shift != 0)
RegionTranslate(region, -right_shift * pixmap_width, -down_shift * pixmap_height);
*n_region = m;
return clipped_regions;
}
glamor_pixmap_clipped_regions *
glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, int *n_region, int repeat_type)
{
return _glamor_compute_clipped_regions(priv, region, n_region, repeat_type, 0);
}

View File

@ -83,9 +83,11 @@ glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo * fbo, int x0, int y0, int w
void
glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv)
{
int w,h;
PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap_priv, w, h);
glamor_set_destination_pixmap_fbo(pixmap_priv->base.fbo, 0, 0,
pixmap_priv->base.pixmap->drawable.width,
pixmap_priv->base.pixmap->drawable.height);
w, h);
}
int
@ -489,16 +491,23 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum ty
}
ready_to_upload:
/* Try fast path firstly, upload the pixmap to the texture attached
* to the fbo directly. */
if (no_alpha == 0
&& revert == REVERT_NONE
&& swap_rb == SWAP_NONE_UPLOADING
&& !need_flip) {
int fbo_x_off, fbo_y_off;
assert(pixmap_priv->base.fbo->tex);
pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off);
assert(x + fbo_x_off >= 0 && y + fbo_y_off >= 0);
assert(x + fbo_x_off + w <= pixmap_priv->base.fbo->width);
assert(y + fbo_y_off + h <= pixmap_priv->base.fbo->height);
__glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->base.fbo->tex,
format, type,
x, y, w, h,
x + fbo_x_off, y + fbo_y_off, w, h,
bits, pbo);
return TRUE;
}
@ -515,7 +524,6 @@ ready_to_upload:
x + w, y + h,
glamor_priv->yInverted,
vertices);
/* Slow path, we need to flip y or wire alpha to 1. */
dispatch = glamor_get_dispatch(glamor_priv);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
@ -586,6 +594,9 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int
pixmap_priv = glamor_get_pixmap_private(pixmap);
glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
if (pixmap_priv->base.gl_fbo)
return 0;
if (pixmap_priv->base.fbo
&& (pixmap_priv->base.fbo->width < pixmap->drawable.width
|| pixmap_priv->base.fbo->height < pixmap->drawable.height)) {
@ -605,8 +616,10 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int
flag = GLAMOR_CREATE_FBO_NO_FBO;
}
if ((flag == 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex)
|| (flag != 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb))
if ((flag == GLAMOR_CREATE_FBO_NO_FBO
&& pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex)
|| (flag == 0
&& pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb))
return 0;
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
@ -614,35 +627,63 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int
else
iformat = format;
if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) {
fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
pixmap->drawable.height,
iformat,
flag);
if (fbo == NULL) {
glamor_fallback
("upload failed, depth %d x %d @depth %d \n",
pixmap->drawable.width, pixmap->drawable.height,
pixmap->drawable.depth);
return -1;
}
glamor_pixmap_attach_fbo(pixmap, fbo);
} else {
/* We do have a fbo, but it may lack of fb or tex. */
glamor_pixmap_ensure_fbo(pixmap, iformat, flag);
}
if (!glamor_pixmap_ensure_fbo(pixmap, iformat, flag))
return -1;
return 0;
}
/*
* upload sub region to a large region.
* */
static void
glamor_put_bits(char *dst_bits, int dst_stride, char *src_bits,
int src_stride, int bpp,
int x, int y, int w, int h)
{
int j;
int byte_per_pixel;
byte_per_pixel = bpp / 8;
src_bits += y * src_stride + (x * byte_per_pixel);
for(j = y; j < y + h; j++)
{
memcpy(dst_bits, src_bits, w * byte_per_pixel);
src_bits += src_stride;
dst_bits += dst_stride;
}
}
/*
* download sub region from a large region.
*/
static void
glamor_get_bits(char *dst_bits, int dst_stride, char *src_bits,
int src_stride, int bpp,
int x, int y, int w, int h)
{
int j;
int byte_per_pixel;
byte_per_pixel = bpp / 8;
dst_bits += y * dst_stride + x * byte_per_pixel;
for(j = y; j < y + h; j++)
{
memcpy(dst_bits, src_bits, w * byte_per_pixel);
src_bits += src_stride;
dst_bits += dst_stride;
}
}
Bool
glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h,
int stride, void *bits, int pbo)
{
GLenum format, type;
int no_alpha, revert, swap_rb;
glamor_pixmap_private *pixmap_priv;
if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format,
@ -657,7 +698,77 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h
if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb))
return FALSE;
return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha, revert, swap_rb,
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
RegionRec region;
BoxRec box;
int n_region;
glamor_pixmap_clipped_regions *clipped_regions;
void *sub_bits;
int i,j;
sub_bits = malloc(h * stride);
if (sub_bits == NULL)
return FALSE;
box.x1 = x;
box.y1 = y;
box.x2 = x + w;
box.y2 = y + h;
RegionInitBoxes(&region, &box, 1);
clipped_regions = glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0);
DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap);
for(i = 0; i < n_region; i++)
{
BoxPtr boxes;
int nbox;
int temp_stride;
void *temp_bits;
assert(pbo == 0);
SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx);
boxes = RegionRects(clipped_regions[i].region);
nbox = RegionNumRects(clipped_regions[i].region);
DEBUGF("split to %d boxes\n", nbox);
for(j = 0; j < nbox; j++)
{
temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1,
pixmap->drawable.depth);
if (boxes[j].x1 == x && temp_stride == stride) {
temp_bits = (char*)bits + (boxes[j].y1 - y) * stride;
} else {
temp_bits = sub_bits;
glamor_put_bits(temp_bits, temp_stride, bits, stride,
pixmap->drawable.bitsPerPixel,
boxes[j].x1 - x, boxes[j].y1 - y,
boxes[j].x2 - boxes[j].x1,
boxes[j].y2 - boxes[j].y1);
}
DEBUGF("upload x %d y %d w %d h %d temp stride %d \n",
boxes[j].x1 - x, boxes[j].y1 - y,
boxes[j].x2 - boxes[j].x1,
boxes[j].y2 - boxes[j].y1, temp_stride);
if (_glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha,
revert, swap_rb, boxes[j].x1, boxes[j].y1,
boxes[j].x2 - boxes[j].x1,
boxes[j].y2 - boxes[j].y1,
temp_stride, temp_bits, pbo) == FALSE) {
RegionUninit(&region);
free(sub_bits);
assert(0);
return FALSE;
}
}
RegionDestroy(clipped_regions[i].region);
}
free(sub_bits);
free(clipped_regions);
RegionUninit(&region);
return TRUE;
} else
return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha, revert, swap_rb,
x, y, w, h, stride, bits, pbo);
}
@ -671,8 +782,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (pixmap_priv
&& (pixmap_priv->base.fbo)
if ((pixmap_priv->base.fbo)
&& (pixmap_priv->base.fbo->pbo_valid)) {
data = NULL;
pbo = pixmap_priv->base.fbo->pbo;
@ -737,7 +847,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe
temp_xscale = 1.0 / w;
temp_yscale = 1.0 / h;
glamor_set_normalize_vcoords((glamor_pixmap_private *)NULL, temp_xscale,
glamor_set_normalize_vcoords((struct glamor_pixmap_private*)NULL,temp_xscale,
temp_yscale,
0, 0,
w, h,
@ -793,13 +903,15 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe
* The pixmap must have a valid FBO, otherwise return a NULL.
* */
void *
glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
int stride, void *bits, int pbo, glamor_access_t access)
static void *
_glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
GLenum type, int no_alpha,
int revert, int swap_rb,
int x, int y, int w, int h,
int stride, void *bits, int pbo, glamor_access_t access)
{
glamor_pixmap_private *pixmap_priv;
GLenum format, type, gl_access = 0, gl_usage = 0;
int no_alpha, revert, swap_rb;
GLenum gl_access = 0, gl_usage = 0;
void *data, *read;
ScreenPtr screen;
glamor_screen_private *glamor_priv =
@ -808,6 +920,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
glamor_pixmap_fbo *temp_fbo = NULL;
int need_post_conversion = 0;
int need_free_data = 0;
int fbo_x_off, fbo_y_off;
data = bits;
screen = pixmap->drawable.pScreen;
@ -831,18 +944,6 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
assert(0);
}
if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format,
&type,
&no_alpha,
&revert,
&swap_rb, 0)) {
ErrorF("Unknown pixmap depth %d.\n",
pixmap->drawable.depth);
assert(0); // Should never happen.
return NULL;
}
glamor_set_destination_pixmap_priv_nc(pixmap_priv);
need_post_conversion = (revert > REVERT_NORMAL);
@ -857,6 +958,8 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
}
}
pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off);
if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
&& !need_post_conversion
&& (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) {
@ -868,6 +971,8 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
}
x = 0;
y = 0;
fbo_x_off = 0;
fbo_y_off = 0;
}
dispatch = glamor_get_dispatch(glamor_priv);
@ -890,7 +995,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
NULL, gl_usage);
}
dispatch->glReadPixels(x, y, w, h, format, type, data);
dispatch->glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, data);
if (!glamor_priv->yInverted) {
assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
@ -913,7 +1018,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
stride *
h,
NULL, GL_STREAM_READ);
dispatch->glReadPixels(0, 0, w, h,
dispatch->glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h,
format, type, 0);
read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER,
GL_READ_ONLY);
@ -946,6 +1051,107 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
return bits;
}
void *
glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
int stride, void *bits, int pbo, glamor_access_t access)
{
GLenum format, type;
int no_alpha, revert, swap_rb;
glamor_pixmap_private *pixmap_priv;
if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format,
&type,
&no_alpha,
&revert,
&swap_rb, 1)) {
glamor_fallback("Unknown pixmap depth %d.\n",
pixmap->drawable.depth);
return NULL;
}
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return NULL;
if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
RegionRec region;
BoxRec box;
int n_region;
glamor_pixmap_clipped_regions *clipped_regions;
void *sub_bits;
int i,j;
sub_bits = malloc(h * stride);
if (sub_bits == NULL)
return FALSE;
box.x1 = x;
box.y1 = y;
box.x2 = x + w;
box.y2 = y + h;
RegionInitBoxes(&region, &box, 1);
clipped_regions = glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0);
DEBUGF("start download large pixmap %p %dx%d \n", pixmap, w, h);
for(i = 0; i < n_region; i++)
{
BoxPtr boxes;
int nbox;
int temp_stride;
void *temp_bits;
assert(pbo == 0);
SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx);
boxes = RegionRects(clipped_regions[i].region);
nbox = RegionNumRects(clipped_regions[i].region);
for(j = 0; j < nbox; j++)
{
temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1,
pixmap->drawable.depth);
if (boxes[j].x1 == x && temp_stride == stride) {
temp_bits = (char*)bits + (boxes[j].y1 - y) * stride;
} else {
temp_bits = sub_bits;
}
DEBUGF("download x %d y %d w %d h %d temp stride %d \n",
boxes[j].x1, boxes[j].y1,
boxes[j].x2 - boxes[j].x1,
boxes[j].y2 - boxes[j].y1, temp_stride);
/* For large pixmap, we don't support pbo currently.*/
assert(pbo == 0);
if (_glamor_download_sub_pixmap_to_cpu(pixmap, format, type, no_alpha,
revert, swap_rb, boxes[j].x1, boxes[j].y1,
boxes[j].x2 - boxes[j].x1,
boxes[j].y2 - boxes[j].y1,
temp_stride, temp_bits, pbo, access) == FALSE) {
RegionUninit(&region);
free(sub_bits);
assert(0);
return NULL;
}
if (boxes[j].x1 != x || temp_stride != stride)
glamor_get_bits(bits, stride, temp_bits, temp_stride,
pixmap->drawable.bitsPerPixel,
boxes[j].x1 - x , boxes[j].y1 - y,
boxes[j].x2 - boxes[j].x1,
boxes[j].y2 - boxes[j].y1);
}
RegionDestroy(clipped_regions[i].region);
}
free(sub_bits);
free(clipped_regions);
RegionUninit(&region);
return bits;
} else
return _glamor_download_sub_pixmap_to_cpu(pixmap, format, type, no_alpha, revert, swap_rb,
x, y, w, h, stride,
bits, pbo, access);
}
/**
* Move a pixmap to CPU memory.
@ -984,7 +1190,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
if (access == GLAMOR_ACCESS_WO
|| glamor_priv->gl_flavor == GLAMOR_GL_ES2
|| (!glamor_priv->has_pack_invert && !glamor_priv->yInverted)) {
|| (!glamor_priv->has_pack_invert && !glamor_priv->yInverted)
|| pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
data = malloc(stride * pixmap->drawable.height);
} else {
dispatch = glamor_get_dispatch(glamor_priv);
@ -1024,6 +1231,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
}
/* fixup a fbo to the exact size as the pixmap. */
/* XXX LARGE pixmap? */
Bool
glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
{
@ -1038,8 +1246,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
drawable = &pixmap_priv->base.pixmap->drawable;
if (pixmap_priv->base.pixmap->drawable.width == pixmap_priv->base.fbo->width
&& pixmap_priv->base.pixmap->drawable.height == pixmap_priv->base.fbo->height)
if (!GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))
return TRUE;
old_fbo = pixmap_priv->base.fbo;
@ -1058,7 +1265,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
scratch_priv = glamor_get_pixmap_private(scratch);
if (!scratch_priv || !scratch_priv->base.fbo)
if (!scratch_priv->base.fbo)
goto fail;
ValidateGC(&scratch->drawable, gc);
@ -1111,14 +1318,13 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces
void *data;
int pbo;
int flag;
assert(x >= 0 && y >= 0);
if (x < 0 || y < 0)
return NULL;
w = (x + w) > pixmap->drawable.width ? (pixmap->drawable.width - x) : w;
h = (y + h) > pixmap->drawable.height ? (pixmap->drawable.height - y) : h;
if (access == GLAMOR_ACCESS_WO) {
sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU);
ErrorF("WO\n");
return sub_pixmap;
}
@ -1127,7 +1333,7 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return NULL;
if (glamor_priv->gl_flavor == GLAMOR_GL_ES2)
if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 || pixmap_priv->type == GLAMOR_TEXTURE_LARGE)
flag = GLAMOR_CREATE_PIXMAP_CPU;
else
flag = GLAMOR_CREATE_PIXMAP_MAP;
@ -1141,17 +1347,16 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces
sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
pbo = sub_pixmap_priv ? (sub_pixmap_priv->base.fbo ? sub_pixmap_priv->base.fbo->pbo : 0): 0;
if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) {
if (pixmap_priv->base.is_picture) {
sub_pixmap_priv->base.picture = pixmap_priv->base.picture;
sub_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture;
}
if (pbo)
data = NULL;
else {
else
data = sub_pixmap->devPrivate.ptr;
assert(flag != GLAMOR_CREATE_PIXMAP_MAP);
}
data = glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h, sub_pixmap->devKind,
data, pbo, access);
if (pbo) {
@ -1173,7 +1378,7 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces
new_sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU);
glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap, NULL, &box, 1, dx, dy, 0, 0, 0, NULL);
glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap->drawable, NULL, &box, 1, dx, dy, 0, 0, 0, NULL);
glamor_compare_pixmaps(new_sub_pixmap, sub_pixmap, 0, 0, w, h, 1, 1);
#endif
@ -1188,8 +1393,7 @@ glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int
glamor_pixmap_private *sub_pixmap_priv;
if (access != GLAMOR_ACCESS_RO) {
sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
if (sub_pixmap_priv
&& sub_pixmap_priv->base.fbo
if (sub_pixmap_priv->base.fbo
&& sub_pixmap_priv->base.fbo->pbo_valid) {
bits = NULL;
pbo = sub_pixmap_priv->base.fbo->pbo;

View File

@ -927,6 +927,9 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
#ifndef GLAMOR_GLES2
#define GLAMOR_GRADIENT_SHADER
#endif
#define GLAMOR_TEXTURED_LARGE_PIXMAP 1
#define GLAMOR_TEXTURED_LARGE_PIXMAP 0
#if 0
#define MAX_FBO_SIZE 512 /* For test purpose only. */
#endif
#endif /* GLAMOR_PRIV_H */

View File

@ -37,7 +37,12 @@
#ifdef RENDER
#include "mipict.h"
#include "fbpict.h"
#if 0
//#define DEBUGF(str, ...) do {} while(0)
#define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__)
//#define DEBUGRegionPrint(x) do {} while (0)
#define DEBUGRegionPrint RegionPrint
#endif
struct shader_key {
enum shader_source source;
enum shader_mask mask;
@ -606,18 +611,20 @@ glamor_set_composite_texture(ScreenPtr screen, int unit,
#endif
/* XXX may be we can eaxctly check whether we need to touch
* the out-of-box area then determine whether we need to fix.
* */
if (repeat_type != RepeatNone)
repeat_type += RepeatFix;
else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
if (picture->transform
|| (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv)))
**/
/*if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE)*/ {
if (repeat_type != RepeatNone)
repeat_type += RepeatFix;
}
if (repeat_type >= RepeatFix) {
glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv);
dispatch->glUniform2fv(wh_location, 1, wh);
else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
|| pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
if (picture->transform
|| (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv)))
repeat_type += RepeatFix;
}
if (repeat_type >= RepeatFix) {
glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv);
dispatch->glUniform2fv(wh_location, 1, wh);
}
}
dispatch->glUniform1i(repeat_location, repeat_type);
glamor_put_dispatch(glamor_priv);
@ -687,53 +694,44 @@ glamor_composite_with_copy(CARD8 op,
INT16 x_source,
INT16 y_source,
INT16 x_dest,
INT16 y_dest, CARD16 width, CARD16 height)
INT16 y_dest,
RegionPtr region)
{
RegionRec region;
int ret = FALSE;
if (!source->pDrawable)
return FALSE;
if (!compatible_formats(op, dest, source))
return FALSE;
if (source->repeat || source->transform)
if (source->repeat || source->transform) {
return FALSE;
}
x_dest += dest->pDrawable->x;
y_dest += dest->pDrawable->y;
x_source += source->pDrawable->x;
y_source += source->pDrawable->y;
if (!miComputeCompositeRegion(&region,
source, NULL, dest,
x_source, y_source,
0, 0, x_dest, y_dest, width, height))
return TRUE;
if (PICT_FORMAT_A(source->format) == 0) {
/* Fallback if we sample outside the source so that we
* swizzle the correct clear color for out-of-bounds texels.
*/
if (region.extents.x1 + x_source - x_dest < 0)
if (region->extents.x1 + x_source - x_dest < 0)
goto cleanup_region;
if (region.extents.x2 + x_source - x_dest > source->pDrawable->width)
if (region->extents.x2 + x_source - x_dest > source->pDrawable->width)
goto cleanup_region;
if (region.extents.y1 + y_source - y_dest < 0)
if (region->extents.y1 + y_source - y_dest < 0)
goto cleanup_region;
if (region.extents.y2 + y_source - y_dest > source->pDrawable->height)
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,
REGION_RECTS(&region),
REGION_NUM_RECTS(&region),
RegionRects(region), RegionNumRects(region),
x_source - x_dest, y_source - y_dest,
FALSE, FALSE, 0, NULL);
cleanup_region:
REGION_UNINIT(dest->pDrawable->pScreen, &region);
return ret;
}
@ -929,12 +927,44 @@ combine_pict_format(PictFormatShort * des, const PictFormatShort src,
return FALSE;
}
static void
glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv,
int repeat_type,
float *matrix,
float xscale, float yscale,
int x1, int y1, int x2, int y2,
int yInverted, float *texcoords)
{
if (!matrix && repeat_type == RepeatNone)
glamor_set_normalize_tcoords(priv, xscale, yscale,
x1, y1,
x2, y2,
yInverted,
texcoords);
else if (matrix && repeat_type == RepeatNone)
glamor_set_transformed_normalize_tcoords(priv, matrix, xscale,
yscale, x1, y1,
x2, y2,
yInverted,
texcoords);
else if (!matrix && repeat_type != RepeatNone)
glamor_set_repeat_normalize_tcoords(priv, repeat_type,
xscale, yscale,
x1, y1,
x2, y2,
yInverted,
texcoords);
else if (matrix && repeat_type != RepeatNone)
assert(0);
}
static Bool
glamor_composite_with_shader(CARD8 op,
PicturePtr source,
PicturePtr mask,
PicturePtr dest,
int nrect, glamor_composite_rect_t * rects)
int nrect,
glamor_composite_rect_t * rects)
{
ScreenPtr screen = dest->pDrawable->pScreen;
glamor_screen_private *glamor_priv =
@ -959,6 +989,7 @@ glamor_composite_with_shader(CARD8 op,
enum glamor_pixmap_status mask_status = GLAMOR_NONE;
PictFormatShort saved_source_format = 0;
float src_matrix[9], mask_matrix[9];
float *psrc_matrix = NULL, *pmask_matrix = NULL;
GLfloat source_solid_color[4], mask_solid_color[4];
int vert_stride = 4;
int nrect_max;
@ -970,20 +1001,23 @@ glamor_composite_with_shader(CARD8 op,
goto fail;
}
memset(&key, 0, sizeof(key));
if (!source->pDrawable) {
if (source->pSourcePict->type == SourcePictTypeSolidFill) {
key.source = SHADER_SOURCE_SOLID;
glamor_get_rgba_from_pixel(source->
pSourcePict->solidFill.
color,
&source_solid_color[0],
&source_solid_color[1],
&source_solid_color[2],
&source_solid_color[3],
PICT_a8r8g8b8);
} else {
glamor_fallback("gradient source\n");
goto fail;
if (!source) {
key.source = SHADER_SOURCE_SOLID;
source_solid_color[0] = 0.0;
source_solid_color[1] = 0.0;
source_solid_color[2] = 0.0;
source_solid_color[3] = 0.0;
} else if (!source->pDrawable) {
if (source->pSourcePict->type == SourcePictTypeSolidFill) {
key.source = SHADER_SOURCE_SOLID;
glamor_get_rgba_from_pixel(source->
pSourcePict->solidFill.
color,
&source_solid_color[0],
&source_solid_color[1],
&source_solid_color[2],
&source_solid_color[3],
PICT_a8r8g8b8);
}
} else {
key.source = SHADER_SOURCE_TEXTURE_ALPHA;
@ -999,9 +1033,6 @@ glamor_composite_with_shader(CARD8 op,
&mask_solid_color[1],
&mask_solid_color[2],
&mask_solid_color[3], PICT_a8r8g8b8);
} else {
glamor_fallback("gradient mask\n");
goto fail;
}
} else {
key.mask = SHADER_MASK_TEXTURE_ALPHA;
@ -1029,7 +1060,7 @@ glamor_composite_with_shader(CARD8 op,
key.in = SHADER_IN_SOURCE_ONLY;
}
if (source->alphaMap) {
if (source && source->alphaMap) {
glamor_fallback("source alphaMap\n");
goto fail;
}
@ -1044,13 +1075,14 @@ glamor_composite_with_shader(CARD8 op,
source_pixmap_priv =
glamor_get_pixmap_private(source_pixmap);
if (source_pixmap == dest_pixmap) {
/* XXX source and the dest share the same texture.
* Does it need special handle? */
glamor_fallback("source == dest\n");
goto fail;
}
if (!source_pixmap_priv || source_pixmap_priv->base.gl_fbo == 0) {
/* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex
if (source_pixmap_priv->base.gl_fbo == 0) {
/* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex
* equal to zero when the pixmap is screen pixmap. Then we may
* refer the tex zero directly latter in the composition.
* refer the tex zero directly latter in the composition.
* It seems that it works fine, but it may have potential problem*/
#ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
source_status = GLAMOR_UPLOAD_PENDING;
@ -1068,7 +1100,7 @@ glamor_composite_with_shader(CARD8 op,
glamor_fallback("mask == dest\n");
goto fail;
}
if (!mask_pixmap_priv || mask_pixmap_priv->base.gl_fbo == 0) {
if (mask_pixmap_priv->base.gl_fbo == 0) {
#ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
mask_status = GLAMOR_UPLOAD_PENDING;
#else
@ -1095,20 +1127,20 @@ glamor_composite_with_shader(CARD8 op,
}
if (source->format != saved_source_format) {
glamor_picture_format_fixup(source,
source_pixmap_priv);
//glamor_picture_format_fixup(source,
// source_pixmap_priv);
}
/* XXX
/* XXX
* By default, glamor_upload_picture_to_texture will wire alpha to 1
* if one picture doesn't have alpha. So we don't do that again in
* if one picture doesn't have alpha. So we don't do that again in
* rendering function. But here is a special case, as source and
* mask share the same texture but may have different formats. For
* mask share the same texture but may have different formats. For
* example, source doesn't have alpha, but mask has alpha. Then the
* texture will have the alpha value for the mask. And will not wire
* to 1 for the source. In this case, we have to use different shader
* to wire the source's alpha to 1.
*
* But this may cause a potential problem if the source's repeat mode
* But this may cause a potential problem if the source's repeat mode
* is REPEAT_NONE, and if the source is smaller than the dest, then
* for the region not covered by the source may be painted incorrectly.
* because we wire the alpha to 1.
@ -1156,13 +1188,15 @@ glamor_composite_with_shader(CARD8 op,
* transformed source and mask, if the transform is not int translate. */
if (key.source != SHADER_SOURCE_SOLID
&& source->transform
&& !pixman_transform_is_int_translate(source->transform)) {
&& !pixman_transform_is_int_translate(source->transform)
&& source_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) {
if (!glamor_fixup_pixmap_priv(screen, source_pixmap_priv))
goto fail;
}
if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID
&& mask->transform
&& !pixman_transform_is_int_translate(mask->transform)) {
&& !pixman_transform_is_int_translate(mask->transform)
&& mask_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) {
if (!glamor_fixup_pixmap_priv(screen, mask_pixmap_priv))
goto fail;
}
@ -1217,7 +1251,10 @@ glamor_composite_with_shader(CARD8 op,
&source_y_off);
pixmap_priv_get_scale(source_pixmap_priv, &src_xscale,
&src_yscale);
glamor_picture_get_matrixf(source, src_matrix);
if (source->transform) {
psrc_matrix = src_matrix;
glamor_picture_get_matrixf(source, psrc_matrix);
}
vert_stride += 4;
}
@ -1226,7 +1263,10 @@ glamor_composite_with_shader(CARD8 op,
&mask_x_off, &mask_y_off);
pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale,
&mask_yscale);
glamor_picture_get_matrixf(mask, mask_matrix);
if (mask->transform) {
pmask_matrix = mask_matrix;
glamor_picture_get_matrixf(mask, pmask_matrix);
}
vert_stride += 4;
}
@ -1252,13 +1292,16 @@ glamor_composite_with_shader(CARD8 op,
x_dest = rects->x_dst + dest_x_off;
y_dest = rects->y_dst + dest_y_off;
x_source = rects->x_src + source_x_off;;
x_source = rects->x_src + source_x_off;
y_source = rects->y_src + source_y_off;
x_mask = rects->x_mask + mask_x_off;
y_mask = rects->y_mask + mask_y_off;
width = rects->width;
height = rects->height;
DEBUGF("dest(%d,%d) source(%d %d) mask (%d %d), width %d height %d \n",
x_dest, y_dest, x_source, y_source,x_mask,y_mask,width,height);
glamor_set_normalize_vcoords(dest_pixmap_priv, dst_xscale,
dst_yscale,
x_dest, y_dest,
@ -1266,41 +1309,21 @@ glamor_composite_with_shader(CARD8 op,
glamor_priv->yInverted,
vertices);
if (key.source != SHADER_SOURCE_SOLID) {
if (source->transform)
glamor_set_transformed_normalize_tcoords
(source_pixmap_priv, src_matrix, src_xscale,
src_yscale, x_source, y_source,
x_source + width, y_source + height,
glamor_priv->yInverted,
source_texcoords);
else
glamor_set_normalize_tcoords
(source_pixmap_priv, src_xscale, src_yscale,
x_source, y_source,
x_source + width, y_source + height,
glamor_priv->yInverted,
source_texcoords);
}
if (key.source != SHADER_SOURCE_SOLID)
glamor_set_normalize_tcoords_generic(
source_pixmap_priv, source->repeatType, psrc_matrix,
src_xscale, src_yscale, x_source, y_source,
x_source + width, y_source + height,
glamor_priv->yInverted, source_texcoords);
if (key.mask != SHADER_MASK_NONE
&& key.mask != SHADER_MASK_SOLID) {
if (mask->transform)
glamor_set_transformed_normalize_tcoords
(mask_pixmap_priv, mask_matrix,
mask_xscale,
mask_yscale, x_mask, y_mask,
x_mask + width, y_mask + height,
glamor_priv->yInverted,
mask_texcoords);
else
glamor_set_normalize_tcoords
(mask_pixmap_priv, mask_xscale,
mask_yscale, x_mask, y_mask,
x_mask + width, y_mask + height,
glamor_priv->yInverted,
mask_texcoords);
}
&& key.mask != SHADER_MASK_SOLID)
glamor_set_normalize_tcoords_generic(
mask_pixmap_priv, mask->repeatType, pmask_matrix,
mask_xscale, mask_yscale, x_mask, y_mask,
x_mask + width, y_mask + height,
glamor_priv->yInverted, mask_texcoords);
glamor_emit_composite_rect(screen,
source_texcoords,
mask_texcoords,
@ -1323,6 +1346,7 @@ glamor_composite_with_shader(CARD8 op,
dispatch->glActiveTexture(GL_TEXTURE1);
dispatch->glDisable(GL_TEXTURE_2D);
#endif
DEBUGF("finish rendering.\n");
dispatch->glUseProgram(0);
if (saved_source_format)
source->format = saved_source_format;
@ -1398,17 +1422,18 @@ glamor_convert_gradient_picture(ScreenPtr screen,
return dst;
}
static Bool
_glamor_composite(CARD8 op,
PicturePtr source,
PicturePtr mask,
PicturePtr dest,
INT16 x_source,
INT16 y_source,
INT16 x_mask,
INT16 y_mask,
INT16 x_dest, INT16 y_dest,
CARD16 width, CARD16 height, Bool fallback)
Bool
glamor_composite_clipped_region(CARD8 op,
PicturePtr source,
PicturePtr mask,
PicturePtr dest,
RegionPtr region,
int x_source,
int y_source,
int x_mask,
int y_mask,
int x_dest,
int y_dest)
{
ScreenPtr screen = dest->pDrawable->pScreen;
glamor_pixmap_private *dest_pixmap_priv;
@ -1419,80 +1444,63 @@ _glamor_composite(CARD8 op,
PixmapPtr source_pixmap = NULL, mask_pixmap = NULL;
PicturePtr temp_src = source, temp_mask = mask;
int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask;
BoxPtr extent;
glamor_composite_rect_t rect[10];
glamor_composite_rect_t *prect = rect;
int prect_size = ARRAY_SIZE(rect);
glamor_screen_private *glamor_priv =
glamor_get_screen_private(screen);
Bool ret = TRUE;
RegionRec region;
int ok = FALSE;
int i;
int width;
int height;
BoxPtr box;
int nbox, i, ok = FALSE;
PixmapPtr sub_dest_pixmap = NULL;
PixmapPtr sub_source_pixmap = NULL;
PixmapPtr sub_mask_pixmap = NULL;
int dest_x_off, dest_y_off, saved_dest_x = 0, saved_dest_y = 0;
int source_x_off, source_y_off, saved_source_x = 0, saved_source_y = 0;
int mask_x_off, mask_y_off, saved_mask_x = 0, saved_mask_y = 0;
DrawablePtr saved_dest_drawable = NULL;
DrawablePtr saved_source_drawable = NULL;
DrawablePtr saved_mask_drawable = NULL;
int nbox;
extent = RegionExtents(region);
box = RegionRects(region);
nbox = RegionNumRects(region);
width = extent->x2 - extent->x1;
height = extent->y2 - extent->y1;
x_temp_src = x_source;
y_temp_src = y_source;
x_temp_mask = x_mask;
y_temp_mask = y_mask;
DEBUGF("Composite Src: (%d, %d)\n"
" Mask: (%d, %d)\n"
" to dst: (%d, %d), size: %d X %d \n",
x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height);
DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n",
x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height);
DEBUGF("dest pixmap %p ", dest_pixmap);
dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
/* Currently. Always fallback to cpu if destination is in CPU memory. */
if (source->pDrawable) {
if (source && source->pDrawable) {
source_pixmap = glamor_get_drawable_pixmap(source->pDrawable);
source_pixmap_priv = glamor_get_pixmap_private(source_pixmap);
if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY)
goto fail;
}
if (mask && mask->pDrawable) {
mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable);
mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap);
if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY)
goto fail;
}
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) {
goto fail;
}
if (op >= ARRAY_SIZE(composite_op_info))
goto fail;
if ((!source->pDrawable
/* XXX is it possible source mask have non-zero drawable.x/y? */
if (source
&& ((!source->pDrawable
&& (source->pSourcePict->type != SourcePictTypeSolidFill))
|| (source->pDrawable
&& !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv)
&&
((width * height * 4 <
(source_pixmap->drawable.width *
source_pixmap->drawable.height))
||
!(glamor_check_fbo_size
(glamor_priv, source_pixmap->drawable.width,
source_pixmap->drawable.height))))) {
&& (source_pixmap->drawable.width != width
|| source_pixmap->drawable.height != height)))) {
temp_src =
glamor_convert_gradient_picture(screen, source,
x_source, y_source,
extent->x1 + x_source - x_dest,
extent->y1 + y_source - y_dest,
width, height);
if (!temp_src) {
temp_src = source;
goto fail;
goto out;
}
x_temp_src = y_temp_src = 0;
x_temp_src = - extent->x1 + x_dest;
y_temp_src = - extent->y1 + y_dest;
}
if (mask
@ -1500,26 +1508,22 @@ _glamor_composite(CARD8 op,
((!mask->pDrawable
&& (mask->pSourcePict->type != SourcePictTypeSolidFill))
|| (mask->pDrawable
&& (!GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv))
&&
((width * height * 4 <
(mask_pixmap->drawable.width *
mask_pixmap->drawable.height))
||
!(glamor_check_fbo_size
(glamor_priv, mask_pixmap->drawable.width,
mask_pixmap->drawable.height)))))) {
&& !GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)
&& (mask_pixmap->drawable.width != width
|| mask_pixmap->drawable.height != height)))) {
/* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity
* to do reduce one convertion. */
temp_mask =
glamor_convert_gradient_picture(screen, mask,
x_mask, y_mask,
extent->x1 + x_mask - x_dest,
extent->y1 + y_mask - y_dest,
width, height);
if (!temp_mask) {
temp_mask = mask;
goto fail;
goto out;
}
x_temp_mask = y_temp_mask = 0;
x_temp_mask = - extent->x1 + x_dest;
y_temp_mask = - extent->y1 + y_dest;
}
/* Do two-pass PictOpOver componentAlpha, until we enable
* dual source color blending.
@ -1527,43 +1531,38 @@ _glamor_composite(CARD8 op,
if (mask && mask->componentAlpha) {
if (op == PictOpOver) {
glamor_composite(PictOpOutReverse,
temp_src, temp_mask, dest,
x_temp_src, y_temp_src,
x_temp_mask, y_temp_mask,
x_dest, y_dest, width, height);
glamor_composite(PictOpAdd,
temp_src, temp_mask, dest,
x_temp_src, y_temp_src,
x_temp_mask, y_temp_mask,
x_dest, y_dest, width, height);
goto done;
glamor_composite_clipped_region(PictOpOutReverse,
temp_src, temp_mask, dest,
region,
x_temp_src, y_temp_src,
x_temp_mask, y_temp_mask,
x_dest, y_dest);
} else if (op == PictOpAtop
|| op == PictOpAtopReverse
|| op == PictOpXor
|| op >= PictOpSaturate) {
glamor_fallback
("glamor_composite(): component alpha op %x\n", op);
goto fail;
glamor_composite_clipped_region(PictOpAdd,
temp_src, temp_mask, dest,
region,
x_temp_src, y_temp_src,
x_temp_mask, y_temp_mask,
x_dest, y_dest);
ok = TRUE;
goto out;
}
}
if (!mask) {
if (!mask && temp_src) {
if (glamor_composite_with_copy(op, temp_src, dest,
x_temp_src, y_temp_src,
x_dest, y_dest, width,
height))
goto done;
x_dest, y_dest, region)) {
ok = TRUE;
goto out;
}
}
/*XXXXX, maybe we can make a copy of dest pixmap.*/
if (source_pixmap == dest_pixmap)
goto full_fallback;
/*XXXXX, self copy?*/
x_dest += dest->pDrawable->x;
y_dest += dest->pDrawable->y;
if (temp_src->pDrawable) {
if (temp_src && temp_src->pDrawable) {
x_temp_src += temp_src->pDrawable->x;
y_temp_src += temp_src->pDrawable->y;
}
@ -1571,16 +1570,6 @@ _glamor_composite(CARD8 op,
x_temp_mask += temp_mask->pDrawable->x;
y_temp_mask += temp_mask->pDrawable->y;
}
if (!miComputeCompositeRegion(&region,
temp_src, temp_mask, dest,
x_temp_src, y_temp_src,
x_temp_mask, y_temp_mask,
x_dest, y_dest, width,
height))
goto done;
box = REGION_RECTS(&region);
nbox = REGION_NUM_RECTS(&region);
if (nbox > ARRAY_SIZE(rect)) {
prect = calloc(nbox, sizeof(*prect));
@ -1612,15 +1601,153 @@ _glamor_composite(CARD8 op,
box += box_cnt;
}
if (prect != rect)
free(prect);
out:
if (temp_src != source)
FreePicture(temp_src, 0);
if (temp_mask != mask)
FreePicture(temp_mask, 0);
return ok;
}
static Bool
_glamor_composite(CARD8 op,
PicturePtr source,
PicturePtr mask,
PicturePtr dest,
INT16 x_source,
INT16 y_source,
INT16 x_mask,
INT16 y_mask,
INT16 x_dest, INT16 y_dest,
CARD16 width, CARD16 height, Bool fallback)
{
ScreenPtr screen = dest->pDrawable->pScreen;
glamor_pixmap_private *dest_pixmap_priv;
glamor_pixmap_private *source_pixmap_priv =
NULL, *mask_pixmap_priv = NULL;
PixmapPtr dest_pixmap =
glamor_get_drawable_pixmap(dest->pDrawable);
PixmapPtr source_pixmap = NULL, mask_pixmap = NULL;
glamor_screen_private *glamor_priv =
glamor_get_screen_private(screen);
Bool ret = TRUE;
RegionRec region;
BoxPtr box, extent;
int nbox, ok = FALSE;
PixmapPtr sub_dest_pixmap = NULL;
PixmapPtr sub_source_pixmap = NULL;
PixmapPtr sub_mask_pixmap = NULL;
int dest_x_off, dest_y_off, saved_dest_x, saved_dest_y;
int source_x_off, source_y_off, saved_source_x, saved_source_y;
int mask_x_off, mask_y_off, saved_mask_x, saved_mask_y;
DrawablePtr saved_dest_drawable;
DrawablePtr saved_source_drawable;
DrawablePtr saved_mask_drawable;
int force_clip = 0;
dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
if (source->pDrawable) {
source_pixmap = glamor_get_drawable_pixmap(source->pDrawable);
source_pixmap_priv = glamor_get_pixmap_private(source_pixmap);
if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY)
goto fail;
}
if (mask && mask->pDrawable) {
mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable);
mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap);
if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY)
goto fail;
}
DEBUGF("source pixmap %p (%d %d) mask(%d %d) dest(%d %d) width %d height %d \n",
source_pixmap, x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) {
goto fail;
}
if (op >= ARRAY_SIZE(composite_op_info))
goto fail;
if (mask && mask->componentAlpha) {
if (op == PictOpAtop
|| op == PictOpAtopReverse
|| op == PictOpXor
|| op >= PictOpSaturate) {
glamor_fallback
("glamor_composite(): component alpha op %x\n", op);
goto fail;
}
}
if (!miComputeCompositeRegion(&region,
source, mask, dest,
x_source + (source_pixmap ? source->pDrawable->x : 0),
y_source + (source_pixmap ? source->pDrawable->y : 0),
x_mask + (mask_pixmap ? mask->pDrawable->x : 0),
y_mask + (mask_pixmap ? mask->pDrawable->y : 0),
x_dest + dest->pDrawable->x,
y_dest + dest->pDrawable->y,
width,
height)) {
ret = TRUE;
goto done;
}
box = REGION_RECTS(&region);
nbox = REGION_NUM_RECTS(&region);
DEBUGF("first clipped when compositing.\n");
DEBUGRegionPrint(&region);
extent = RegionExtents(&region);
if (nbox == 0) {
ret = TRUE;
goto done;
}
/* If destination is not a large pixmap, but the region is larger
* than texture size limitation, and source or mask is memory pixmap,
* then there may be need to load a large memory pixmap to a
* texture, and this is not permitted. Then we force to clip the
* destination and make sure latter will not upload a large memory
* pixmap. */
if (!glamor_check_fbo_size(glamor_priv,
extent->x2 - extent->x1, extent->y2 - extent->y1)
&& (dest_pixmap_priv->type != GLAMOR_TEXTURE_LARGE)
&& ((source_pixmap_priv
&& source_pixmap_priv->type == GLAMOR_MEMORY)
|| (mask_pixmap_priv
&& mask_pixmap_priv->type == GLAMOR_MEMORY)
|| (!source_pixmap_priv
&& (source->pSourcePict->type != SourcePictTypeSolidFill))
|| (!mask_pixmap_priv && mask
&& mask->pSourcePict->type != SourcePictTypeSolidFill)))
force_clip = 1;
if (force_clip || dest_pixmap_priv->type == GLAMOR_TEXTURE_LARGE
|| (source_pixmap_priv
&& source_pixmap_priv->type == GLAMOR_TEXTURE_LARGE)
|| (mask_pixmap_priv
&& mask_pixmap_priv->type == GLAMOR_TEXTURE_LARGE))
goto fail;
else
ok = glamor_composite_clipped_region(op, source,
mask, dest, &region,
x_source, y_source,
x_mask, y_mask,
x_dest, y_dest);
REGION_UNINIT(dest->pDrawable->pScreen, &region);
if (ok)
goto done;
fail:
if (!fallback
&& glamor_ddx_fallback_check_pixmap(&dest_pixmap->drawable)
&& (!source_pixmap
&& (!source_pixmap
|| glamor_ddx_fallback_check_pixmap(&source_pixmap->drawable))
&& (!mask_pixmap
|| glamor_ddx_fallback_check_pixmap(&mask_pixmap->drawable))) {
@ -1662,13 +1789,11 @@ fail:
x_ ##p = 0; \
y_ ##p = 0; \
} } while(0)
GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
if (source->pDrawable)
if (source->pDrawable && !source->transform)
GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO);
if (mask && mask->pDrawable)
if (mask && mask->pDrawable && !mask->transform)
GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO);
full_fallback:
if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) {
if (source_pixmap == dest_pixmap || glamor_prepare_access_picture
@ -1711,12 +1836,6 @@ full_fallback:
PUT_SUB_PICTURE(source, GLAMOR_ACCESS_RO);
PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
done:
if (temp_src != source)
FreePicture(temp_src, 0);
if (temp_mask != mask)
FreePicture(temp_mask, 0);
if (prect != rect)
free(prect);
return ret;
}
@ -1754,9 +1873,6 @@ glamor_composite_nf(CARD8 op,
FALSE);
}
/**
* Creates an appropriate picture to upload our alpha mask into (which
* we calculated in system memory)
@ -1797,7 +1913,7 @@ glamor_create_mask_picture(ScreenPtr screen,
* glamor_trapezoids is a copy of miTrapezoids that does all the trapezoid
* accumulation in system memory.
*/
static Bool
static Bool
_glamor_trapezoids(CARD8 op,
PicturePtr src, PicturePtr dst,
PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
@ -1885,7 +2001,7 @@ glamor_trapezoids(CARD8 op,
PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
int ntrap, xTrapezoid * traps)
{
_glamor_trapezoids(op, src, dst, mask_format, x_src,
_glamor_trapezoids(op, src, dst, mask_format, x_src,
y_src, ntrap, traps, TRUE);
}
@ -1895,7 +2011,7 @@ glamor_trapezoids_nf(CARD8 op,
PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
int ntrap, xTrapezoid * traps)
{
return _glamor_trapezoids(op, src, dst, mask_format, x_src,
return _glamor_trapezoids(op, src, dst, mask_format, x_src,
y_src, ntrap, traps, FALSE);
}
@ -1912,8 +2028,12 @@ glamor_composite_glyph_rects(CARD8 op,
ValidatePicture(src);
ValidatePicture(dst);
if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects))
return;
if (!(glamor_is_large_picture(src)
|| (mask && glamor_is_large_picture(mask))
|| glamor_is_large_picture(dst))) {
if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects))
return;
}
n = nrect;
r = rects;

View File

@ -102,10 +102,9 @@ glamor_fini_tile_shader(ScreenPtr screen)
glamor_put_dispatch(glamor_priv);
}
Bool
glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
static void
_glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
int x, int y, int width, int height,
unsigned char alu, unsigned long planemask,
int tile_x, int tile_y)
{
ScreenPtr screen = pixmap->drawable.pScreen;
@ -126,48 +125,17 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
glamor_pixmap_private *src_pixmap_priv;
glamor_pixmap_private *dst_pixmap_priv;
float wh[2];
src_pixmap_priv = glamor_get_pixmap_private(tile);
dst_pixmap_priv = glamor_get_pixmap_private(pixmap);
if (src_pixmap_priv == NULL || dst_pixmap_priv == NULL)
goto fail;
if (glamor_priv->tile_prog == 0) {
glamor_fallback("Tiling unsupported\n");
goto fail;
}
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) {
glamor_fallback("dest has no fbo.\n");
goto fail;
}
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) {
/* XXX dynamic uploading candidate. */
glamor_fallback("Non-texture tile pixmap\n");
goto fail;
}
if (!glamor_set_planemask(pixmap, planemask)) {
glamor_fallback("unsupported planemask %lx\n", planemask);
goto fail;
}
glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale);
dispatch = glamor_get_dispatch(glamor_priv);
if (!glamor_set_alu(dispatch, alu)) {
glamor_put_dispatch(glamor_priv);
goto fail;
}
pixmap_priv_get_scale(src_pixmap_priv, &src_xscale,
&src_yscale);
dispatch = glamor_get_dispatch(glamor_priv);
dispatch->glUseProgram(glamor_priv->tile_prog);
glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv);
dispatch->glUniform2fv(glamor_priv->tile_wh, 1, wh);
dispatch->glActiveTexture(GL_TEXTURE0);
dispatch->glBindTexture(GL_TEXTURE_2D,
@ -185,21 +153,23 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
#ifndef GLAMOR_GLES2
dispatch->glEnable(GL_TEXTURE_2D);
#endif
glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale,
src_yscale,
tile_x1, tile_y1,
tile_x2, tile_y2,
glamor_priv->yInverted,
source_texcoords);
glamor_set_repeat_normalize_tcoords
(src_pixmap_priv, RepeatNormal,
src_xscale, src_yscale,
tile_x1, tile_y1,
tile_x2, tile_y2,
glamor_priv->yInverted,
source_texcoords);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
GL_FLOAT, GL_FALSE,
2 * sizeof(float),
source_texcoords);
dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale,
dst_yscale,
x1, y1, x2, y2,
glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, dst_yscale,
x1, y1,
x2, y2,
glamor_priv->yInverted, vertices);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
@ -214,11 +184,139 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
#endif
dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
dispatch->glUseProgram(0);
glamor_put_dispatch(glamor_priv);
}
Bool
glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
int x, int y, int width, int height,
unsigned char alu, unsigned long planemask,
int tile_x, int tile_y)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv =
glamor_get_screen_private(screen);
glamor_pixmap_private *dst_pixmap_priv;
glamor_pixmap_private *src_pixmap_priv;
glamor_gl_dispatch *dispatch;
dst_pixmap_priv = glamor_get_pixmap_private(pixmap);
src_pixmap_priv = glamor_get_pixmap_private(tile);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv))
return FALSE;
if (glamor_priv->tile_prog == 0) {
glamor_fallback("Tiling unsupported\n");
goto fail;
}
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) {
/* XXX dynamic uploading candidate. */
glamor_fallback("Non-texture tile pixmap\n");
goto fail;
}
if (!glamor_set_planemask(pixmap, planemask)) {
glamor_fallback("unsupported planemask %lx\n", planemask);
goto fail;
}
dispatch = glamor_get_dispatch(glamor_priv);
if (!glamor_set_alu(dispatch, alu)) {
glamor_fallback("unsupported alu %x\n", alu);
glamor_put_dispatch(glamor_priv);
goto fail;
}
if (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, k;
BoxRec box;
RegionRec region;
box.x1 = x;
box.y1 = y;
box.x2 = x + width;
box.y2 = y + height;
RegionInitBoxes(&region, &box, 1);
clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv,
&region, &n_dst_region, 0);
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);
if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
RegionTranslate(clipped_dst_regions[i].region,
tile_x - x, tile_y - y);
DEBUGF("tiled a large src pixmap. %dx%d \n", tile->drawable.width, tile->drawable.height);
clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv,
clipped_dst_regions[i].region,
&n_src_region, 1);
DEBUGF("got %d src regions %d \n", n_src_region);
for (j = 0; j < n_src_region; j++)
{
SET_PIXMAP_FBO_CURRENT(src_pixmap_priv, clipped_src_regions[j].block_idx);
RegionTranslate(clipped_src_regions[j].region,
x - tile_x,
y - tile_y);
current_boxes = RegionRects(clipped_src_regions[j].region);
n_current_boxes = RegionNumRects(clipped_src_regions[j].region);
for(k = 0; k < n_current_boxes; k++)
{
DEBUGF("Tile on %d %d %d %d dst block id %d tile block id %d tilex %d tiley %d\n",
current_boxes[k].x1, current_boxes[k].y1,
current_boxes[k].x2 - current_boxes[k].x1,
current_boxes[k].y2 - current_boxes[k].y1,
clipped_dst_regions[i].block_idx,
clipped_src_regions[j].block_idx,
(tile_x + (current_boxes[k].x1 - x)),
tile_y + (current_boxes[k].y1 - y));
_glamor_tile(pixmap, tile,
current_boxes[k].x1, current_boxes[k].y1,
current_boxes[k].x2 - current_boxes[k].x1,
current_boxes[k].y2 - current_boxes[k].y1,
(tile_x + (current_boxes[k].x1 - x)),
(tile_y + (current_boxes[k].y1 - y)));
}
RegionDestroy(clipped_src_regions[j].region);
}
free(clipped_src_regions);
} else {
current_boxes = RegionRects(clipped_dst_regions[i].region);
n_current_boxes = RegionNumRects(clipped_dst_regions[i].region);
for(k = 0; k < n_current_boxes; k++)
{
_glamor_tile(pixmap, tile,
current_boxes[k].x1, current_boxes[k].y1,
current_boxes[k].x2 - current_boxes[k].x1,
current_boxes[k].y2 - current_boxes[k].y1,
(tile_x + (current_boxes[k].x1 - x)),
(tile_y + (current_boxes[k].y1 - y)));
}
}
RegionDestroy(clipped_dst_regions[i].region);
}
free(clipped_dst_regions);
RegionUninit(&region);
}
else
_glamor_tile(pixmap, tile, x, y, width, height, tile_x, tile_y);
glamor_set_alu(dispatch, GXcopy);
glamor_set_planemask(pixmap, ~0);
glamor_put_dispatch(glamor_priv);
return TRUE;
fail:
fail:
return FALSE;
}

View File

@ -41,8 +41,10 @@
#define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \
do { \
*(_pxscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.width; \
*(_pyscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.height; \
int w,h; \
PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, w, h); \
*(_pxscale_) = 1.0 / w; \
*(_pyscale_) = 1.0 / h; \
} while(0)
#define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \
@ -106,6 +108,52 @@
} \
} while(0)
#define _glamor_get_repeat_coords(priv, repeat_type, tx1, \
ty1, tx2, ty2, \
_x1_, _y1_, _x2_, \
_y2_, c, d, odd_x, odd_y) \
do { \
if (repeat_type == RepeatReflect) { \
assert(0); \
} else if (repeat_type == RepeatNormal) { \
tx1 = (c - priv->box.x1); \
ty1 = (d - priv->box.y1); \
tx2 = tx1 + ((_x2_) - (_x1_)); \
ty2 = ty1 + ((_y2_) - (_y1_)); \
} else { \
assert(0); \
} \
} while(0)
/* _x1_ ... _y2_ must be integer. */
#define glamor_get_repeat_coords(priv, repeat_type, tx1, \
ty1, tx2, ty2, _x1_, _y1_, _x2_, \
_y2_) \
do { \
int c, d; \
int odd_x = 0, odd_y = 0; \
DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n", \
(priv)->base.pixmap->drawable.width, \
priv->box.x1, priv->box.x2, \
priv->box.y1, priv->box.y2); \
modulus((_x1_), (priv)->base.pixmap->drawable.width, c); \
modulus((_y1_), (priv)->base.pixmap->drawable.height, d); \
DEBUGF("c %d d %d \n", c, d); \
if (repeat_type == RepeatReflect) { \
odd_x = abs((_x1_ - c) \
/ (priv->base.pixmap->drawable.width)) & 1; \
odd_y = abs((_y1_ - d) \
/ (priv->base.pixmap->drawable.height)) & 1; \
} \
_glamor_get_repeat_coords(priv, repeat_type, tx1, ty1, tx2, ty2,\
_x1_, _y1_, _x2_, _y2_, c, d, \
odd_x, odd_y); \
} while(0)
#define glamor_transform_point(matrix, tx, ty, x, y) \
do { \
int i; \
@ -213,6 +261,24 @@
tx2, ty2, yInverted, vertices); \
} while(0)
#define glamor_set_repeat_normalize_tcoords(priv, repeat_type, \
xscale, yscale, \
_x1_, _y1_, _x2_, _y2_, \
yInverted, vertices) \
do { \
float tx1, tx2, ty1, ty2; \
if (priv->type == GLAMOR_TEXTURE_LARGE) \
glamor_get_repeat_coords((&priv->large), repeat_type, \
tx1, ty1, tx2, ty2, \
_x1_, _y1_, _x2_, _y2_); \
else { \
tx1 = _x1_; tx2 = _x2_; ty1 = _y1_; ty2 = _y2_; \
} \
_glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \
tx2, ty2, yInverted, vertices); \
} while(0)
#define glamor_set_tcoords(width, height, x1, y1, x2, y2, \
yInverted, vertices) \
do { \
@ -303,7 +369,7 @@ glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox)
}
inline static void
glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy)
glamor_translate_boxes(BoxPtr boxes, int nbox, int dx, int dy)
{
int i;
for (i = 0; i < nbox; i++) {