glamor_largepixmap: first commit for large pixmap.
authorZhigang Gong <zhigang.gong@linux.intel.com>
Sun, 10 Jun 2012 17:02:30 +0000 (01:02 +0800)
committerEric Anholt <eric@anholt.net>
Wed, 18 Dec 2013 19:23:51 +0000 (11:23 -0800)
This is the first commit to add support for large pixmap.
The large here means a pixmap is larger than the texutre's
size limitation thus can't fit into one single texutre.

The previous implementation will simply fallback to use a
in memory pixmap to contain the large pixmap which is
very slow in practice.

The basic idea here is to use an array of texture to hold
the large pixmap. And when we need to get a specific area
of the pixmap, we just need to compute/clip the correct
region and find the corresponding fbo.

We need to implement some auxiliary routines to clip every
rendering operations into small pieces which can fit into
one texture.

The complex part is the transformation/repeat/repeatReflect
and repeat pad and their comination. We will support all of
them step by step.

This commit just add some necessary data structure to represent
the large pixmap, and doesn't change any rendering process.
This commit doesn't add real large pixmap support.

Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
15 files changed:
glamor/glamor.c
glamor/glamor.h
glamor/glamor_copyarea.c
glamor/glamor_core.c
glamor/glamor_debug.h
glamor/glamor_fbo.c
glamor/glamor_fill.c
glamor/glamor_gradient.c
glamor/glamor_picture.c
glamor/glamor_pixmap.c
glamor/glamor_priv.h
glamor/glamor_putimage.c
glamor/glamor_render.c
glamor/glamor_tile.c
glamor/glamor_utils.h

index 6b6fa0b..a22f445 100644 (file)
@@ -73,8 +73,8 @@ glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type)
        if (pixmap_priv == NULL) {
                pixmap_priv = calloc(sizeof(*pixmap_priv), 1);
                glamor_set_pixmap_private(pixmap, pixmap_priv);
-               pixmap_priv->container = pixmap;
-               pixmap_priv->glamor_priv = glamor_priv;
+               pixmap_priv->base.pixmap = pixmap;
+               pixmap_priv->base.glamor_priv = glamor_priv;
        }
        pixmap_priv->type = type;
 }
@@ -91,7 +91,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
        glamor_priv = glamor_get_screen_private(screen);
        pixmap_priv = glamor_get_pixmap_private(pixmap);
 
-       if (pixmap_priv->fbo) {
+       if (pixmap_priv->base.fbo) {
                fbo = glamor_pixmap_detach_fbo(pixmap_priv);
                glamor_destroy_fbo(fbo);
        }
@@ -117,10 +117,10 @@ glamor_set_screen_pixmap(PixmapPtr screen_pixmap, PixmapPtr *back_pixmap)
 
        glamor_priv = glamor_get_screen_private(screen_pixmap->drawable.pScreen);
        pixmap_priv = glamor_get_pixmap_private(screen_pixmap);
-       glamor_priv->screen_fbo = pixmap_priv->fbo->fb;
+       glamor_priv->screen_fbo = pixmap_priv->base.fbo->fb;
 
-       pixmap_priv->fbo->width = screen_pixmap->drawable.width;
-       pixmap_priv->fbo->height = screen_pixmap->drawable.height;
+       pixmap_priv->base.fbo->width = screen_pixmap->drawable.width;
+       pixmap_priv->base.fbo->height = screen_pixmap->drawable.height;
 
        glamor_priv->back_pixmap = back_pixmap;
 }
@@ -159,8 +159,8 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
        if (usage == GLAMOR_CREATE_PIXMAP_MAP)
                type = GLAMOR_MEMORY_MAP;
 
-       pixmap_priv->container = pixmap;
-       pixmap_priv->glamor_priv = glamor_priv;
+       pixmap_priv->base.pixmap = pixmap;
+       pixmap_priv->base.glamor_priv = glamor_priv;
        pixmap_priv->type = type;
 
        gl_iformat_for_depth(depth, &format);
index c2db86a..fe3e4f8 100644 (file)
@@ -55,7 +55,9 @@ typedef enum  glamor_pixmap_type {
        GLAMOR_TEXTURE_DRM,
        GLAMOR_SEPARATE_TEXTURE,
        GLAMOR_DRM_ONLY,
-       GLAMOR_TEXTURE_ONLY
+       GLAMOR_TEXTURE_ONLY,
+       GLAMOR_TEXTURE_LARGE,
+       GLAMOR_TEXTURE_PACK
 } glamor_pixmap_type_t;
 
 #define GLAMOR_EGL_EXTERNAL_BUFFER 3
index 356e0f9..84a449c 100644 (file)
@@ -75,7 +75,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
 
        dispatch = glamor_get_dispatch(glamor_priv);
        dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT,
-                                   src_pixmap_priv->fbo->fb);
+                                   src_pixmap_priv->base.fbo->fb);
        glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off,
                                   &dst_y_off);
        glamor_get_drawable_deltas(src, src_pixmap, &src_x_off,
@@ -164,7 +164,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
                return FALSE;
        }
 
-       if (!src_pixmap_priv || !src_pixmap_priv->gl_fbo) {
+       if (!src_pixmap_priv || !src_pixmap_priv->base.gl_fbo) {
 #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
                glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n");
                return FALSE;
@@ -209,7 +209,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
 
        dispatch->glActiveTexture(GL_TEXTURE0);
        dispatch->glBindTexture(GL_TEXTURE_2D,
-                               src_pixmap_priv->fbo->tex);
+                               src_pixmap_priv->base.fbo->tex);
 #ifndef GLAMOR_GLES2
        dispatch->glEnable(GL_TEXTURE_2D);
        dispatch->glTexParameteri(GL_TEXTURE_2D,
@@ -239,7 +239,8 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
 
        for (i = 0; i < nbox; i++) {
 
-               glamor_set_normalize_vcoords(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,
@@ -247,7 +248,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
                                             glamor_priv->yInverted,
                                             vertices);
 
-               glamor_set_normalize_tcoords(src_xscale,
+               glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale,
                                             src_yscale,
                                             box[i].x1 + dx,
                                             box[i].y1 + dy,
@@ -320,7 +321,7 @@ _glamor_copy_n_to_n(DrawablePtr src,
        glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off,
                                   &dst_y_off);
 
-       if (src_pixmap_priv->fbo && src_pixmap_priv->fbo->fb == dst_pixmap_priv->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++) {
@@ -333,7 +334,7 @@ _glamor_copy_n_to_n(DrawablePtr src,
        }
 #ifndef GLAMOR_GLES2
        if ((overlaped
-            || !src_pixmap_priv->gl_tex || !dst_pixmap_priv->gl_tex)
+            || !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex)
            && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx,
                                           dy)) {
                ret = TRUE;
index 009a089..8ba3347 100644 (file)
@@ -43,9 +43,9 @@ glamor_get_drawable_location(const DrawablePtr drawable)
            glamor_get_pixmap_private(pixmap);
        glamor_screen_private *glamor_priv =
            glamor_get_screen_private(drawable->pScreen);
-       if (pixmap_priv == NULL || pixmap_priv->gl_fbo == 0)
+       if (pixmap_priv == NULL || pixmap_priv->base.gl_fbo == 0)
                return 'm';
-       if (pixmap_priv->fbo->fb == glamor_priv->screen_fbo)
+       if (pixmap_priv->base.fbo->fb == glamor_priv->screen_fbo)
                return 's';
        else
                return 'f';
@@ -327,7 +327,7 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode)
                glamor_restore_pixmap_to_texture(pixmap);
        }
 
-       if (pixmap_priv->fbo->pbo != 0 && pixmap_priv->fbo->pbo_valid) {
+       if (pixmap_priv->base.fbo->pbo != 0 && pixmap_priv->base.fbo->pbo_valid) {
                glamor_gl_dispatch *dispatch;
 
                assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
@@ -335,20 +335,20 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode)
                dispatch = glamor_get_dispatch(glamor_priv);
                dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
                dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-               dispatch->glDeleteBuffers(1, &pixmap_priv->fbo->pbo);
+               dispatch->glDeleteBuffers(1, &pixmap_priv->base.fbo->pbo);
                glamor_put_dispatch(glamor_priv);
 
-               pixmap_priv->fbo->pbo_valid = FALSE;
-               pixmap_priv->fbo->pbo = 0;
+               pixmap_priv->base.fbo->pbo_valid = FALSE;
+               pixmap_priv->base.fbo->pbo = 0;
        } else {
                free(pixmap->devPrivate.ptr);
        }
 
        if (pixmap_priv->type == GLAMOR_TEXTURE_DRM)
-               pixmap->devKind = pixmap_priv->drm_stride;
+               pixmap->devKind = pixmap_priv->base.drm_stride;
 
-       if (pixmap_priv->gl_fbo == GLAMOR_FBO_DOWNLOADED)
-               pixmap_priv->gl_fbo = GLAMOR_FBO_NORMAL;
+       if (pixmap_priv->base.gl_fbo == GLAMOR_FBO_DOWNLOADED)
+               pixmap_priv->base.gl_fbo = GLAMOR_FBO_NORMAL;
 
        pixmap->devPrivate.ptr = NULL;
 }
index 99dce04..f0c969b 100644 (file)
@@ -107,8 +107,10 @@ AbortServer(void)
                     _glamor_priv_->delayed_fallback_string);           \
       _glamor_priv_->delayed_fallback_pending = 0;  } } while(0)
 
-#define DEBUGF(str, ...)
+#define DEBUGF(str, ...)  do {} while(0)
 //#define DEBUGF(str, ...) ErrorF(str, ##__VA_ARGS__)
+#define DEBUGRegionPrint(x) do {} while (0)
+//#define DEBUGRegionPrint RegionPrint
 
 
 #endif
index f4e02b2..5337149 100644 (file)
@@ -412,11 +412,11 @@ glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv)
        if (pixmap_priv == NULL)
                return NULL;
 
-       fbo = pixmap_priv->fbo;
+       fbo = pixmap_priv->base.fbo;
        if (fbo == NULL)
                return NULL;
 
-       pixmap_priv->fbo = NULL;
+       pixmap_priv->base.fbo = NULL;
        return fbo;
 }
 
@@ -434,25 +434,25 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo)
                pixmap_priv = calloc(1, sizeof(*pixmap_priv));
                dixSetPrivate(&pixmap->devPrivates,
                              glamor_pixmap_private_key, pixmap_priv);
-               pixmap_priv->container = pixmap;
-               pixmap_priv->glamor_priv = glamor_priv;
+               pixmap_priv->base.pixmap = pixmap;
+               pixmap_priv->base.glamor_priv = glamor_priv;
                pixmap_priv->type = GLAMOR_MEMORY;
        }
 
-       if (pixmap_priv->fbo)
+       if (pixmap_priv->base.fbo)
                return;
 
-       pixmap_priv->fbo = fbo;
+       pixmap_priv->base.fbo = fbo;
 
        switch (pixmap_priv->type) {
        case GLAMOR_TEXTURE_ONLY:
        case GLAMOR_TEXTURE_DRM:
-               pixmap_priv->gl_fbo = 1;
+               pixmap_priv->base.gl_fbo = 1;
                if (fbo->tex != 0)
-                       pixmap_priv->gl_tex = 1;
+                       pixmap_priv->base.gl_tex = 1;
                else {
                        /* XXX For the Xephyr only, may be broken now.*/
-                       pixmap_priv->gl_tex = 0;
+                       pixmap_priv->base.gl_tex = 0;
                }
        case GLAMOR_MEMORY_MAP:
                pixmap->devPrivate.ptr = NULL;
@@ -472,7 +472,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->fbo == NULL) {
+       if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) {
 
                fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
                                        pixmap->drawable.height,
@@ -484,12 +484,12 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag)
                glamor_pixmap_attach_fbo(pixmap, fbo);
        } else {
                /* We do have a fbo, but it may lack of fb or tex. */
-               if (!pixmap_priv->fbo->tex)
-                       pixmap_priv->fbo->tex = _glamor_create_tex(glamor_priv, pixmap->drawable.width,
+               if (!pixmap_priv->base.fbo->tex)
+                       pixmap_priv->base.fbo->tex = _glamor_create_tex(glamor_priv, pixmap->drawable.width,
                                                                   pixmap->drawable.height, format);
 
-               if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->fbo->fb == 0)
-                       glamor_pixmap_ensure_fb(pixmap_priv->fbo);
+               if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->base.fbo->fb == 0)
+                       glamor_pixmap_ensure_fb(pixmap_priv->base.fbo);
        }
 
        pixmap_priv = glamor_get_pixmap_private(pixmap);
@@ -504,7 +504,7 @@ glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back)
 
        front_priv = glamor_get_pixmap_private(front);
        back_priv = glamor_get_pixmap_private(back);
-       temp_fbo = front_priv->fbo;
-       front_priv->fbo = back_priv->fbo;
-       back_priv->fbo = temp_fbo;
+       temp_fbo = front_priv->base.fbo;
+       front_priv->base.fbo = back_priv->base.fbo;
+       back_priv->base.fbo = temp_fbo;
 }
index 57dd698..b63756d 100644 (file)
@@ -239,7 +239,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
        dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
        pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
 
-       glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2,
+       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);
index ab2c2ed..09e33d7 100644 (file)
@@ -806,14 +806,14 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen,
               *xscale, *yscale, x_source, y_source,
               dst_picture->pDrawable->width, dst_picture->pDrawable->height);
 
-       glamor_set_normalize_vcoords(*xscale, *yscale,
+       glamor_set_normalize_vcoords(pixmap_priv, *xscale, *yscale,
                                     0, 0,
                                     (INT16)(dst_picture->pDrawable->width),
                                     (INT16)(dst_picture->pDrawable->height),
                                     glamor_priv->yInverted, vertices);
 
        if (tex_normalize) {
-               glamor_set_normalize_tcoords(*xscale, *yscale,
+               glamor_set_normalize_tcoords(pixmap_priv, *xscale, *yscale,
                                             x_source, y_source,
                                             (INT16)(dst_picture->pDrawable->width + x_source),
                                             (INT16)(dst_picture->pDrawable->height + y_source),
index a6d21f1..44e1e40 100644 (file)
@@ -101,8 +101,8 @@ glamor_create_picture(PicturePtr picture)
                }
        }
 
-       pixmap_priv->is_picture = 1;
-       pixmap_priv->pict_format = picture->format;
+       pixmap_priv->base.is_picture = 1;
+       pixmap_priv->base.picture = picture;
 
        return miCreatePicture(picture);
 }
@@ -123,8 +123,8 @@ glamor_destroy_picture(PicturePtr picture)
        pixmap_priv = glamor_get_pixmap_private(pixmap);
 
        if (pixmap_priv) {
-               pixmap_priv->is_picture = 0;
-               pixmap_priv->pict_format = 0;
+               pixmap_priv->base.is_picture = 0;
+               pixmap_priv->base.picture = NULL;
        }
        miDestroyPicture(picture);
 }
@@ -133,5 +133,5 @@ void
 glamor_picture_format_fixup(PicturePtr picture,
                            glamor_pixmap_private * pixmap_priv)
 {
-       pixmap_priv->pict_format = picture->format;
+       pixmap_priv->base.picture = picture;
 }
index f0c1586..fa05bed 100644 (file)
@@ -83,9 +83,9 @@ 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)
 {
-       glamor_set_destination_pixmap_fbo(pixmap_priv->fbo, 0, 0,
-                                         pixmap_priv->container->drawable.width,
-                                         pixmap_priv->container->drawable.height);
+       glamor_set_destination_pixmap_fbo(pixmap_priv->base.fbo, 0, 0,
+                                         pixmap_priv->base.pixmap->drawable.width,
+                                         pixmap_priv->base.pixmap->drawable.height);
 }
 
 int
@@ -495,8 +495,8 @@ ready_to_upload:
            && revert == REVERT_NONE
            && swap_rb == SWAP_NONE_UPLOADING
            && !need_flip) {
-               assert(pixmap_priv->fbo->tex);
-               __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->fbo->tex,
+               assert(pixmap_priv->base.fbo->tex);
+               __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->base.fbo->tex,
                                                  format, type,
                                                  x, y, w, h,
                                                  bits, pbo);
@@ -509,7 +509,7 @@ ready_to_upload:
                ptexcoords = texcoords_inv;
 
        pixmap_priv_get_dest_scale(pixmap_priv, &dst_xscale, &dst_yscale);
-       glamor_set_normalize_vcoords(dst_xscale,
+       glamor_set_normalize_vcoords(pixmap_priv, dst_xscale,
                                     dst_yscale,
                                     x, y,
                                     x + w, y + h,
@@ -586,14 +586,14 @@ 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->fbo
-            && (pixmap_priv->fbo->width < pixmap->drawable.width
-           || pixmap_priv->fbo->height < pixmap->drawable.height)) {
+       if (pixmap_priv->base.fbo
+            && (pixmap_priv->base.fbo->width < pixmap->drawable.width
+           || pixmap_priv->base.fbo->height < pixmap->drawable.height)) {
                fbo = glamor_pixmap_detach_fbo(pixmap_priv);
                glamor_destroy_fbo(fbo);
         }
 
-       if (pixmap_priv->fbo && pixmap_priv->fbo->fb)
+       if (pixmap_priv->base.fbo && pixmap_priv->base.fbo->fb)
                return 0;
 
        if (!(no_alpha
@@ -605,8 +605,8 @@ 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->fbo && pixmap_priv->fbo->tex)
-           || (flag != 0 && pixmap_priv && pixmap_priv->fbo && pixmap_priv->fbo->fb))
+       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))
                return 0;
 
        if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
@@ -614,7 +614,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int
        else
                iformat = format;
 
-       if (pixmap_priv == NULL || pixmap_priv->fbo == NULL) {
+       if (pixmap_priv == NULL || pixmap_priv->base.fbo == NULL) {
 
                fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
                                        pixmap->drawable.height,
@@ -672,10 +672,10 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
        pixmap_priv = glamor_get_pixmap_private(pixmap);
 
        if (pixmap_priv
-           && (pixmap_priv->fbo)
-           && (pixmap_priv->fbo->pbo_valid)) {
+           && (pixmap_priv->base.fbo)
+           && (pixmap_priv->base.fbo->pbo_valid)) {
                data = NULL;
-               pbo = pixmap_priv->fbo->pbo;
+               pbo = pixmap_priv->base.fbo->pbo;
        } else {
                data = pixmap->devPrivate.ptr;
                pbo = 0;
@@ -737,7 +737,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(temp_xscale,
+       glamor_set_normalize_vcoords((glamor_pixmap_private *)NULL, temp_xscale,
                                     temp_yscale,
                                     0, 0,
                                     w, h,
@@ -750,7 +750,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe
        dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
        pixmap_priv_get_scale(source_priv, &source_xscale, &source_yscale);
-       glamor_set_normalize_tcoords(source_xscale,
+       glamor_set_normalize_tcoords(source_priv, source_xscale,
                                     source_yscale,
                                     x, y,
                                     x + w, y + h,
@@ -763,7 +763,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h, GLe
        dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
        dispatch->glActiveTexture(GL_TEXTURE0);
-       dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->fbo->tex);
+       dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->base.fbo->tex);
        dispatch->glTexParameteri(GL_TEXTURE_2D,
                                  GL_TEXTURE_MIN_FILTER,
                                  GL_NEAREST);
@@ -988,16 +988,16 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
                data = malloc(stride * pixmap->drawable.height);
        } else {
                dispatch = glamor_get_dispatch(glamor_priv);
-               if (pixmap_priv->fbo->pbo == 0)
+               if (pixmap_priv->base.fbo->pbo == 0)
                        dispatch->glGenBuffers(1,
-                                              &pixmap_priv->fbo->pbo);
+                                              &pixmap_priv->base.fbo->pbo);
                glamor_put_dispatch(glamor_priv);
-               pbo = pixmap_priv->fbo->pbo;
+               pbo = pixmap_priv->base.fbo->pbo;
        }
 
        if (pixmap_priv->type == GLAMOR_TEXTURE_DRM) {
                stride = PixmapBytePad(pixmap->drawable.width, pixmap->drawable.depth);
-               pixmap_priv->drm_stride = pixmap->devKind;
+               pixmap_priv->base.drm_stride = pixmap->devKind;
                pixmap->devKind = stride;
        }
 
@@ -1014,9 +1014,9 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
        }
 
        if (pbo != 0)
-               pixmap_priv->fbo->pbo_valid = 1;
+               pixmap_priv->base.fbo->pbo_valid = 1;
 
-       pixmap_priv->gl_fbo = GLAMOR_FBO_DOWNLOADED;
+       pixmap_priv->base.gl_fbo = GLAMOR_FBO_DOWNLOADED;
 
        pixmap->devPrivate.ptr = dst;
 
@@ -1036,14 +1036,14 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
        GCPtr gc = NULL;
        int ret = FALSE;
 
-       drawable = &pixmap_priv->container->drawable;
+       drawable = &pixmap_priv->base.pixmap->drawable;
 
-       if (pixmap_priv->container->drawable.width == pixmap_priv->fbo->width
-           && pixmap_priv->container->drawable.height == pixmap_priv->fbo->height)
+       if (pixmap_priv->base.pixmap->drawable.width == pixmap_priv->base.fbo->width
+           && pixmap_priv->base.pixmap->drawable.height == pixmap_priv->base.fbo->height)
                return  TRUE;
 
-       old_fbo = pixmap_priv->fbo;
-       glamor_priv = pixmap_priv->glamor_priv;
+       old_fbo = pixmap_priv->base.fbo;
+       glamor_priv = pixmap_priv->base.glamor_priv;
 
        if (!old_fbo)
                return FALSE;
@@ -1058,7 +1058,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
 
        scratch_priv = glamor_get_pixmap_private(scratch);
 
-       if (!scratch_priv || !scratch_priv->fbo)
+       if (!scratch_priv || !scratch_priv->base.fbo)
                goto fail;
 
        ValidateGC(&scratch->drawable, gc);
@@ -1069,7 +1069,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
                         0, 0);
        old_fbo = glamor_pixmap_detach_fbo(pixmap_priv);
        new_fbo = glamor_pixmap_detach_fbo(scratch_priv);
-       glamor_pixmap_attach_fbo(pixmap_priv->container, new_fbo);
+       glamor_pixmap_attach_fbo(pixmap_priv->base.pixmap, new_fbo);
        glamor_pixmap_attach_fbo(scratch, old_fbo);
 
        DEBUGF("old %dx%d type %d\n",
@@ -1139,11 +1139,11 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces
                return NULL;
 
        sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
-       pbo = sub_pixmap_priv ? (sub_pixmap_priv->fbo ? sub_pixmap_priv->fbo->pbo : 0): 0;
+       pbo = sub_pixmap_priv ? (sub_pixmap_priv->base.fbo ? sub_pixmap_priv->base.fbo->pbo : 0): 0;
 
-       if (pixmap_priv->is_picture) {
-               sub_pixmap_priv->pict_format = pixmap_priv->pict_format;
-               sub_pixmap_priv->is_picture = pixmap_priv->is_picture;
+       if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) {
+               sub_pixmap_priv->base.picture = pixmap_priv->base.picture;
+               sub_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture;
        }
 
        if (pbo)
@@ -1157,7 +1157,7 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h, glamor_acces
        if (pbo) {
                assert(sub_pixmap->devPrivate.ptr == NULL);
                sub_pixmap->devPrivate.ptr = data;
-               sub_pixmap_priv->fbo->pbo_valid = 1;
+               sub_pixmap_priv->base.fbo->pbo_valid = 1;
        }
 #if 0
        struct pixman_box16 box;
@@ -1189,10 +1189,10 @@ glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y, int
        if (access != GLAMOR_ACCESS_RO) {
                sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
                if (sub_pixmap_priv
-                   && sub_pixmap_priv->fbo
-                   && sub_pixmap_priv->fbo->pbo_valid) {
+                   && sub_pixmap_priv->base.fbo
+                   && sub_pixmap_priv->base.fbo->pbo_valid) {
                        bits = NULL;
-                       pbo = sub_pixmap_priv->fbo->pbo;
+                       pbo = sub_pixmap_priv->base.fbo->pbo;
                } else {
                        bits = sub_pixmap->devPrivate.ptr;
                        pbo = 0;
index a817f78..2172d17 100644 (file)
@@ -309,19 +309,132 @@ typedef struct glamor_pixmap_fbo {
  * @gl_tex:  The pixmap is in a gl texture originally.
  * @is_picture: The drawable is attached to a picture.
  * @pict_format: the corresponding picture's format.
- * @container: The corresponding pixmap's pointer.
+ * @pixmap: The corresponding pixmap's pointer.
+ *
+ * For GLAMOR_TEXTURE_LARGE, nbox should larger than 1.
+ * And the box and fbo will both have nbox elements.
+ * and box[i] store the relatively coords in this pixmap
+ * of the fbo[i]. The reason why use boxes not region to
+ * represent this structure is we may need to use overlapped
+ * boxes for one pixmap for some special reason.
+ *
+ * pixmap
+ * ******************
+ * *  fbo0 * fbo1   *
+ * *       *        *
+ * ******************
+ * *  fbo2 * fbo3   *
+ * *       *        *
+ * ******************
+ *
+ * Let's assume the texture has size of 1024x1024
+ * box[0] = {0,0,1024,1024}
+ * box[1] = {1024,0,2048,2048}
+ * ...
+ *
+ * For GLAMOR_TEXTURE_ATLAS nbox should be 1. And box
+ * and fbo both has one elements, and the box store
+ * the relatively coords in the fbo of this pixmap:
+ *
+ * fbo
+ * ******************
+ * *   pixmap       *
+ * *   *********    *
+ * *   *       *    *
+ * *   *********    *
+ * *                *
+ * ******************
+ *
+ * Assume the pixmap is at the (100,100) relatively to
+ * the fbo's origin.
+ * box[0]={100, 100, 1124, 1124};
+ *
+ * Considering large pixmap is not a normal case, to keep
+ * it simple, I designe it as the following way.
+ * When deal with a large pixmap, it split the working
+ * rectangle into serval boxes, and each box fit into a
+ * corresponding fbo. And then the rendering function will
+ * loop from the left-top box to the right-bottom box,
+ * each time, we will set current box and current fbo
+ * to the box and fbo elements. Thus the inner routines
+ * can handle it as normal, only the coords calculation need
+ * to aware of it's large pixmap.
+ *
+ * Currently, we haven't implemented the atlas pixmap.
+ *
  **/
-typedef struct glamor_pixmap_private {
+
+typedef struct glamor_pixmap_clipped_regions{
+       int block_idx;
+       RegionPtr region;
+} glamor_pixmap_clipped_regions;
+
+#define SET_PIXMAP_FBO_CURRENT(priv, idx)                              \
+  do {                                                                 \
+       if (priv->type == GLAMOR_TEXTURE_LARGE) {                       \
+               (priv)->large.base.fbo = priv->large.fbo_array[idx];    \
+               (priv)->large.box = priv->large.box_array[idx];         \
+       }                                                               \
+  } while(0)
+
+typedef struct glamor_pixmap_private_base {
+       glamor_pixmap_type_t type;
        unsigned char gl_fbo:2;
        unsigned char is_picture:1;
        unsigned char gl_tex:1;
-       glamor_pixmap_type_t type;
        glamor_pixmap_fbo *fbo;
-       PictFormatShort pict_format;
-       PixmapPtr container;
+       PixmapPtr pixmap;
        int drm_stride;
        glamor_screen_private *glamor_priv;
-} glamor_pixmap_private;
+       PicturePtr picture;
+}glamor_pixmap_private_base_t;
+
+/*
+ * @base.fbo: current fbo.
+ * @box: current fbo's coords in the whole pixmap.
+ * @block_w: block width of this large pixmap.
+ * @block_h: block height of this large pixmap.
+ * @block_wcnt: block count in one block row.
+ * @block_hcnt: block count in one block column.
+ * @nbox: total block count.
+ * @box_array: contains each block's corresponding box.
+ * @fbo_array: contains each block's fbo pointer.
+ *
+ **/
+typedef struct glamor_pixmap_private_large {
+       union {
+               glamor_pixmap_type_t type;
+               glamor_pixmap_private_base_t base;
+       };
+       BoxRec box;
+       int block_w;
+       int block_h;
+       int block_wcnt;
+       int block_hcnt;
+       int nbox;
+       BoxPtr box_array;
+       glamor_pixmap_fbo **fbo_array;
+}glamor_pixmap_private_large_t;
+
+/*
+ * @box: the relative coords in the corresponding fbo.
+ */
+typedef struct glamor_pixmap_private_atlas {
+       union {
+               glamor_pixmap_type_t type;
+               glamor_pixmap_private_base_t base;
+       };
+       BoxRec box;
+}glamor_pixmap_private_atlas_t;
+
+typedef struct glamor_pixmap_private {
+       union {
+               glamor_pixmap_type_t type;
+               glamor_pixmap_private_base_t base;
+               glamor_pixmap_private_large_t large;
+               glamor_pixmap_private_atlas_t atlas;
+       };
+}glamor_pixmap_private;
 
 /* 
  * Pixmap dynamic status, used by dynamic upload feature.
@@ -404,6 +517,7 @@ glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_pri
 glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv,
                                      int w, int h, GLenum format, int flag);
 void glamor_destroy_fbo(glamor_pixmap_fbo *fbo);
+void glamor_pixmap_destroy_fbo(glamor_pixmap_private *priv);
 void glamor_purge_fbo(glamor_pixmap_fbo *fbo);
 
 void glamor_init_pixmap_fbo(ScreenPtr screen);
@@ -413,6 +527,11 @@ void glamor_fbo_expire(glamor_screen_private *glamor_priv);
 void glamor_init_pixmap_fbo(ScreenPtr screen);
 void glamor_fini_pixmap_fbo(ScreenPtr screen);
 
+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 *);
+
 Bool glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv);
 
 /* glamor_copyarea.c */
@@ -543,6 +662,19 @@ void glamor_init_putimage_shaders(ScreenPtr screen);
 void glamor_fini_putimage_shaders(ScreenPtr screen);
 
 /* glamor_render.c */
+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);
+
 void glamor_composite(CARD8 op,
                      PicturePtr pSrc,
                      PicturePtr pMask,
@@ -552,6 +684,7 @@ void glamor_composite(CARD8 op,
                      INT16 xMask,
                      INT16 yMask,
                      INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
+
 void glamor_trapezoids(CARD8 op,
                       PicturePtr src, PicturePtr dst,
                       PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
@@ -654,7 +787,6 @@ Bool
 glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h,
                                    int stride, void *bits, int pbo);
 
-
 PixmapPtr
 glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y,
                      int w, int h, glamor_access_t access);
@@ -662,6 +794,44 @@ void
 glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y,
                      int w, int h, glamor_access_t access);
 
+glamor_pixmap_clipped_regions *
+glamor_compute_clipped_regions(glamor_pixmap_private *priv, RegionPtr region, int *clipped_nbox, int repeat_type);
+
+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 *
+glamor_compute_transform_clipped_regions(glamor_pixmap_private *priv, struct pixman_transform *transform,
+                                        RegionPtr region, int *n_region, int dx, int dy, int repeat_type);
+
+Bool
+glamor_composite_largepixmap_region(CARD8 op,
+                         PicturePtr source,
+                         PicturePtr mask,
+                         PicturePtr dest,
+                         glamor_pixmap_private * source_pixmap_priv,
+                         glamor_pixmap_private * mask_pixmap_priv,
+                         glamor_pixmap_private * dest_pixmap_priv,
+                         RegionPtr region, Bool force_clip,
+                         INT16 x_source,
+                         INT16 y_source,
+                         INT16 x_mask,
+                         INT16 y_mask,
+                         INT16 x_dest, INT16 y_dest,
+                         CARD16 width, CARD16 height);
+
+Bool
+glamor_get_transform_block_size(struct pixman_transform *transform,
+                          int block_w, int block_h,
+                          int *transformed_block_w,
+                          int *transformed_block_h);
+
+void
+glamor_get_transform_extent_from_box(struct pixman_box32 *temp_box,
+               struct pixman_transform *transform);
 
 /**
  * Upload a picture to gl texture. Similar to the
@@ -757,5 +927,6 @@ 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
 
 #endif                         /* GLAMOR_PRIV_H */
index d1e3a83..6d62bd7 100644 (file)
@@ -295,9 +295,9 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
 
                temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap);
 
-               if (pixmap_priv->is_picture) {
-                       temp_pixmap_priv->pict_format = pixmap_priv->pict_format;
-                       temp_pixmap_priv->is_picture = pixmap_priv->is_picture;
+               if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) {
+                       temp_pixmap_priv->base.picture = pixmap_priv->base.picture;
+                       temp_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture;
                }
 
                glamor_upload_sub_pixmap_to_texture(temp_pixmap, 0, 0, w, h,
index 907d65b..6a584ba 100644 (file)
@@ -545,7 +545,7 @@ glamor_set_composite_texture(ScreenPtr screen, int unit,
 
        dispatch = glamor_get_dispatch(glamor_priv);
        dispatch->glActiveTexture(GL_TEXTURE0 + unit);
-       dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex);
+       dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->base.fbo->tex);
        repeat_type = picture->repeatType;
        switch (picture->repeatType) {
        case RepeatNone:
@@ -1047,7 +1047,7 @@ glamor_composite_with_shader(CARD8 op,
                        glamor_fallback("source == dest\n");
                        goto fail;
                }
-               if (!source_pixmap_priv || source_pixmap_priv->gl_fbo == 0) {
+               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 
                         * equal to zero when the pixmap is screen pixmap. Then we may
                         * refer the tex zero directly latter in the composition. 
@@ -1068,7 +1068,7 @@ glamor_composite_with_shader(CARD8 op,
                        glamor_fallback("mask == dest\n");
                        goto fail;
                }
-               if (!mask_pixmap_priv || mask_pixmap_priv->gl_fbo == 0) {
+               if (!mask_pixmap_priv || mask_pixmap_priv->base.gl_fbo == 0) {
 #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
                        mask_status = GLAMOR_UPLOAD_PENDING;
 #else
@@ -1259,7 +1259,7 @@ glamor_composite_with_shader(CARD8 op,
                        width = rects->width;
                        height = rects->height;
 
-                       glamor_set_normalize_vcoords(dst_xscale,
+                       glamor_set_normalize_vcoords(dest_pixmap_priv, dst_xscale,
                                                     dst_yscale,
                                                     x_dest, y_dest,
                                                     x_dest + width, y_dest + height,
@@ -1269,14 +1269,14 @@ glamor_composite_with_shader(CARD8 op,
                        if (key.source != SHADER_SOURCE_SOLID) {
                                if (source->transform)
                                        glamor_set_transformed_normalize_tcoords
-                                               (src_matrix, src_xscale,
+                                               (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
-                                               (src_xscale, src_yscale,
+                                               (source_pixmap_priv, src_xscale, src_yscale,
                                                 x_source, y_source,
                                                 x_source + width, y_source + height,
                                                 glamor_priv->yInverted,
@@ -1287,7 +1287,7 @@ glamor_composite_with_shader(CARD8 op,
                            && key.mask != SHADER_MASK_SOLID) {
                                if (mask->transform)
                                        glamor_set_transformed_normalize_tcoords
-                                               (mask_matrix,
+                                               (mask_pixmap_priv, mask_matrix,
                                                 mask_xscale,
                                                 mask_yscale, x_mask, y_mask,
                                                 x_mask + width, y_mask + height,
@@ -1295,7 +1295,7 @@ glamor_composite_with_shader(CARD8 op,
                                                 mask_texcoords);
                                else
                                        glamor_set_normalize_tcoords
-                                               (mask_xscale,
+                                               (mask_pixmap_priv, mask_xscale,
                                                 mask_yscale, x_mask, y_mask,
                                                 x_mask + width, y_mask + height,
                                                 glamor_priv->yInverted,
index 6790550..c6b88d2 100644 (file)
@@ -166,13 +166,12 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
                              &src_yscale);
        dispatch->glUseProgram(glamor_priv->tile_prog);
 
-       wh[0] = (float)src_pixmap_priv->fbo->width / tile->drawable.width;
-       wh[1] = (float)src_pixmap_priv->fbo->height / tile->drawable.height;
+       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,
-                               src_pixmap_priv->fbo->tex);
+                               src_pixmap_priv->base.fbo->tex);
        dispatch->glTexParameteri(GL_TEXTURE_2D,
                                  GL_TEXTURE_MIN_FILTER,
                                  GL_NEAREST);
@@ -186,7 +185,8 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
 #ifndef GLAMOR_GLES2
        dispatch->glEnable(GL_TEXTURE_2D);
 #endif
-       glamor_set_normalize_tcoords(src_xscale, src_yscale,
+       glamor_set_normalize_tcoords(src_pixmap_priv, src_xscale,
+                                    src_yscale,
                                     tile_x1, tile_y1,
                                     tile_x2, tile_y2,
                                     glamor_priv->yInverted,
@@ -197,7 +197,8 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
                                        source_texcoords);
        dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
-       glamor_set_normalize_vcoords(dst_xscale, dst_yscale,
+       glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale,
+                                    dst_yscale,
                                     x1, y1, x2, y2,
                                     glamor_priv->yInverted, vertices);
 
index 4af6739..90a1657 100644 (file)
 
 #define pixmap_priv_get_dest_scale(_pixmap_priv_, _pxscale_, _pyscale_)        \
    do {                                                                        \
-    *(_pxscale_) = 1.0 / (_pixmap_priv_)->container->drawable.width;   \
-    *(_pyscale_) = 1.0 / (_pixmap_priv_)->container->drawable.height;  \
+    *(_pxscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.width;                 \
+    *(_pyscale_) = 1.0 / (_pixmap_priv_)->base.pixmap->drawable.height;                        \
   } while(0)
 
 #define pixmap_priv_get_scale(_pixmap_priv_, _pxscale_, _pyscale_)     \
    do {                                                                        \
-    *(_pxscale_) = 1.0 / (_pixmap_priv_)->fbo->width;                  \
-    *(_pyscale_) = 1.0 / (_pixmap_priv_)->fbo->height;                 \
+    *(_pxscale_) = 1.0 / (_pixmap_priv_)->base.fbo->width;                     \
+    *(_pyscale_) = 1.0 / (_pixmap_priv_)->base.fbo->height;                    \
   } while(0)
 
-#define GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(priv)                         \
-       (priv->fbo->width != priv->container->drawable.width    \
-        || priv->fbo->height != priv->container->drawable.height)
+#define GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(priv)                 \
+   (priv->base.fbo->width != priv->base.pixmap->drawable.width         \
+      || priv->base.fbo->height != priv->base.pixmap->drawable.height) \
+
+#define PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, w, h)                        \
+  do {                                                         \
+       if (priv->type == GLAMOR_TEXTURE_LARGE) {               \
+               w = priv->large.box.x2 - priv->large.box.x1;    \
+               h = priv->large.box.y2 - priv->large.box.y1;    \
+       } else {                                                \
+               w = priv->base.pixmap->drawable.width;          \
+               h = priv->base.pixmap->drawable.height;         \
+       }                                                       \
+  } while(0)
+
+#define glamor_pixmap_fbo_fix_wh_ratio(wh, priv)               \
+  do {                                                         \
+       int actual_w, actual_h;                                 \
+       PIXMAP_PRIV_GET_ACTUAL_SIZE(priv, actual_w, actual_h);  \
+       wh[0] = (float)priv->base.fbo->width / actual_w;        \
+       wh[1] = (float)priv->base.fbo->height / actual_h;       \
+  } while(0)
 
-#define glamor_pixmap_fbo_fix_wh_ratio(wh, priv)  do {                 \
-       wh[0] = (float)priv->fbo->width                                 \
-               / priv->container->drawable.width;                      \
-       wh[1] = (float)priv->fbo->height                                \
-               / priv->container->drawable.height;                     \
-       } while(0)
+#define pixmap_priv_get_fbo_off(_priv_, _xoff_, _yoff_)                \
+   do {                                                                \
+       if (_priv_ && (_priv_)->type                            \
+               == GLAMOR_TEXTURE_LARGE) {                      \
+               *(_xoff_) = - (_priv_)->large.box.x1;   \
+               *(_yoff_) = - (_priv_)->large.box.y1;   \
+       } else {                                                \
+               *(_xoff_) = 0;                                  \
+               *(_yoff_) = 0;                                  \
+       }                                                       \
+   } while(0)
 
 #define xFixedToFloat(_val_) ((float)xFixedToInt(_val_)                        \
                              + ((float)xFixedFrac(_val_) / 65536.0))
       }                                                                        \
   }  while(0)
 
-#define glamor_set_transformed_point(matrix, xscale, yscale, texcoord, \
-                                     x, y, yInverted)                  \
+#define glamor_transform_point(matrix, tx, ty, x, y)                   \
   do {                                                                 \
-    float result[4];                                                   \
     int i;                                                             \
-    float tx, ty;                                                      \
-                                                                       \
+    float result[4];                                                   \
     for (i = 0; i < 3; i++) {                                          \
       result[i] = (matrix)[i * 3] * (x) + (matrix)[i * 3 + 1] * (y)    \
        + (matrix)[i * 3 + 2];                                          \
     }                                                                  \
     tx = result[0] / result[2];                                                \
     ty = result[1] / result[2];                                                \
+  } while(0)
+
+#define _glamor_set_normalize_tpoint(xscale, yscale, _tx_, _ty_,       \
+                                    texcoord, yInverted)               \
+  do {                                                                 \
+       (texcoord)[0] = t_from_x_coord_x(xscale, _tx_);                 \
+       if (yInverted)                                                  \
+               (texcoord)[1] = t_from_x_coord_y_inverted(yscale, _ty_);\
+       else                                                            \
+               (texcoord)[1] = t_from_x_coord_y(yscale, _ty_);         \
+        DEBUGF("normalized point tx %f ty %f \n", (texcoord)[0],       \
+               (texcoord)[1]);                                         \
+  } while(0)
+
+#define glamor_set_transformed_point(priv, matrix, xscale,             \
+                                    yscale, texcoord,                  \
+                                     x, y,                             \
+                                    yInverted)                         \
+  do {                                                                 \
+    float tx, ty;                                                      \
+    int fbo_x_off, fbo_y_off;                                          \
+    pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off);             \
+    glamor_transform_point(matrix, tx, ty, x, y);                      \
+    DEBUGF("tx %f ty %f fbooff %d %d \n",                              \
+           tx, ty, fbo_x_off, fbo_y_off);                              \
                                                                        \
+    tx += fbo_x_off;                                                   \
+    ty += fbo_y_off;                                                   \
     (texcoord)[0] = t_from_x_coord_x(xscale, tx);                      \
     if (yInverted)                                                     \
       (texcoord)[1] = t_from_x_coord_y_inverted(yscale, ty);           \
     else                                                               \
       (texcoord)[1] = t_from_x_coord_y(yscale, ty);                    \
+    DEBUGF("normalized tx %f ty %f \n", (texcoord)[0], (texcoord)[1]); \
   } while(0)
 
-
-#define glamor_set_transformed_normalize_tcoords( matrix,              \
+#define glamor_set_transformed_normalize_tcoords( priv,                        \
+                                                 matrix,               \
                                                  xscale,               \
                                                  yscale,               \
                                                   tx1, ty1, tx2, ty2,   \
                                                   yInverted, texcoords)        \
   do {                                                                 \
-    glamor_set_transformed_point(matrix, xscale, yscale,               \
+    glamor_set_transformed_point(priv, matrix, xscale, yscale,         \
                                 texcoords, tx1, ty1,                   \
                                 yInverted);                            \
-    glamor_set_transformed_point(matrix, xscale, yscale,               \
+    glamor_set_transformed_point(priv, matrix, xscale, yscale,         \
                                 texcoords + 2, tx2, ty1,               \
                                 yInverted);                            \
-    glamor_set_transformed_point(matrix, xscale, yscale,               \
+    glamor_set_transformed_point(priv, matrix, xscale, yscale,         \
                                 texcoords + 4, tx2, ty2,               \
                                 yInverted);                            \
-    glamor_set_transformed_point(matrix, xscale, yscale,               \
+    glamor_set_transformed_point(priv, matrix, xscale, yscale,         \
                                 texcoords + 6, tx1, ty2,               \
                                 yInverted);                            \
   } while (0)
 
-#define glamor_set_normalize_tcoords(xscale, yscale, x1, y1, x2, y2,   \
-                                     yInverted, vertices)              \
+#define _glamor_set_normalize_tcoords(xscale, yscale, tx1,             \
+                                     ty1, tx2, ty2,                    \
+                                     yInverted, vertices)              \
   do {                                                                 \
-    (vertices)[0] = t_from_x_coord_x(xscale, x1);                      \
-    (vertices)[2] = t_from_x_coord_x(xscale, x2);                      \
+    (vertices)[0] = t_from_x_coord_x(xscale, tx1);                     \
+    (vertices)[2] = t_from_x_coord_x(xscale, tx2);                     \
     (vertices)[4] = (vertices)[2];                                     \
     (vertices)[6] = (vertices)[0];                                     \
     if (yInverted) {                                                   \
-      (vertices)[1] = t_from_x_coord_y_inverted(yscale, y1);           \
-      (vertices)[5] = t_from_x_coord_y_inverted(yscale, y2);           \
+      (vertices)[1] = t_from_x_coord_y_inverted(yscale, ty1);          \
+      (vertices)[5] = t_from_x_coord_y_inverted(yscale, ty2);          \
     }                                                                  \
     else {                                                             \
-      (vertices)[1] = t_from_x_coord_y(yscale, y1);                    \
-      (vertices)[5] = t_from_x_coord_y(yscale, y2);                    \
+      (vertices)[1] = t_from_x_coord_y(yscale, ty1);                   \
+      (vertices)[5] = t_from_x_coord_y(yscale, ty2);                   \
     }                                                                  \
     (vertices)[3] = (vertices)[1];                                     \
     (vertices)[7] = (vertices)[5];                                     \
+    DEBUGF("texture %f %f %f %f\n", tx1, ty1, tx2, ty2);               \
+    DEBUGF("texture %f %f %f %f\n", (vertices)[0], (vertices)[1],      \
+       (vertices)[2], (vertices)[3]);                                  \
+    DEBUGF("texture %f %f %f %f\n", (vertices)[4], (vertices)[5],      \
+       (vertices)[6], (vertices)[7]);                                  \
   } while(0)
 
+#define glamor_set_normalize_tcoords(priv, xscale, yscale,             \
+                                    x1, y1, x2, y2,                    \
+                                     yInverted, vertices)              \
+  do {                                                                 \
+     float tx1, tx2, ty1, ty2;                                         \
+     int fbo_x_off, fbo_y_off;                                         \
+     pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off);            \
+     tx1 = x1 + fbo_x_off;                                             \
+     tx2 = x2 + fbo_x_off;                                             \
+     ty1 = y1 + fbo_y_off;                                             \
+     ty2 = y2 + fbo_y_off;                                             \
+     _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 {                                                       \
     } while(0)
 
 
-#define glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2,   \
+#define glamor_set_normalize_vcoords(priv, xscale, yscale,             \
+                                    x1, y1, x2, y2,                    \
                                      yInverted, vertices)              \
-    do {                                                               \
-       (vertices)[0] = v_from_x_coord_x(xscale, x1);                   \
-       (vertices)[2] = v_from_x_coord_x(xscale, x2);                   \
-       (vertices)[4] = (vertices)[2];                                  \
-       (vertices)[6] = (vertices)[0];                                  \
-       if (yInverted) {                                                \
-           (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1);      \
-           (vertices)[5] = v_from_x_coord_y_inverted(yscale, y2);      \
-       }                                                               \
-       else {                                                          \
-           (vertices)[1] = v_from_x_coord_y(yscale, y1);               \
-           (vertices)[5] = v_from_x_coord_y(yscale, y2);               \
-       }                                                               \
-       (vertices)[3] = (vertices)[1];                                  \
-       (vertices)[7] = (vertices)[5];                                  \
-    } while(0)
+  do {                                                                 \
+    int fbo_x_off, fbo_y_off;                                          \
+    pixmap_priv_get_fbo_off(priv, &fbo_x_off, &fbo_y_off);             \
+    (vertices)[0] = v_from_x_coord_x(xscale, x1 + fbo_x_off);          \
+    (vertices)[2] = v_from_x_coord_x(xscale, x2 + fbo_x_off);          \
+    (vertices)[4] = (vertices)[2];                                     \
+    (vertices)[6] = (vertices)[0];                                     \
+    if (yInverted) {                                                   \
+      (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1 + fbo_y_off);\
+      (vertices)[5] = v_from_x_coord_y_inverted(yscale, y2 + fbo_y_off);\
+    }                                                                  \
+    else {                                                             \
+      (vertices)[1] = v_from_x_coord_y(yscale, y1 + fbo_y_off);                \
+      (vertices)[5] = v_from_x_coord_y(yscale, y2 + fbo_y_off);                \
+    }                                                                  \
+    (vertices)[3] = (vertices)[1];                                     \
+    (vertices)[7] = (vertices)[5];                                     \
+  } while(0)
 
 #define glamor_set_normalize_pt(xscale, yscale, x, y,          \
                                 yInverted, pt)                 \
@@ -244,10 +317,11 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy)
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
 #define ALIGN(i,m)     (((i) + (m) - 1) & ~((m) - 1))
 #define MIN(a,b)       ((a) < (b) ? (a) : (b))
+#define MAX(a,b)       ((a) > (b) ? (a) : (b))
 
 #define glamor_check_fbo_size(_glamor_,_w_, _h_)    ((_w_) > 0 && (_h_) > 0 \
-                                                    && (_w_) < _glamor_->max_fbo_size  \
-                                                    && (_h_) < _glamor_->max_fbo_size)
+                                                    && (_w_) <= _glamor_->max_fbo_size  \
+                                                    && (_h_) <= _glamor_->max_fbo_size)
 
 /* For 1bpp pixmap, we don't store it as texture. */
 #define glamor_check_pixmap_fbo_depth(_depth_) (                       \
@@ -258,9 +332,9 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy)
                                                || _depth_ == 30        \
                                                || _depth_ == 32)
 
-#define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->is_picture == 1)
-#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)    (pixmap_priv && pixmap_priv->gl_fbo == GLAMOR_FBO_NORMAL)
-#define GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv)    (pixmap_priv && (pixmap_priv->gl_fbo == GLAMOR_FBO_DOWNLOADED))
+#define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->base.is_picture == 1)
+#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)    (pixmap_priv && pixmap_priv->base.gl_fbo == GLAMOR_FBO_NORMAL)
+#define GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv)    (pixmap_priv && (pixmap_priv->base.gl_fbo == GLAMOR_FBO_DOWNLOADED))
 
 /**
  * Borrow from uxa.
@@ -315,7 +389,7 @@ format_for_pixmap(PixmapPtr pixmap)
 
        pixmap_priv = glamor_get_pixmap_private(pixmap);
        if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv))
-               pict_format = pixmap_priv->pict_format;
+               pict_format = pixmap_priv->base.picture->format;
        else
                pict_format = format_for_depth(pixmap->drawable.depth);
 
@@ -659,7 +733,7 @@ glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
 
        pixmap_priv = glamor_get_pixmap_private(pixmap);
        if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv))
-               pict_format = pixmap_priv->pict_format;
+               pict_format = pixmap_priv->base.picture->format;
        else
                pict_format = format_for_depth(pixmap->drawable.depth);
 
@@ -783,6 +857,24 @@ inline static Bool glamor_ddx_fallback_check_gc(GCPtr gc)
         }
        return (!pixmap || glamor_ddx_fallback_check_pixmap(&pixmap->drawable));
 }
+inline static Bool glamor_is_large_pixmap(PixmapPtr pixmap)
+{
+       glamor_pixmap_private *priv;
+
+       priv = glamor_get_pixmap_private(pixmap);
+       return (priv->type == GLAMOR_TEXTURE_LARGE);
+}
+
+inline static Bool glamor_is_large_picture(PicturePtr picture)
+{
+       PixmapPtr pixmap;
+
+       if (picture->pDrawable) {
+               pixmap = glamor_get_drawable_pixmap(picture->pDrawable);
+               return glamor_is_large_pixmap(pixmap);
+       }
+       return FALSE;
+}
 
 inline static Bool glamor_tex_format_is_readable(GLenum format)
 {