glamor_glyphblt.c\
glamor_polyops.c\
glamor_pixmap.c\
+ glamor_largepixmap.c\
glamor_picture.c\
glamor_window.c\
glamor_gl_dispatch.c\
if (w > 32767 || h > 32767)
return NullPixmap;
- if (usage == GLAMOR_CREATE_PIXMAP_CPU
- || (w == 0 && h == 0)
- || !glamor_check_pixmap_fbo_depth(depth))
+ if ((usage == GLAMOR_CREATE_PIXMAP_CPU
+ || (w == 0 && h == 0)
+ || !glamor_check_pixmap_fbo_depth(depth))
+ || (!GLAMOR_TEXTURED_LARGE_PIXMAP &&
+ !glamor_check_fbo_size(glamor_priv, w, h)))
return fbCreatePixmap(screen, w, h, depth, usage);
else
pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
pixmap_priv->base.pixmap = pixmap;
pixmap_priv->base.glamor_priv = glamor_priv;
- pixmap_priv->type = type;
gl_iformat_for_depth(depth, &format);
- fbo = glamor_create_fbo(glamor_priv, w, h, format, usage);
+
+ pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
+ screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);
+
+ if (type == GLAMOR_MEMORY_MAP || glamor_check_fbo_size(glamor_priv, w, h)) {
+ pixmap_priv->type = type;
+ fbo = glamor_create_fbo(glamor_priv, w, h, format, usage);
+ }
+ else {
+ DEBUGF("Create LARGE pixmap %p width %d height %d\n", pixmap, w, h);
+ pixmap_priv->type = GLAMOR_TEXTURE_LARGE;
+ fbo = glamor_create_fbo_array(glamor_priv, w, h, format, usage,
+ glamor_priv->max_fbo_size,
+ glamor_priv->max_fbo_size,
+ pixmap_priv);
+ }
if (fbo == NULL) {
fbDestroyPixmap(pixmap);
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;
}
glamor_pixmap_private *pixmap_priv;
pixmap_priv = glamor_get_pixmap_private(pixmap);
- if (pixmap_priv != NULL) {
- glamor_pixmap_fbo *fbo;
- fbo = glamor_pixmap_detach_fbo(pixmap_priv);
- if (fbo)
- glamor_destroy_fbo(fbo);
- free(pixmap_priv);
- }
+ if (pixmap_priv != NULL)
+ glamor_pixmap_destroy_fbo(pixmap_priv);
}
}
glamor_gl_has_extension("GL_EXT_framebuffer_blit");
glamor_priv->_dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE,
&glamor_priv->max_fbo_size);
+#ifdef MAX_FBO_SIZE
+ glamor_priv->max_fbo_size = MAX_FBO_SIZE;
+#endif
glamor_set_debug_level(&glamor_debug_level);
ScreenPtr screen = dst->pScreen;
PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
- glamor_pixmap_private *src_pixmap_priv;
+ glamor_pixmap_private *src_pixmap_priv, *dst_pixmap_priv;
glamor_screen_private *glamor_priv =
glamor_get_screen_private(screen);
glamor_gl_dispatch *dispatch;
int dst_x_off, dst_y_off, src_x_off, src_y_off, i;
+ int fbo_x_off, fbo_y_off;
+ int src_fbo_x_off, src_fbo_y_off;
if (!glamor_priv->has_fbo_blit) {
glamor_delayed_fallback(screen,
return FALSE;
}
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
+ dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
if (gc) {
if (gc->alu != GXcopy) {
glamor_delayed_fallback(screen, "non-copy ALU\n");
return FALSE;
}
- if (!glamor_pm_is_solid(dst, gc->planemask)) {
- glamor_delayed_fallback(screen,
- "non-solid planemask\n");
- return FALSE;
- }
}
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) {
if (glamor_set_destination_pixmap(dst_pixmap))
return FALSE;
+ pixmap_priv_get_fbo_off(dst_pixmap_priv, &fbo_x_off, &fbo_y_off);
+ pixmap_priv_get_fbo_off(src_pixmap_priv, &src_fbo_x_off, &src_fbo_y_off);
+
dispatch = glamor_get_dispatch(glamor_priv);
dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT,
src_pixmap_priv->base.fbo->fb);
&dst_y_off);
glamor_get_drawable_deltas(src, src_pixmap, &src_x_off,
&src_y_off);
- src_y_off += dy;
+ dst_x_off += fbo_x_off;
+ dst_y_off += fbo_y_off;
+ src_y_off += dy + src_fbo_y_off;
+ src_x_off += src_fbo_x_off;
for (i = 0; i < nbox; i++) {
if (glamor_priv->yInverted) {
int src_x_off, src_y_off, dst_x_off, dst_y_off;
enum glamor_pixmap_status src_status = GLAMOR_NONE;
GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale;
- int alu = GXcopy;
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
- if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) {
- glamor_delayed_fallback(dst->pScreen, "dst has no fbo.\n");
- return FALSE;
- }
-
- if (!src_pixmap_priv || !src_pixmap_priv->base.gl_fbo) {
+ if (!src_pixmap_priv->base.gl_fbo) {
#ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n");
return FALSE;
#endif
}
- if (gc) {
- if (!glamor_set_planemask(dst_pixmap, gc->planemask))
- return FALSE;
- alu = gc->alu;
- }
pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale);
pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale);
dispatch = glamor_get_dispatch(glamor_priv);
- if (!glamor_set_alu(dispatch, alu)) {
- glamor_put_dispatch(glamor_priv);
- return FALSE;
- }
glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
for (i = 0; i < nbox; i++) {
- glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale,
- dst_yscale,
+ glamor_set_normalize_vcoords(dst_pixmap_priv,
+ dst_xscale, dst_yscale,
box[i].x1 + dst_x_off,
box[i].y1 + dst_y_off,
box[i].x2 + dst_x_off,
glamor_priv->yInverted,
vertices);
- glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale,
+ glamor_set_normalize_tcoords(src_pixmap_priv,
+ src_xscale,
src_yscale,
box[i].x1 + dx,
box[i].y1 + dy,
return TRUE;
}
-static Bool
-_glamor_copy_n_to_n(DrawablePtr src,
- DrawablePtr dst,
- GCPtr gc,
- BoxPtr box,
- int nbox,
- int dx,
- int dy,
- Bool reverse,
- Bool upsidedown, Pixel bitplane,
- void *closure, Bool fallback)
+static Bool
+__glamor_copy_n_to_n(DrawablePtr src,
+ DrawablePtr dst,
+ GCPtr gc,
+ BoxPtr box,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown, Pixel bitplane,
+ void *closure)
{
- glamor_access_t dst_access;
PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL;
DrawablePtr temp_src = src;
glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
int overlaped = 0;
Bool ret = FALSE;
- if (nbox == 0)
- return TRUE;
dst_pixmap = glamor_get_drawable_pixmap(dst);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
src_pixmap = glamor_get_drawable_pixmap(src);
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
screen = dst_pixmap->drawable.pScreen;
glamor_priv = glamor_get_screen_private(dst->pScreen);
-
- if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) {
- glamor_fallback("dest pixmap %p has no fbo. \n",
- dst_pixmap);
- goto fail;
- }
-
- if (!src_pixmap_priv) {
- glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY);
- src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
- }
-
glamor_get_drawable_deltas(src, src_pixmap, &src_x_off,
&src_y_off);
+
glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off,
&dst_y_off);
- if (src_pixmap_priv->base.fbo && src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) {
+ if (src_pixmap_priv->base.fbo
+ && src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) {
int x_shift = abs(src_x_off - dx - dst_x_off);
int y_shift = abs(src_y_off - dy - dst_y_off);
for (i = 0; i < nbox; i++) {
}
}
}
+ DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n",
+ box[0].x1, box[0].y1,
+ box[0].x2 - box[0].x1, box[0].y2 - box[0].y1,
+ dx, dy,
+ src_pixmap, dst_pixmap);
#ifndef GLAMOR_GLES2
if ((overlaped
|| !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex)
/* Overlaped indicate the src and dst are the same pixmap. */
if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)
- && ((bound.x2 - bound.x1) * (bound.y2 - bound.y1)
+ && (((bound.x2 - bound.x1) * (bound.y2 - bound.y1)
* 4 >
src_pixmap->drawable.width *
- src_pixmap->drawable.height))) {
+ src_pixmap->drawable.height)
+ || !(glamor_check_fbo_size(glamor_priv,
+ src_pixmap->drawable.width,
+ src_pixmap->drawable.height))))) {
temp_pixmap = glamor_create_pixmap(screen,
bound.x2 - bound.x1,
drawable.depth,
overlaped ? 0 :
GLAMOR_CREATE_PIXMAP_CPU);
+ assert(bound.x2 - bound.x1 <= glamor_priv->max_fbo_size);
+ assert(bound.y2 - bound.y1 <= glamor_priv->max_fbo_size);
if (!temp_pixmap)
- goto fail;
- glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1);
+ goto done;
+ glamor_translate_boxes(box, nbox, -bound.x1, -bound.y1);
temp_src = &temp_pixmap->drawable;
if (overlaped)
fbCopyNtoN(src, temp_src, gc, box, nbox,
temp_dx + bound.x1, temp_dy + bound.y1,
reverse, upsidedown, bitplane, closure);
- glamor_transform_boxes(box, nbox, bound.x1, bound.y1);
+ glamor_translate_boxes(box, nbox, bound.x1, bound.y1);
temp_dx = -bound.x1;
temp_dy = -bound.y1;
} else {
if (glamor_copy_n_to_n_textured
(temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) {
ret = TRUE;
- goto done;
+ }
+done:
+ if (temp_src != src)
+ glamor_destroy_pixmap(temp_pixmap);
+ return ret;
+}
+
+static Bool
+_glamor_copy_n_to_n(DrawablePtr src,
+ DrawablePtr dst,
+ GCPtr gc,
+ BoxPtr box,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown, Pixel bitplane,
+ void *closure, Bool fallback)
+{
+ glamor_access_t dst_access;
+ PixmapPtr dst_pixmap, src_pixmap;
+ glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
+ glamor_screen_private *glamor_priv;
+ glamor_gl_dispatch *dispatch;
+ BoxPtr extent;
+ RegionRec region;
+ ScreenPtr screen;
+ int src_x_off, src_y_off, dst_x_off, dst_y_off;
+ Bool ret = FALSE;
+ int ok = TRUE;
+ int force_clip = 0;
+
+ if (nbox == 0)
+ return TRUE;
+ dst_pixmap = glamor_get_drawable_pixmap(dst);
+ dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
+ src_pixmap = glamor_get_drawable_pixmap(src);
+ src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
+ screen = dst_pixmap->drawable.pScreen;
+
+ glamor_priv = glamor_get_screen_private(dst->pScreen);
+
+ DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n",
+ box[0].x1, box[0].y1,
+ box[0].x2 - box[0].x1, box[0].y2 - box[0].y1,
+ dx, dy,
+ src_pixmap, dst_pixmap);
+
+ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv))
+ goto fall_back;
+
+ if (gc) {
+ if (!glamor_set_planemask(dst_pixmap, gc->planemask))
+ goto fail;
+ dispatch = glamor_get_dispatch(glamor_priv);
+ if (!glamor_set_alu(dispatch, gc->alu)) {
+ glamor_put_dispatch(glamor_priv);
+ goto fail;
+ }
+ glamor_put_dispatch(glamor_priv);
+ }
+
+ if (!src_pixmap_priv) {
+ glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY);
+ src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
+ }
+
+ glamor_get_drawable_deltas(src, src_pixmap, &src_x_off,
+ &src_y_off);
+ glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off,
+ &dst_y_off);
+
+ RegionInitBoxes(®ion, box, nbox);
+ extent = RegionExtents(®ion);
+
+ if (!glamor_check_fbo_size(glamor_priv,
+ extent->x2 - extent->x1, extent->y2 - extent->y1)
+ && (src_pixmap_priv->type == GLAMOR_MEMORY
+ || (src_pixmap_priv == dst_pixmap_priv))) {
+ force_clip = 1;
}
+ if (force_clip || dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE
+ || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
+ glamor_pixmap_clipped_regions *clipped_dst_regions;
+ int n_dst_region, i, j;
+ PixmapPtr temp_source_pixmap;
+ glamor_pixmap_private *temp_source_priv = NULL;
+ int temp_dx = 0, temp_dy = 0;
+
+ RegionTranslate(®ion, dst_x_off, dst_y_off);
+ if (!force_clip)
+ clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv,
+ ®ion, &n_dst_region, 0);
+ else
+ clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv,
+ ®ion, &n_dst_region,
+ glamor_priv->max_fbo_size,
+ glamor_priv->max_fbo_size);
+ 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(®ion);
+ } else {
+ ok = __glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy,
+ reverse, upsidedown, bitplane,
+ closure);
+ }
- fail:
-
- if (!fallback
+fail:
+ dispatch = glamor_get_dispatch(glamor_priv);
+ glamor_set_alu(dispatch, GXcopy);
+ glamor_put_dispatch(glamor_priv);
+
+ if (ok)
+ return TRUE;
+fall_back:
+ if (!fallback
&& glamor_ddx_fallback_check_pixmap(src)
&& glamor_ddx_fallback_check_pixmap(dst))
goto done;
done:
glamor_clear_delayed_fallbacks(src->pScreen);
glamor_clear_delayed_fallbacks(dst->pScreen);
- if (temp_src != src)
- glamor_destroy_pixmap(temp_pixmap);
return ret;
}
int dx,
int dy,
Bool reverse,
- Bool upsidedown, Pixel bitplane,
+ Bool upsidedown, Pixel bitplane,
void *closure)
{
- _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx,
+ _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx,
dy, reverse, upsidedown, bitplane, closure, TRUE);
}
int dx,
int dy,
Bool reverse,
- Bool upsidedown, Pixel bitplane,
+ Bool upsidedown, Pixel bitplane,
void *closure)
{
- return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx,
+ return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx,
dy, reverse, upsidedown, bitplane, closure, FALSE);
}
if (fbo->fb == 0 || n_format == -1
|| fbo->glamor_priv->fbo_cache_watermark >= FBO_CACHE_THRESHOLD) {
- fbo->glamor_priv->tick ++;
+ fbo->glamor_priv->tick += GLAMOR_CACHE_EXPIRE_MAX;
+ glamor_fbo_expire(fbo->glamor_priv);
glamor_purge_fbo(fbo);
return;
}
return fbo;
}
+static glamor_pixmap_fbo *
+_glamor_create_fbo_array(glamor_screen_private *glamor_priv,
+ int w, int h, GLenum format, int flag,
+ int block_w, int block_h,
+ glamor_pixmap_private *pixmap_priv,
+ int has_fbo)
+{
+ int block_wcnt;
+ int block_hcnt;
+ glamor_pixmap_fbo **fbo_array;
+ BoxPtr box_array;
+ int i,j;
+ glamor_pixmap_private_large_t *priv;
+
+ priv = &pixmap_priv->large;
+
+ block_wcnt = (w + block_w - 1) / block_w;
+ block_hcnt = (h + block_h - 1) / block_h;
+
+ box_array = calloc(block_wcnt * block_hcnt, sizeof(box_array[0]));
+ if (box_array == NULL)
+ return NULL;
+
+ fbo_array = calloc(block_wcnt * block_hcnt, sizeof(glamor_pixmap_fbo*));
+ if (fbo_array == NULL) {
+ free(box_array);
+ return FALSE;
+ }
+ for(i = 0; i < block_hcnt; i++)
+ {
+ int block_y1, block_y2;
+ int fbo_w, fbo_h;
+
+ block_y1 = i * block_h;
+ block_y2 = (block_y1 + block_h) > h ? h : (block_y1 + block_h);
+ fbo_h = block_y2 - block_y1;
+
+ for (j = 0; j < block_wcnt; j++)
+ {
+ box_array[i * block_wcnt + j].x1 = j * block_w;
+ box_array[i * block_wcnt + j].y1 = block_y1;
+ box_array[i * block_wcnt + j].x2 = (j + 1) * block_w > w ? w : (j + 1) * block_w;
+ box_array[i * block_wcnt + j].y2 = block_y2;
+ fbo_w = box_array[i * block_wcnt + j].x2 - box_array[i * block_wcnt + j].x1;
+ if (!has_fbo)
+ fbo_array[i * block_wcnt + j] = glamor_create_fbo(glamor_priv,
+ fbo_w, fbo_h, format,
+ GLAMOR_CREATE_PIXMAP_FIXUP);
+ else
+ fbo_array[i * block_wcnt + j] = priv->base.fbo;
+ if (fbo_array[i * block_wcnt + j] == NULL)
+ goto cleanup;
+ }
+ }
+
+ priv->box = box_array[0];
+ priv->box_array = box_array;
+ priv->fbo_array = fbo_array;
+ priv->block_wcnt = block_wcnt;
+ priv->block_hcnt = block_hcnt;
+ return fbo_array[0];
+
+cleanup:
+ for(i = 0; i < block_wcnt * block_hcnt; i++)
+ if ((fbo_array)[i])
+ glamor_destroy_fbo((fbo_array)[i]);
+ free(box_array);
+ free(fbo_array);
+ return NULL;
+}
+
+
+/* Create a fbo array to cover the w*h region, by using block_w*block_h
+ * block.*/
+glamor_pixmap_fbo *
+glamor_create_fbo_array(glamor_screen_private *glamor_priv,
+ int w, int h, GLenum format, int flag,
+ int block_w, int block_h,
+ glamor_pixmap_private *pixmap_priv)
+{
+ pixmap_priv->large.block_w = block_w;
+ pixmap_priv->large.block_h = block_h;
+ return _glamor_create_fbo_array(glamor_priv, w, h, format, flag,
+ block_w, block_h, pixmap_priv, 0);
+}
+
glamor_pixmap_fbo *
glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv)
{
pixmap_priv = glamor_get_pixmap_private(pixmap);
- if (pixmap_priv == NULL) {
- glamor_screen_private *glamor_priv;
- glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
- pixmap_priv = calloc(1, sizeof(*pixmap_priv));
- dixSetPrivate(&pixmap->devPrivates,
- glamor_pixmap_private_key, pixmap_priv);
- pixmap_priv->base.pixmap = pixmap;
- pixmap_priv->base.glamor_priv = glamor_priv;
- pixmap_priv->type = GLAMOR_MEMORY;
- }
-
if (pixmap_priv->base.fbo)
return;
pixmap_priv->base.fbo = fbo;
switch (pixmap_priv->type) {
+ case GLAMOR_TEXTURE_LARGE:
case GLAMOR_TEXTURE_ONLY:
case GLAMOR_TEXTURE_DRM:
pixmap_priv->base.gl_fbo = 1;
}
}
+void
+glamor_pixmap_destroy_fbo(glamor_pixmap_private *priv)
+{
+ glamor_pixmap_fbo *fbo;
+ if (priv->type == GLAMOR_TEXTURE_LARGE) {
+ int i;
+ glamor_pixmap_private_large_t *large = &priv->large;
+ for(i = 0; i < large->block_wcnt * large->block_hcnt; i++)
+ glamor_destroy_fbo(large->fbo_array[i]);
+ free(large->fbo_array);
+ } else {
+ fbo = glamor_pixmap_detach_fbo(priv);
+ if (fbo)
+ glamor_destroy_fbo(fbo);
+ free(priv);
+ }
+}
Bool
glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag)
glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
pixmap_priv = glamor_get_pixmap_private(pixmap);
- if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) {
+ if (pixmap_priv->base.fbo == NULL) {
fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
pixmap->drawable.height,
glamor_pixmap_ensure_fb(pixmap_priv->base.fbo);
}
- pixmap_priv = glamor_get_pixmap_private(pixmap);
return TRUE;
}
glamor_put_dispatch(glamor_priv);
}
-Bool
-glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
- unsigned char alu, unsigned long planemask,
- unsigned long fg_pixel)
+static void
+_glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
+ float *color)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_screen_private *glamor_priv =
int x2 = x + width;
int y1 = y;
int y2 = y + height;
- GLfloat color[4];
float vertices[8];
GLfloat xscale, yscale;
- if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) {
- glamor_fallback("dest %p has no fbo.\n", pixmap);
+ glamor_set_destination_pixmap_priv_nc(pixmap_priv);
+
+ dispatch = glamor_get_dispatch(glamor_priv);
+ dispatch->glUseProgram(glamor_priv->solid_prog);
+
+ dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location,
+ 1, color);
+
+ dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+ GL_FALSE, 2 * sizeof(float),
+ vertices);
+ dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+ pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
+
+ glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale,
+ x1, y1,
+ x2, y2,
+ glamor_priv->yInverted, vertices);
+ dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+ dispatch->glUseProgram(0);
+ glamor_put_dispatch(glamor_priv);
+}
+
+Bool
+glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
+ unsigned char alu, unsigned long planemask,
+ unsigned long fg_pixel)
+{
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ glamor_screen_private *glamor_priv =
+ glamor_get_screen_private(screen);
+ glamor_pixmap_private *pixmap_priv;
+ glamor_gl_dispatch *dispatch;
+ GLfloat color[4];
+
+ pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return FALSE;
- }
if (!glamor_set_planemask(pixmap, planemask)) {
glamor_fallback
&color[2],
&color[3], format_for_pixmap(pixmap));
- glamor_set_destination_pixmap_priv_nc(pixmap_priv);
-
dispatch = glamor_get_dispatch(glamor_priv);
if (!glamor_set_alu(dispatch, alu)) {
if (alu == GXclear)
return FALSE;
}
}
- dispatch->glUseProgram(glamor_priv->solid_prog);
- dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location,
- 1, color);
+ if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
+ RegionRec region;
+ BoxRec box;
+ int n_region;
+ glamor_pixmap_clipped_regions *clipped_regions;
+ int i,j;
- dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
- GL_FALSE, 2 * sizeof(float),
- vertices);
- dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
- pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = x + width;
+ box.y2 = y + height;
+ RegionInitBoxes(®ion, &box, 1);
+ clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &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(®ion);
+ } else
+ _glamor_solid(pixmap,
+ x,
+ y,
+ width, height,
+ color);
- glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale, x1, y1, x2, y2,
- glamor_priv->yInverted, vertices);
- dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
- dispatch->glUseProgram(0);
glamor_set_alu(dispatch, GXcopy);
glamor_put_dispatch(glamor_priv);
+
return TRUE;
}
--- /dev/null
+#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);
+}
void
glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv)
{
+ int w,h;
+
+ PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap_priv, w, h);
glamor_set_destination_pixmap_fbo(pixmap_priv->base.fbo, 0, 0,
- pixmap_priv->base.pixmap->drawable.width,
- pixmap_priv->base.pixmap->drawable.height);
+ w, h);
}
int
}
ready_to_upload:
+
/* Try fast path firstly, upload the pixmap to the texture attached
* to the fbo directly. */
if (no_alpha == 0
&& revert == REVERT_NONE
&& swap_rb == SWAP_NONE_UPLOADING
&& !need_flip) {
+ int fbo_x_off, fbo_y_off;
assert(pixmap_priv->base.fbo->tex);
+ pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off);
+
+ assert(x + fbo_x_off >= 0 && y + fbo_y_off >= 0);
+ assert(x + fbo_x_off + w <= pixmap_priv->base.fbo->width);
+ assert(y + fbo_y_off + h <= pixmap_priv->base.fbo->height);
__glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->base.fbo->tex,
format, type,
- x, y, w, h,
+ x + fbo_x_off, y + fbo_y_off, w, h,
bits, pbo);
return TRUE;
}
x + w, y + h,
glamor_priv->yInverted,
vertices);
-
/* Slow path, we need to flip y or wire alpha to 1. */
dispatch = glamor_get_dispatch(glamor_priv);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
pixmap_priv = glamor_get_pixmap_private(pixmap);
glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
+ if (pixmap_priv->base.gl_fbo)
+ return 0;
+
if (pixmap_priv->base.fbo
&& (pixmap_priv->base.fbo->width < pixmap->drawable.width
|| pixmap_priv->base.fbo->height < pixmap->drawable.height)) {
flag = GLAMOR_CREATE_FBO_NO_FBO;
}
- if ((flag == 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex)
- || (flag != 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb))
+ if ((flag == GLAMOR_CREATE_FBO_NO_FBO
+ && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex)
+ || (flag == 0
+ && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb))
return 0;
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
else
iformat = format;
- if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) {
-
- fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
- pixmap->drawable.height,
- iformat,
- flag);
- if (fbo == NULL) {
- glamor_fallback
- ("upload failed, depth %d x %d @depth %d \n",
- pixmap->drawable.width, pixmap->drawable.height,
- pixmap->drawable.depth);
- return -1;
- }
+ if (!glamor_pixmap_ensure_fbo(pixmap, iformat, flag))
+ 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;
+}
+
+/*
+ * 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;
- return 0;
+ byte_per_pixel = bpp / 8;
+ dst_bits += y * dst_stride + x * byte_per_pixel;
+
+ for(j = y; j < y + h; j++)
+ {
+ memcpy(dst_bits, src_bits, w * byte_per_pixel);
+ src_bits += src_stride;
+ dst_bits += dst_stride;
+ }
}
+
Bool
glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h,
int stride, void *bits, int pbo)
{
GLenum format, type;
int no_alpha, revert, swap_rb;
+ glamor_pixmap_private *pixmap_priv;
if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format,
if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb))
return FALSE;
- return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha, revert, swap_rb,
+ pixmap_priv = glamor_get_pixmap_private(pixmap);
+ if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
+ RegionRec region;
+ BoxRec box;
+ int n_region;
+ glamor_pixmap_clipped_regions *clipped_regions;
+ void *sub_bits;
+ int i,j;
+
+ sub_bits = malloc(h * stride);
+ if (sub_bits == NULL)
+ return FALSE;
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = x + w;
+ box.y2 = y + h;
+ RegionInitBoxes(®ion, &box, 1);
+ clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &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(®ion);
+ free(sub_bits);
+ assert(0);
+ return FALSE;
+ }
+ }
+ RegionDestroy(clipped_regions[i].region);
+ }
+ free(sub_bits);
+ free(clipped_regions);
+ RegionUninit(®ion);
+ 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);
}
pixmap_priv = glamor_get_pixmap_private(pixmap);
- if (pixmap_priv
- && (pixmap_priv->base.fbo)
+ if ((pixmap_priv->base.fbo)
&& (pixmap_priv->base.fbo->pbo_valid)) {
data = NULL;
pbo = pixmap_priv->base.fbo->pbo;
temp_xscale = 1.0 / w;
temp_yscale = 1.0 / h;
- glamor_set_normalize_vcoords((glamor_pixmap_private *)NULL, temp_xscale,
+ glamor_set_normalize_vcoords((struct glamor_pixmap_private*)NULL,temp_xscale,
temp_yscale,
0, 0,
w, h,
* The pixmap must have a valid FBO, otherwise return a NULL.
* */
-void *
-glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
- int stride, void *bits, int pbo, glamor_access_t access)
+static void *
+_glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
+ GLenum type, int no_alpha,
+ int revert, int swap_rb,
+ int x, int y, int w, int h,
+ int stride, void *bits, int pbo, glamor_access_t access)
{
glamor_pixmap_private *pixmap_priv;
- GLenum format, type, gl_access = 0, gl_usage = 0;
- int no_alpha, revert, swap_rb;
+ GLenum gl_access = 0, gl_usage = 0;
void *data, *read;
ScreenPtr screen;
glamor_screen_private *glamor_priv =
glamor_pixmap_fbo *temp_fbo = NULL;
int need_post_conversion = 0;
int need_free_data = 0;
+ int fbo_x_off, fbo_y_off;
data = bits;
screen = pixmap->drawable.pScreen;
assert(0);
}
- if (glamor_get_tex_format_type_from_pixmap(pixmap,
- &format,
- &type,
- &no_alpha,
- &revert,
- &swap_rb, 0)) {
- ErrorF("Unknown pixmap depth %d.\n",
- pixmap->drawable.depth);
- assert(0); // Should never happen.
- return NULL;
- }
-
glamor_set_destination_pixmap_priv_nc(pixmap_priv);
need_post_conversion = (revert > REVERT_NORMAL);
}
}
+ pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off);
+
if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
&& !need_post_conversion
&& (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) {
}
x = 0;
y = 0;
+ fbo_x_off = 0;
+ fbo_y_off = 0;
}
dispatch = glamor_get_dispatch(glamor_priv);
NULL, gl_usage);
}
- dispatch->glReadPixels(x, y, w, h, format, type, data);
+ dispatch->glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, data);
if (!glamor_priv->yInverted) {
assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
stride *
h,
NULL, GL_STREAM_READ);
- dispatch->glReadPixels(0, 0, w, h,
+ dispatch->glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h,
format, type, 0);
read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER,
GL_READ_ONLY);
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(®ion, &box, 1);
+ clipped_regions = glamor_compute_clipped_regions(pixmap_priv, ®ion, &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(®ion);
+ 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(®ion);
+ 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.
if (access == GLAMOR_ACCESS_WO
|| glamor_priv->gl_flavor == GLAMOR_GL_ES2
- || (!glamor_priv->has_pack_invert && !glamor_priv->yInverted)) {
+ || (!glamor_priv->has_pack_invert && !glamor_priv->yInverted)
+ || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
data = malloc(stride * pixmap->drawable.height);
} else {
dispatch = glamor_get_dispatch(glamor_priv);
}
/* fixup a fbo to the exact size as the pixmap. */
+/* XXX LARGE pixmap? */
Bool
glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
{
drawable = &pixmap_priv->base.pixmap->drawable;
- if (pixmap_priv->base.pixmap->drawable.width == pixmap_priv->base.fbo->width
- && pixmap_priv->base.pixmap->drawable.height == pixmap_priv->base.fbo->height)
+ if (!GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))
return TRUE;
old_fbo = pixmap_priv->base.fbo;
scratch_priv = glamor_get_pixmap_private(scratch);
- if (!scratch_priv || !scratch_priv->base.fbo)
+ if (!scratch_priv->base.fbo)
goto fail;
ValidateGC(&scratch->drawable, gc);
void *data;
int pbo;
int flag;
-
- assert(x >= 0 && y >= 0);
+ if (x < 0 || y < 0)
+ return NULL;
w = (x + w) > pixmap->drawable.width ? (pixmap->drawable.width - x) : w;
h = (y + h) > pixmap->drawable.height ? (pixmap->drawable.height - y) : h;
if (access == GLAMOR_ACCESS_WO) {
sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU);
- ErrorF("WO\n");
return sub_pixmap;
}
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return NULL;
- if (glamor_priv->gl_flavor == GLAMOR_GL_ES2)
+ if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 || pixmap_priv->type == GLAMOR_TEXTURE_LARGE)
flag = GLAMOR_CREATE_PIXMAP_CPU;
else
flag = GLAMOR_CREATE_PIXMAP_MAP;
sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
pbo = sub_pixmap_priv ? (sub_pixmap_priv->base.fbo ? sub_pixmap_priv->base.fbo->pbo : 0): 0;
- if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) {
+ if (pixmap_priv->base.is_picture) {
sub_pixmap_priv->base.picture = pixmap_priv->base.picture;
sub_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture;
}
if (pbo)
data = NULL;
- else {
+ else
data = sub_pixmap->devPrivate.ptr;
- assert(flag != GLAMOR_CREATE_PIXMAP_MAP);
- }
+
data = glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h, sub_pixmap->devKind,
data, pbo, access);
if (pbo) {
new_sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU);
- glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap, NULL, &box, 1, dx, dy, 0, 0, 0, NULL);
+ glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap->drawable, NULL, &box, 1, dx, dy, 0, 0, 0, NULL);
glamor_compare_pixmaps(new_sub_pixmap, sub_pixmap, 0, 0, w, h, 1, 1);
#endif
glamor_pixmap_private *sub_pixmap_priv;
if (access != GLAMOR_ACCESS_RO) {
sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
- if (sub_pixmap_priv
- && sub_pixmap_priv->base.fbo
+ if (sub_pixmap_priv->base.fbo
&& sub_pixmap_priv->base.fbo->pbo_valid) {
bits = NULL;
pbo = sub_pixmap_priv->base.fbo->pbo;
#ifndef GLAMOR_GLES2
#define GLAMOR_GRADIENT_SHADER
#endif
-#define GLAMOR_TEXTURED_LARGE_PIXMAP 1
+#define GLAMOR_TEXTURED_LARGE_PIXMAP 0
+#if 0
+#define MAX_FBO_SIZE 512 /* For test purpose only. */
+#endif
#endif /* GLAMOR_PRIV_H */
#ifdef RENDER
#include "mipict.h"
#include "fbpict.h"
-
+#if 0
+//#define DEBUGF(str, ...) do {} while(0)
+#define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__)
+//#define DEBUGRegionPrint(x) do {} while (0)
+#define DEBUGRegionPrint RegionPrint
+#endif
struct shader_key {
enum shader_source source;
enum shader_mask mask;
#endif
/* XXX may be we can eaxctly check whether we need to touch
* the out-of-box area then determine whether we need to fix.
- * */
- if (repeat_type != RepeatNone)
- repeat_type += RepeatFix;
- else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
- if (picture->transform
- || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv)))
+ **/
+ /*if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE)*/ {
+ if (repeat_type != RepeatNone)
repeat_type += RepeatFix;
- }
-
- if (repeat_type >= RepeatFix) {
- glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv);
- dispatch->glUniform2fv(wh_location, 1, wh);
+ else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
+ || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
+ if (picture->transform
+ || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv)))
+ repeat_type += RepeatFix;
+ }
+ if (repeat_type >= RepeatFix) {
+ glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv);
+ dispatch->glUniform2fv(wh_location, 1, wh);
+ }
}
dispatch->glUniform1i(repeat_location, repeat_type);
glamor_put_dispatch(glamor_priv);
INT16 x_source,
INT16 y_source,
INT16 x_dest,
- INT16 y_dest, CARD16 width, CARD16 height)
+ INT16 y_dest,
+ RegionPtr region)
{
- RegionRec region;
int ret = FALSE;
-
if (!source->pDrawable)
return FALSE;
if (!compatible_formats(op, dest, source))
return FALSE;
- if (source->repeat || source->transform)
+ if (source->repeat || source->transform) {
return FALSE;
+ }
x_dest += dest->pDrawable->x;
y_dest += dest->pDrawable->y;
x_source += source->pDrawable->x;
y_source += source->pDrawable->y;
- if (!miComputeCompositeRegion(®ion,
- source, NULL, dest,
- x_source, y_source,
- 0, 0, x_dest, y_dest, width, height))
- return TRUE;
-
if (PICT_FORMAT_A(source->format) == 0) {
/* Fallback if we sample outside the source so that we
* swizzle the correct clear color for out-of-bounds texels.
*/
- if (region.extents.x1 + x_source - x_dest < 0)
+ if (region->extents.x1 + x_source - x_dest < 0)
goto cleanup_region;
- if (region.extents.x2 + x_source - x_dest > source->pDrawable->width)
+ if (region->extents.x2 + x_source - x_dest > source->pDrawable->width)
goto cleanup_region;
- if (region.extents.y1 + y_source - y_dest < 0)
+ if (region->extents.y1 + y_source - y_dest < 0)
goto cleanup_region;
- if (region.extents.y2 + y_source - y_dest > source->pDrawable->height)
+ if (region->extents.y2 + y_source - y_dest > source->pDrawable->height)
goto cleanup_region;
}
-
ret = glamor_copy_n_to_n_nf(source->pDrawable,
dest->pDrawable, NULL,
- REGION_RECTS(®ion),
- REGION_NUM_RECTS(®ion),
+ RegionRects(region), RegionNumRects(region),
x_source - x_dest, y_source - y_dest,
FALSE, FALSE, 0, NULL);
cleanup_region:
- REGION_UNINIT(dest->pDrawable->pScreen, ®ion);
return ret;
}
return FALSE;
}
+static void
+glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv,
+ int repeat_type,
+ float *matrix,
+ float xscale, float yscale,
+ int x1, int y1, int x2, int y2,
+ int yInverted, float *texcoords)
+{
+ if (!matrix && repeat_type == RepeatNone)
+ glamor_set_normalize_tcoords(priv, xscale, yscale,
+ x1, y1,
+ x2, y2,
+ yInverted,
+ texcoords);
+ else if (matrix && repeat_type == RepeatNone)
+ glamor_set_transformed_normalize_tcoords(priv, matrix, xscale,
+ yscale, x1, y1,
+ x2, y2,
+ yInverted,
+ texcoords);
+ else if (!matrix && repeat_type != RepeatNone)
+ glamor_set_repeat_normalize_tcoords(priv, repeat_type,
+ xscale, yscale,
+ x1, y1,
+ x2, y2,
+ yInverted,
+ texcoords);
+ else if (matrix && repeat_type != RepeatNone)
+ assert(0);
+}
+
static Bool
glamor_composite_with_shader(CARD8 op,
PicturePtr source,
PicturePtr mask,
PicturePtr dest,
- int nrect, glamor_composite_rect_t * rects)
+ int nrect,
+ glamor_composite_rect_t * rects)
{
ScreenPtr screen = dest->pDrawable->pScreen;
glamor_screen_private *glamor_priv =
enum glamor_pixmap_status mask_status = GLAMOR_NONE;
PictFormatShort saved_source_format = 0;
float src_matrix[9], mask_matrix[9];
+ float *psrc_matrix = NULL, *pmask_matrix = NULL;
GLfloat source_solid_color[4], mask_solid_color[4];
int vert_stride = 4;
int nrect_max;
goto fail;
}
memset(&key, 0, sizeof(key));
- if (!source->pDrawable) {
- if (source->pSourcePict->type == SourcePictTypeSolidFill) {
- key.source = SHADER_SOURCE_SOLID;
- glamor_get_rgba_from_pixel(source->
- pSourcePict->solidFill.
- color,
- &source_solid_color[0],
- &source_solid_color[1],
- &source_solid_color[2],
- &source_solid_color[3],
- PICT_a8r8g8b8);
- } else {
- glamor_fallback("gradient source\n");
- goto fail;
+ if (!source) {
+ key.source = SHADER_SOURCE_SOLID;
+ source_solid_color[0] = 0.0;
+ source_solid_color[1] = 0.0;
+ source_solid_color[2] = 0.0;
+ source_solid_color[3] = 0.0;
+ } else if (!source->pDrawable) {
+ if (source->pSourcePict->type == SourcePictTypeSolidFill) {
+ key.source = SHADER_SOURCE_SOLID;
+ glamor_get_rgba_from_pixel(source->
+ pSourcePict->solidFill.
+ color,
+ &source_solid_color[0],
+ &source_solid_color[1],
+ &source_solid_color[2],
+ &source_solid_color[3],
+ PICT_a8r8g8b8);
}
} else {
key.source = SHADER_SOURCE_TEXTURE_ALPHA;
&mask_solid_color[1],
&mask_solid_color[2],
&mask_solid_color[3], PICT_a8r8g8b8);
- } else {
- glamor_fallback("gradient mask\n");
- goto fail;
}
} else {
key.mask = SHADER_MASK_TEXTURE_ALPHA;
key.in = SHADER_IN_SOURCE_ONLY;
}
- if (source->alphaMap) {
+ if (source && source->alphaMap) {
glamor_fallback("source alphaMap\n");
goto fail;
}
source_pixmap_priv =
glamor_get_pixmap_private(source_pixmap);
if (source_pixmap == dest_pixmap) {
+ /* XXX source and the dest share the same texture.
+ * Does it need special handle? */
glamor_fallback("source == dest\n");
- goto fail;
}
- if (!source_pixmap_priv || source_pixmap_priv->base.gl_fbo == 0) {
- /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex
+ if (source_pixmap_priv->base.gl_fbo == 0) {
+ /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex
* equal to zero when the pixmap is screen pixmap. Then we may
- * refer the tex zero directly latter in the composition.
+ * refer the tex zero directly latter in the composition.
* It seems that it works fine, but it may have potential problem*/
#ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
source_status = GLAMOR_UPLOAD_PENDING;
glamor_fallback("mask == dest\n");
goto fail;
}
- if (!mask_pixmap_priv || mask_pixmap_priv->base.gl_fbo == 0) {
+ if (mask_pixmap_priv->base.gl_fbo == 0) {
#ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
mask_status = GLAMOR_UPLOAD_PENDING;
#else
}
if (source->format != saved_source_format) {
- glamor_picture_format_fixup(source,
- source_pixmap_priv);
+ //glamor_picture_format_fixup(source,
+ // source_pixmap_priv);
}
- /* XXX
+ /* XXX
* By default, glamor_upload_picture_to_texture will wire alpha to 1
- * if one picture doesn't have alpha. So we don't do that again in
+ * if one picture doesn't have alpha. So we don't do that again in
* rendering function. But here is a special case, as source and
- * mask share the same texture but may have different formats. For
+ * mask share the same texture but may have different formats. For
* example, source doesn't have alpha, but mask has alpha. Then the
* texture will have the alpha value for the mask. And will not wire
* to 1 for the source. In this case, we have to use different shader
* to wire the source's alpha to 1.
*
- * But this may cause a potential problem if the source's repeat mode
+ * But this may cause a potential problem if the source's repeat mode
* is REPEAT_NONE, and if the source is smaller than the dest, then
* for the region not covered by the source may be painted incorrectly.
* because we wire the alpha to 1.
* transformed source and mask, if the transform is not int translate. */
if (key.source != SHADER_SOURCE_SOLID
&& source->transform
- && !pixman_transform_is_int_translate(source->transform)) {
+ && !pixman_transform_is_int_translate(source->transform)
+ && source_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) {
if (!glamor_fixup_pixmap_priv(screen, source_pixmap_priv))
goto fail;
}
if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID
&& mask->transform
- && !pixman_transform_is_int_translate(mask->transform)) {
+ && !pixman_transform_is_int_translate(mask->transform)
+ && mask_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) {
if (!glamor_fixup_pixmap_priv(screen, mask_pixmap_priv))
goto fail;
}
&source_y_off);
pixmap_priv_get_scale(source_pixmap_priv, &src_xscale,
&src_yscale);
- glamor_picture_get_matrixf(source, src_matrix);
+ if (source->transform) {
+ psrc_matrix = src_matrix;
+ glamor_picture_get_matrixf(source, psrc_matrix);
+ }
vert_stride += 4;
}
&mask_x_off, &mask_y_off);
pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale,
&mask_yscale);
- glamor_picture_get_matrixf(mask, mask_matrix);
+ if (mask->transform) {
+ pmask_matrix = mask_matrix;
+ glamor_picture_get_matrixf(mask, pmask_matrix);
+ }
vert_stride += 4;
}
x_dest = rects->x_dst + dest_x_off;
y_dest = rects->y_dst + dest_y_off;
- x_source = rects->x_src + source_x_off;;
+ x_source = rects->x_src + source_x_off;
y_source = rects->y_src + source_y_off;
x_mask = rects->x_mask + mask_x_off;
y_mask = rects->y_mask + mask_y_off;
width = rects->width;
height = rects->height;
+ DEBUGF("dest(%d,%d) source(%d %d) mask (%d %d), width %d height %d \n",
+ x_dest, y_dest, x_source, y_source,x_mask,y_mask,width,height);
+
glamor_set_normalize_vcoords(dest_pixmap_priv, dst_xscale,
dst_yscale,
x_dest, y_dest,
glamor_priv->yInverted,
vertices);
- if (key.source != SHADER_SOURCE_SOLID) {
- if (source->transform)
- glamor_set_transformed_normalize_tcoords
- (source_pixmap_priv, src_matrix, src_xscale,
- src_yscale, x_source, y_source,
- x_source + width, y_source + height,
- glamor_priv->yInverted,
- source_texcoords);
- else
- glamor_set_normalize_tcoords
- (source_pixmap_priv, src_xscale, src_yscale,
- x_source, y_source,
- x_source + width, y_source + height,
- glamor_priv->yInverted,
- source_texcoords);
- }
+ if (key.source != SHADER_SOURCE_SOLID)
+ glamor_set_normalize_tcoords_generic(
+ source_pixmap_priv, source->repeatType, psrc_matrix,
+ src_xscale, src_yscale, x_source, y_source,
+ x_source + width, y_source + height,
+ glamor_priv->yInverted, source_texcoords);
if (key.mask != SHADER_MASK_NONE
- && key.mask != SHADER_MASK_SOLID) {
- if (mask->transform)
- glamor_set_transformed_normalize_tcoords
- (mask_pixmap_priv, mask_matrix,
- mask_xscale,
- mask_yscale, x_mask, y_mask,
- x_mask + width, y_mask + height,
- glamor_priv->yInverted,
- mask_texcoords);
- else
- glamor_set_normalize_tcoords
- (mask_pixmap_priv, mask_xscale,
- mask_yscale, x_mask, y_mask,
- x_mask + width, y_mask + height,
- glamor_priv->yInverted,
- mask_texcoords);
- }
+ && key.mask != SHADER_MASK_SOLID)
+ glamor_set_normalize_tcoords_generic(
+ mask_pixmap_priv, mask->repeatType, pmask_matrix,
+ mask_xscale, mask_yscale, x_mask, y_mask,
+ x_mask + width, y_mask + height,
+ glamor_priv->yInverted, mask_texcoords);
+
glamor_emit_composite_rect(screen,
source_texcoords,
mask_texcoords,
dispatch->glActiveTexture(GL_TEXTURE1);
dispatch->glDisable(GL_TEXTURE_2D);
#endif
+ DEBUGF("finish rendering.\n");
dispatch->glUseProgram(0);
if (saved_source_format)
source->format = saved_source_format;
return dst;
}
-static Bool
-_glamor_composite(CARD8 op,
- PicturePtr source,
- PicturePtr mask,
- PicturePtr dest,
- INT16 x_source,
- INT16 y_source,
- INT16 x_mask,
- INT16 y_mask,
- INT16 x_dest, INT16 y_dest,
- CARD16 width, CARD16 height, Bool fallback)
+Bool
+glamor_composite_clipped_region(CARD8 op,
+ PicturePtr source,
+ PicturePtr mask,
+ PicturePtr dest,
+ RegionPtr region,
+ int x_source,
+ int y_source,
+ int x_mask,
+ int y_mask,
+ int x_dest,
+ int y_dest)
{
ScreenPtr screen = dest->pDrawable->pScreen;
glamor_pixmap_private *dest_pixmap_priv;
PixmapPtr source_pixmap = NULL, mask_pixmap = NULL;
PicturePtr temp_src = source, temp_mask = mask;
int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask;
+
+ BoxPtr extent;
glamor_composite_rect_t rect[10];
glamor_composite_rect_t *prect = rect;
int prect_size = ARRAY_SIZE(rect);
- glamor_screen_private *glamor_priv =
- glamor_get_screen_private(screen);
- Bool ret = TRUE;
- RegionRec region;
+ int ok = FALSE;
+ int i;
+ int width;
+ int height;
BoxPtr box;
- int nbox, i, ok = FALSE;
- PixmapPtr sub_dest_pixmap = NULL;
- PixmapPtr sub_source_pixmap = NULL;
- PixmapPtr sub_mask_pixmap = NULL;
- int dest_x_off, dest_y_off, saved_dest_x = 0, saved_dest_y = 0;
- int source_x_off, source_y_off, saved_source_x = 0, saved_source_y = 0;
- int mask_x_off, mask_y_off, saved_mask_x = 0, saved_mask_y = 0;
- DrawablePtr saved_dest_drawable = NULL;
- DrawablePtr saved_source_drawable = NULL;
- DrawablePtr saved_mask_drawable = NULL;
+ int nbox;
+ extent = RegionExtents(region);
+ box = RegionRects(region);
+ nbox = RegionNumRects(region);
+ width = extent->x2 - extent->x1;
+ height = extent->y2 - extent->y1;
x_temp_src = x_source;
y_temp_src = y_source;
x_temp_mask = x_mask;
y_temp_mask = y_mask;
-
- DEBUGF("Composite Src: (%d, %d)\n"
- " Mask: (%d, %d)\n"
- " to dst: (%d, %d), size: %d X %d \n",
- x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height);
+ DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n",
+ x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height);
+ DEBUGF("dest pixmap %p ", dest_pixmap);
dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
/* Currently. Always fallback to cpu if destination is in CPU memory. */
- if (source->pDrawable) {
+ if (source && source->pDrawable) {
source_pixmap = glamor_get_drawable_pixmap(source->pDrawable);
source_pixmap_priv = glamor_get_pixmap_private(source_pixmap);
- if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY)
- goto fail;
}
if (mask && mask->pDrawable) {
mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable);
mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap);
- if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY)
- goto fail;
- }
-
- if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) {
- goto fail;
}
- if (op >= ARRAY_SIZE(composite_op_info))
- goto fail;
-
- if ((!source->pDrawable
+ /* XXX is it possible source mask have non-zero drawable.x/y? */
+ if (source
+ && ((!source->pDrawable
&& (source->pSourcePict->type != SourcePictTypeSolidFill))
|| (source->pDrawable
&& !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv)
- &&
- ((width * height * 4 <
- (source_pixmap->drawable.width *
- source_pixmap->drawable.height))
- ||
- !(glamor_check_fbo_size
- (glamor_priv, source_pixmap->drawable.width,
- source_pixmap->drawable.height))))) {
+ && (source_pixmap->drawable.width != width
+ || source_pixmap->drawable.height != height)))) {
temp_src =
glamor_convert_gradient_picture(screen, source,
- x_source, y_source,
+ extent->x1 + x_source - x_dest,
+ extent->y1 + y_source - y_dest,
width, height);
if (!temp_src) {
temp_src = source;
- goto fail;
+ goto out;
}
- x_temp_src = y_temp_src = 0;
+ x_temp_src = - extent->x1 + x_dest;
+ y_temp_src = - extent->y1 + y_dest;
}
if (mask
((!mask->pDrawable
&& (mask->pSourcePict->type != SourcePictTypeSolidFill))
|| (mask->pDrawable
- && (!GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv))
- &&
- ((width * height * 4 <
- (mask_pixmap->drawable.width *
- mask_pixmap->drawable.height))
- ||
- !(glamor_check_fbo_size
- (glamor_priv, mask_pixmap->drawable.width,
- mask_pixmap->drawable.height)))))) {
+ && !GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)
+ && (mask_pixmap->drawable.width != width
+ || mask_pixmap->drawable.height != height)))) {
/* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity
* to do reduce one convertion. */
temp_mask =
glamor_convert_gradient_picture(screen, mask,
- x_mask, y_mask,
+ extent->x1 + x_mask - x_dest,
+ extent->y1 + y_mask - y_dest,
width, height);
if (!temp_mask) {
temp_mask = mask;
- goto fail;
+ goto out;
}
- x_temp_mask = y_temp_mask = 0;
+ x_temp_mask = - extent->x1 + x_dest;
+ y_temp_mask = - extent->y1 + y_dest;
}
/* Do two-pass PictOpOver componentAlpha, until we enable
* dual source color blending.
if (mask && mask->componentAlpha) {
if (op == PictOpOver) {
- glamor_composite(PictOpOutReverse,
- temp_src, temp_mask, dest,
- x_temp_src, y_temp_src,
- x_temp_mask, y_temp_mask,
- x_dest, y_dest, width, height);
- glamor_composite(PictOpAdd,
- temp_src, temp_mask, dest,
- x_temp_src, y_temp_src,
- x_temp_mask, y_temp_mask,
- x_dest, y_dest, width, height);
- goto done;
-
- } else if (op == PictOpAtop
- || op == PictOpAtopReverse
- || op == PictOpXor
- || op >= PictOpSaturate) {
- glamor_fallback
- ("glamor_composite(): component alpha op %x\n", op);
- goto fail;
+ glamor_composite_clipped_region(PictOpOutReverse,
+ temp_src, temp_mask, dest,
+ region,
+ x_temp_src, y_temp_src,
+ x_temp_mask, y_temp_mask,
+ x_dest, y_dest);
+
+ glamor_composite_clipped_region(PictOpAdd,
+ temp_src, temp_mask, dest,
+ region,
+ x_temp_src, y_temp_src,
+ x_temp_mask, y_temp_mask,
+ x_dest, y_dest);
+ ok = TRUE;
+ goto out;
}
}
- if (!mask) {
+ if (!mask && temp_src) {
if (glamor_composite_with_copy(op, temp_src, dest,
x_temp_src, y_temp_src,
- x_dest, y_dest, width,
- height))
- goto done;
+ x_dest, y_dest, region)) {
+ ok = TRUE;
+ goto out;
+ }
}
- /*XXXXX, maybe we can make a copy of dest pixmap.*/
- if (source_pixmap == dest_pixmap)
- goto full_fallback;
+ /*XXXXX, self copy?*/
x_dest += dest->pDrawable->x;
y_dest += dest->pDrawable->y;
- if (temp_src->pDrawable) {
+ if (temp_src && temp_src->pDrawable) {
x_temp_src += temp_src->pDrawable->x;
y_temp_src += temp_src->pDrawable->y;
}
x_temp_mask += temp_mask->pDrawable->x;
y_temp_mask += temp_mask->pDrawable->y;
}
- if (!miComputeCompositeRegion(®ion,
- 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(®ion);
- nbox = REGION_NUM_RECTS(®ion);
if (nbox > ARRAY_SIZE(rect)) {
prect = calloc(nbox, sizeof(*prect));
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(®ion,
+ 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(®ion);
+ nbox = REGION_NUM_RECTS(®ion);
+ DEBUGF("first clipped when compositing.\n");
+ DEBUGRegionPrint(®ion);
+ extent = RegionExtents(®ion);
+ 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, ®ion,
+ x_source, y_source,
+ x_mask, y_mask,
+ x_dest, y_dest);
+
REGION_UNINIT(dest->pDrawable->pScreen, ®ion);
if (ok)
goto done;
-
fail:
if (!fallback
&& glamor_ddx_fallback_check_pixmap(&dest_pixmap->drawable)
- && (!source_pixmap
+ && (!source_pixmap
|| glamor_ddx_fallback_check_pixmap(&source_pixmap->drawable))
&& (!mask_pixmap
|| glamor_ddx_fallback_check_pixmap(&mask_pixmap->drawable))) {
x_ ##p = 0; \
y_ ##p = 0; \
} } while(0)
-
GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
- if (source->pDrawable)
+ if (source->pDrawable && !source->transform)
GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO);
- if (mask && mask->pDrawable)
+ if (mask && mask->pDrawable && !mask->transform)
GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO);
-
full_fallback:
if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) {
if (source_pixmap == dest_pixmap || glamor_prepare_access_picture
PUT_SUB_PICTURE(source, GLAMOR_ACCESS_RO);
PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
done:
- if (temp_src != source)
- FreePicture(temp_src, 0);
- if (temp_mask != mask)
- FreePicture(temp_mask, 0);
- if (prect != rect)
- free(prect);
return ret;
}
FALSE);
}
-
-
-
/**
* Creates an appropriate picture to upload our alpha mask into (which
* we calculated in system memory)
* glamor_trapezoids is a copy of miTrapezoids that does all the trapezoid
* accumulation in system memory.
*/
-static Bool
+static Bool
_glamor_trapezoids(CARD8 op,
PicturePtr src, PicturePtr dst,
PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
int ntrap, xTrapezoid * traps)
{
- _glamor_trapezoids(op, src, dst, mask_format, x_src,
+ _glamor_trapezoids(op, src, dst, mask_format, x_src,
y_src, ntrap, traps, TRUE);
}
PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
int ntrap, xTrapezoid * traps)
{
- return _glamor_trapezoids(op, src, dst, mask_format, x_src,
+ return _glamor_trapezoids(op, src, dst, mask_format, x_src,
y_src, ntrap, traps, FALSE);
}
ValidatePicture(src);
ValidatePicture(dst);
- if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects))
- return;
+ if (!(glamor_is_large_picture(src)
+ || (mask && glamor_is_large_picture(mask))
+ || glamor_is_large_picture(dst))) {
+ if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects))
+ return;
+ }
n = nrect;
r = rects;
glamor_put_dispatch(glamor_priv);
}
-Bool
-glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
+static void
+_glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
int x, int y, int width, int height,
- unsigned char alu, unsigned long planemask,
int tile_x, int tile_y)
{
ScreenPtr screen = pixmap->drawable.pScreen;
glamor_pixmap_private *src_pixmap_priv;
glamor_pixmap_private *dst_pixmap_priv;
float wh[2];
-
src_pixmap_priv = glamor_get_pixmap_private(tile);
dst_pixmap_priv = glamor_get_pixmap_private(pixmap);
- if (src_pixmap_priv == NULL || dst_pixmap_priv == NULL)
- goto fail;
-
- if (glamor_priv->tile_prog == 0) {
- glamor_fallback("Tiling unsupported\n");
- goto fail;
- }
-
- if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) {
- glamor_fallback("dest has no fbo.\n");
- goto fail;
- }
- if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) {
- /* XXX dynamic uploading candidate. */
- glamor_fallback("Non-texture tile pixmap\n");
- goto fail;
- }
-
- if (!glamor_set_planemask(pixmap, planemask)) {
- glamor_fallback("unsupported planemask %lx\n", planemask);
- goto fail;
- }
-
glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale);
-
- dispatch = glamor_get_dispatch(glamor_priv);
- if (!glamor_set_alu(dispatch, alu)) {
- glamor_put_dispatch(glamor_priv);
- goto fail;
- }
-
pixmap_priv_get_scale(src_pixmap_priv, &src_xscale,
&src_yscale);
+ dispatch = glamor_get_dispatch(glamor_priv);
dispatch->glUseProgram(glamor_priv->tile_prog);
glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv);
-
dispatch->glUniform2fv(glamor_priv->tile_wh, 1, wh);
dispatch->glActiveTexture(GL_TEXTURE0);
dispatch->glBindTexture(GL_TEXTURE_2D,
#ifndef GLAMOR_GLES2
dispatch->glEnable(GL_TEXTURE_2D);
#endif
- glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale,
- src_yscale,
- tile_x1, tile_y1,
- tile_x2, tile_y2,
- glamor_priv->yInverted,
- source_texcoords);
+ glamor_set_repeat_normalize_tcoords
+ (src_pixmap_priv, RepeatNormal,
+ src_xscale, src_yscale,
+ tile_x1, tile_y1,
+ tile_x2, tile_y2,
+ glamor_priv->yInverted,
+ source_texcoords);
+
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
GL_FLOAT, GL_FALSE,
2 * sizeof(float),
source_texcoords);
dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
- glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale,
- dst_yscale,
- x1, y1, x2, y2,
+ glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, dst_yscale,
+ x1, y1,
+ x2, y2,
glamor_priv->yInverted, vertices);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
#endif
dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
dispatch->glUseProgram(0);
+ glamor_put_dispatch(glamor_priv);
+}
+
+Bool
+glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
+ int x, int y, int width, int height,
+ unsigned char alu, unsigned long planemask,
+ int tile_x, int tile_y)
+{
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ glamor_screen_private *glamor_priv =
+ glamor_get_screen_private(screen);
+ glamor_pixmap_private *dst_pixmap_priv;
+ glamor_pixmap_private *src_pixmap_priv;
+ glamor_gl_dispatch *dispatch;
+
+ dst_pixmap_priv = glamor_get_pixmap_private(pixmap);
+ src_pixmap_priv = glamor_get_pixmap_private(tile);
+
+ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv))
+ return FALSE;
+
+ if (glamor_priv->tile_prog == 0) {
+ glamor_fallback("Tiling unsupported\n");
+ goto fail;
+ }
+
+ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) {
+ /* XXX dynamic uploading candidate. */
+ glamor_fallback("Non-texture tile pixmap\n");
+ goto fail;
+ }
+
+ if (!glamor_set_planemask(pixmap, planemask)) {
+ glamor_fallback("unsupported planemask %lx\n", planemask);
+ goto fail;
+ }
+
+ dispatch = glamor_get_dispatch(glamor_priv);
+ if (!glamor_set_alu(dispatch, alu)) {
+ glamor_fallback("unsupported alu %x\n", alu);
+ glamor_put_dispatch(glamor_priv);
+ goto fail;
+ }
+
+ if (dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE
+ || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
+ glamor_pixmap_clipped_regions *clipped_dst_regions;
+ int n_dst_region, i, j, k;
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = x + width;
+ box.y2 = y + height;
+ RegionInitBoxes(®ion, &box, 1);
+ clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv,
+ ®ion, &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(®ion);
+ }
+ else
+ _glamor_tile(pixmap, tile, x, y, width, height, tile_x, tile_y);
+
glamor_set_alu(dispatch, GXcopy);
- glamor_set_planemask(pixmap, ~0);
glamor_put_dispatch(glamor_priv);
return TRUE;
-
- fail:
+fail:
return FALSE;
+
}
#define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \
do { \
- *(_pxscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.width; \
- *(_pyscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.height; \
+ int w,h; \
+ PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, w, h); \
+ *(_pxscale_) = 1.0 / w; \
+ *(_pyscale_) = 1.0 / h; \
} while(0)
#define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \
} \
} while(0)
+#define _glamor_get_repeat_coords(priv, repeat_type, tx1, \
+ ty1, tx2, ty2, \
+ _x1_, _y1_, _x2_, \
+ _y2_, c, d, odd_x, odd_y) \
+ do { \
+ if (repeat_type == RepeatReflect) { \
+ assert(0); \
+ } else if (repeat_type == RepeatNormal) { \
+ tx1 = (c - priv->box.x1); \
+ ty1 = (d - priv->box.y1); \
+ tx2 = tx1 + ((_x2_) - (_x1_)); \
+ ty2 = ty1 + ((_y2_) - (_y1_)); \
+ } else { \
+ assert(0); \
+ } \
+ } while(0)
+
+
+
+/* _x1_ ... _y2_ must be integer. */
+#define glamor_get_repeat_coords(priv, repeat_type, tx1, \
+ ty1, tx2, ty2, _x1_, _y1_, _x2_, \
+ _y2_) \
+ do { \
+ int c, d; \
+ int odd_x = 0, odd_y = 0; \
+ DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n", \
+ (priv)->base.pixmap->drawable.width, \
+ priv->box.x1, priv->box.x2, \
+ priv->box.y1, priv->box.y2); \
+ modulus((_x1_), (priv)->base.pixmap->drawable.width, c); \
+ modulus((_y1_), (priv)->base.pixmap->drawable.height, d); \
+ DEBUGF("c %d d %d \n", c, d); \
+ if (repeat_type == RepeatReflect) { \
+ odd_x = abs((_x1_ - c) \
+ / (priv->base.pixmap->drawable.width)) & 1; \
+ odd_y = abs((_y1_ - d) \
+ / (priv->base.pixmap->drawable.height)) & 1; \
+ } \
+ _glamor_get_repeat_coords(priv, repeat_type, tx1, ty1, tx2, ty2,\
+ _x1_, _y1_, _x2_, _y2_, c, d, \
+ odd_x, odd_y); \
+ } while(0)
+
+
+
#define glamor_transform_point(matrix, tx, ty, x, y) \
do { \
int i; \
tx2, ty2, yInverted, vertices); \
} while(0)
+#define glamor_set_repeat_normalize_tcoords(priv, repeat_type, \
+ xscale, yscale, \
+ _x1_, _y1_, _x2_, _y2_, \
+ yInverted, vertices) \
+ do { \
+ float tx1, tx2, ty1, ty2; \
+ if (priv->type == GLAMOR_TEXTURE_LARGE) \
+ glamor_get_repeat_coords((&priv->large), repeat_type, \
+ tx1, ty1, tx2, ty2, \
+ _x1_, _y1_, _x2_, _y2_); \
+ else { \
+ tx1 = _x1_; tx2 = _x2_; ty1 = _y1_; ty2 = _y2_; \
+ } \
+ _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \
+ tx2, ty2, yInverted, vertices); \
+ } while(0)
+
+
#define glamor_set_tcoords(width, height, x1, y1, x2, y2, \
yInverted, vertices) \
do { \
}
inline static void
-glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy)
+glamor_translate_boxes(BoxPtr boxes, int nbox, int dx, int dy)
{
int i;
for (i = 0; i < nbox; i++) {