[cogl] bitmap: Support pre/unpre-multiplying any format



commit 1b47ff0dfe1c73d9c580f876781b06f7a9720047
Author: Neil Roberts <neil linux intel com>
Date:   Fri Mar 2 18:03:02 2012 +0000

    bitmap: Support pre/unpre-multiplying any format
    
    If the fast-path inplace premult conversion can't be used then it will
    now fallback to unpacking the buffer into a row of guint16s and use
    the generic conversion.
    
    Reviewed-by: Robert Bragg <robert linux intel com>

 cogl/cogl-bitmap-conversion.c |   81 ++++++++++++++++++++++++++++-------------
 1 files changed, 56 insertions(+), 25 deletions(-)
---
diff --git a/cogl/cogl-bitmap-conversion.c b/cogl/cogl-bitmap-conversion.c
index 5b971f8..6ff5a03 100644
--- a/cogl/cogl-bitmap-conversion.c
+++ b/cogl/cogl-bitmap-conversion.c
@@ -279,7 +279,7 @@ _cogl_bitmap_premult_unpacked_span_guint16 (guint16 *data,
 }
 
 static gboolean
-_cogl_bitmap_can_premult (CoglPixelFormat format)
+_cogl_bitmap_can_fast_premult (CoglPixelFormat format)
 {
   switch (format & ~COGL_PREMULT_BIT)
     {
@@ -379,7 +379,7 @@ _cogl_bitmap_convert_into_bitmap (CoglBitmap *src_bmp,
   /* If the base format is the same then we can just copy the bitmap
      instead */
   if ((src_format & ~COGL_PREMULT_BIT) == (dst_format & ~COGL_PREMULT_BIT) &&
-      (!need_premult || _cogl_bitmap_can_premult (dst_format)))
+      (!need_premult || _cogl_bitmap_can_fast_premult (dst_format)))
     {
       if (!_cogl_bitmap_copy_subregion (src_bmp, dst_bmp,
                                         0, 0, /* src_x / src_y */
@@ -504,6 +504,7 @@ gboolean
 _cogl_bitmap_unpremult (CoglBitmap *bmp)
 {
   guint8          *p, *data;
+  guint16         *tmp_row;
   int              x,y;
   CoglPixelFormat  format;
   int              width, height;
@@ -514,35 +515,50 @@ _cogl_bitmap_unpremult (CoglBitmap *bmp)
   height = _cogl_bitmap_get_height (bmp);
   rowstride = _cogl_bitmap_get_rowstride (bmp);
 
-  /* If we can premult that implies we can un-premult too... */
-  if (!_cogl_bitmap_can_premult (format))
-    return FALSE;
-
   if ((data = _cogl_bitmap_map (bmp,
                                 COGL_BUFFER_ACCESS_READ |
                                 COGL_BUFFER_ACCESS_WRITE,
                                 0)) == NULL)
     return FALSE;
 
+  /* If we can't directly unpremult the data inline then we'll
+     allocate a temporary row and unpack the data. This assumes if we
+     can fast premult then we can also fast unpremult */
+  if (_cogl_bitmap_can_fast_premult (format))
+    tmp_row = NULL;
+  else
+    tmp_row = g_malloc (sizeof (guint16) * 4 * width);
+
   for (y = 0; y < height; y++)
     {
       p = (guint8*) data + y * rowstride;
 
-      if (format & COGL_AFIRST_BIT)
+      if (tmp_row)
+        {
+          _cogl_unpack_guint16 (format, p, tmp_row, width);
+          _cogl_bitmap_unpremult_unpacked_span_guint16 (tmp_row, width);
+          _cogl_pack_guint16 (format, tmp_row, p, width);
+        }
+      else
         {
-          for (x = 0; x < width; x++)
+          if (format & COGL_AFIRST_BIT)
             {
-              if (p[0] == 0)
-                _cogl_unpremult_alpha_0 (p);
-              else
-                _cogl_unpremult_alpha_first (p);
-              p += 4;
+              for (x = 0; x < width; x++)
+                {
+                  if (p[0] == 0)
+                    _cogl_unpremult_alpha_0 (p);
+                  else
+                    _cogl_unpremult_alpha_first (p);
+                  p += 4;
+                }
             }
+          else
+            _cogl_bitmap_unpremult_unpacked_span_guint8 (p, width);
         }
-      else
-        _cogl_bitmap_unpremult_unpacked_span_guint8 (p, width);
     }
 
+  g_free (tmp_row);
+
   _cogl_bitmap_unmap (bmp);
 
   _cogl_bitmap_set_format (bmp, format & ~COGL_PREMULT_BIT);
@@ -554,6 +570,7 @@ gboolean
 _cogl_bitmap_premult (CoglBitmap *bmp)
 {
   guint8          *p, *data;
+  guint16         *tmp_row;
   int              x,y;
   CoglPixelFormat  format;
   int              width, height;
@@ -564,32 +581,46 @@ _cogl_bitmap_premult (CoglBitmap *bmp)
   height = _cogl_bitmap_get_height (bmp);
   rowstride = _cogl_bitmap_get_rowstride (bmp);
 
-  /* Make sure format supported for un-premultiplication */
-  if (!_cogl_bitmap_can_premult (format))
-    return FALSE;
-
   if ((data = _cogl_bitmap_map (bmp,
                                 COGL_BUFFER_ACCESS_READ |
                                 COGL_BUFFER_ACCESS_WRITE,
                                 0)) == NULL)
     return FALSE;
 
+  /* If we can't directly premult the data inline then we'll allocate
+     a temporary row and unpack the data. */
+  if (_cogl_bitmap_can_fast_premult (format))
+    tmp_row = NULL;
+  else
+    tmp_row = g_malloc (sizeof (guint16) * 4 * width);
+
   for (y = 0; y < height; y++)
     {
       p = (guint8*) data + y * rowstride;
 
-      if (format & COGL_AFIRST_BIT)
+      if (tmp_row)
+        {
+          _cogl_unpack_guint16 (format, p, tmp_row, width);
+          _cogl_bitmap_premult_unpacked_span_guint16 (tmp_row, width);
+          _cogl_pack_guint16 (format, tmp_row, p, width);
+        }
+      else
         {
-          for (x = 0; x < width; x++)
+          if (format & COGL_AFIRST_BIT)
             {
-              _cogl_premult_alpha_first (p);
-              p += 4;
+              for (x = 0; x < width; x++)
+                {
+                  _cogl_premult_alpha_first (p);
+                  p += 4;
+                }
             }
+          else
+            _cogl_bitmap_premult_unpacked_span_guint8 (p, width);
         }
-      else
-        _cogl_bitmap_premult_unpacked_span_guint8 (p, width);
     }
 
+  g_free (tmp_row);
+
   _cogl_bitmap_unmap (bmp);
 
   _cogl_bitmap_set_format (bmp, format | COGL_PREMULT_BIT);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]