[PATCH] glamor: only use (un)pack_subimage when available

Maarten Lankhorst maarten.lankhorst at ubuntu.com
Mon Jan 19 03:32:54 PST 2015


Check for GL_EXT_unpack_subimage and GL_NV_pack_subimage to
check if GL_(UN)PACK_ROW_LENGTH is available. Set the offsets
manually to prevent calls to GL_(UN)PACK_SKIP_*.

Check support for GL_NV_pack_subimage as suggested by Matt Turner.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst at ubuntu.com>

---
 glamor/glamor.c          |  8 +++++++
 glamor/glamor_priv.h     |  2 ++
 glamor/glamor_transfer.c | 55 +++++++++++++++++++++++++++++++-----------------
 3 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/glamor/glamor.c b/glamor/glamor.c
index e6e8647..6859f5d 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -412,6 +412,14 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         epoxy_has_gl_extension("GL_ARB_buffer_storage");
     glamor_priv->has_nv_texture_barrier =
         epoxy_has_gl_extension("GL_NV_texture_barrier");
+    glamor_priv->has_unpack_subimage =
+        glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP ||
+        epoxy_gl_version() >= 30 ||
+        epoxy_has_gl_extension("GL_EXT_unpack_subimage");
+    glamor_priv->has_pack_subimage =
+        glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP ||
+        epoxy_gl_version() >= 30 ||
+        epoxy_has_gl_extension("GL_NV_pack_subimage");
 
     glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size);
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index ffd327e..ec69f08 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -235,6 +235,8 @@ typedef struct glamor_screen_private {
     int has_buffer_storage;
     int has_khr_debug;
     int has_nv_texture_barrier;
+    int has_pack_subimage;
+    int has_unpack_subimage;
     int max_fbo_size;
     int has_rw_pbo;
 
diff --git a/glamor/glamor_transfer.c b/glamor/glamor_transfer.c
index 8914155..c920435 100644
--- a/glamor/glamor_transfer.c
+++ b/glamor/glamor_transfer.c
@@ -73,7 +73,9 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
     glamor_make_current(glamor_priv);
 
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-    glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
+
+    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);
@@ -92,25 +94,34 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
             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;
 
-            glPixelStorei(GL_UNPACK_SKIP_ROWS, y1 - dy_dst + dy_src);
-            glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1 - dx_dst + dx_src);
-
-            glTexSubImage2D(GL_TEXTURE_2D, 0,
-                            x1 - box->x1, y1 - box->y1,
-                            x2 - x1, y2 - y1,
-                            format, type,
-                            bits);
+            if (glamor_priv->has_unpack_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);
+            } 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);
+            }
         }
     }
 
-    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
-    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+    if (glamor_priv->has_unpack_subimage)
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
 }
 
 /*
@@ -166,7 +177,8 @@ glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
     glamor_make_current(glamor_priv);
 
     glPixelStorei(GL_PACK_ALIGNMENT, 4);
-    glPixelStorei(GL_PACK_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);
@@ -183,20 +195,25 @@ glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
             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;
 
             boxes++;
 
             if (x2 <= x1 || y2 <= y1)
                 continue;
 
-            glPixelStorei(GL_PACK_SKIP_PIXELS, x1 - dx_src + dx_dst);
-            glPixelStorei(GL_PACK_SKIP_ROWS, y1 - dy_src + dy_dst);
-            glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, format, type, bits);
+            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);
+            } else {
+                for (; y1 < y2; y1++, ofs += byte_stride)
+                    glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, 1, format, type, bits + ofs);
+            }
         }
     }
-    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
-    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
-    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+    if (glamor_priv->has_pack_subimage)
+        glPixelStorei(GL_PACK_ROW_LENGTH, 0);
 }
 
 /*
-- 
2.2.2




More information about the xorg-devel mailing list