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_glyphblt.c\
glamor_polyops.c\ glamor_polyops.c\
glamor_pixmap.c\ glamor_pixmap.c\
glamor_largepixmap.c\
glamor_picture.c\ glamor_picture.c\
glamor_window.c\ glamor_window.c\
glamor_gl_dispatch.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) if (w > 32767 || h > 32767)
return NullPixmap; return NullPixmap;
if (usage == GLAMOR_CREATE_PIXMAP_CPU if ((usage == GLAMOR_CREATE_PIXMAP_CPU
|| (w == 0 && h == 0) || (w == 0 && h == 0)
|| !glamor_check_pixmap_fbo_depth(depth)) || !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); return fbCreatePixmap(screen, w, h, depth, usage);
else else
pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); 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.pixmap = pixmap;
pixmap_priv->base.glamor_priv = glamor_priv; pixmap_priv->base.glamor_priv = glamor_priv;
pixmap_priv->type = type;
gl_iformat_for_depth(depth, &format); 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) { if (fbo == NULL) {
fbDestroyPixmap(pixmap); fbDestroyPixmap(pixmap);
@ -174,8 +190,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
glamor_pixmap_attach_fbo(pixmap, fbo); 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; return pixmap;
} }
@ -186,13 +200,8 @@ glamor_destroy_textured_pixmap(PixmapPtr pixmap)
glamor_pixmap_private *pixmap_priv; glamor_pixmap_private *pixmap_priv;
pixmap_priv = glamor_get_pixmap_private(pixmap); pixmap_priv = glamor_get_pixmap_private(pixmap);
if (pixmap_priv != NULL) { if (pixmap_priv != NULL)
glamor_pixmap_fbo *fbo; glamor_pixmap_destroy_fbo(pixmap_priv);
fbo = glamor_pixmap_detach_fbo(pixmap_priv);
if (fbo)
glamor_destroy_fbo(fbo);
free(pixmap_priv);
}
} }
} }
@ -315,6 +324,9 @@ glamor_init(ScreenPtr screen, unsigned int flags)
glamor_gl_has_extension("GL_EXT_framebuffer_blit"); glamor_gl_has_extension("GL_EXT_framebuffer_blit");
glamor_priv->_dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, glamor_priv->_dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE,
&glamor_priv->max_fbo_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); 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; ScreenPtr screen = dst->pScreen;
PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); 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_screen_private *glamor_priv =
glamor_get_screen_private(screen); glamor_get_screen_private(screen);
glamor_gl_dispatch *dispatch; glamor_gl_dispatch *dispatch;
int dst_x_off, dst_y_off, src_x_off, src_y_off, i; 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) { if (!glamor_priv->has_fbo_blit) {
glamor_delayed_fallback(screen, glamor_delayed_fallback(screen,
@ -52,17 +54,13 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
return FALSE; return FALSE;
} }
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
if (gc) { if (gc) {
if (gc->alu != GXcopy) { if (gc->alu != GXcopy) {
glamor_delayed_fallback(screen, "non-copy ALU\n"); glamor_delayed_fallback(screen, "non-copy ALU\n");
return FALSE; 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)) { 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)) if (glamor_set_destination_pixmap(dst_pixmap))
return FALSE; 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 = glamor_get_dispatch(glamor_priv);
dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT,
src_pixmap_priv->base.fbo->fb); src_pixmap_priv->base.fbo->fb);
@ -80,7 +81,10 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
&dst_y_off); &dst_y_off);
glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, glamor_get_drawable_deltas(src, src_pixmap, &src_x_off,
&src_y_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++) { for (i = 0; i < nbox; i++) {
if (glamor_priv->yInverted) { 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; int src_x_off, src_y_off, dst_x_off, dst_y_off;
enum glamor_pixmap_status src_status = GLAMOR_NONE; enum glamor_pixmap_status src_status = GLAMOR_NONE;
GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale;
int alu = GXcopy;
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { if (!src_pixmap_priv->base.gl_fbo) {
glamor_delayed_fallback(dst->pScreen, "dst has no fbo.\n");
return FALSE;
}
if (!src_pixmap_priv || !src_pixmap_priv->base.gl_fbo) {
#ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n");
return FALSE; return FALSE;
@ -177,11 +175,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
#endif #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_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale);
pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_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); 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); glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, 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++) { for (i = 0; i < nbox; i++) {
glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, glamor_set_normalize_vcoords(dst_pixmap_priv,
dst_yscale, dst_xscale, dst_yscale,
box[i].x1 + dst_x_off, box[i].x1 + dst_x_off,
box[i].y1 + dst_y_off, box[i].y1 + dst_y_off,
box[i].x2 + dst_x_off, box[i].x2 + dst_x_off,
@ -248,7 +237,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
glamor_priv->yInverted, glamor_priv->yInverted,
vertices); vertices);
glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale, glamor_set_normalize_tcoords(src_pixmap_priv,
src_xscale,
src_yscale, src_yscale,
box[i].x1 + dx, box[i].x1 + dx,
box[i].y1 + dy, box[i].y1 + dy,
@ -271,18 +261,17 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
} }
static Bool static Bool
_glamor_copy_n_to_n(DrawablePtr src, __glamor_copy_n_to_n(DrawablePtr src,
DrawablePtr dst, DrawablePtr dst,
GCPtr gc, GCPtr gc,
BoxPtr box, BoxPtr box,
int nbox, int nbox,
int dx, int dx,
int dy, int dy,
Bool reverse, Bool reverse,
Bool upsidedown, Pixel bitplane, Bool upsidedown, Pixel bitplane,
void *closure, Bool fallback) void *closure)
{ {
glamor_access_t dst_access;
PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL; PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL;
DrawablePtr temp_src = src; DrawablePtr temp_src = src;
glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
@ -296,32 +285,20 @@ _glamor_copy_n_to_n(DrawablePtr src,
int overlaped = 0; int overlaped = 0;
Bool ret = FALSE; Bool ret = FALSE;
if (nbox == 0)
return TRUE;
dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap = glamor_get_drawable_pixmap(dst);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
src_pixmap = glamor_get_drawable_pixmap(src); src_pixmap = glamor_get_drawable_pixmap(src);
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
screen = dst_pixmap->drawable.pScreen; screen = dst_pixmap->drawable.pScreen;
glamor_priv = glamor_get_screen_private(dst->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, glamor_get_drawable_deltas(src, src_pixmap, &src_x_off,
&src_y_off); &src_y_off);
glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off,
&dst_y_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 x_shift = abs(src_x_off - dx - dst_x_off);
int y_shift = abs(src_y_off - dy - dst_y_off); int y_shift = abs(src_y_off - dy - dst_y_off);
for (i = 0; i < nbox; i++) { 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 #ifndef GLAMOR_GLES2
if ((overlaped if ((overlaped
|| !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex) || !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. */ /* Overlaped indicate the src and dst are the same pixmap. */
if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) 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 > * 4 >
src_pixmap->drawable.width * 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, temp_pixmap = glamor_create_pixmap(screen,
bound.x2 - bound.x1, bound.x2 - bound.x1,
@ -357,9 +342,11 @@ _glamor_copy_n_to_n(DrawablePtr src,
drawable.depth, drawable.depth,
overlaped ? 0 : overlaped ? 0 :
GLAMOR_CREATE_PIXMAP_CPU); 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) if (!temp_pixmap)
goto fail; goto done;
glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); glamor_translate_boxes(box, nbox, -bound.x1, -bound.y1);
temp_src = &temp_pixmap->drawable; temp_src = &temp_pixmap->drawable;
if (overlaped) if (overlaped)
@ -371,7 +358,7 @@ _glamor_copy_n_to_n(DrawablePtr src,
fbCopyNtoN(src, temp_src, gc, box, nbox, fbCopyNtoN(src, temp_src, gc, box, nbox,
temp_dx + bound.x1, temp_dy + bound.y1, temp_dx + bound.x1, temp_dy + bound.y1,
reverse, upsidedown, bitplane, closure); 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_dx = -bound.x1;
temp_dy = -bound.y1; temp_dy = -bound.y1;
} else { } else {
@ -383,12 +370,220 @@ _glamor_copy_n_to_n(DrawablePtr src,
if (glamor_copy_n_to_n_textured if (glamor_copy_n_to_n_textured
(temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { (temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) {
ret = TRUE; 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: 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 if (!fallback
&& glamor_ddx_fallback_check_pixmap(src) && glamor_ddx_fallback_check_pixmap(src)
&& glamor_ddx_fallback_check_pixmap(dst)) && glamor_ddx_fallback_check_pixmap(dst))
@ -428,8 +623,6 @@ _glamor_copy_n_to_n(DrawablePtr src,
done: done:
glamor_clear_delayed_fallbacks(src->pScreen); glamor_clear_delayed_fallbacks(src->pScreen);
glamor_clear_delayed_fallbacks(dst->pScreen); glamor_clear_delayed_fallbacks(dst->pScreen);
if (temp_src != src)
glamor_destroy_pixmap(temp_pixmap);
return ret; return ret;
} }

View File

@ -175,7 +175,8 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo)
if (fbo->fb == 0 || n_format == -1 if (fbo->fb == 0 || n_format == -1
|| fbo->glamor_priv->fbo_cache_watermark >= FBO_CACHE_THRESHOLD) { || 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); glamor_purge_fbo(fbo);
return; return;
} }
@ -404,6 +405,92 @@ no_tex:
return fbo; 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_fbo *
glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv) 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); 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) if (pixmap_priv->base.fbo)
return; return;
pixmap_priv->base.fbo = fbo; pixmap_priv->base.fbo = fbo;
switch (pixmap_priv->type) { switch (pixmap_priv->type) {
case GLAMOR_TEXTURE_LARGE:
case GLAMOR_TEXTURE_ONLY: case GLAMOR_TEXTURE_ONLY:
case GLAMOR_TEXTURE_DRM: case GLAMOR_TEXTURE_DRM:
pixmap_priv->base.gl_fbo = 1; 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 Bool
glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) 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); glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
pixmap_priv = glamor_get_pixmap_private(pixmap); 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, fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
pixmap->drawable.height, 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); glamor_pixmap_ensure_fb(pixmap_priv->base.fbo);
} }
pixmap_priv = glamor_get_pixmap_private(pixmap);
return TRUE; return TRUE;
} }

View File

@ -180,10 +180,9 @@ glamor_fini_solid_shader(ScreenPtr screen)
glamor_put_dispatch(glamor_priv); glamor_put_dispatch(glamor_priv);
} }
Bool static void
glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, _glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
unsigned char alu, unsigned long planemask, float *color)
unsigned long fg_pixel)
{ {
ScreenPtr screen = pixmap->drawable.pScreen; ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv = 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 x2 = x + width;
int y1 = y; int y1 = y;
int y2 = y + height; int y2 = y + height;
GLfloat color[4];
float vertices[8]; float vertices[8];
GLfloat xscale, yscale; GLfloat xscale, yscale;
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { glamor_set_destination_pixmap_priv_nc(pixmap_priv);
glamor_fallback("dest %p has no fbo.\n", pixmap);
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; return FALSE;
}
if (!glamor_set_planemask(pixmap, planemask)) { if (!glamor_set_planemask(pixmap, planemask)) {
glamor_fallback glamor_fallback
@ -216,8 +250,6 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
&color[2], &color[2],
&color[3], format_for_pixmap(pixmap)); &color[3], format_for_pixmap(pixmap));
glamor_set_destination_pixmap_priv_nc(pixmap_priv);
dispatch = glamor_get_dispatch(glamor_priv); dispatch = glamor_get_dispatch(glamor_priv);
if (!glamor_set_alu(dispatch, alu)) { if (!glamor_set_alu(dispatch, alu)) {
if (alu == GXclear) if (alu == GXclear)
@ -228,23 +260,47 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
return FALSE; return FALSE;
} }
} }
dispatch->glUseProgram(glamor_priv->solid_prog);
dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
1, color); RegionRec region;
BoxRec box;
int n_region;
glamor_pixmap_clipped_regions *clipped_regions;
int i,j;
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, box.x1 = x;
GL_FALSE, 2 * sizeof(float), box.y1 = y;
vertices); box.x2 = x + width;
dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); box.y2 = y + height;
pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); 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_set_alu(dispatch, GXcopy);
glamor_put_dispatch(glamor_priv); glamor_put_dispatch(glamor_priv);
return TRUE; 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 void
glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) 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, glamor_set_destination_pixmap_fbo(pixmap_priv->base.fbo, 0, 0,
pixmap_priv->base.pixmap->drawable.width, w, h);
pixmap_priv->base.pixmap->drawable.height);
} }
int int
@ -489,16 +491,23 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum ty
} }
ready_to_upload: ready_to_upload:
/* Try fast path firstly, upload the pixmap to the texture attached /* Try fast path firstly, upload the pixmap to the texture attached
* to the fbo directly. */ * to the fbo directly. */
if (no_alpha == 0 if (no_alpha == 0
&& revert == REVERT_NONE && revert == REVERT_NONE
&& swap_rb == SWAP_NONE_UPLOADING && swap_rb == SWAP_NONE_UPLOADING
&& !need_flip) { && !need_flip) {
int fbo_x_off, fbo_y_off;
assert(pixmap_priv->base.fbo->tex); 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, __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->base.fbo->tex,
format, type, format, type,
x, y, w, h, x + fbo_x_off, y + fbo_y_off, w, h,
bits, pbo); bits, pbo);
return TRUE; return TRUE;
} }
@ -515,7 +524,6 @@ ready_to_upload:
x + w, y + h, x + w, y + h,
glamor_priv->yInverted, glamor_priv->yInverted,
vertices); vertices);
/* Slow path, we need to flip y or wire alpha to 1. */ /* Slow path, we need to flip y or wire alpha to 1. */
dispatch = glamor_get_dispatch(glamor_priv); dispatch = glamor_get_dispatch(glamor_priv);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, 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); pixmap_priv = glamor_get_pixmap_private(pixmap);
glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
if (pixmap_priv->base.gl_fbo)
return 0;
if (pixmap_priv->base.fbo if (pixmap_priv->base.fbo
&& (pixmap_priv->base.fbo->width < pixmap->drawable.width && (pixmap_priv->base.fbo->width < pixmap->drawable.width
|| pixmap_priv->base.fbo->height < pixmap->drawable.height)) { || 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; flag = GLAMOR_CREATE_FBO_NO_FBO;
} }
if ((flag == 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex) if ((flag == GLAMOR_CREATE_FBO_NO_FBO
|| (flag != 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb)) && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex)
|| (flag == 0
&& pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb))
return 0; return 0;
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) 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 else
iformat = format; iformat = format;
if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) { if (!glamor_pixmap_ensure_fbo(pixmap, iformat, flag))
return -1;
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);
}
return 0; 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 Bool
glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h, glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h,
int stride, void *bits, int pbo) int stride, void *bits, int pbo)
{ {
GLenum format, type; GLenum format, type;
int no_alpha, revert, swap_rb; int no_alpha, revert, swap_rb;
glamor_pixmap_private *pixmap_priv;
if (glamor_get_tex_format_type_from_pixmap(pixmap, if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format, &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)) if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb))
return FALSE; 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); 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); pixmap_priv = glamor_get_pixmap_private(pixmap);
if (pixmap_priv if ((pixmap_priv->base.fbo)
&& (pixmap_priv->base.fbo)
&& (pixmap_priv->base.fbo->pbo_valid)) { && (pixmap_priv->base.fbo->pbo_valid)) {
data = NULL; data = NULL;
pbo = pixmap_priv->base.fbo->pbo; 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_xscale = 1.0 / w;
temp_yscale = 1.0 / h; 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, temp_yscale,
0, 0, 0, 0,
w, h, 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. * The pixmap must have a valid FBO, otherwise return a NULL.
* */ * */
void * static void *
glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
int stride, void *bits, int pbo, glamor_access_t access) 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; glamor_pixmap_private *pixmap_priv;
GLenum format, type, gl_access = 0, gl_usage = 0; GLenum gl_access = 0, gl_usage = 0;
int no_alpha, revert, swap_rb;
void *data, *read; void *data, *read;
ScreenPtr screen; ScreenPtr screen;
glamor_screen_private *glamor_priv = 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; glamor_pixmap_fbo *temp_fbo = NULL;
int need_post_conversion = 0; int need_post_conversion = 0;
int need_free_data = 0; int need_free_data = 0;
int fbo_x_off, fbo_y_off;
data = bits; data = bits;
screen = pixmap->drawable.pScreen; 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); 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); glamor_set_destination_pixmap_priv_nc(pixmap_priv);
need_post_conversion = (revert > REVERT_NORMAL); 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 if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
&& !need_post_conversion && !need_post_conversion
&& (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) { && (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; x = 0;
y = 0; y = 0;
fbo_x_off = 0;
fbo_y_off = 0;
} }
dispatch = glamor_get_dispatch(glamor_priv); 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); 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) { if (!glamor_priv->yInverted) {
assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); 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 * stride *
h, h,
NULL, GL_STREAM_READ); 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); format, type, 0);
read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER,
GL_READ_ONLY); 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; 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. * 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 if (access == GLAMOR_ACCESS_WO
|| glamor_priv->gl_flavor == GLAMOR_GL_ES2 || 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); data = malloc(stride * pixmap->drawable.height);
} else { } else {
dispatch = glamor_get_dispatch(glamor_priv); 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. */ /* fixup a fbo to the exact size as the pixmap. */
/* XXX LARGE pixmap? */
Bool Bool
glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) 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; drawable = &pixmap_priv->base.pixmap->drawable;
if (pixmap_priv->base.pixmap->drawable.width == pixmap_priv->base.fbo->width if (!GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))
&& pixmap_priv->base.pixmap->drawable.height == pixmap_priv->base.fbo->height)
return TRUE; return TRUE;
old_fbo = pixmap_priv->base.fbo; 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); scratch_priv = glamor_get_pixmap_private(scratch);
if (!scratch_priv || !scratch_priv->base.fbo) if (!scratch_priv->base.fbo)
goto fail; goto fail;
ValidateGC(&scratch->drawable, gc); 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; void *data;
int pbo; int pbo;
int flag; int flag;
if (x < 0 || y < 0)
assert(x >= 0 && y >= 0); return NULL;
w = (x + w) > pixmap->drawable.width ? (pixmap->drawable.width - x) : w; w = (x + w) > pixmap->drawable.width ? (pixmap->drawable.width - x) : w;
h = (y + h) > pixmap->drawable.height ? (pixmap->drawable.height - y) : h; h = (y + h) > pixmap->drawable.height ? (pixmap->drawable.height - y) : h;
if (access == GLAMOR_ACCESS_WO) { if (access == GLAMOR_ACCESS_WO) {
sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h, sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU); pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU);
ErrorF("WO\n");
return sub_pixmap; 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)) if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return NULL; 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; flag = GLAMOR_CREATE_PIXMAP_CPU;
else else
flag = GLAMOR_CREATE_PIXMAP_MAP; 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); 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; 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.picture = pixmap_priv->base.picture;
sub_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture; sub_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture;
} }
if (pbo) if (pbo)
data = NULL; data = NULL;
else { else
data = sub_pixmap->devPrivate.ptr; 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 = glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h, sub_pixmap->devKind,
data, pbo, access); data, pbo, access);
if (pbo) { 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, new_sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU); 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); glamor_compare_pixmaps(new_sub_pixmap, sub_pixmap, 0, 0, w, h, 1, 1);
#endif #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; glamor_pixmap_private *sub_pixmap_priv;
if (access != GLAMOR_ACCESS_RO) { if (access != GLAMOR_ACCESS_RO) {
sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
if (sub_pixmap_priv if (sub_pixmap_priv->base.fbo
&& sub_pixmap_priv->base.fbo
&& sub_pixmap_priv->base.fbo->pbo_valid) { && sub_pixmap_priv->base.fbo->pbo_valid) {
bits = NULL; bits = NULL;
pbo = sub_pixmap_priv->base.fbo->pbo; 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 #ifndef GLAMOR_GLES2
#define GLAMOR_GRADIENT_SHADER #define GLAMOR_GRADIENT_SHADER
#endif #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 */ #endif /* GLAMOR_PRIV_H */

View File

@ -37,7 +37,12 @@
#ifdef RENDER #ifdef RENDER
#include "mipict.h" #include "mipict.h"
#include "fbpict.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 { struct shader_key {
enum shader_source source; enum shader_source source;
enum shader_mask mask; enum shader_mask mask;
@ -606,18 +611,20 @@ glamor_set_composite_texture(ScreenPtr screen, int unit,
#endif #endif
/* XXX may be we can eaxctly check whether we need to touch /* XXX may be we can eaxctly check whether we need to touch
* the out-of-box area then determine whether we need to fix. * the out-of-box area then determine whether we need to fix.
* */ **/
if (repeat_type != RepeatNone) /*if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE)*/ {
repeat_type += RepeatFix; if (repeat_type != RepeatNone)
else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
if (picture->transform
|| (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv)))
repeat_type += RepeatFix; repeat_type += RepeatFix;
} else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
|| pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
if (repeat_type >= RepeatFix) { if (picture->transform
glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv)))
dispatch->glUniform2fv(wh_location, 1, wh); 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); dispatch->glUniform1i(repeat_location, repeat_type);
glamor_put_dispatch(glamor_priv); glamor_put_dispatch(glamor_priv);
@ -687,53 +694,44 @@ glamor_composite_with_copy(CARD8 op,
INT16 x_source, INT16 x_source,
INT16 y_source, INT16 y_source,
INT16 x_dest, INT16 x_dest,
INT16 y_dest, CARD16 width, CARD16 height) INT16 y_dest,
RegionPtr region)
{ {
RegionRec region;
int ret = FALSE; int ret = FALSE;
if (!source->pDrawable) if (!source->pDrawable)
return FALSE; return FALSE;
if (!compatible_formats(op, dest, source)) if (!compatible_formats(op, dest, source))
return FALSE; return FALSE;
if (source->repeat || source->transform) if (source->repeat || source->transform) {
return FALSE; return FALSE;
}
x_dest += dest->pDrawable->x; x_dest += dest->pDrawable->x;
y_dest += dest->pDrawable->y; y_dest += dest->pDrawable->y;
x_source += source->pDrawable->x; x_source += source->pDrawable->x;
y_source += source->pDrawable->y; 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) { if (PICT_FORMAT_A(source->format) == 0) {
/* Fallback if we sample outside the source so that we /* Fallback if we sample outside the source so that we
* swizzle the correct clear color for out-of-bounds texels. * 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; 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; goto cleanup_region;
if (region.extents.y1 + y_source - y_dest < 0) if (region->extents.y1 + y_source - y_dest < 0)
goto cleanup_region; 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; goto cleanup_region;
} }
ret = glamor_copy_n_to_n_nf(source->pDrawable, ret = glamor_copy_n_to_n_nf(source->pDrawable,
dest->pDrawable, NULL, dest->pDrawable, NULL,
REGION_RECTS(&region), RegionRects(region), RegionNumRects(region),
REGION_NUM_RECTS(&region),
x_source - x_dest, y_source - y_dest, x_source - x_dest, y_source - y_dest,
FALSE, FALSE, 0, NULL); FALSE, FALSE, 0, NULL);
cleanup_region: cleanup_region:
REGION_UNINIT(dest->pDrawable->pScreen, &region);
return ret; return ret;
} }
@ -929,12 +927,44 @@ combine_pict_format(PictFormatShort * des, const PictFormatShort src,
return FALSE; 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 static Bool
glamor_composite_with_shader(CARD8 op, glamor_composite_with_shader(CARD8 op,
PicturePtr source, PicturePtr source,
PicturePtr mask, PicturePtr mask,
PicturePtr dest, PicturePtr dest,
int nrect, glamor_composite_rect_t * rects) int nrect,
glamor_composite_rect_t * rects)
{ {
ScreenPtr screen = dest->pDrawable->pScreen; ScreenPtr screen = dest->pDrawable->pScreen;
glamor_screen_private *glamor_priv = glamor_screen_private *glamor_priv =
@ -959,6 +989,7 @@ glamor_composite_with_shader(CARD8 op,
enum glamor_pixmap_status mask_status = GLAMOR_NONE; enum glamor_pixmap_status mask_status = GLAMOR_NONE;
PictFormatShort saved_source_format = 0; PictFormatShort saved_source_format = 0;
float src_matrix[9], mask_matrix[9]; float src_matrix[9], mask_matrix[9];
float *psrc_matrix = NULL, *pmask_matrix = NULL;
GLfloat source_solid_color[4], mask_solid_color[4]; GLfloat source_solid_color[4], mask_solid_color[4];
int vert_stride = 4; int vert_stride = 4;
int nrect_max; int nrect_max;
@ -970,20 +1001,23 @@ glamor_composite_with_shader(CARD8 op,
goto fail; goto fail;
} }
memset(&key, 0, sizeof(key)); memset(&key, 0, sizeof(key));
if (!source->pDrawable) { if (!source) {
if (source->pSourcePict->type == SourcePictTypeSolidFill) { key.source = SHADER_SOURCE_SOLID;
key.source = SHADER_SOURCE_SOLID; source_solid_color[0] = 0.0;
glamor_get_rgba_from_pixel(source-> source_solid_color[1] = 0.0;
pSourcePict->solidFill. source_solid_color[2] = 0.0;
color, source_solid_color[3] = 0.0;
&source_solid_color[0], } else if (!source->pDrawable) {
&source_solid_color[1], if (source->pSourcePict->type == SourcePictTypeSolidFill) {
&source_solid_color[2], key.source = SHADER_SOURCE_SOLID;
&source_solid_color[3], glamor_get_rgba_from_pixel(source->
PICT_a8r8g8b8); pSourcePict->solidFill.
} else { color,
glamor_fallback("gradient source\n"); &source_solid_color[0],
goto fail; &source_solid_color[1],
&source_solid_color[2],
&source_solid_color[3],
PICT_a8r8g8b8);
} }
} else { } else {
key.source = SHADER_SOURCE_TEXTURE_ALPHA; key.source = SHADER_SOURCE_TEXTURE_ALPHA;
@ -999,9 +1033,6 @@ glamor_composite_with_shader(CARD8 op,
&mask_solid_color[1], &mask_solid_color[1],
&mask_solid_color[2], &mask_solid_color[2],
&mask_solid_color[3], PICT_a8r8g8b8); &mask_solid_color[3], PICT_a8r8g8b8);
} else {
glamor_fallback("gradient mask\n");
goto fail;
} }
} else { } else {
key.mask = SHADER_MASK_TEXTURE_ALPHA; key.mask = SHADER_MASK_TEXTURE_ALPHA;
@ -1029,7 +1060,7 @@ glamor_composite_with_shader(CARD8 op,
key.in = SHADER_IN_SOURCE_ONLY; key.in = SHADER_IN_SOURCE_ONLY;
} }
if (source->alphaMap) { if (source && source->alphaMap) {
glamor_fallback("source alphaMap\n"); glamor_fallback("source alphaMap\n");
goto fail; goto fail;
} }
@ -1044,10 +1075,11 @@ glamor_composite_with_shader(CARD8 op,
source_pixmap_priv = source_pixmap_priv =
glamor_get_pixmap_private(source_pixmap); glamor_get_pixmap_private(source_pixmap);
if (source_pixmap == dest_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"); glamor_fallback("source == dest\n");
goto fail;
} }
if (!source_pixmap_priv || source_pixmap_priv->base.gl_fbo == 0) { if (source_pixmap_priv->base.gl_fbo == 0) {
/* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex /* 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 * 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.
@ -1068,7 +1100,7 @@ glamor_composite_with_shader(CARD8 op,
glamor_fallback("mask == dest\n"); glamor_fallback("mask == dest\n");
goto fail; 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 #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
mask_status = GLAMOR_UPLOAD_PENDING; mask_status = GLAMOR_UPLOAD_PENDING;
#else #else
@ -1095,8 +1127,8 @@ glamor_composite_with_shader(CARD8 op,
} }
if (source->format != saved_source_format) { if (source->format != saved_source_format) {
glamor_picture_format_fixup(source, //glamor_picture_format_fixup(source,
source_pixmap_priv); // source_pixmap_priv);
} }
/* XXX /* XXX
* By default, glamor_upload_picture_to_texture will wire alpha to 1 * By default, glamor_upload_picture_to_texture will wire alpha to 1
@ -1156,13 +1188,15 @@ glamor_composite_with_shader(CARD8 op,
* transformed source and mask, if the transform is not int translate. */ * transformed source and mask, if the transform is not int translate. */
if (key.source != SHADER_SOURCE_SOLID if (key.source != SHADER_SOURCE_SOLID
&& source->transform && 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)) if (!glamor_fixup_pixmap_priv(screen, source_pixmap_priv))
goto fail; goto fail;
} }
if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID
&& mask->transform && 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)) if (!glamor_fixup_pixmap_priv(screen, mask_pixmap_priv))
goto fail; goto fail;
} }
@ -1217,7 +1251,10 @@ glamor_composite_with_shader(CARD8 op,
&source_y_off); &source_y_off);
pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, pixmap_priv_get_scale(source_pixmap_priv, &src_xscale,
&src_yscale); &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; vert_stride += 4;
} }
@ -1226,7 +1263,10 @@ glamor_composite_with_shader(CARD8 op,
&mask_x_off, &mask_y_off); &mask_x_off, &mask_y_off);
pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale,
&mask_yscale); &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; vert_stride += 4;
} }
@ -1252,13 +1292,16 @@ glamor_composite_with_shader(CARD8 op,
x_dest = rects->x_dst + dest_x_off; x_dest = rects->x_dst + dest_x_off;
y_dest = rects->y_dst + dest_y_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; y_source = rects->y_src + source_y_off;
x_mask = rects->x_mask + mask_x_off; x_mask = rects->x_mask + mask_x_off;
y_mask = rects->y_mask + mask_y_off; y_mask = rects->y_mask + mask_y_off;
width = rects->width; width = rects->width;
height = rects->height; 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, glamor_set_normalize_vcoords(dest_pixmap_priv, dst_xscale,
dst_yscale, dst_yscale,
x_dest, y_dest, x_dest, y_dest,
@ -1266,41 +1309,21 @@ glamor_composite_with_shader(CARD8 op,
glamor_priv->yInverted, glamor_priv->yInverted,
vertices); vertices);
if (key.source != SHADER_SOURCE_SOLID) { if (key.source != SHADER_SOURCE_SOLID)
if (source->transform) glamor_set_normalize_tcoords_generic(
glamor_set_transformed_normalize_tcoords source_pixmap_priv, source->repeatType, psrc_matrix,
(source_pixmap_priv, src_matrix, src_xscale, src_xscale, src_yscale, x_source, y_source,
src_yscale, x_source, y_source, x_source + width, y_source + height,
x_source + width, y_source + height, glamor_priv->yInverted, source_texcoords);
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.mask != SHADER_MASK_NONE if (key.mask != SHADER_MASK_NONE
&& key.mask != SHADER_MASK_SOLID) { && key.mask != SHADER_MASK_SOLID)
if (mask->transform) glamor_set_normalize_tcoords_generic(
glamor_set_transformed_normalize_tcoords mask_pixmap_priv, mask->repeatType, pmask_matrix,
(mask_pixmap_priv, mask_matrix, mask_xscale, mask_yscale, x_mask, y_mask,
mask_xscale, x_mask + width, y_mask + height,
mask_yscale, x_mask, y_mask, glamor_priv->yInverted, mask_texcoords);
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);
}
glamor_emit_composite_rect(screen, glamor_emit_composite_rect(screen,
source_texcoords, source_texcoords,
mask_texcoords, mask_texcoords,
@ -1323,6 +1346,7 @@ glamor_composite_with_shader(CARD8 op,
dispatch->glActiveTexture(GL_TEXTURE1); dispatch->glActiveTexture(GL_TEXTURE1);
dispatch->glDisable(GL_TEXTURE_2D); dispatch->glDisable(GL_TEXTURE_2D);
#endif #endif
DEBUGF("finish rendering.\n");
dispatch->glUseProgram(0); dispatch->glUseProgram(0);
if (saved_source_format) if (saved_source_format)
source->format = saved_source_format; source->format = saved_source_format;
@ -1398,17 +1422,18 @@ glamor_convert_gradient_picture(ScreenPtr screen,
return dst; return dst;
} }
static Bool Bool
_glamor_composite(CARD8 op, glamor_composite_clipped_region(CARD8 op,
PicturePtr source, PicturePtr source,
PicturePtr mask, PicturePtr mask,
PicturePtr dest, PicturePtr dest,
INT16 x_source, RegionPtr region,
INT16 y_source, int x_source,
INT16 x_mask, int y_source,
INT16 y_mask, int x_mask,
INT16 x_dest, INT16 y_dest, int y_mask,
CARD16 width, CARD16 height, Bool fallback) int x_dest,
int y_dest)
{ {
ScreenPtr screen = dest->pDrawable->pScreen; ScreenPtr screen = dest->pDrawable->pScreen;
glamor_pixmap_private *dest_pixmap_priv; glamor_pixmap_private *dest_pixmap_priv;
@ -1419,80 +1444,63 @@ _glamor_composite(CARD8 op,
PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; PixmapPtr source_pixmap = NULL, mask_pixmap = NULL;
PicturePtr temp_src = source, temp_mask = mask; PicturePtr temp_src = source, temp_mask = mask;
int x_temp_src, y_temp_src, x_temp_mask, y_temp_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 rect[10];
glamor_composite_rect_t *prect = rect; glamor_composite_rect_t *prect = rect;
int prect_size = ARRAY_SIZE(rect); int prect_size = ARRAY_SIZE(rect);
glamor_screen_private *glamor_priv = int ok = FALSE;
glamor_get_screen_private(screen); int i;
Bool ret = TRUE; int width;
RegionRec region; int height;
BoxPtr box; BoxPtr box;
int nbox, i, ok = FALSE; int nbox;
PixmapPtr sub_dest_pixmap = NULL; extent = RegionExtents(region);
PixmapPtr sub_source_pixmap = NULL; box = RegionRects(region);
PixmapPtr sub_mask_pixmap = NULL; nbox = RegionNumRects(region);
int dest_x_off, dest_y_off, saved_dest_x = 0, saved_dest_y = 0; width = extent->x2 - extent->x1;
int source_x_off, source_y_off, saved_source_x = 0, saved_source_y = 0; height = extent->y2 - extent->y1;
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;
x_temp_src = x_source; x_temp_src = x_source;
y_temp_src = y_source; y_temp_src = y_source;
x_temp_mask = x_mask; x_temp_mask = x_mask;
y_temp_mask = y_mask; y_temp_mask = y_mask;
DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n",
DEBUGF("Composite Src: (%d, %d)\n" x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height);
" Mask: (%d, %d)\n" DEBUGF("dest pixmap %p ", dest_pixmap);
" to dst: (%d, %d), size: %d X %d \n",
x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height);
dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
/* Currently. Always fallback to cpu if destination is in CPU memory. */ /* 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 = glamor_get_drawable_pixmap(source->pDrawable);
source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); 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) { if (mask && mask->pDrawable) {
mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable);
mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); 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)) { /* XXX is it possible source mask have non-zero drawable.x/y? */
goto fail; if (source
} && ((!source->pDrawable
if (op >= ARRAY_SIZE(composite_op_info))
goto fail;
if ((!source->pDrawable
&& (source->pSourcePict->type != SourcePictTypeSolidFill)) && (source->pSourcePict->type != SourcePictTypeSolidFill))
|| (source->pDrawable || (source->pDrawable
&& !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv)
&& && (source_pixmap->drawable.width != width
((width * height * 4 < || source_pixmap->drawable.height != height)))) {
(source_pixmap->drawable.width *
source_pixmap->drawable.height))
||
!(glamor_check_fbo_size
(glamor_priv, source_pixmap->drawable.width,
source_pixmap->drawable.height))))) {
temp_src = temp_src =
glamor_convert_gradient_picture(screen, source, glamor_convert_gradient_picture(screen, source,
x_source, y_source, extent->x1 + x_source - x_dest,
extent->y1 + y_source - y_dest,
width, height); width, height);
if (!temp_src) { if (!temp_src) {
temp_src = source; 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 if (mask
@ -1500,26 +1508,22 @@ _glamor_composite(CARD8 op,
((!mask->pDrawable ((!mask->pDrawable
&& (mask->pSourcePict->type != SourcePictTypeSolidFill)) && (mask->pSourcePict->type != SourcePictTypeSolidFill))
|| (mask->pDrawable || (mask->pDrawable
&& (!GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)) && !GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)
&& && (mask_pixmap->drawable.width != width
((width * height * 4 < || mask_pixmap->drawable.height != height)))) {
(mask_pixmap->drawable.width *
mask_pixmap->drawable.height))
||
!(glamor_check_fbo_size
(glamor_priv, mask_pixmap->drawable.width,
mask_pixmap->drawable.height)))))) {
/* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity
* to do reduce one convertion. */ * to do reduce one convertion. */
temp_mask = temp_mask =
glamor_convert_gradient_picture(screen, 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); width, height);
if (!temp_mask) { if (!temp_mask) {
temp_mask = 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 /* Do two-pass PictOpOver componentAlpha, until we enable
* dual source color blending. * dual source color blending.
@ -1527,43 +1531,38 @@ _glamor_composite(CARD8 op,
if (mask && mask->componentAlpha) { if (mask && mask->componentAlpha) {
if (op == PictOpOver) { if (op == PictOpOver) {
glamor_composite(PictOpOutReverse, glamor_composite_clipped_region(PictOpOutReverse,
temp_src, temp_mask, dest, temp_src, temp_mask, dest,
x_temp_src, y_temp_src, region,
x_temp_mask, y_temp_mask, x_temp_src, y_temp_src,
x_dest, y_dest, width, height); x_temp_mask, y_temp_mask,
glamor_composite(PictOpAdd, x_dest, y_dest);
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;
} else if (op == PictOpAtop glamor_composite_clipped_region(PictOpAdd,
|| op == PictOpAtopReverse temp_src, temp_mask, dest,
|| op == PictOpXor region,
|| op >= PictOpSaturate) { x_temp_src, y_temp_src,
glamor_fallback x_temp_mask, y_temp_mask,
("glamor_composite(): component alpha op %x\n", op); x_dest, y_dest);
goto fail; ok = TRUE;
goto out;
} }
} }
if (!mask) { if (!mask && temp_src) {
if (glamor_composite_with_copy(op, temp_src, dest, if (glamor_composite_with_copy(op, temp_src, dest,
x_temp_src, y_temp_src, x_temp_src, y_temp_src,
x_dest, y_dest, width, x_dest, y_dest, region)) {
height)) ok = TRUE;
goto done; goto out;
}
} }
/*XXXXX, maybe we can make a copy of dest pixmap.*/ /*XXXXX, self copy?*/
if (source_pixmap == dest_pixmap)
goto full_fallback;
x_dest += dest->pDrawable->x; x_dest += dest->pDrawable->x;
y_dest += dest->pDrawable->y; y_dest += dest->pDrawable->y;
if (temp_src->pDrawable) { if (temp_src && temp_src->pDrawable) {
x_temp_src += temp_src->pDrawable->x; x_temp_src += temp_src->pDrawable->x;
y_temp_src += temp_src->pDrawable->y; y_temp_src += temp_src->pDrawable->y;
} }
@ -1571,16 +1570,6 @@ _glamor_composite(CARD8 op,
x_temp_mask += temp_mask->pDrawable->x; x_temp_mask += temp_mask->pDrawable->x;
y_temp_mask += temp_mask->pDrawable->y; 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)) { if (nbox > ARRAY_SIZE(rect)) {
prect = calloc(nbox, sizeof(*prect)); prect = calloc(nbox, sizeof(*prect));
@ -1612,10 +1601,148 @@ _glamor_composite(CARD8 op,
box += box_cnt; 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); REGION_UNINIT(dest->pDrawable->pScreen, &region);
if (ok) if (ok)
goto done; goto done;
fail: fail:
if (!fallback if (!fallback
@ -1662,13 +1789,11 @@ fail:
x_ ##p = 0; \ x_ ##p = 0; \
y_ ##p = 0; \ y_ ##p = 0; \
} } while(0) } } while(0)
GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
if (source->pDrawable) if (source->pDrawable && !source->transform)
GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO); GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO);
if (mask && mask->pDrawable) if (mask && mask->pDrawable && !mask->transform)
GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO); GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO);
full_fallback: full_fallback:
if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) {
if (source_pixmap == dest_pixmap || glamor_prepare_access_picture 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(source, GLAMOR_ACCESS_RO);
PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
done: done:
if (temp_src != source)
FreePicture(temp_src, 0);
if (temp_mask != mask)
FreePicture(temp_mask, 0);
if (prect != rect)
free(prect);
return ret; return ret;
} }
@ -1754,9 +1873,6 @@ glamor_composite_nf(CARD8 op,
FALSE); FALSE);
} }
/** /**
* Creates an appropriate picture to upload our alpha mask into (which * Creates an appropriate picture to upload our alpha mask into (which
* we calculated in system memory) * we calculated in system memory)
@ -1912,8 +2028,12 @@ glamor_composite_glyph_rects(CARD8 op,
ValidatePicture(src); ValidatePicture(src);
ValidatePicture(dst); ValidatePicture(dst);
if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects)) if (!(glamor_is_large_picture(src)
return; || (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; n = nrect;
r = rects; r = rects;

View File

@ -102,10 +102,9 @@ glamor_fini_tile_shader(ScreenPtr screen)
glamor_put_dispatch(glamor_priv); glamor_put_dispatch(glamor_priv);
} }
Bool static void
glamor_tile(PixmapPtr pixmap, PixmapPtr tile, _glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
int x, int y, int width, int height, int x, int y, int width, int height,
unsigned char alu, unsigned long planemask,
int tile_x, int tile_y) int tile_x, int tile_y)
{ {
ScreenPtr screen = pixmap->drawable.pScreen; ScreenPtr screen = pixmap->drawable.pScreen;
@ -126,48 +125,17 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
glamor_pixmap_private *src_pixmap_priv; glamor_pixmap_private *src_pixmap_priv;
glamor_pixmap_private *dst_pixmap_priv; glamor_pixmap_private *dst_pixmap_priv;
float wh[2]; float wh[2];
src_pixmap_priv = glamor_get_pixmap_private(tile); src_pixmap_priv = glamor_get_pixmap_private(tile);
dst_pixmap_priv = glamor_get_pixmap_private(pixmap); 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); glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); 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, pixmap_priv_get_scale(src_pixmap_priv, &src_xscale,
&src_yscale); &src_yscale);
dispatch = glamor_get_dispatch(glamor_priv);
dispatch->glUseProgram(glamor_priv->tile_prog); dispatch->glUseProgram(glamor_priv->tile_prog);
glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv); glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv);
dispatch->glUniform2fv(glamor_priv->tile_wh, 1, wh); dispatch->glUniform2fv(glamor_priv->tile_wh, 1, wh);
dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glActiveTexture(GL_TEXTURE0);
dispatch->glBindTexture(GL_TEXTURE_2D, dispatch->glBindTexture(GL_TEXTURE_2D,
@ -185,21 +153,23 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
#ifndef GLAMOR_GLES2 #ifndef GLAMOR_GLES2
dispatch->glEnable(GL_TEXTURE_2D); dispatch->glEnable(GL_TEXTURE_2D);
#endif #endif
glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale, glamor_set_repeat_normalize_tcoords
src_yscale, (src_pixmap_priv, RepeatNormal,
tile_x1, tile_y1, src_xscale, src_yscale,
tile_x2, tile_y2, tile_x1, tile_y1,
glamor_priv->yInverted, tile_x2, tile_y2,
source_texcoords); glamor_priv->yInverted,
source_texcoords);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
GL_FLOAT, GL_FALSE, GL_FLOAT, GL_FALSE,
2 * sizeof(float), 2 * sizeof(float),
source_texcoords); source_texcoords);
dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, dst_yscale,
dst_yscale, x1, y1,
x1, y1, x2, y2, x2, y2,
glamor_priv->yInverted, vertices); glamor_priv->yInverted, vertices);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
@ -214,11 +184,139 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
#endif #endif
dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
dispatch->glUseProgram(0); 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_alu(dispatch, GXcopy);
glamor_set_planemask(pixmap, ~0);
glamor_put_dispatch(glamor_priv); glamor_put_dispatch(glamor_priv);
return TRUE; return TRUE;
fail:
fail:
return FALSE; return FALSE;
} }

View File

@ -41,8 +41,10 @@
#define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ #define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \
do { \ do { \
*(_pxscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.width; \ int w,h; \
*(_pyscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.height; \ PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, w, h); \
*(_pxscale_) = 1.0 / w; \
*(_pyscale_) = 1.0 / h; \
} while(0) } while(0)
#define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \
@ -106,6 +108,52 @@
} \ } \
} while(0) } 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) \ #define glamor_transform_point(matrix, tx, ty, x, y) \
do { \ do { \
int i; \ int i; \
@ -213,6 +261,24 @@
tx2, ty2, yInverted, vertices); \ tx2, ty2, yInverted, vertices); \
} while(0) } 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, \ #define glamor_set_tcoords(width, height, x1, y1, x2, y2, \
yInverted, vertices) \ yInverted, vertices) \
do { \ do { \
@ -303,7 +369,7 @@ glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox)
} }
inline static void 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; int i;
for (i = 0; i < nbox; i++) { for (i = 0; i < nbox; i++) {