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); glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
int dst_x_off, dst_y_off, src_x_off, src_y_off, i; int dst_x_off, dst_y_off, src_x_off, src_y_off, i;
if (src == dst) {
glamor_delayed_fallback(screen,"src == dest\n");
return FALSE;
}
if (!GLEW_EXT_framebuffer_blit) { if (!GLEW_EXT_framebuffer_blit) {
glamor_delayed_fallback(screen,"no EXT_framebuffer_blit\n"); glamor_delayed_fallback(screen,"no EXT_framebuffer_blit\n");
return FALSE; return FALSE;
} }
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
@ -121,78 +116,6 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
return TRUE; 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 static Bool
glamor_copy_n_to_n_textured(DrawablePtr src, glamor_copy_n_to_n_textured(DrawablePtr src,
DrawablePtr dst, 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; int src_x_off, src_y_off, dst_x_off, dst_y_off;
enum glamor_pixmap_status src_status = GLAMOR_NONE; enum glamor_pixmap_status src_status = GLAMOR_NONE;
GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale; GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale;
int flush_needed = 0;
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
if (src == dst) {
glamor_delayed_fallback(dst->pScreen, "same src/dst\n");
goto fail;
}
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) {
glamor_delayed_fallback(dst->pScreen, "dst has no fbo.\n"); glamor_delayed_fallback(dst->pScreen, "dst has no fbo.\n");
goto fail; goto fail;
} }
if (!src_pixmap_priv->gl_tex) { if (!src_pixmap_priv->gl_fbo) {
#ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n");
goto fail; goto fail;
@ -237,6 +156,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
goto fail; goto fail;
#endif #endif
} }
else
flush_needed = 1;
if (gc) { if (gc) {
glamor_set_alu(gc->alu); 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_set_destination_pixmap_priv_nc(src_pixmap_priv);
glamor_validate_pixmap(src_pixmap); glamor_validate_pixmap(src_pixmap);
} }
} }
glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv); 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++) { for (i = 0; i < nbox; i++) {
glamor_set_normalize_vcoords(dst_xscale, dst_yscale, glamor_set_normalize_vcoords(dst_xscale, dst_yscale,
box[i].x1 + dst_x_off, box[i].x1 + dst_x_off,
box[i].y1 + dst_y_off, box[i].y1 + dst_y_off,
@ -308,6 +229,9 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
} }
/* The source texture is bound to a fbo, we have to flush it here. */
if (flush_needed)
glFlush();
return TRUE; return TRUE;
fail: fail:
@ -337,8 +261,14 @@ glamor_copy_n_to_n(DrawablePtr src,
ScreenPtr screen; ScreenPtr screen;
int temp_dx = dx; int temp_dx = dx;
int temp_dy = dy; 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 = glamor_get_drawable_pixmap(dst);
dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
src_pixmap = glamor_get_drawable_pixmap(src);
src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
screen = dst_pixmap->drawable.pScreen; screen = dst_pixmap->drawable.pScreen;
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) {
@ -346,19 +276,29 @@ glamor_copy_n_to_n(DrawablePtr src,
goto fail; 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; goto done;
return; 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); glamor_calculate_boxes_bound(&bound, box, nbox);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)
@ -370,7 +310,7 @@ glamor_copy_n_to_n(DrawablePtr src,
bound.y2 - bound.y1, bound.y2 - bound.y1,
src_pixmap->drawable.depth, src_pixmap->drawable.depth,
GLAMOR_CREATE_PIXMAP_CPU); GLAMOR_CREATE_PIXMAP_CPU);
if (!temp_src) if (!temp_pixmap)
goto fail; goto fail;
glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1);
temp_src = &temp_pixmap->drawable; 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)) { if (glamor_copy_n_to_n_textured(temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) {
goto done; goto done;
} }
fail: fail:
glamor_report_delayed_fallbacks(src->pScreen); glamor_report_delayed_fallbacks(src->pScreen);
@ -406,7 +347,8 @@ glamor_copy_n_to_n(DrawablePtr src,
dst_access = GLAMOR_ACCESS_WO; dst_access = GLAMOR_ACCESS_WO;
if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) { 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, fbCopyNtoN(src, dst, gc, box, nbox,
dx, dy, reverse, upsidedown, bitplane, dx, dy, reverse, upsidedown, bitplane,
closure); closure);
@ -428,34 +370,10 @@ RegionPtr
glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc, glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
int srcx, int srcy, int width, int height, int dstx, int dsty) 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; RegionPtr region;
region = miDoCopy(src, dst, gc, region = miDoCopy(src, dst, gc,
srcx, srcy, width, height, srcx, srcy, width, height,
dstx, dsty, glamor_copy_n_to_n, 0, NULL); dstx, dsty, glamor_copy_n_to_n, 0, NULL);
return region; 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
} }