diff --git a/src/glamor_copyarea.c b/src/glamor_copyarea.c index 4e6f953..257fb5c 100644 --- a/src/glamor_copyarea.c +++ b/src/glamor_copyarea.c @@ -163,16 +163,37 @@ glamor_copy_n_to_n_textured(DrawablePtr src, src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); dst_pixmap_priv = glamor_get_pixmap_private(dst_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.gl_fbo) { #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n"); return FALSE; #else - src_status = glamor_upload_pixmap_to_texture(src_pixmap); - if (src_status != GLAMOR_UPLOAD_DONE) - return FALSE; - - src_pixmap_priv = glamor_get_pixmap_private(src_pixmap); + /* Optimize when the source doesn't have an FBO, just upload + the data directly to the dest FBO */ + int src_stride = src_pixmap->devKind; + int bpp = src_pixmap->drawable.bitsPerPixel; + CARD8 *src_data = NULL; + for (i = 0; i < nbox; i++) { + int x = box[i].x1 + dst_x_off; + int y = box[i].y1 + dst_y_off; + int w = box[i].x2 - box[i].x1; + int h = box[i].y2 - box[i].y1; + src_data = src_pixmap->devPrivate.ptr + (box[i].y1 + dy + + src_y_off) * src_stride + + (box[i].x1 + dx + src_x_off) * (bpp / 8); + if (!glamor_upload_sub_pixmap_to_texture(dst_pixmap, + x, y, w, h, + src_stride, src_data, 0)) { + ErrorF("Failed to upload the sub pixmap to dst\n"); + return FALSE; + } + } + return TRUE; #endif } @@ -180,8 +201,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src, pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale); pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale); - glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, - &dst_y_off); dispatch = glamor_get_dispatch(glamor_priv); @@ -192,11 +211,11 @@ glamor_copy_n_to_n_textured(DrawablePtr src, vertices); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); - glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, - &src_y_off); + dx += src_x_off; dy += src_y_off; + dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex); @@ -335,7 +354,7 @@ __glamor_copy_n_to_n(DrawablePtr src, * 4 > src_pixmap->drawable.width * src_pixmap->drawable.height) - || !(glamor_check_fbo_size(glamor_priv, + || !(glamor_check_fbo_size(glamor_priv, src_pixmap->drawable.width, src_pixmap->drawable.height))))) { diff --git a/src/glamor_pixmap.c b/src/glamor_pixmap.c index 84694ec..68a9214 100644 --- a/src/glamor_pixmap.c +++ b/src/glamor_pixmap.c @@ -387,7 +387,7 @@ static void __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex, GLenum format, GLenum type, - int x, int y, int w, int h, + int x, int y, int w, int h, int stride, void *bits, int pbo) { glamor_screen_private *glamor_priv = @@ -395,6 +395,12 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex, glamor_gl_dispatch *dispatch; int non_sub = 0; unsigned int iformat = 0; + int bpp = depth_for_type(type); + int alignment = bpp / 8; + if (stride == 0) { + alignment = 4; + } + dispatch = glamor_get_dispatch(glamor_priv); if (*tex == 0) { @@ -412,11 +418,13 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex, GL_NEAREST); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); if (bits == NULL) dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); + + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / alignment); if (non_sub) dispatch->glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, @@ -428,6 +436,8 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex, format, type, bits); + dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + if (bits == NULL) dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glamor_put_dispatch(glamor_priv); @@ -511,7 +521,7 @@ ready_to_upload: 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 + fbo_x_off, y + fbo_y_off, w, h, + x + fbo_x_off, y + fbo_y_off, w, h, stride, bits, pbo); return TRUE; } @@ -542,7 +552,7 @@ ready_to_upload: glamor_set_destination_pixmap_priv_nc(pixmap_priv); __glamor_upload_pixmap_to_texture(pixmap, &tex, format, type, - 0, 0, w, h, + 0, 0, w, h, stride, bits, pbo); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, tex); @@ -807,7 +817,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap) if (glamor_upload_sub_pixmap_to_texture(pixmap, 0, 0, pixmap->drawable.width, pixmap->drawable.height, - pixmap->devKind, + 0, data, pbo)) ret = GLAMOR_UPLOAD_DONE; else diff --git a/src/glamor_putimage.c b/src/glamor_putimage.c index 99f7ac6..c389685 100644 --- a/src/glamor_putimage.c +++ b/src/glamor_putimage.c @@ -300,13 +300,13 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, } glamor_upload_sub_pixmap_to_texture(temp_pixmap, 0, 0, w, h, - pixmap->devKind, bits, 0); - + 0, bits, 0); glamor_copy_area(&temp_pixmap->drawable, drawable, gc, 0, 0, w, h, x, y); glamor_destroy_pixmap(temp_pixmap); - } else + } else { glamor_upload_sub_pixmap_to_texture(pixmap, x + drawable->x + x_off, y + drawable->y + y_off, - w, h, PixmapBytePad(w, depth), bits, 0); + w, h, 0, bits, 0); + } ret = TRUE; goto done; diff --git a/src/glamor_setspans.c b/src/glamor_setspans.c index 3d447b6..32fd8cf 100644 --- a/src/glamor_setspans.c +++ b/src/glamor_setspans.c @@ -69,7 +69,7 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, if (x1 >= x2) continue; glamor_upload_sub_pixmap_to_texture(dest_pixmap, x1 + x_off, y1 + y_off, x2 - x1, 1, - PixmapBytePad(widths[i], drawable->depth), + 0, drawpixels_src, 0); } drawpixels_src += PixmapBytePad(widths[i], drawable->depth); diff --git a/src/glamor_utils.h b/src/glamor_utils.h index d307838..cf0f1eb 100644 --- a/src/glamor_utils.h +++ b/src/glamor_utils.h @@ -880,6 +880,26 @@ format_for_depth(int depth) } } +static inline int +depth_for_type(GLenum type) +{ + switch (type) { + case GL_UNSIGNED_BYTE: + return 8; + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_2_10_10_10_REV: + return 32; + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + return 16; + default: + return 0; + } +} + static inline void gl_iformat_for_depth(int depth, GLenum * format) {