glamor: Avoid 2D bitblit if possible.

It turns out that the use of fbo blit is one of the root cause
which lead to slow drawing, especially slow filling rects.

We guess there should be a performance bug in the mesa driver
or even in the kernel drm driver. Currently, the only thing
glamor can do is to avoid calling those functions.

We check whether the copy source and destination has overlapped
region, if it has, we have to call fbo blit function. If it has
not, we can load the source texture directly and draw it to the
target texture. We totally don't need the glCopyPixels here, so
remove it.

By apply this patch, the rendering time of firefox-planet-gnome
decrease to 10.4 seconds. At the same platform, uxa driver get 13
seconds. This is the first time we get better performance than
uxa driver.

Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
This commit is contained in:
Zhigang Gong 2011-07-20 13:35:25 +08:00
parent 5c4d53c512
commit 1f3f3baf14

View File

@ -47,15 +47,10 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
int dst_x_off, dst_y_off, src_x_off, src_y_off, i;
if (src == dst) {
glamor_delayed_fallback(screen,"src == dest\n");
return FALSE;
}
if (!GLEW_EXT_framebuffer_blit) {
glamor_delayed_fallback(screen,"no EXT_framebuffer_blit\n");
return FALSE;
}
}
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
@ -121,78 +116,6 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
return TRUE;
}
static Bool
glamor_copy_n_to_n_copypixels(DrawablePtr src,
DrawablePtr dst,
GCPtr gc,
BoxPtr box,
int nbox,
int dx,
int dy)
{
ScreenPtr screen = dst->pScreen;
PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
glamor_screen_private *glamor_priv =
glamor_get_screen_private(screen);
glamor_pixmap_private *pixmap_priv;
int x_off, y_off, i;
if (src != dst) {
glamor_delayed_fallback(screen, "src != dest\n");
return FALSE;
}
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;
}
}
pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
if (pixmap_priv->pending_op.type == GLAMOR_PENDING_FILL)
return TRUE;
if (glamor_set_destination_pixmap(dst_pixmap)) {
glamor_delayed_fallback(screen, "dst has no fbo.\n");
return FALSE;
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(0, dst_pixmap->drawable.width,
0, dst_pixmap->drawable.height,
-1, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glamor_get_drawable_deltas(dst, dst_pixmap, &x_off, &y_off);
for (i = 0; i < nbox; i++) {
if(glamor_priv->yInverted) {
glRasterPos2i(box[i].x1 + x_off,
box[i].y1 + y_off);
glCopyPixels(box[i].x1 + dx + x_off,
box[i].y1 + dy + y_off,
box[i].x2 - box[i].x1,
box[i].y2 - box[i].y1,
GL_COLOR);
} else {
int flip_y1 = dst_pixmap->drawable.height - box[i].y2 + y_off;
glRasterPos2i(box[i].x1 + x_off,
flip_y1);
glCopyPixels(box[i].x1 + dx + x_off,
flip_y1 - dy,
box[i].x2 - box[i].x1,
box[i].y2 - box[i].y1,
GL_COLOR);
}
}
return TRUE;
}
static Bool
glamor_copy_n_to_n_textured(DrawablePtr src,
DrawablePtr dst,
@ -213,21 +136,17 @@ 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 flush_needed = 0;
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
if (src == dst) {
glamor_delayed_fallback(dst->pScreen, "same src/dst\n");
goto fail;
}
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) {
glamor_delayed_fallback(dst->pScreen, "dst has no fbo.\n");
goto fail;
}
if (!src_pixmap_priv->gl_tex) {
if (!src_pixmap_priv->gl_fbo) {
#ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n");
goto fail;
@ -237,6 +156,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
goto fail;
#endif
}
else
flush_needed = 1;
if (gc) {
glamor_set_alu(gc->alu);
@ -246,7 +167,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
glamor_set_destination_pixmap_priv_nc(src_pixmap_priv);
glamor_validate_pixmap(src_pixmap);
}
}
glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
@ -283,6 +203,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
}
for (i = 0; i < nbox; i++) {
glamor_set_normalize_vcoords(dst_xscale, dst_yscale,
box[i].x1 + dst_x_off,
box[i].y1 + dst_y_off,
@ -308,6 +229,9 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
/* The source texture is bound to a fbo, we have to flush it here. */
if (flush_needed)
glFlush();
return TRUE;
fail:
@ -337,8 +261,14 @@ glamor_copy_n_to_n(DrawablePtr src,
ScreenPtr screen;
int temp_dx = dx;
int temp_dy = dy;
int src_x_off, src_y_off, dst_x_off, dst_y_off;
int i;
int overlaped = 0;
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;
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) {
@ -346,19 +276,29 @@ glamor_copy_n_to_n(DrawablePtr src,
goto fail;
}
if (glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) {
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->fb == dst_pixmap_priv->fb) {
int x_shift = abs(src_x_off - dx - dst_x_off);
int y_shift = abs(src_y_off - dy - dst_y_off);
for ( i = 0; i < nbox; i++)
{
if (x_shift < abs(box[i].x2 - box[i].x1)
&& y_shift < abs(box[i].y2 - box[i].y1)) {
overlaped = 1;
break;
}
}
}
/* XXX need revisit to handle overlapped area copying. */
if ( overlaped
&& glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) {
goto done;
return;
}
if (glamor_copy_n_to_n_copypixels(src, dst, gc, box, nbox, dx, dy)){
goto done;
return;
}
src_pixmap = glamor_get_drawable_pixmap(src);
src_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
glamor_calculate_boxes_bound(&bound, box, nbox);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)
@ -370,7 +310,7 @@ glamor_copy_n_to_n(DrawablePtr src,
bound.y2 - bound.y1,
src_pixmap->drawable.depth,
GLAMOR_CREATE_PIXMAP_CPU);
if (!temp_src)
if (!temp_pixmap)
goto fail;
glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1);
temp_src = &temp_pixmap->drawable;
@ -391,6 +331,7 @@ glamor_copy_n_to_n(DrawablePtr src,
if (glamor_copy_n_to_n_textured(temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) {
goto done;
}
fail:
glamor_report_delayed_fallbacks(src->pScreen);
@ -406,7 +347,8 @@ glamor_copy_n_to_n(DrawablePtr src,
dst_access = GLAMOR_ACCESS_WO;
if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) {
if (dst == src || glamor_prepare_access(src, GLAMOR_ACCESS_RO)) {
if (dst == src
|| glamor_prepare_access(src, GLAMOR_ACCESS_RO)) {
fbCopyNtoN(src, dst, gc, box, nbox,
dx, dy, reverse, upsidedown, bitplane,
closure);
@ -428,34 +370,10 @@ RegionPtr
glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
int srcx, int srcy, int width, int height, int dstx, int dsty)
{
#if 0
ScreenPtr screen = dst->pScreen;
PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap);
#endif
RegionPtr region;
region = miDoCopy(src, dst, gc,
srcx, srcy, width, height,
dstx, dsty, glamor_copy_n_to_n, 0, NULL);
return region;
#if 0
fail:
glamor_fallback("glamor_copy_area from %p to %p (%c,%c)\n", src, dst,
glamor_get_drawable_location(src),
glamor_get_drawable_location(dst));
region = NULL;
if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) {
if (glamor_prepare_access(src, GLAMOR_ACCESS_RO)) {
region = fbCopyArea(src, dst, gc, srcx, srcy, width, height,
dstx, dsty);
glamor_finish_access(src);
}
glamor_finish_access(dst);
}
return region;
#endif
}