libgralloc: Get the stride information from libadreno_utils.so

libadreno_utils.so is an adreno utility library. It computes the
optimal stride required for a surface of a particular width and
bpp. Using this computed stride allows us to efficiently use the
dual memory channels and increase performance.
Currently the utility library only computes the optimal stride
for RGB surfaces.

Change-Id: I0f70bd11602a5144515ab07c3bd2b80a01586a06
diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk
index f4e3834..749a672 100644
--- a/libgralloc/Android.mk
+++ b/libgralloc/Android.mk
@@ -35,7 +35,7 @@
 LOCAL_MODULE                  := libmemalloc
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libgenlock libqdutils
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libgenlock libqdutils libdl
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdmemalloc\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
 LOCAL_SRC_FILES               :=  ionalloc.cpp alloc_controller.cpp
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 5aca758..ebd7e98 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -29,6 +29,7 @@
 
 #include <cutils/log.h>
 #include <fcntl.h>
+#include <dlfcn.h>
 #include "gralloc_priv.h"
 #include "alloc_controller.h"
 #include "memalloc.h"
@@ -84,29 +85,72 @@
 }
 
 //-------------- AdrenoMemInfo-----------------------//
+AdrenoMemInfo::AdrenoMemInfo()
+{
+    libadreno_utils = ::dlopen("libadreno_utils.so", RTLD_NOW);
+    if (libadreno_utils) {
+        *(void **)&LINK_adreno_compute_padding = ::dlsym(libadreno_utils,
+                                           "compute_surface_padding");
+    }
+}
+
+AdrenoMemInfo::~AdrenoMemInfo()
+{
+    if (libadreno_utils) {
+        ::dlclose(libadreno_utils);
+    }
+}
+
 int AdrenoMemInfo::getStride(int width, int format)
 {
     int stride = ALIGN(width, 32);
-    switch (format)
-    {
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
-            stride = ALIGN(width, 32);
-            break;
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
-            stride = ALIGN(width, 128);
-            break;
-        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-        case HAL_PIXEL_FORMAT_YV12:
-        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
-        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
-            stride = ALIGN(width, 16);
-            break;
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
-            stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
-            break;
-        default: break;
+    // Currently surface padding is only computed for RGB* surfaces.
+    if (format < 0x7) {
+        int bpp = 4;
+        switch(format)
+        {
+            case HAL_PIXEL_FORMAT_RGB_888:
+                bpp = 3;
+                break;
+            case HAL_PIXEL_FORMAT_RGB_565:
+            case HAL_PIXEL_FORMAT_RGBA_5551:
+            case HAL_PIXEL_FORMAT_RGBA_4444:
+                bpp = 2;
+                break;
+            default: break;
+        }
+        if ((libadreno_utils) && (LINK_adreno_compute_padding)) {
+            int surface_tile_height = 1;   // Linear surface
+            int raster_mode         = 1;   // Adreno TW raster mode.
+            int padding_threshold   = 512; // Threshold for padding surfaces.
+            // the function below expects the width to be a multiple of
+            // 32 pixels, hence we pass stride instead of width.
+            stride = LINK_adreno_compute_padding(stride, bpp,
+                                      surface_tile_height, raster_mode,
+                                      padding_threshold);
+        }
+    } else {
+        switch (format)
+        {
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+                stride = ALIGN(width, 32);
+                break;
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+                stride = ALIGN(width, 128);
+                break;
+            case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            case HAL_PIXEL_FORMAT_YV12:
+            case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+            case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+                stride = ALIGN(width, 16);
+                break;
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+                stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
+                break;
+            default: break;
+        }
     }
     return stride;
 }
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index c6bd137..5343c35 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -84,12 +84,25 @@
 class AdrenoMemInfo : public android::Singleton <AdrenoMemInfo>
 {
     public:
-    AdrenoMemInfo() {}
+    AdrenoMemInfo();
 
-    ~AdrenoMemInfo() {}
+    ~AdrenoMemInfo();
 
+    /*
+     * Function to compute the adreno stride based on the width and format.
+     *
+     * @return stride.
+     */
     int getStride(int width, int format);
 
     private:
+        // Pointer to the padding library.
+        void *libadreno_utils;
+
+        // link to the surface padding library.
+        int (*LINK_adreno_compute_padding) (int width, int bpp,
+                                                int surface_tile_height,
+                                                int screen_tile_height,
+                                                int padding_threshold);
 };
 #endif /* GR_H_ */