display: edo panel: display quality optimization

Because edo panel design using delta pixel design,
so you can see aliasing in the display edges
of the panel. In order to optimize the display
quality,add algorithms to rending the framebuff data.

If we detect the display pixel design is Delta,
disable mdpcomp to get the whole single layer framebuff,
then use the algorithms to optimize the pixel arrangement.

Change-Id: I4d6ac7e2bae13548ed35807eb6a2b7d933101cb4
Signed-off-by: l00212897 <gang.li@huawei.com>
diff --git a/msm8226/libhwcomposer/Android.mk b/msm8226/libhwcomposer/Android.mk
index ef7778b..bb9bbec 100644
--- a/msm8226/libhwcomposer/Android.mk
+++ b/msm8226/libhwcomposer/Android.mk
@@ -30,4 +30,14 @@
                                  hwc_dump_layers.cpp \
                                  hwc_ad.cpp \
                                  hwc_virtual.cpp
+
+ifeq ($(TARGET_USES_DELTA_PANEL),true)
+LOCAL_CFLAGS                  += -O3 -march=armv7-a -mfloat-abi=softfp -mfpu=neon
+LOCAL_CFLAGS                  += -DDELTA_PANEL
+LOCAL_CFLAGS                  += $(DELTA_PANEL_CFLAGS)
+LOCAL_LDLIBS                  := -llog -ldl
+LOCAL_ARM_MODE                := arm
+LOCAL_SRC_FILES               += hwc_delta_panel.cpp
+endif #TARGET_USES_DELTA_PANEL
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8226/libhwcomposer/hwc.cpp b/msm8226/libhwcomposer/hwc.cpp
index 929121f..32f33af 100644
--- a/msm8226/libhwcomposer/hwc.cpp
+++ b/msm8226/libhwcomposer/hwc.cpp
@@ -39,13 +39,23 @@
 #include "hwc_ad.h"
 #include "profiler.h"
 #include "hwc_virtual.h"
+#ifdef DELTA_PANEL
+#include "hwc_delta_panel.h"
+#endif
 
 using namespace qhwc;
 using namespace overlay;
+#ifdef DELTA_PANEL
+using namespace gralloc;
+#endif
 
 #define VSYNC_DEBUG 0
 #define POWER_MODE_DEBUG 1
 
+#ifdef DELTA_PANEL
+static bool is_delta_panel = false;
+#endif
+
 static int hwc_device_open(const struct hw_module_t* module,
                            const char* name,
                            struct hw_device_t** device);
@@ -554,6 +564,19 @@
 
 }
 
+#ifdef DELTA_PANEL
+/*
+ * Return the type of allocator -
+ * these are used for mapping/unmapping
+ */
+static IMemAlloc* getAllocator(int flags)
+{
+    IMemAlloc* memalloc;
+    IAllocController* alloc_ctrl = IAllocController::getInstance();
+    memalloc = alloc_ctrl->getAllocator(flags);
+    return memalloc;
+}
+#endif
 
 static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
     ATRACE_CALL();
@@ -572,6 +595,25 @@
                 fd = ctx->mMDPComp[dpy]->drawOverlap(ctx, list);
         }
 
+        //TODO We dont check for SKIP flag on this layer because we need PAN
+        //always. Last layer is always FB
+        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+
+#ifdef DELTA_PANEL
+        if(true == is_delta_panel){
+            sync_wait(fbLayer->acquireFenceFd, 1000);
+            if(hnd) {
+                if(hnd->base) {
+                    deltaPanelRendering((unsigned char *)hnd->base, DELTA_PANEL_WIDTH,
+                            DELTA_PANEL_HEIGHT);
+                    IMemAlloc* memalloc = getAllocator(hnd->flags);
+                    memalloc->clean_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd,
+                            CACHE_CLEAN_AND_INVALIDATE);
+                }
+            }
+        }
+#endif
+
         if(list->numHwLayers > 1)
             hwc_sync(ctx, list, dpy, fd);
 
@@ -584,9 +626,6 @@
             ret = -1;
         }
 
-        //TODO We dont check for SKIP flag on this layer because we need PAN
-        //always. Last layer is always FB
-        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
         if(copybitDone && ctx->mMDP.version >= qdutils::MDP_V4_0) {
             hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
         }
@@ -895,6 +934,16 @@
         dev->device.setActiveConfig     = hwc_setActiveConfig;
         *device = &dev->device.common;
         status = 0;
+
+#ifdef DELTA_PANEL
+        char property[PROPERTY_VALUE_MAX];
+        if((property_get("ro.hwc.is_delta_panel", property, NULL) > 0) &&
+           (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+            (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+            ALOGD("%s: Display is delta panel", __FUNCTION__);
+            is_delta_panel = true;
+        }
+#endif
     }
     return status;
 }
diff --git a/msm8226/libhwcomposer/hwc_delta_panel.cpp b/msm8226/libhwcomposer/hwc_delta_panel.cpp
new file mode 100644
index 0000000..d3bb964
--- /dev/null
+++ b/msm8226/libhwcomposer/hwc_delta_panel.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <malloc.h>
+#include <arm_neon.h>
+#include "hwc_delta_panel.h"
+
+#define BYTE_PER_PIXEL 4
+#define X_LAST 392
+
+const static int X_START_TABLE[] = {0,176,168,160,152,152,144,144,136,136,136,128,128,128,120,
+                                   120,120,112,112,112,112,104,104,104,104,96,96,96,96,96,88,
+                                   88,88,88,88,80,80,80,80,80,80,72,72,72,72,72,72,64,64,64,64,
+                                   64,64,64,64,56,56,56,56,56,56,56,48,48,48,48,48,48,48,48,48,
+                                   40,40,40,40,40,40,40,40,40,40,32,32,32,32,32,32,32,32,32,32,
+                                   32,32,24,24,24,24,24,24,24,24,24,24,24,24,24,16,16,16,16,16,
+                                   16,16,16,16,16,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,
+                                   8,8,8,8,8,8,8,8,8,8,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+                                   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,
+                                   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,16,16,16,16,16,
+                                   16,16,16,16,16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24,
+                                   24,24,24,24,24,32,32,32,32,32,32,32,32,32,32,32,32,40,40,40,
+                                   40,40,40,40,40,40,40,48,48,48,48,48,48,48,48,48,56,56,56,56,
+                                   56,56,56,64,64,64,64,64,64,64,64,72,72,72,72,72,72,80,80,80,
+                                   80,80,80,88,88,88,88,88,96,96,96,96,96,104,104,104,104,112,
+                                   112,112,112,120,120,120,128,128,128,136,136,136,144,144,152,
+                                   152,160,168,176};
+
+const static int TABLE_SIZE = sizeof(X_START_TABLE) / sizeof(X_START_TABLE[0]);
+const static uint8_t MASK[8] = {0xff, 0, 0xff, 0, 0xff, 0, 0xff, 0};
+const static uint8x8_t MASK_8X8 = vld1_u8(MASK);
+const static uint8x8_t THREE_8X8 = vdup_n_u8(3);
+
+const static inline uint8x8_t renderSingleChannel(uint8x8x4_t pixelAbove, uint8x8x4_t pixelCenter,
+        uint8x8x4_t pixelBelow, int channel) {
+    uint8x8_t temp;
+    uint16x8_t temp1;
+    uint16x8_t temp2;
+    uint16x8_t temp3;
+
+    temp = vbsl_u8(MASK_8X8, pixelAbove.val[channel], pixelBelow.val[channel]);
+    temp1 = vmovl_u8(temp);
+    temp2 = vmull_u8(pixelCenter.val[channel], THREE_8X8);
+    temp3 = vaddq_u16(temp2, temp1);
+    return vshrn_n_u16(temp3, 2);
+}
+
+/*
+ * Delta Real Panel Rending - Delta real pixel rending for Wearable device panel.
+ * pImage - Point to head of display image
+ * width - Input image width
+ * height - Input image height
+ */
+void deltaPanelRendering(uint8_t *pImage, int width, int height)
+{
+    int x, y;
+    uint8_t *pData;
+    int byteWidth;
+    uint32_t *pPixelAbove, *pPixelCenter, *pPixelBelow;
+    int64_t diff;
+    int xStart, xEnd;
+
+    byteWidth = width * BYTE_PER_PIXEL;
+    pData = pImage + byteWidth;
+
+    // center
+    for(y = 1; y < (height - 1) && y < TABLE_SIZE; y++)
+    {
+        xStart = X_START_TABLE[y];
+        xEnd = X_LAST - X_START_TABLE[y];
+        pPixelCenter = ((uint32_t*)pData) + xStart;
+        pPixelAbove = pPixelCenter - width;
+        pPixelBelow = pPixelCenter + width;
+
+        // process 8 pixels
+        for(x = xStart; x <= xEnd; x += 8)
+        {
+            uint8x8x4_t pixelAbove = vld4_u8((uint8_t *)pPixelAbove);
+            uint8x8x4_t pixelCenter = vld4_u8((uint8_t *)pPixelCenter);
+            uint8x8x4_t pixelBelow = vld4_u8((uint8_t *)pPixelBelow);
+
+#ifdef DELTA_PANEL_R
+            pixelCenter.val[0] = renderSingleChannel(pixelAbove, pixelCenter, pixelBelow, 0);
+#endif
+
+#ifdef DELTA_PANEL_G
+            pixelCenter.val[1] = renderSingleChannel(pixelAbove, pixelCenter, pixelBelow, 1);
+#endif
+
+#ifdef DELTA_PANEL_B
+            pixelCenter.val[2] = renderSingleChannel(pixelAbove, pixelCenter, pixelBelow, 2);
+#endif
+            vst4_u8((uint8_t *)pPixelCenter, pixelCenter);
+            pPixelAbove += 8;
+            pPixelCenter += 8;
+            pPixelBelow += 8;
+        }
+
+        pData += byteWidth;
+    }
+}
diff --git a/msm8226/libhwcomposer/hwc_delta_panel.h b/msm8226/libhwcomposer/hwc_delta_panel.h
new file mode 100644
index 0000000..4600c22
--- /dev/null
+++ b/msm8226/libhwcomposer/hwc_delta_panel.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HWC_DELTA_PANEL_H
+#define HWC_DELTA_PANEL_H
+
+void deltaPanelRendering(uint8_t *pImage, int width, int height);
+
+#endif //HWC_DELTA_PANEL_H
+
diff --git a/msm8226/libhwcomposer/hwc_mdpcomp.cpp b/msm8226/libhwcomposer/hwc_mdpcomp.cpp
index bbc6981..dbdad1f 100644
--- a/msm8226/libhwcomposer/hwc_mdpcomp.cpp
+++ b/msm8226/libhwcomposer/hwc_mdpcomp.cpp
@@ -120,6 +120,14 @@
         sEnabled = true;
     }
 
+#ifdef DELTA_PANEL
+    if((property_get("ro.hwc.is_delta_panel", property, NULL) > 0) &&
+       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        sEnabled = false;
+    }
+#endif
+
     sEnableMixedMode = true;
     if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
        (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||