XXX: glamor: Fix glamor_upload_boxes and glamor_download_boxes for ES2

Maarten Lankhorst maarten.lankhorst at canonical.com
Mon Jan 26 06:39:34 PST 2015


Some GLES2 implementations don't support GL_UNSIGNED_8888_REV and only
guarantee less fancy things to work. Use the infrastructure from glamor_pixmap.c
to implement glamor_upload_boxes, and use the glamor_es2_pixmap_read_prepare function
to implement glamor_download_boxes.

Contains a small hack in _glamor_upload_bits_to_pixmap_texture to take fastpath more often
and not regress previous users. Needs some input on how to fix this..
---
SetSpans and GetSpans are still using glamor_format_for_pixmap, so I guess they're buggy on es2 too.
Is there any testcase I could use to trigger those?

--- a/glamor/glamor_transfer.c
+++ b/glamor/glamor_transfer.c
@@ -52,30 +52,49 @@
 }
 
 /*
- * Write a region of bits into a pixmap
+ * Upload a region of data
  */
+
 void
-glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
-                    int dx_src, int dy_src,
-                    int dx_dst, int dy_dst,
-                    uint8_t *bits, uint32_t byte_stride)
-{
-    ScreenPtr                   screen = pixmap->drawable.pScreen;
-    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
-    glamor_pixmap_private       *priv = glamor_get_pixmap_private(pixmap);
-    int                         box_x, box_y;
-    int                         bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
-    GLenum                      type;
-    GLenum                      format;
+glamor_upload_region(PixmapPtr pixmap, RegionPtr region,
+                     int region_x, int region_y,
+                     uint8_t *bits, uint32_t byte_stride)
+{
+    glamor_upload_boxes(pixmap, RegionRects(region), RegionNumRects(region),
+                        -region_x, -region_y,
+                        0, 0,
+                        bits, byte_stride);
+}
 
-    glamor_format_for_pixmap(pixmap, &format, &type);
+/*
+ * Take the data in the pixmap and stuff it back into the FBO
+ */
+void
+glamor_upload_pixmap(PixmapPtr pixmap)
+{
+    BoxRec box;
 
-    glamor_make_current(glamor_priv);
+    box.x1 = 0;
+    box.x2 = pixmap->drawable.width;
+    box.y1 = 0;
+    box.y2 = pixmap->drawable.height;
+    glamor_upload_boxes(pixmap, &box, 1, 0, 0, 0, 0,
+                        pixmap->devPrivate.ptr, pixmap->devKind);
+}
 
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+static void
+__glamor_download_boxes_noconv(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                               int dx_src, int dy_src, int dx_dst, int dy_dst,
+                               uint8_t *bits, uint32_t byte_stride, GLenum format, GLenum type)
+{
+    ScreenPtr screen = pixmap->drawable.pScreen;
+    int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
+    int box_x, box_y;
 
-    if (glamor_priv->has_unpack_subimage)
-        glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
+    if (glamor_priv->has_pack_subimage)
+        glPixelStorei(GL_PACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
 
     glamor_pixmap_loop(priv, box_x, box_y) {
         BoxPtr                  box = glamor_pixmap_box_at(priv, box_x, box_y);
@@ -83,100 +102,115 @@
         BoxPtr                  boxes = in_boxes;
         int                     nbox = in_nbox;
 
-        glActiveTexture(GL_TEXTURE0);
-        glBindTexture(GL_TEXTURE_2D, fbo->tex);
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
 
         while (nbox--) {
 
             /* compute drawable coordinates */
-            int x1 = MAX(boxes->x1 + dx_dst, box->x1);
-            int x2 = MIN(boxes->x2 + dx_dst, box->x2);
-            int y1 = MAX(boxes->y1 + dy_dst, box->y1);
-            int y2 = MIN(boxes->y2 + dy_dst, box->y2);
+            int x1 = MAX(boxes->x1 + dx_src, box->x1);
+            int x2 = MIN(boxes->x2 + dx_src, box->x2);
+            int y1 = MAX(boxes->y1 + dy_src, box->y1);
+            int y2 = MIN(boxes->y2 + dy_src, box->y2);
 
-            size_t ofs = (y1 - dy_dst + dy_src) * byte_stride;
-            ofs += (x1 - dx_dst + dx_src) * bytes_per_pixel;
+            size_t ofs = (y1 - dy_src + dy_dst) * byte_stride;
+            ofs += (x1 - dx_src + dx_dst) * bytes_per_pixel;
 
             boxes++;
 
             if (x2 <= x1 || y2 <= y1)
                 continue;
 
-            if (glamor_priv->has_unpack_subimage ||
+            if (glamor_priv->has_pack_subimage ||
                 x2 - x1 == byte_stride / bytes_per_pixel) {
-                glTexSubImage2D(GL_TEXTURE_2D, 0,
-                                x1 - box->x1, y1 - box->y1,
-                                x2 - x1, y2 - y1,
-                                format, type,
-                                bits + ofs);
+                glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, format, type, bits + ofs);
             } else {
                 for (; y1 < y2; y1++, ofs += byte_stride)
-                    glTexSubImage2D(GL_TEXTURE_2D, 0,
-                                    x1 - box->x1, y1 - box->y1,
-                                    x2 - x1, 1,
-                                    format, type,
-                                    bits + ofs);
+                    glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, 1, format, type, bits + ofs);
             }
         }
     }
 
-    if (glamor_priv->has_unpack_subimage)
-        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-}
-
-/*
- * Upload a region of data
- */
-
-void
-glamor_upload_region(PixmapPtr pixmap, RegionPtr region,
-                     int region_x, int region_y,
-                     uint8_t *bits, uint32_t byte_stride)
-{
-    glamor_upload_boxes(pixmap, RegionRects(region), RegionNumRects(region),
-                        -region_x, -region_y,
-                        0, 0,
-                        bits, byte_stride);
+    if (glamor_priv->has_pack_subimage)
+        glPixelStorei(GL_PACK_ROW_LENGTH, 0);
 }
 
 /*
- * Take the data in the pixmap and stuff it back into the FBO
- */
-void
-glamor_upload_pixmap(PixmapPtr pixmap)
+ * as gles2 only support a very small set of color format and
+ * type when do glReadPixel,
+ * Before we use glReadPixels to get back a textured pixmap,
+ * Use shader to convert it to a supported format and thus
+ * get a new temporary pixmap returned.
+ * */
+
+static glamor_pixmap_fbo *
+glamor_es2_pixmap_read_prepare(ScreenPtr screen, glamor_screen_private *glamor_priv,
+                               glamor_pixmap_fbo *fbo, int x, int y, int w, int h,
+                               GLenum format, GLenum type, int no_alpha,
+                               int revert, int swap_rb)
 {
-    BoxRec box;
-
-    box.x1 = 0;
-    box.x2 = pixmap->drawable.width;
-    box.y1 = 0;
-    box.y2 = pixmap->drawable.height;
-    glamor_upload_boxes(pixmap, &box, 1, 0, 0, 0, 0,
-                        pixmap->devPrivate.ptr, pixmap->devKind);
+    glamor_pixmap_fbo *temp_fbo;
+    float temp_xscale, temp_yscale, source_xscale, source_yscale;
+    static float vertices[8];
+    static float texcoords[8];
+
+    temp_fbo = glamor_create_fbo(glamor_priv, w, h, format, 0);
+    if (temp_fbo == NULL)
+        return NULL;
+
+    temp_xscale = 1.0 / w;
+    temp_yscale = 1.0 / h;
+
+    source_xscale = 1.0 / fbo->width;
+    source_yscale = 1.0 / fbo->height;
+
+    glamor_set_normalize_vcoords((struct glamor_pixmap_private *) NULL,
+                                 temp_xscale, temp_yscale, 0, 0, w, h,
+                                 vertices);
+
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
+                          2 * sizeof(float), vertices);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+    _glamor_set_normalize_tcoords(source_xscale,
+                                  source_yscale,
+                                  x, y,
+                                  x + w, y + h,
+                                  texcoords, 2);
+
+    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
+                          2 * sizeof(float), texcoords);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, fbo->tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glamor_set_destination_pixmap_fbo(temp_fbo, 0, 0, w, h);
+    glamor_set_alu(screen, GXcopy);
+    glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
+    glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
+    glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb);
+
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    return temp_fbo;
 }
 
-/*
- * Read stuff from the pixmap FBOs and write to memory
- */
-void
-glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
-                      int dx_src, int dy_src,
-                      int dx_dst, int dy_dst,
-                      uint8_t *bits, uint32_t byte_stride)
+static void
+__glamor_download_boxes_revert(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                               int dx_src, int dy_src, int dx_dst, int dy_dst,
+                               uint8_t *bits, uint32_t byte_stride, GLenum format, GLenum type,
+                               int no_alpha, int revert, int swap_rb)
 {
     ScreenPtr screen = pixmap->drawable.pScreen;
+    int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
     int box_x, box_y;
-    int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
-    GLenum type;
-    GLenum format;
 
-    glamor_format_for_pixmap(pixmap, &format, &type);
-
-    glamor_make_current(glamor_priv);
-
-    glPixelStorei(GL_PACK_ALIGNMENT, 4);
     if (glamor_priv->has_pack_subimage)
         glPixelStorei(GL_PACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
 
@@ -186,15 +220,15 @@
         BoxPtr                  boxes = in_boxes;
         int                     nbox = in_nbox;
 
-        glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
-
         while (nbox--) {
+            glamor_pixmap_fbo *temp;
 
             /* compute drawable coordinates */
-            int                     x1 = MAX(boxes->x1 + dx_src, box->x1);
-            int                     x2 = MIN(boxes->x2 + dx_src, box->x2);
-            int                     y1 = MAX(boxes->y1 + dy_src, box->y1);
-            int                     y2 = MIN(boxes->y2 + dy_src, box->y2);
+            int x1 = MAX(boxes->x1 + dx_src, box->x1);
+            int x2 = MIN(boxes->x2 + dx_src, box->x2);
+            int y1 = MAX(boxes->y1 + dy_src, box->y1);
+            int y2 = MIN(boxes->y2 + dy_src, box->y2);
+
             size_t ofs = (y1 - dy_src + dy_dst) * byte_stride;
             ofs += (x1 - dx_src + dx_dst) * bytes_per_pixel;
 
@@ -203,19 +237,60 @@
             if (x2 <= x1 || y2 <= y1)
                 continue;
 
+            temp = glamor_es2_pixmap_read_prepare(screen, glamor_priv, fbo,
+                                                  x1 - box->x1, y1 - box->y1,
+                                                  x2 - x1, y2 - y1,
+                                                  format, type, no_alpha,
+                                                  revert, swap_rb);
+
             if (glamor_priv->has_pack_subimage ||
                 x2 - x1 == byte_stride / bytes_per_pixel) {
-                glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, format, type, bits + ofs);
+                glReadPixels(0, 0, x2 - x1, y2 - y1, format, type, bits + ofs);
             } else {
-                for (; y1 < y2; y1++, ofs += byte_stride)
-                    glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, 1, format, type, bits + ofs);
+                for (y2 -= y1, y1 = 0; y1 < y2; y1++, ofs += byte_stride)
+                    glReadPixels(0, y1, x2 - x1, 1, format, type, bits + ofs);
             }
+            glBindFramebuffer(GL_FRAMEBUFFER, 0);
+            glamor_destroy_fbo(temp);
         }
     }
+
     if (glamor_priv->has_pack_subimage)
         glPixelStorei(GL_PACK_ROW_LENGTH, 0);
 }
 
+
+/*
+ * Read stuff from the pixmap FBOs and write to memory
+ */
+void
+glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                      int dx_src, int dy_src,
+                      int dx_dst, int dy_dst,
+                      uint8_t *bits, uint32_t byte_stride)
+{
+    ScreenPtr screen = pixmap->drawable.pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    GLenum type, format;
+    int no_alpha, revert, swap_rb;
+
+    glamor_make_current(glamor_priv);
+
+    glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, &no_alpha, &revert, &swap_rb, 0);
+
+    glPixelStorei(GL_PACK_ALIGNMENT, 4);
+
+    if (revert == REVERT_NONE && swap_rb == SWAP_NONE_DOWNLOADING)
+        __glamor_download_boxes_noconv(pixmap, in_boxes, in_nbox,
+                                       dx_src, dy_src, dx_dst, dy_dst,
+                                       bits, byte_stride, format, type);
+    else
+        __glamor_download_boxes_revert(pixmap, in_boxes, in_nbox,
+                                       dx_src, dy_src, dx_dst, dy_dst,
+                                       bits, byte_stride, format, type,
+                                       no_alpha, revert, swap_rb);
+}
+
 /*
  * Read data from the pixmap FBO
  */
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -30,6 +30,8 @@
 #include <stdlib.h>
 
 #include "glamor_priv.h"
+#include "glamor_transfer.h"
+
 /**
  * Sets the offsets to add to coordinates to make them address the same bits in
  * the backing drawable. These coordinates are nonzero only for redirected
@@ -457,7 +459,7 @@
     return 0;
 }
 
-static int
+int
 glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
                                        GLenum *format,
                                        GLenum *type,
@@ -698,12 +700,13 @@
                                   GLenum format,
                                   GLenum type,
                                   int x, int y, int w, int h,
-                                  void *bits, int pbo)
+                                  void *bits, int stride, int bytes_per_pixel, int pbo)
 {
     glamor_screen_private *glamor_priv =
         glamor_get_screen_private(pixmap->drawable.pScreen);
     int non_sub = 0;
     unsigned int iformat = 0;
+    int direct;
 
     glamor_make_current(glamor_priv);
     if (*tex == 0) {
@@ -723,10 +726,22 @@
         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
         glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
     }
-    if (non_sub)
+
+    direct = glamor_priv->has_unpack_subimage || (w * bytes_per_pixel == stride);
+    if (non_sub && direct)
         glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits);
-    else
+    else if (!non_sub && direct)
         glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, format, type, bits);
+    else {
+        if (non_sub)
+            glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, NULL);
+
+        while (h--) {
+            glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, 1, format, type, bits);
+            y--;
+            bits += stride;
+        }
+    }
 
     if (bits == NULL)
         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
@@ -743,7 +758,6 @@
     glamor_screen_private *glamor_priv =
         glamor_get_screen_private(pixmap->drawable.pScreen);
     static float vertices[8];
-
     static float texcoords_inv[8] = { 0, 0,
         1, 0,
         1, 1,
@@ -753,6 +767,7 @@
     float dst_xscale, dst_yscale;
     GLuint tex = 0;
     int need_free_bits = 0;
+    int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
 
     if (bits == NULL)
         goto ready_to_upload;
@@ -787,12 +802,7 @@
 
     /* 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
-#ifdef WALKAROUND_LARGE_TEXTURE_MAP
-        && pixmap_priv->type != GLAMOR_TEXTURE_LARGE
-#endif
-        ) {
+    if (revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING) {
         int fbo_x_off, fbo_y_off;
 
         assert(pixmap_priv->base.fbo->tex);
@@ -804,7 +814,7 @@
         __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->base.fbo->tex,
                                           format, type,
                                           x + fbo_x_off, y + fbo_y_off, w, h,
-                                          bits, pbo);
+                                          bits, stride, bytes_per_pixel, pbo);
     } else {
         ptexcoords = texcoords_inv;
 
@@ -826,7 +836,7 @@
         glamor_set_destination_pixmap_priv_nc(pixmap_priv);
         glamor_set_alu(screen, GXcopy);
         __glamor_upload_pixmap_to_texture(pixmap, &tex,
-                                          format, type, 0, 0, w, h, bits, pbo);
+                                          format, type, 0, 0, w, h, bits, stride, bytes_per_pixel, pbo);
         glActiveTexture(GL_TEXTURE0);
         glBindTexture(GL_TEXTURE_2D, tex);
 
@@ -1060,76 +1070,6 @@
     return ret;
 }
 
-/*
- * as gles2 only support a very small set of color format and
- * type when do glReadPixel,
- * Before we use glReadPixels to get back a textured pixmap,
- * Use shader to convert it to a supported format and thus
- * get a new temporary pixmap returned.
- * */
-
-glamor_pixmap_fbo *
-glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
-                               GLenum format, GLenum type, int no_alpha,
-                               int revert, int swap_rb)
-{
-    glamor_pixmap_private *source_priv;
-    glamor_screen_private *glamor_priv;
-    ScreenPtr screen;
-    glamor_pixmap_fbo *temp_fbo;
-    float temp_xscale, temp_yscale, source_xscale, source_yscale;
-    static float vertices[8];
-    static float texcoords[8];
-
-    screen = source->drawable.pScreen;
-
-    glamor_priv = glamor_get_screen_private(screen);
-    source_priv = glamor_get_pixmap_private(source);
-    temp_fbo = glamor_create_fbo(glamor_priv, w, h, format, 0);
-    if (temp_fbo == NULL)
-        return NULL;
-
-    glamor_make_current(glamor_priv);
-    temp_xscale = 1.0 / w;
-    temp_yscale = 1.0 / h;
-
-    glamor_set_normalize_vcoords((struct glamor_pixmap_private *) NULL,
-                                 temp_xscale, temp_yscale, 0, 0, w, h,
-                                 vertices);
-
-    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
-                          2 * sizeof(float), vertices);
-    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
-
-    pixmap_priv_get_scale(source_priv, &source_xscale, &source_yscale);
-    glamor_set_normalize_tcoords(source_priv, source_xscale,
-                                 source_yscale,
-                                 x, y,
-                                 x + w, y + h,
-                                 texcoords);
-
-    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
-                          2 * sizeof(float), texcoords);
-    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, source_priv->base.fbo->tex);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-    glamor_set_destination_pixmap_fbo(temp_fbo, 0, 0, w, h);
-    glamor_set_alu(screen, GXcopy);
-    glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
-    glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
-    glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb);
-
-    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
-    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    return temp_fbo;
-}
-
 /* fixup a fbo to the exact size as the pixmap. */
 /* XXX LARGE pixmap? */
 Bool
@@ -1188,3 +1128,67 @@
 
     return ret;
 }
+
+
+/*
+ * Write a region of bits into a pixmap
+ */
+void
+glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                    int dx_src, int dy_src,
+                    int dx_dst, int dy_dst,
+                    uint8_t *bits, uint32_t byte_stride)
+{
+    ScreenPtr                   screen = pixmap->drawable.pScreen;
+    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
+    glamor_pixmap_private       *priv = glamor_get_pixmap_private(pixmap);
+    int                         box_x, box_y;
+    int                         bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
+    GLenum                      type;
+    GLenum                      format;
+    int no_alpha, revert, swap_rb;
+
+    glamor_get_tex_format_type_from_pixmap(pixmap, &format, &type, &no_alpha, &revert, &swap_rb, 1);
+
+    glamor_make_current(glamor_priv);
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+    if (glamor_priv->has_unpack_subimage)
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
+
+    glamor_pixmap_loop(priv, box_x, box_y) {
+        BoxPtr                  box = glamor_pixmap_box_at(priv, box_x, box_y);
+        glamor_pixmap_fbo       *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y);
+        BoxPtr                  boxes = in_boxes;
+        int                     nbox = in_nbox;
+
+        while (nbox--) {
+
+            /* compute drawable coordinates */
+            int x1 = MAX(boxes->x1 + dx_dst, box->x1);
+            int x2 = MIN(boxes->x2 + dx_dst, box->x2);
+            int y1 = MAX(boxes->y1 + dy_dst, box->y1);
+            int y2 = MIN(boxes->y2 + dy_dst, box->y2);
+
+            size_t ofs = (y1 - dy_dst + dy_src) * byte_stride;
+            ofs += (x1 - dx_dst + dx_src) * bytes_per_pixel;
+
+            boxes++;
+
+            if (x2 <= x1 || y2 <= y1)
+                continue;
+
+            glActiveTexture(GL_TEXTURE0);
+            glBindTexture(GL_TEXTURE_2D, fbo->tex);
+            _glamor_upload_bits_to_pixmap_texture(pixmap, format, type,
+                                                  no_alpha, revert, swap_rb,
+                                                  x1, y1, x2 - x1, y2 - y1,
+                                                  byte_stride, bits + ofs, 0);
+        }
+    }
+
+    if (glamor_priv->has_unpack_subimage)
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+}
+



More information about the xorg-devel mailing list