diff options
author | Zhigang Gong <zhigang.gong@linux.intel.com> | 2012-06-11 01:52:14 +0800 |
---|---|---|
committer | Zhigang Gong <zhigang.gong@linux.intel.com> | 2012-06-11 16:16:46 +0800 |
commit | e836be57a45c3acee73251190593a882428fa7ed (patch) | |
tree | 0caad53536b12948a6669bba239d7bdb4f5f2da0 | |
parent | 25ba2dcf0e9858edc93fafa0d77f6d1a574bd833 (diff) |
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>
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/glamor.c | 40 | ||||
-rw-r--r-- | src/glamor_copyarea.c | 329 | ||||
-rw-r--r-- | src/glamor_fbo.c | 121 | ||||
-rw-r--r-- | src/glamor_fill.c | 102 | ||||
-rw-r--r-- | src/glamor_largepixmap.c | 412 | ||||
-rw-r--r-- | src/glamor_pixmap.c | 328 | ||||
-rw-r--r-- | src/glamor_priv.h | 5 | ||||
-rw-r--r-- | src/glamor_render.c | 562 | ||||
-rw-r--r-- | src/glamor_tile.c | 192 | ||||
-rw-r--r-- | src/glamor_utils.h | 72 |
11 files changed, 1711 insertions, 453 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 2e94ffd..421846c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,6 +42,7 @@ libglamor_la_SOURCES = \ glamor_glyphblt.c\ glamor_polyops.c\ glamor_pixmap.c\ + glamor_largepixmap.c\ glamor_picture.c\ glamor_window.c\ glamor_gl_dispatch.c\ diff --git a/src/glamor.c b/src/glamor.c index a22f445..74b22d3 100644 --- a/src/glamor.c +++ b/src/glamor.c @@ -141,9 +141,11 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w > 32767 || h > 32767) return NullPixmap; - if (usage == GLAMOR_CREATE_PIXMAP_CPU - || (w == 0 && h == 0) - || !glamor_check_pixmap_fbo_depth(depth)) + if ((usage == GLAMOR_CREATE_PIXMAP_CPU + || (w == 0 && h == 0) + || !glamor_check_pixmap_fbo_depth(depth)) + || (!GLAMOR_TEXTURED_LARGE_PIXMAP && + !glamor_check_fbo_size(glamor_priv, w, h))) return fbCreatePixmap(screen, w, h, depth, usage); else pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); @@ -161,10 +163,24 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, pixmap_priv->base.pixmap = pixmap; pixmap_priv->base.glamor_priv = glamor_priv; - pixmap_priv->type = type; gl_iformat_for_depth(depth, &format); - fbo = glamor_create_fbo(glamor_priv, w, h, format, usage); + + pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3; + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); + + if (type == GLAMOR_MEMORY_MAP || glamor_check_fbo_size(glamor_priv, w, h)) { + pixmap_priv->type = type; + fbo = glamor_create_fbo(glamor_priv, w, h, format, usage); + } + else { + DEBUGF("Create LARGE pixmap %p width %d height %d\n", pixmap, w, h); + pixmap_priv->type = GLAMOR_TEXTURE_LARGE; + fbo = glamor_create_fbo_array(glamor_priv, w, h, format, usage, + glamor_priv->max_fbo_size, + glamor_priv->max_fbo_size, + pixmap_priv); + } if (fbo == NULL) { fbDestroyPixmap(pixmap); @@ -174,8 +190,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, glamor_pixmap_attach_fbo(pixmap, fbo); - pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3; - screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); return pixmap; } @@ -186,13 +200,8 @@ glamor_destroy_textured_pixmap(PixmapPtr pixmap) glamor_pixmap_private *pixmap_priv; pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv != NULL) { - glamor_pixmap_fbo *fbo; - fbo = glamor_pixmap_detach_fbo(pixmap_priv); - if (fbo) - glamor_destroy_fbo(fbo); - free(pixmap_priv); - } + if (pixmap_priv != NULL) + glamor_pixmap_destroy_fbo(pixmap_priv); } } @@ -315,6 +324,9 @@ glamor_init(ScreenPtr screen, unsigned int flags) glamor_gl_has_extension("GL_EXT_framebuffer_blit"); glamor_priv->_dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); +#ifdef MAX_FBO_SIZE + glamor_priv->max_fbo_size = MAX_FBO_SIZE; +#endif glamor_set_debug_level(&glamor_debug_level); diff --git a/src/glamor_copyarea.c b/src/glamor_copyarea.c index 84a449c..4d68dbe 100644 --- a/src/glamor_copyarea.c +++ b/src/glamor_copyarea.c @@ -40,11 +40,13 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, ScreenPtr screen = dst->pScreen; PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); - glamor_pixmap_private *src_pixmap_priv; + glamor_pixmap_private *src_pixmap_priv, *dst_pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_gl_dispatch *dispatch; int dst_x_off, dst_y_off, src_x_off, src_y_off, i; + int fbo_x_off, fbo_y_off; + int src_fbo_x_off, src_fbo_y_off; if (!glamor_priv->has_fbo_blit) { glamor_delayed_fallback(screen, @@ -52,17 +54,13 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, return FALSE; } src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); if (gc) { if (gc->alu != GXcopy) { glamor_delayed_fallback(screen, "non-copy ALU\n"); return FALSE; } - if (!glamor_pm_is_solid(dst, gc->planemask)) { - glamor_delayed_fallback(screen, - "non-solid planemask\n"); - return FALSE; - } } if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { @@ -73,6 +71,9 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, if (glamor_set_destination_pixmap(dst_pixmap)) return FALSE; + pixmap_priv_get_fbo_off(dst_pixmap_priv, &fbo_x_off, &fbo_y_off); + pixmap_priv_get_fbo_off(src_pixmap_priv, &src_fbo_x_off, &src_fbo_y_off); + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->base.fbo->fb); @@ -80,7 +81,10 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src, &dst_y_off); glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); - src_y_off += dy; + dst_x_off += fbo_x_off; + dst_y_off += fbo_y_off; + src_y_off += dy + src_fbo_y_off; + src_x_off += src_fbo_x_off; for (i = 0; i < nbox; i++) { if (glamor_priv->yInverted) { @@ -154,17 +158,11 @@ glamor_copy_n_to_n_textured(DrawablePtr src, int src_x_off, src_y_off, dst_x_off, dst_y_off; enum glamor_pixmap_status src_status = GLAMOR_NONE; GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; - int alu = GXcopy; src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { - glamor_delayed_fallback(dst->pScreen, "dst has no fbo.\n"); - return FALSE; - } - - if (!src_pixmap_priv || !src_pixmap_priv->base.gl_fbo) { + if (!src_pixmap_priv->base.gl_fbo) { #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); return FALSE; @@ -177,11 +175,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, #endif } - if (gc) { - if (!glamor_set_planemask(dst_pixmap, gc->planemask)) - return FALSE; - alu = gc->alu; - } pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); @@ -191,10 +184,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, dispatch = glamor_get_dispatch(glamor_priv); - if (!glamor_set_alu(dispatch, alu)) { - glamor_put_dispatch(glamor_priv); - return FALSE; - } glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, @@ -239,8 +228,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, for (i = 0; i < nbox; i++) { - glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, - dst_yscale, + glamor_set_normalize_vcoords(dst_pixmap_priv, + dst_xscale, dst_yscale, box[i].x1 + dst_x_off, box[i].y1 + dst_y_off, box[i].x2 + dst_x_off, @@ -248,7 +237,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src, glamor_priv->yInverted, vertices); - glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale, + glamor_set_normalize_tcoords(src_pixmap_priv, + src_xscale, src_yscale, box[i].x1 + dx, box[i].y1 + dy, @@ -270,19 +260,18 @@ glamor_copy_n_to_n_textured(DrawablePtr src, return TRUE; } -static Bool -_glamor_copy_n_to_n(DrawablePtr src, - DrawablePtr dst, - GCPtr gc, - BoxPtr box, - int nbox, - int dx, - int dy, - Bool reverse, - Bool upsidedown, Pixel bitplane, - void *closure, Bool fallback) +static Bool +__glamor_copy_n_to_n(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, + void *closure) { - glamor_access_t dst_access; PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL; DrawablePtr temp_src = src; glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; @@ -296,32 +285,20 @@ _glamor_copy_n_to_n(DrawablePtr src, int overlaped = 0; Bool ret = FALSE; - if (nbox == 0) - return TRUE; dst_pixmap = glamor_get_drawable_pixmap(dst); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); src_pixmap = glamor_get_drawable_pixmap(src); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); screen = dst_pixmap->drawable.pScreen; glamor_priv = glamor_get_screen_private(dst->pScreen); - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { - glamor_fallback("dest pixmap %p has no fbo. \n", - dst_pixmap); - goto fail; - } - - if (!src_pixmap_priv) { - glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY); - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); - } - glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off); + glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off); - if (src_pixmap_priv->base.fbo && src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) { + if (src_pixmap_priv->base.fbo + && src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) { int x_shift = abs(src_x_off - dx - dst_x_off); int y_shift = abs(src_y_off - dy - dst_y_off); for (i = 0; i < nbox; i++) { @@ -332,6 +309,11 @@ _glamor_copy_n_to_n(DrawablePtr src, } } } + DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n", + box[0].x1, box[0].y1, + box[0].x2 - box[0].x1, box[0].y2 - box[0].y1, + dx, dy, + src_pixmap, dst_pixmap); #ifndef GLAMOR_GLES2 if ((overlaped || !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex) @@ -345,10 +327,13 @@ _glamor_copy_n_to_n(DrawablePtr src, /* Overlaped indicate the src and dst are the same pixmap. */ if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) - && ((bound.x2 - bound.x1) * (bound.y2 - bound.y1) + && (((bound.x2 - bound.x1) * (bound.y2 - bound.y1) * 4 > src_pixmap->drawable.width * - src_pixmap->drawable.height))) { + src_pixmap->drawable.height) + || !(glamor_check_fbo_size(glamor_priv, + src_pixmap->drawable.width, + src_pixmap->drawable.height))))) { temp_pixmap = glamor_create_pixmap(screen, bound.x2 - bound.x1, @@ -357,9 +342,11 @@ _glamor_copy_n_to_n(DrawablePtr src, drawable.depth, overlaped ? 0 : GLAMOR_CREATE_PIXMAP_CPU); + assert(bound.x2 - bound.x1 <= glamor_priv->max_fbo_size); + assert(bound.y2 - bound.y1 <= glamor_priv->max_fbo_size); if (!temp_pixmap) - goto fail; - glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); + goto done; + glamor_translate_boxes(box, nbox, -bound.x1, -bound.y1); temp_src = &temp_pixmap->drawable; if (overlaped) @@ -371,7 +358,7 @@ _glamor_copy_n_to_n(DrawablePtr src, fbCopyNtoN(src, temp_src, gc, box, nbox, temp_dx + bound.x1, temp_dy + bound.y1, reverse, upsidedown, bitplane, closure); - glamor_transform_boxes(box, nbox, bound.x1, bound.y1); + glamor_translate_boxes(box, nbox, bound.x1, bound.y1); temp_dx = -bound.x1; temp_dy = -bound.y1; } else { @@ -383,13 +370,221 @@ _glamor_copy_n_to_n(DrawablePtr src, if (glamor_copy_n_to_n_textured (temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { ret = TRUE; - goto done; + } +done: + if (temp_src != src) + glamor_destroy_pixmap(temp_pixmap); + return ret; +} + +static Bool +_glamor_copy_n_to_n(DrawablePtr src, + DrawablePtr dst, + GCPtr gc, + BoxPtr box, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, Pixel bitplane, + void *closure, Bool fallback) +{ + glamor_access_t dst_access; + PixmapPtr dst_pixmap, src_pixmap; + glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; + glamor_screen_private *glamor_priv; + glamor_gl_dispatch *dispatch; + BoxPtr extent; + RegionRec region; + ScreenPtr screen; + int src_x_off, src_y_off, dst_x_off, dst_y_off; + Bool ret = FALSE; + int ok = TRUE; + int force_clip = 0; + + if (nbox == 0) + return TRUE; + dst_pixmap = glamor_get_drawable_pixmap(dst); + dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); + src_pixmap = glamor_get_drawable_pixmap(src); + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + screen = dst_pixmap->drawable.pScreen; + + glamor_priv = glamor_get_screen_private(dst->pScreen); + + DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n", + box[0].x1, box[0].y1, + box[0].x2 - box[0].x1, box[0].y2 - box[0].y1, + dx, dy, + src_pixmap, dst_pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) + goto fall_back; + + if (gc) { + if (!glamor_set_planemask(dst_pixmap, gc->planemask)) + goto fail; + dispatch = glamor_get_dispatch(glamor_priv); + if (!glamor_set_alu(dispatch, gc->alu)) { + glamor_put_dispatch(glamor_priv); + goto fail; + } + glamor_put_dispatch(glamor_priv); + } + + if (!src_pixmap_priv) { + glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY); + src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + } + + 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; @@ -428,8 +623,6 @@ _glamor_copy_n_to_n(DrawablePtr src, done: glamor_clear_delayed_fallbacks(src->pScreen); glamor_clear_delayed_fallbacks(dst->pScreen); - if (temp_src != src) - glamor_destroy_pixmap(temp_pixmap); return ret; } @@ -455,10 +648,10 @@ glamor_copy_n_to_n(DrawablePtr src, int dx, int dy, Bool reverse, - Bool upsidedown, Pixel bitplane, + Bool upsidedown, Pixel bitplane, void *closure) { - _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, + _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure, TRUE); } @@ -471,10 +664,10 @@ glamor_copy_n_to_n_nf(DrawablePtr src, int dx, int dy, Bool reverse, - Bool upsidedown, Pixel bitplane, + Bool upsidedown, Pixel bitplane, void *closure) { - return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, + return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure, FALSE); } diff --git a/src/glamor_fbo.c b/src/glamor_fbo.c index 5337149..1ab7686 100644 --- a/src/glamor_fbo.c +++ b/src/glamor_fbo.c @@ -175,7 +175,8 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) if (fbo->fb == 0 || n_format == -1 || fbo->glamor_priv->fbo_cache_watermark >= FBO_CACHE_THRESHOLD) { - fbo->glamor_priv->tick ++; + fbo->glamor_priv->tick += GLAMOR_CACHE_EXPIRE_MAX; + glamor_fbo_expire(fbo->glamor_priv); glamor_purge_fbo(fbo); return; } @@ -404,6 +405,92 @@ no_tex: return fbo; } +static glamor_pixmap_fbo * +_glamor_create_fbo_array(glamor_screen_private *glamor_priv, + int w, int h, GLenum format, int flag, + int block_w, int block_h, + glamor_pixmap_private *pixmap_priv, + int has_fbo) +{ + int block_wcnt; + int block_hcnt; + glamor_pixmap_fbo **fbo_array; + BoxPtr box_array; + int i,j; + glamor_pixmap_private_large_t *priv; + + priv = &pixmap_priv->large; + + block_wcnt = (w + block_w - 1) / block_w; + block_hcnt = (h + block_h - 1) / block_h; + + box_array = calloc(block_wcnt * block_hcnt, sizeof(box_array[0])); + if (box_array == NULL) + return NULL; + + fbo_array = calloc(block_wcnt * block_hcnt, sizeof(glamor_pixmap_fbo*)); + if (fbo_array == NULL) { + free(box_array); + return FALSE; + } + for(i = 0; i < block_hcnt; i++) + { + int block_y1, block_y2; + int fbo_w, fbo_h; + + block_y1 = i * block_h; + block_y2 = (block_y1 + block_h) > h ? h : (block_y1 + block_h); + fbo_h = block_y2 - block_y1; + + for (j = 0; j < block_wcnt; j++) + { + box_array[i * block_wcnt + j].x1 = j * block_w; + box_array[i * block_wcnt + j].y1 = block_y1; + box_array[i * block_wcnt + j].x2 = (j + 1) * block_w > w ? w : (j + 1) * block_w; + box_array[i * block_wcnt + j].y2 = block_y2; + fbo_w = box_array[i * block_wcnt + j].x2 - box_array[i * block_wcnt + j].x1; + if (!has_fbo) + fbo_array[i * block_wcnt + j] = glamor_create_fbo(glamor_priv, + fbo_w, fbo_h, format, + GLAMOR_CREATE_PIXMAP_FIXUP); + else + fbo_array[i * block_wcnt + j] = priv->base.fbo; + if (fbo_array[i * block_wcnt + j] == NULL) + goto cleanup; + } + } + + priv->box = box_array[0]; + priv->box_array = box_array; + priv->fbo_array = fbo_array; + priv->block_wcnt = block_wcnt; + priv->block_hcnt = block_hcnt; + return fbo_array[0]; + +cleanup: + for(i = 0; i < block_wcnt * block_hcnt; i++) + if ((fbo_array)[i]) + glamor_destroy_fbo((fbo_array)[i]); + free(box_array); + free(fbo_array); + return NULL; +} + + +/* Create a fbo array to cover the w*h region, by using block_w*block_h + * block.*/ +glamor_pixmap_fbo * +glamor_create_fbo_array(glamor_screen_private *glamor_priv, + int w, int h, GLenum format, int flag, + int block_w, int block_h, + glamor_pixmap_private *pixmap_priv) +{ + pixmap_priv->large.block_w = block_w; + pixmap_priv->large.block_h = block_h; + return _glamor_create_fbo_array(glamor_priv, w, h, format, flag, + block_w, block_h, pixmap_priv, 0); +} + glamor_pixmap_fbo * glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv) { @@ -428,23 +515,13 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo) pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv == NULL) { - glamor_screen_private *glamor_priv; - glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); - pixmap_priv = calloc(1, sizeof(*pixmap_priv)); - dixSetPrivate(&pixmap->devPrivates, - glamor_pixmap_private_key, pixmap_priv); - pixmap_priv->base.pixmap = pixmap; - pixmap_priv->base.glamor_priv = glamor_priv; - pixmap_priv->type = GLAMOR_MEMORY; - } - if (pixmap_priv->base.fbo) return; pixmap_priv->base.fbo = fbo; switch (pixmap_priv->type) { + case GLAMOR_TEXTURE_LARGE: case GLAMOR_TEXTURE_ONLY: case GLAMOR_TEXTURE_DRM: pixmap_priv->base.gl_fbo = 1; @@ -462,6 +539,23 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo) } } +void +glamor_pixmap_destroy_fbo(glamor_pixmap_private *priv) +{ + glamor_pixmap_fbo *fbo; + if (priv->type == GLAMOR_TEXTURE_LARGE) { + int i; + glamor_pixmap_private_large_t *large = &priv->large; + for(i = 0; i < large->block_wcnt * large->block_hcnt; i++) + glamor_destroy_fbo(large->fbo_array[i]); + free(large->fbo_array); + } else { + fbo = glamor_pixmap_detach_fbo(priv); + if (fbo) + glamor_destroy_fbo(fbo); + free(priv); + } +} Bool glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) @@ -472,7 +566,7 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) { + if (pixmap_priv->base.fbo == NULL) { fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, pixmap->drawable.height, @@ -492,7 +586,6 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) glamor_pixmap_ensure_fb(pixmap_priv->base.fbo); } - pixmap_priv = glamor_get_pixmap_private(pixmap); return TRUE; } diff --git a/src/glamor_fill.c b/src/glamor_fill.c index b63756d..5b84dd6 100644 --- a/src/glamor_fill.c +++ b/src/glamor_fill.c @@ -180,10 +180,9 @@ glamor_fini_solid_shader(ScreenPtr screen) glamor_put_dispatch(glamor_priv); } -Bool -glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, - unsigned char alu, unsigned long planemask, - unsigned long fg_pixel) +static void +_glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, + float *color) { ScreenPtr screen = pixmap->drawable.pScreen; glamor_screen_private *glamor_priv = @@ -195,14 +194,49 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, int x2 = x + width; int y1 = y; int y2 = y + height; - GLfloat color[4]; float vertices[8]; GLfloat xscale, yscale; - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { - glamor_fallback("dest %p has no fbo.\n", pixmap); + glamor_set_destination_pixmap_priv_nc(pixmap_priv); + + dispatch = glamor_get_dispatch(glamor_priv); + dispatch->glUseProgram(glamor_priv->solid_prog); + + dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, + 1, color); + + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, + GL_FALSE, 2 * sizeof(float), + vertices); + dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); + pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); + + glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale, + x1, y1, + x2, y2, + glamor_priv->yInverted, vertices); + dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); + dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); +} + +Bool +glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + unsigned long fg_pixel) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_pixmap_private *pixmap_priv; + glamor_gl_dispatch *dispatch; + GLfloat color[4]; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return FALSE; - } if (!glamor_set_planemask(pixmap, planemask)) { glamor_fallback @@ -216,8 +250,6 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, &color[2], &color[3], format_for_pixmap(pixmap)); - glamor_set_destination_pixmap_priv_nc(pixmap_priv); - dispatch = glamor_get_dispatch(glamor_priv); if (!glamor_set_alu(dispatch, alu)) { if (alu == GXclear) @@ -228,23 +260,47 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height, return FALSE; } } - dispatch->glUseProgram(glamor_priv->solid_prog); - dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, - 1, color); + if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + RegionRec region; + BoxRec box; + int n_region; + glamor_pixmap_clipped_regions *clipped_regions; + int i,j; - dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, - GL_FALSE, 2 * sizeof(float), - vertices); - dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale); + box.x1 = x; + box.y1 = y; + box.x2 = x + width; + box.y2 = y + height; + RegionInitBoxes(®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; } diff --git a/src/glamor_largepixmap.c b/src/glamor_largepixmap.c new file mode 100644 index 0000000..e8c1030 --- /dev/null +++ b/src/glamor_largepixmap.c @@ -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); +} diff --git a/src/glamor_pixmap.c b/src/glamor_pixmap.c index fa05bed..ca38a2b 100644 --- a/src/glamor_pixmap.c +++ b/src/glamor_pixmap.c @@ -83,9 +83,11 @@ glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo * fbo, int x0, int y0, int w void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) { + int w,h; + + PIXMAP_PRIV_GET_ACTUAL_SIZE(pixmap_priv, w, h); glamor_set_destination_pixmap_fbo(pixmap_priv->base.fbo, 0, 0, - pixmap_priv->base.pixmap->drawable.width, - pixmap_priv->base.pixmap->drawable.height); + w, h); } int @@ -489,16 +491,23 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum ty } ready_to_upload: + /* Try fast path firstly, upload the pixmap to the texture attached * to the fbo directly. */ if (no_alpha == 0 && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING && !need_flip) { + int fbo_x_off, fbo_y_off; assert(pixmap_priv->base.fbo->tex); + pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off); + + assert(x + fbo_x_off >= 0 && y + fbo_y_off >= 0); + assert(x + fbo_x_off + w <= pixmap_priv->base.fbo->width); + assert(y + fbo_y_off + h <= pixmap_priv->base.fbo->height); __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->base.fbo->tex, format, type, - x, y, w, h, + x + fbo_x_off, y + fbo_y_off, w, h, bits, pbo); return TRUE; } @@ -515,7 +524,6 @@ ready_to_upload: x + w, y + h, glamor_priv->yInverted, vertices); - /* Slow path, we need to flip y or wire alpha to 1. */ dispatch = glamor_get_dispatch(glamor_priv); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, @@ -586,6 +594,9 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); + if (pixmap_priv->base.gl_fbo) + return 0; + if (pixmap_priv->base.fbo && (pixmap_priv->base.fbo->width < pixmap->drawable.width || pixmap_priv->base.fbo->height < pixmap->drawable.height)) { @@ -605,8 +616,10 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int flag = GLAMOR_CREATE_FBO_NO_FBO; } - if ((flag == 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex) - || (flag != 0 && pixmap_priv && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb)) + if ((flag == GLAMOR_CREATE_FBO_NO_FBO + && pixmap_priv->base.fbo && pixmap_priv->base.fbo->tex) + || (flag == 0 + && pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb)) return 0; if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) @@ -614,35 +627,63 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int else iformat = format; - if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) { - - fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, - pixmap->drawable.height, - iformat, - flag); - if (fbo == NULL) { - glamor_fallback - ("upload failed, depth %d x %d @depth %d \n", - pixmap->drawable.width, pixmap->drawable.height, - pixmap->drawable.depth); - return -1; - } + 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, @@ -657,7 +698,77 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb)) return FALSE; - return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha, revert, swap_rb, + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + RegionRec region; + BoxRec box; + int n_region; + glamor_pixmap_clipped_regions *clipped_regions; + void *sub_bits; + int i,j; + + sub_bits = malloc(h * stride); + if (sub_bits == NULL) + return FALSE; + box.x1 = x; + box.y1 = y; + box.x2 = x + w; + box.y2 = y + h; + RegionInitBoxes(®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); } @@ -671,8 +782,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) pixmap_priv = glamor_get_pixmap_private(pixmap); - if (pixmap_priv - && (pixmap_priv->base.fbo) + if ((pixmap_priv->base.fbo) && (pixmap_priv->base.fbo->pbo_valid)) { data = NULL; pbo = pixmap_priv->base.fbo->pbo; @@ -737,7 +847,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe temp_xscale = 1.0 / w; temp_yscale = 1.0 / h; - glamor_set_normalize_vcoords((glamor_pixmap_private *)NULL, temp_xscale, + glamor_set_normalize_vcoords((struct glamor_pixmap_private*)NULL,temp_xscale, temp_yscale, 0, 0, w, h, @@ -793,13 +903,15 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe * The pixmap must have a valid FBO, otherwise return a NULL. * */ -void * -glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, - int stride, void *bits, int pbo, glamor_access_t access) +static void * +_glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format, + GLenum type, int no_alpha, + int revert, int swap_rb, + int x, int y, int w, int h, + int stride, void *bits, int pbo, glamor_access_t access) { glamor_pixmap_private *pixmap_priv; - GLenum format, type, gl_access = 0, gl_usage = 0; - int no_alpha, revert, swap_rb; + GLenum gl_access = 0, gl_usage = 0; void *data, *read; ScreenPtr screen; glamor_screen_private *glamor_priv = @@ -808,6 +920,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, glamor_pixmap_fbo *temp_fbo = NULL; int need_post_conversion = 0; int need_free_data = 0; + int fbo_x_off, fbo_y_off; data = bits; screen = pixmap->drawable.pScreen; @@ -831,18 +944,6 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, assert(0); } - if (glamor_get_tex_format_type_from_pixmap(pixmap, - &format, - &type, - &no_alpha, - &revert, - &swap_rb, 0)) { - ErrorF("Unknown pixmap depth %d.\n", - pixmap->drawable.depth); - assert(0); // Should never happen. - return NULL; - } - glamor_set_destination_pixmap_priv_nc(pixmap_priv); need_post_conversion = (revert > REVERT_NORMAL); @@ -857,6 +958,8 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, } } + pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off); + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 && !need_post_conversion && (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) { @@ -868,6 +971,8 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, } x = 0; y = 0; + fbo_x_off = 0; + fbo_y_off = 0; } dispatch = glamor_get_dispatch(glamor_priv); @@ -890,7 +995,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, NULL, gl_usage); } - dispatch->glReadPixels(x, y, w, h, format, type, data); + dispatch->glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, data); if (!glamor_priv->yInverted) { assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP); @@ -913,7 +1018,7 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, stride * h, NULL, GL_STREAM_READ); - dispatch->glReadPixels(0, 0, w, h, + dispatch->glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, 0); read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); @@ -946,6 +1051,107 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, return bits; } +void * +glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h, + int stride, void *bits, int pbo, glamor_access_t access) +{ + GLenum format, type; + int no_alpha, revert, swap_rb; + glamor_pixmap_private *pixmap_priv; + + if (glamor_get_tex_format_type_from_pixmap(pixmap, + &format, + &type, + &no_alpha, + &revert, + &swap_rb, 1)) { + glamor_fallback("Unknown pixmap depth %d.\n", + pixmap->drawable.depth); + return NULL; + } + + pixmap_priv = glamor_get_pixmap_private(pixmap); + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) + return NULL; + + if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + + RegionRec region; + BoxRec box; + int n_region; + glamor_pixmap_clipped_regions *clipped_regions; + void *sub_bits; + int i,j; + + sub_bits = malloc(h * stride); + if (sub_bits == NULL) + return FALSE; + box.x1 = x; + box.y1 = y; + box.x2 = x + w; + box.y2 = y + h; + RegionInitBoxes(®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. @@ -984,7 +1190,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) if (access == GLAMOR_ACCESS_WO || glamor_priv->gl_flavor == GLAMOR_GL_ES2 - || (!glamor_priv->has_pack_invert && !glamor_priv->yInverted)) { + || (!glamor_priv->has_pack_invert && !glamor_priv->yInverted) + || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { data = malloc(stride * pixmap->drawable.height); } else { dispatch = glamor_get_dispatch(glamor_priv); @@ -1024,6 +1231,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) } /* fixup a fbo to the exact size as the pixmap. */ +/* XXX LARGE pixmap? */ Bool glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) { @@ -1038,8 +1246,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) drawable = &pixmap_priv->base.pixmap->drawable; - if (pixmap_priv->base.pixmap->drawable.width == pixmap_priv->base.fbo->width - && pixmap_priv->base.pixmap->drawable.height == pixmap_priv->base.fbo->height) + if (!GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv)) return TRUE; old_fbo = pixmap_priv->base.fbo; @@ -1058,7 +1265,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) scratch_priv = glamor_get_pixmap_private(scratch); - if (!scratch_priv || !scratch_priv->base.fbo) + if (!scratch_priv->base.fbo) goto fail; ValidateGC(&scratch->drawable, gc); @@ -1111,14 +1318,13 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces void *data; int pbo; int flag; - - assert(x >= 0 && y >= 0); + if (x < 0 || y < 0) + return NULL; w = (x + w) > pixmap->drawable.width ? (pixmap->drawable.width - x) : w; h = (y + h) > pixmap->drawable.height ? (pixmap->drawable.height - y) : h; if (access == GLAMOR_ACCESS_WO) { sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h, pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU); - ErrorF("WO\n"); return sub_pixmap; } @@ -1127,7 +1333,7 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) return NULL; - if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) + if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) flag = GLAMOR_CREATE_PIXMAP_CPU; else flag = GLAMOR_CREATE_PIXMAP_MAP; @@ -1141,17 +1347,16 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); pbo = sub_pixmap_priv ? (sub_pixmap_priv->base.fbo ? sub_pixmap_priv->base.fbo->pbo : 0): 0; - if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) { + if (pixmap_priv->base.is_picture) { sub_pixmap_priv->base.picture = pixmap_priv->base.picture; sub_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture; } if (pbo) data = NULL; - else { + else data = sub_pixmap->devPrivate.ptr; - assert(flag != GLAMOR_CREATE_PIXMAP_MAP); - } + data = glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h, sub_pixmap->devKind, data, pbo, access); if (pbo) { @@ -1173,7 +1378,7 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces new_sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h, pixmap->drawable.depth, GLAMOR_CREATE_PIXMAP_CPU); - glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap, NULL, &box, 1, dx, dy, 0, 0, 0, NULL); + glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap->drawable, NULL, &box, 1, dx, dy, 0, 0, 0, NULL); glamor_compare_pixmaps(new_sub_pixmap, sub_pixmap, 0, 0, w, h, 1, 1); #endif @@ -1188,8 +1393,7 @@ glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int glamor_pixmap_private *sub_pixmap_priv; if (access != GLAMOR_ACCESS_RO) { sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap); - if (sub_pixmap_priv - && sub_pixmap_priv->base.fbo + if (sub_pixmap_priv->base.fbo && sub_pixmap_priv->base.fbo->pbo_valid) { bits = NULL; pbo = sub_pixmap_priv->base.fbo->pbo; diff --git a/src/glamor_priv.h b/src/glamor_priv.h index 2172d17..d9f6438 100644 --- a/src/glamor_priv.h +++ b/src/glamor_priv.h @@ -927,6 +927,9 @@ glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, #ifndef GLAMOR_GLES2 #define GLAMOR_GRADIENT_SHADER #endif -#define GLAMOR_TEXTURED_LARGE_PIXMAP 1 +#define GLAMOR_TEXTURED_LARGE_PIXMAP 0 +#if 0 +#define MAX_FBO_SIZE 512 /* For test purpose only. */ +#endif #endif /* GLAMOR_PRIV_H */ diff --git a/src/glamor_render.c b/src/glamor_render.c index 6a584ba..48a5bb3 100644 --- a/src/glamor_render.c +++ b/src/glamor_render.c @@ -37,7 +37,12 @@ #ifdef RENDER #include "mipict.h" #include "fbpict.h" - +#if 0 +//#define DEBUGF(str, ...) do {} while(0) +#define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__) +//#define DEBUGRegionPrint(x) do {} while (0) +#define DEBUGRegionPrint RegionPrint +#endif struct shader_key { enum shader_source source; enum shader_mask mask; @@ -606,18 +611,20 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, #endif /* XXX may be we can eaxctly check whether we need to touch * the out-of-box area then determine whether we need to fix. - * */ - if (repeat_type != RepeatNone) - repeat_type += RepeatFix; - else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { - if (picture->transform - || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))) + **/ + /*if (pixmap_priv->type != GLAMOR_TEXTURE_LARGE)*/ { + if (repeat_type != RepeatNone) repeat_type += RepeatFix; - } - - if (repeat_type >= RepeatFix) { - glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); - dispatch->glUniform2fv(wh_location, 1, wh); + else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 + || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + if (picture->transform + || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))) + repeat_type += RepeatFix; + } + if (repeat_type >= RepeatFix) { + glamor_pixmap_fbo_fix_wh_ratio(wh, pixmap_priv); + dispatch->glUniform2fv(wh_location, 1, wh); + } } dispatch->glUniform1i(repeat_location, repeat_type); glamor_put_dispatch(glamor_priv); @@ -687,53 +694,44 @@ glamor_composite_with_copy(CARD8 op, INT16 x_source, INT16 y_source, INT16 x_dest, - INT16 y_dest, CARD16 width, CARD16 height) + INT16 y_dest, + RegionPtr region) { - RegionRec region; int ret = FALSE; - if (!source->pDrawable) return FALSE; if (!compatible_formats(op, dest, source)) return FALSE; - if (source->repeat || source->transform) + if (source->repeat || source->transform) { return FALSE; + } x_dest += dest->pDrawable->x; y_dest += dest->pDrawable->y; x_source += source->pDrawable->x; y_source += source->pDrawable->y; - if (!miComputeCompositeRegion(®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; } @@ -929,12 +927,44 @@ combine_pict_format(PictFormatShort * des, const PictFormatShort src, return FALSE; } +static void +glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv, + int repeat_type, + float *matrix, + float xscale, float yscale, + int x1, int y1, int x2, int y2, + int yInverted, float *texcoords) +{ + if (!matrix && repeat_type == RepeatNone) + glamor_set_normalize_tcoords(priv, xscale, yscale, + x1, y1, + x2, y2, + yInverted, + texcoords); + else if (matrix && repeat_type == RepeatNone) + glamor_set_transformed_normalize_tcoords(priv, matrix, xscale, + yscale, x1, y1, + x2, y2, + yInverted, + texcoords); + else if (!matrix && repeat_type != RepeatNone) + glamor_set_repeat_normalize_tcoords(priv, repeat_type, + xscale, yscale, + x1, y1, + x2, y2, + yInverted, + texcoords); + else if (matrix && repeat_type != RepeatNone) + assert(0); +} + static Bool glamor_composite_with_shader(CARD8 op, PicturePtr source, PicturePtr mask, PicturePtr dest, - int nrect, glamor_composite_rect_t * rects) + int nrect, + glamor_composite_rect_t * rects) { ScreenPtr screen = dest->pDrawable->pScreen; glamor_screen_private *glamor_priv = @@ -959,6 +989,7 @@ glamor_composite_with_shader(CARD8 op, enum glamor_pixmap_status mask_status = GLAMOR_NONE; PictFormatShort saved_source_format = 0; float src_matrix[9], mask_matrix[9]; + float *psrc_matrix = NULL, *pmask_matrix = NULL; GLfloat source_solid_color[4], mask_solid_color[4]; int vert_stride = 4; int nrect_max; @@ -970,20 +1001,23 @@ glamor_composite_with_shader(CARD8 op, goto fail; } memset(&key, 0, sizeof(key)); - if (!source->pDrawable) { - if (source->pSourcePict->type == SourcePictTypeSolidFill) { - key.source = SHADER_SOURCE_SOLID; - glamor_get_rgba_from_pixel(source-> - pSourcePict->solidFill. - color, - &source_solid_color[0], - &source_solid_color[1], - &source_solid_color[2], - &source_solid_color[3], - PICT_a8r8g8b8); - } else { - glamor_fallback("gradient source\n"); - goto fail; + if (!source) { + key.source = SHADER_SOURCE_SOLID; + source_solid_color[0] = 0.0; + source_solid_color[1] = 0.0; + source_solid_color[2] = 0.0; + source_solid_color[3] = 0.0; + } else if (!source->pDrawable) { + if (source->pSourcePict->type == SourcePictTypeSolidFill) { + key.source = SHADER_SOURCE_SOLID; + glamor_get_rgba_from_pixel(source-> + pSourcePict->solidFill. + color, + &source_solid_color[0], + &source_solid_color[1], + &source_solid_color[2], + &source_solid_color[3], + PICT_a8r8g8b8); } } else { key.source = SHADER_SOURCE_TEXTURE_ALPHA; @@ -999,9 +1033,6 @@ glamor_composite_with_shader(CARD8 op, &mask_solid_color[1], &mask_solid_color[2], &mask_solid_color[3], PICT_a8r8g8b8); - } else { - glamor_fallback("gradient mask\n"); - goto fail; } } else { key.mask = SHADER_MASK_TEXTURE_ALPHA; @@ -1029,7 +1060,7 @@ glamor_composite_with_shader(CARD8 op, key.in = SHADER_IN_SOURCE_ONLY; } - if (source->alphaMap) { + if (source && source->alphaMap) { glamor_fallback("source alphaMap\n"); goto fail; } @@ -1044,13 +1075,14 @@ glamor_composite_with_shader(CARD8 op, source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); if (source_pixmap == dest_pixmap) { + /* XXX source and the dest share the same texture. + * Does it need special handle? */ glamor_fallback("source == dest\n"); - goto fail; } - if (!source_pixmap_priv || source_pixmap_priv->base.gl_fbo == 0) { - /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex + if (source_pixmap_priv->base.gl_fbo == 0) { + /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex * equal to zero when the pixmap is screen pixmap. Then we may - * refer the tex zero directly latter in the composition. + * refer the tex zero directly latter in the composition. * It seems that it works fine, but it may have potential problem*/ #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD source_status = GLAMOR_UPLOAD_PENDING; @@ -1068,7 +1100,7 @@ glamor_composite_with_shader(CARD8 op, glamor_fallback("mask == dest\n"); goto fail; } - if (!mask_pixmap_priv || mask_pixmap_priv->base.gl_fbo == 0) { + if (mask_pixmap_priv->base.gl_fbo == 0) { #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD mask_status = GLAMOR_UPLOAD_PENDING; #else @@ -1095,20 +1127,20 @@ glamor_composite_with_shader(CARD8 op, } if (source->format != saved_source_format) { - glamor_picture_format_fixup(source, - source_pixmap_priv); + //glamor_picture_format_fixup(source, + // source_pixmap_priv); } - /* XXX + /* XXX * By default, glamor_upload_picture_to_texture will wire alpha to 1 - * if one picture doesn't have alpha. So we don't do that again in + * if one picture doesn't have alpha. So we don't do that again in * rendering function. But here is a special case, as source and - * mask share the same texture but may have different formats. For + * mask share the same texture but may have different formats. For * example, source doesn't have alpha, but mask has alpha. Then the * texture will have the alpha value for the mask. And will not wire * to 1 for the source. In this case, we have to use different shader * to wire the source's alpha to 1. * - * But this may cause a potential problem if the source's repeat mode + * But this may cause a potential problem if the source's repeat mode * is REPEAT_NONE, and if the source is smaller than the dest, then * for the region not covered by the source may be painted incorrectly. * because we wire the alpha to 1. @@ -1156,13 +1188,15 @@ glamor_composite_with_shader(CARD8 op, * transformed source and mask, if the transform is not int translate. */ if (key.source != SHADER_SOURCE_SOLID && source->transform - && !pixman_transform_is_int_translate(source->transform)) { + && !pixman_transform_is_int_translate(source->transform) + && source_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { if (!glamor_fixup_pixmap_priv(screen, source_pixmap_priv)) goto fail; } if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID && mask->transform - && !pixman_transform_is_int_translate(mask->transform)) { + && !pixman_transform_is_int_translate(mask->transform) + && mask_pixmap_priv->type != GLAMOR_TEXTURE_LARGE) { if (!glamor_fixup_pixmap_priv(screen, mask_pixmap_priv)) goto fail; } @@ -1217,7 +1251,10 @@ glamor_composite_with_shader(CARD8 op, &source_y_off); pixmap_priv_get_scale(source_pixmap_priv, &src_xscale, &src_yscale); - glamor_picture_get_matrixf(source, src_matrix); + if (source->transform) { + psrc_matrix = src_matrix; + glamor_picture_get_matrixf(source, psrc_matrix); + } vert_stride += 4; } @@ -1226,7 +1263,10 @@ glamor_composite_with_shader(CARD8 op, &mask_x_off, &mask_y_off); pixmap_priv_get_scale(mask_pixmap_priv, &mask_xscale, &mask_yscale); - glamor_picture_get_matrixf(mask, mask_matrix); + if (mask->transform) { + pmask_matrix = mask_matrix; + glamor_picture_get_matrixf(mask, pmask_matrix); + } vert_stride += 4; } @@ -1252,13 +1292,16 @@ glamor_composite_with_shader(CARD8 op, x_dest = rects->x_dst + dest_x_off; y_dest = rects->y_dst + dest_y_off; - x_source = rects->x_src + source_x_off;; + x_source = rects->x_src + source_x_off; y_source = rects->y_src + source_y_off; x_mask = rects->x_mask + mask_x_off; y_mask = rects->y_mask + mask_y_off; width = rects->width; height = rects->height; + DEBUGF("dest(%d,%d) source(%d %d) mask (%d %d), width %d height %d \n", + x_dest, y_dest, x_source, y_source,x_mask,y_mask,width,height); + glamor_set_normalize_vcoords(dest_pixmap_priv, dst_xscale, dst_yscale, x_dest, y_dest, @@ -1266,41 +1309,21 @@ glamor_composite_with_shader(CARD8 op, glamor_priv->yInverted, vertices); - if (key.source != SHADER_SOURCE_SOLID) { - if (source->transform) - glamor_set_transformed_normalize_tcoords - (source_pixmap_priv, src_matrix, src_xscale, - src_yscale, x_source, y_source, - x_source + width, y_source + height, - glamor_priv->yInverted, - source_texcoords); - else - glamor_set_normalize_tcoords - (source_pixmap_priv, src_xscale, src_yscale, - x_source, y_source, - x_source + width, y_source + height, - glamor_priv->yInverted, - source_texcoords); - } + if (key.source != SHADER_SOURCE_SOLID) + glamor_set_normalize_tcoords_generic( + source_pixmap_priv, source->repeatType, psrc_matrix, + src_xscale, src_yscale, x_source, y_source, + x_source + width, y_source + height, + glamor_priv->yInverted, source_texcoords); if (key.mask != SHADER_MASK_NONE - && key.mask != SHADER_MASK_SOLID) { - if (mask->transform) - glamor_set_transformed_normalize_tcoords - (mask_pixmap_priv, mask_matrix, - mask_xscale, - mask_yscale, x_mask, y_mask, - x_mask + width, y_mask + height, - glamor_priv->yInverted, - mask_texcoords); - else - glamor_set_normalize_tcoords - (mask_pixmap_priv, mask_xscale, - mask_yscale, x_mask, y_mask, - x_mask + width, y_mask + height, - glamor_priv->yInverted, - mask_texcoords); - } + && key.mask != SHADER_MASK_SOLID) + glamor_set_normalize_tcoords_generic( + mask_pixmap_priv, mask->repeatType, pmask_matrix, + mask_xscale, mask_yscale, x_mask, y_mask, + x_mask + width, y_mask + height, + glamor_priv->yInverted, mask_texcoords); + glamor_emit_composite_rect(screen, source_texcoords, mask_texcoords, @@ -1323,6 +1346,7 @@ glamor_composite_with_shader(CARD8 op, dispatch->glActiveTexture(GL_TEXTURE1); dispatch->glDisable(GL_TEXTURE_2D); #endif + DEBUGF("finish rendering.\n"); dispatch->glUseProgram(0); if (saved_source_format) source->format = saved_source_format; @@ -1398,17 +1422,18 @@ glamor_convert_gradient_picture(ScreenPtr screen, return dst; } -static Bool -_glamor_composite(CARD8 op, - PicturePtr source, - PicturePtr mask, - PicturePtr dest, - INT16 x_source, - INT16 y_source, - INT16 x_mask, - INT16 y_mask, - INT16 x_dest, INT16 y_dest, - CARD16 width, CARD16 height, Bool fallback) +Bool +glamor_composite_clipped_region(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + RegionPtr region, + int x_source, + int y_source, + int x_mask, + int y_mask, + int x_dest, + int y_dest) { ScreenPtr screen = dest->pDrawable->pScreen; glamor_pixmap_private *dest_pixmap_priv; @@ -1419,80 +1444,63 @@ _glamor_composite(CARD8 op, PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; PicturePtr temp_src = source, temp_mask = mask; int x_temp_src, y_temp_src, x_temp_mask, y_temp_mask; + + BoxPtr extent; glamor_composite_rect_t rect[10]; glamor_composite_rect_t *prect = rect; int prect_size = ARRAY_SIZE(rect); - glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - Bool ret = TRUE; - RegionRec region; + int ok = FALSE; + int i; + int width; + int height; BoxPtr box; - int nbox, i, ok = FALSE; - PixmapPtr sub_dest_pixmap = NULL; - PixmapPtr sub_source_pixmap = NULL; - PixmapPtr sub_mask_pixmap = NULL; - int dest_x_off, dest_y_off, saved_dest_x = 0, saved_dest_y = 0; - int source_x_off, source_y_off, saved_source_x = 0, saved_source_y = 0; - int mask_x_off, mask_y_off, saved_mask_x = 0, saved_mask_y = 0; - DrawablePtr saved_dest_drawable = NULL; - DrawablePtr saved_source_drawable = NULL; - DrawablePtr saved_mask_drawable = NULL; + int nbox; + extent = RegionExtents(region); + box = RegionRects(region); + nbox = RegionNumRects(region); + width = extent->x2 - extent->x1; + height = extent->y2 - extent->y1; x_temp_src = x_source; y_temp_src = y_source; x_temp_mask = x_mask; y_temp_mask = y_mask; - - DEBUGF("Composite Src: (%d, %d)\n" - " Mask: (%d, %d)\n" - " to dst: (%d, %d), size: %d X %d \n", - x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); + DEBUGF("clipped (%d %d) (%d %d) (%d %d) width %d height %d \n", + x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); + DEBUGF("dest pixmap %p ", dest_pixmap); dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); /* Currently. Always fallback to cpu if destination is in CPU memory. */ - if (source->pDrawable) { + if (source && source->pDrawable) { source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); - if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY) - goto fail; } if (mask && mask->pDrawable) { mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); - if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY) - goto fail; - } - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { - goto fail; } - if (op >= ARRAY_SIZE(composite_op_info)) - goto fail; - - if ((!source->pDrawable + /* XXX is it possible source mask have non-zero drawable.x/y? */ + if (source + && ((!source->pDrawable && (source->pSourcePict->type != SourcePictTypeSolidFill)) || (source->pDrawable && !GLAMOR_PIXMAP_PRIV_HAS_FBO(source_pixmap_priv) - && - ((width * height * 4 < - (source_pixmap->drawable.width * - source_pixmap->drawable.height)) - || - !(glamor_check_fbo_size - (glamor_priv, source_pixmap->drawable.width, - source_pixmap->drawable.height))))) { + && (source_pixmap->drawable.width != width + || source_pixmap->drawable.height != height)))) { temp_src = glamor_convert_gradient_picture(screen, source, - x_source, y_source, + extent->x1 + x_source - x_dest, + extent->y1 + y_source - y_dest, width, height); if (!temp_src) { temp_src = source; - goto fail; + goto out; } - x_temp_src = y_temp_src = 0; + x_temp_src = - extent->x1 + x_dest; + y_temp_src = - extent->y1 + y_dest; } if (mask @@ -1500,26 +1508,22 @@ _glamor_composite(CARD8 op, ((!mask->pDrawable && (mask->pSourcePict->type != SourcePictTypeSolidFill)) || (mask->pDrawable - && (!GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv)) - && - ((width * height * 4 < - (mask_pixmap->drawable.width * - mask_pixmap->drawable.height)) - || - !(glamor_check_fbo_size - (glamor_priv, mask_pixmap->drawable.width, - mask_pixmap->drawable.height)))))) { + && !GLAMOR_PIXMAP_PRIV_HAS_FBO(mask_pixmap_priv) + && (mask_pixmap->drawable.width != width + || mask_pixmap->drawable.height != height)))) { /* XXX if mask->pDrawable is the same as source->pDrawable, we have an opportunity * to do reduce one convertion. */ temp_mask = glamor_convert_gradient_picture(screen, mask, - x_mask, y_mask, + extent->x1 + x_mask - x_dest, + extent->y1 + y_mask - y_dest, width, height); if (!temp_mask) { temp_mask = mask; - goto fail; + goto out; } - x_temp_mask = y_temp_mask = 0; + x_temp_mask = - extent->x1 + x_dest; + y_temp_mask = - extent->y1 + y_dest; } /* Do two-pass PictOpOver componentAlpha, until we enable * dual source color blending. @@ -1527,43 +1531,38 @@ _glamor_composite(CARD8 op, if (mask && mask->componentAlpha) { if (op == PictOpOver) { - glamor_composite(PictOpOutReverse, - temp_src, temp_mask, dest, - x_temp_src, y_temp_src, - x_temp_mask, y_temp_mask, - x_dest, y_dest, width, height); - glamor_composite(PictOpAdd, - temp_src, temp_mask, dest, - x_temp_src, y_temp_src, - x_temp_mask, y_temp_mask, - x_dest, y_dest, width, height); - goto done; - - } 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; } @@ -1571,16 +1570,6 @@ _glamor_composite(CARD8 op, 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)); @@ -1612,15 +1601,153 @@ _glamor_composite(CARD8 op, box += box_cnt; } + if (prect != rect) + free(prect); +out: + if (temp_src != source) + FreePicture(temp_src, 0); + if (temp_mask != mask) + FreePicture(temp_mask, 0); + + return ok; +} + +static Bool +_glamor_composite(CARD8 op, + PicturePtr source, + PicturePtr mask, + PicturePtr dest, + INT16 x_source, + INT16 y_source, + INT16 x_mask, + INT16 y_mask, + INT16 x_dest, INT16 y_dest, + CARD16 width, CARD16 height, Bool fallback) +{ + ScreenPtr screen = dest->pDrawable->pScreen; + glamor_pixmap_private *dest_pixmap_priv; + glamor_pixmap_private *source_pixmap_priv = + NULL, *mask_pixmap_priv = NULL; + PixmapPtr dest_pixmap = + glamor_get_drawable_pixmap(dest->pDrawable); + PixmapPtr source_pixmap = NULL, mask_pixmap = NULL; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + Bool ret = TRUE; + RegionRec region; + BoxPtr box, extent; + int nbox, ok = FALSE; + PixmapPtr sub_dest_pixmap = NULL; + PixmapPtr sub_source_pixmap = NULL; + PixmapPtr sub_mask_pixmap = NULL; + int dest_x_off, dest_y_off, saved_dest_x, saved_dest_y; + int source_x_off, source_y_off, saved_source_x, saved_source_y; + int mask_x_off, mask_y_off, saved_mask_x, saved_mask_y; + DrawablePtr saved_dest_drawable; + DrawablePtr saved_source_drawable; + DrawablePtr saved_mask_drawable; + int force_clip = 0; + + dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); + + if (source->pDrawable) { + source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); + source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); + if (source_pixmap_priv && source_pixmap_priv->type == GLAMOR_DRM_ONLY) + goto fail; + } + + if (mask && mask->pDrawable) { + mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); + mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); + if (mask_pixmap_priv && mask_pixmap_priv->type == GLAMOR_DRM_ONLY) + goto fail; + } + + DEBUGF("source pixmap %p (%d %d) mask(%d %d) dest(%d %d) width %d height %d \n", + source_pixmap, x_source, y_source, x_mask, y_mask, x_dest, y_dest, width, height); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { + goto fail; + } + + if (op >= ARRAY_SIZE(composite_op_info)) + goto fail; + + if (mask && mask->componentAlpha) { + if (op == PictOpAtop + || op == PictOpAtopReverse + || op == PictOpXor + || op >= PictOpSaturate) { + glamor_fallback + ("glamor_composite(): component alpha op %x\n", op); + goto fail; + } + } + + if (!miComputeCompositeRegion(®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))) { @@ -1662,13 +1789,11 @@ fail: x_ ##p = 0; \ y_ ##p = 0; \ } } while(0) - GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); - if (source->pDrawable) + if (source->pDrawable && !source->transform) GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO); - if (mask && mask->pDrawable) + if (mask && mask->pDrawable && !mask->transform) GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO); - full_fallback: if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) { if (source_pixmap == dest_pixmap || glamor_prepare_access_picture @@ -1711,12 +1836,6 @@ full_fallback: PUT_SUB_PICTURE(source, GLAMOR_ACCESS_RO); PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW); done: - if (temp_src != source) - FreePicture(temp_src, 0); - if (temp_mask != mask) - FreePicture(temp_mask, 0); - if (prect != rect) - free(prect); return ret; } @@ -1754,9 +1873,6 @@ glamor_composite_nf(CARD8 op, FALSE); } - - - /** * Creates an appropriate picture to upload our alpha mask into (which * we calculated in system memory) @@ -1797,7 +1913,7 @@ glamor_create_mask_picture(ScreenPtr screen, * glamor_trapezoids is a copy of miTrapezoids that does all the trapezoid * accumulation in system memory. */ -static Bool +static Bool _glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, @@ -1885,7 +2001,7 @@ glamor_trapezoids(CARD8 op, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, int ntrap, xTrapezoid * traps) { - _glamor_trapezoids(op, src, dst, mask_format, x_src, + _glamor_trapezoids(op, src, dst, mask_format, x_src, y_src, ntrap, traps, TRUE); } @@ -1895,7 +2011,7 @@ glamor_trapezoids_nf(CARD8 op, PictFormatPtr mask_format, INT16 x_src, INT16 y_src, int ntrap, xTrapezoid * traps) { - return _glamor_trapezoids(op, src, dst, mask_format, x_src, + return _glamor_trapezoids(op, src, dst, mask_format, x_src, y_src, ntrap, traps, FALSE); } @@ -1912,8 +2028,12 @@ glamor_composite_glyph_rects(CARD8 op, ValidatePicture(src); ValidatePicture(dst); - if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects)) - return; + if (!(glamor_is_large_picture(src) + || (mask && glamor_is_large_picture(mask)) + || glamor_is_large_picture(dst))) { + if (glamor_composite_with_shader(op, src, mask, dst, nrect, rects)) + return; + } n = nrect; r = rects; diff --git a/src/glamor_tile.c b/src/glamor_tile.c index c6b88d2..871479b 100644 --- a/src/glamor_tile.c +++ b/src/glamor_tile.c @@ -102,10 +102,9 @@ glamor_fini_tile_shader(ScreenPtr screen) glamor_put_dispatch(glamor_priv); } -Bool -glamor_tile(PixmapPtr pixmap, PixmapPtr tile, +static void +_glamor_tile(PixmapPtr pixmap, PixmapPtr tile, int x, int y, int width, int height, - unsigned char alu, unsigned long planemask, int tile_x, int tile_y) { ScreenPtr screen = pixmap->drawable.pScreen; @@ -126,48 +125,17 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_pixmap_private *src_pixmap_priv; glamor_pixmap_private *dst_pixmap_priv; float wh[2]; - src_pixmap_priv = glamor_get_pixmap_private(tile); dst_pixmap_priv = glamor_get_pixmap_private(pixmap); - if (src_pixmap_priv == NULL || dst_pixmap_priv == NULL) - goto fail; - - if (glamor_priv->tile_prog == 0) { - glamor_fallback("Tiling unsupported\n"); - goto fail; - } - - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { - glamor_fallback("dest has no fbo.\n"); - goto fail; - } - if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { - /* XXX dynamic uploading candidate. */ - glamor_fallback("Non-texture tile pixmap\n"); - goto fail; - } - - if (!glamor_set_planemask(pixmap, planemask)) { - glamor_fallback("unsupported planemask %lx\n", planemask); - goto fail; - } - glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); - - dispatch = glamor_get_dispatch(glamor_priv); - if (!glamor_set_alu(dispatch, alu)) { - glamor_put_dispatch(glamor_priv); - goto fail; - } - pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); + dispatch = glamor_get_dispatch(glamor_priv); dispatch->glUseProgram(glamor_priv->tile_prog); glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv); - dispatch->glUniform2fv(glamor_priv->tile_wh, 1, wh); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, @@ -185,21 +153,23 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, #ifndef GLAMOR_GLES2 dispatch->glEnable(GL_TEXTURE_2D); #endif - glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale, - src_yscale, - tile_x1, tile_y1, - tile_x2, tile_y2, - glamor_priv->yInverted, - source_texcoords); + glamor_set_repeat_normalize_tcoords + (src_pixmap_priv, RepeatNormal, + src_xscale, src_yscale, + tile_x1, tile_y1, + tile_x2, tile_y2, + glamor_priv->yInverted, + source_texcoords); + dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), source_texcoords); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); - glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, - dst_yscale, - x1, y1, x2, y2, + glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, dst_yscale, + x1, y1, + x2, y2, glamor_priv->yInverted, vertices); dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, @@ -214,11 +184,139 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, #endif dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glUseProgram(0); + glamor_put_dispatch(glamor_priv); +} + +Bool +glamor_tile(PixmapPtr pixmap, PixmapPtr tile, + int x, int y, int width, int height, + unsigned char alu, unsigned long planemask, + int tile_x, int tile_y) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_pixmap_private *dst_pixmap_priv; + glamor_pixmap_private *src_pixmap_priv; + glamor_gl_dispatch *dispatch; + + dst_pixmap_priv = glamor_get_pixmap_private(pixmap); + src_pixmap_priv = glamor_get_pixmap_private(tile); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) + return FALSE; + + if (glamor_priv->tile_prog == 0) { + glamor_fallback("Tiling unsupported\n"); + goto fail; + } + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) { + /* XXX dynamic uploading candidate. */ + glamor_fallback("Non-texture tile pixmap\n"); + goto fail; + } + + if (!glamor_set_planemask(pixmap, planemask)) { + glamor_fallback("unsupported planemask %lx\n", planemask); + goto fail; + } + + dispatch = glamor_get_dispatch(glamor_priv); + if (!glamor_set_alu(dispatch, alu)) { + glamor_fallback("unsupported alu %x\n", alu); + glamor_put_dispatch(glamor_priv); + goto fail; + } + + if (dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE + || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) { + glamor_pixmap_clipped_regions *clipped_dst_regions; + int n_dst_region, i, j, k; + BoxRec box; + RegionRec region; + + box.x1 = x; + box.y1 = y; + box.x2 = x + width; + box.y2 = y + height; + RegionInitBoxes(®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; + } diff --git a/src/glamor_utils.h b/src/glamor_utils.h index 90a1657..44c8175 100644 --- a/src/glamor_utils.h +++ b/src/glamor_utils.h @@ -41,8 +41,10 @@ #define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ do { \ - *(_pxscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.width; \ - *(_pyscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.height; \ + int w,h; \ + PIXMAP_PRIV_GET_ACTUAL_SIZE(_pixmap_priv_, w, h); \ + *(_pxscale_) = 1.0 / w; \ + *(_pyscale_) = 1.0 / h; \ } while(0) #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_) \ @@ -106,6 +108,52 @@ } \ } while(0) +#define _glamor_get_repeat_coords(priv, repeat_type, tx1, \ + ty1, tx2, ty2, \ + _x1_, _y1_, _x2_, \ + _y2_, c, d, odd_x, odd_y) \ + do { \ + if (repeat_type == RepeatReflect) { \ + assert(0); \ + } else if (repeat_type == RepeatNormal) { \ + tx1 = (c - priv->box.x1); \ + ty1 = (d - priv->box.y1); \ + tx2 = tx1 + ((_x2_) - (_x1_)); \ + ty2 = ty1 + ((_y2_) - (_y1_)); \ + } else { \ + assert(0); \ + } \ + } while(0) + + + +/* _x1_ ... _y2_ must be integer. */ +#define glamor_get_repeat_coords(priv, repeat_type, tx1, \ + ty1, tx2, ty2, _x1_, _y1_, _x2_, \ + _y2_) \ + do { \ + int c, d; \ + int odd_x = 0, odd_y = 0; \ + DEBUGF("width %d box.x1 %d x2 %d y1 %d y2 %d\n", \ + (priv)->base.pixmap->drawable.width, \ + priv->box.x1, priv->box.x2, \ + priv->box.y1, priv->box.y2); \ + modulus((_x1_), (priv)->base.pixmap->drawable.width, c); \ + modulus((_y1_), (priv)->base.pixmap->drawable.height, d); \ + DEBUGF("c %d d %d \n", c, d); \ + if (repeat_type == RepeatReflect) { \ + odd_x = abs((_x1_ - c) \ + / (priv->base.pixmap->drawable.width)) & 1; \ + odd_y = abs((_y1_ - d) \ + / (priv->base.pixmap->drawable.height)) & 1; \ + } \ + _glamor_get_repeat_coords(priv, repeat_type, tx1, ty1, tx2, ty2,\ + _x1_, _y1_, _x2_, _y2_, c, d, \ + odd_x, odd_y); \ + } while(0) + + + #define glamor_transform_point(matrix, tx, ty, x, y) \ do { \ int i; \ @@ -213,6 +261,24 @@ tx2, ty2, yInverted, vertices); \ } while(0) +#define glamor_set_repeat_normalize_tcoords(priv, repeat_type, \ + xscale, yscale, \ + _x1_, _y1_, _x2_, _y2_, \ + yInverted, vertices) \ + do { \ + float tx1, tx2, ty1, ty2; \ + if (priv->type == GLAMOR_TEXTURE_LARGE) \ + glamor_get_repeat_coords((&priv->large), repeat_type, \ + tx1, ty1, tx2, ty2, \ + _x1_, _y1_, _x2_, _y2_); \ + else { \ + tx1 = _x1_; tx2 = _x2_; ty1 = _y1_; ty2 = _y2_; \ + } \ + _glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1, \ + tx2, ty2, yInverted, vertices); \ + } while(0) + + #define glamor_set_tcoords(width, height, x1, y1, x2, y2, \ yInverted, vertices) \ do { \ @@ -303,7 +369,7 @@ glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox) } inline static void -glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) +glamor_translate_boxes(BoxPtr boxes, int nbox, int dx, int dy) { int i; for (i = 0; i < nbox; i++) { |