hwc: Set GPU performance hint.

1. Set the GPU hint flag to high for MIXED/GPU composition only for
   first frame after MDP to GPU/MIXED mode transition.
2. Set the GPU hint to default if the current composition type is GPU
   due to idle fallback or MDP composition.

Change-Id: I208a778017435a5a4620142da9d9fb3c50e09155
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 893fee0..bfcfa78 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -212,6 +212,7 @@
             if(ctx->mCopyBit[dpy])
                 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
         }
+        setGPUHint(ctx, list);
     }
     return 0;
 }
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 22b8baf..2d65755 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -53,6 +53,7 @@
     static bool init(hwc_context_t *ctx);
     static void resetIdleFallBack() { sIdleFallBack = false; }
     static void reset() { sHandleTimeout = false; };
+    static bool isIdleFallback() { return sIdleFallBack; }
 
 protected:
     enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 751aef3..d9e75dc 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -52,6 +52,26 @@
 using namespace overlay::utils;
 namespace ovutils = overlay::utils;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EGLAPI EGLBoolean eglGpuPerfHintQCOM(EGLDisplay dpy, EGLContext ctx,
+                                           EGLint *attrib_list);
+#define EGL_GPU_HINT_1        0x32D0
+#define EGL_GPU_HINT_2        0x32D1
+
+#define EGL_GPU_LEVEL_0       0x0
+#define EGL_GPU_LEVEL_1       0x1
+#define EGL_GPU_LEVEL_2       0x2
+#define EGL_GPU_LEVEL_3       0x3
+#define EGL_GPU_LEVEL_4       0x4
+#define EGL_GPU_LEVEL_5       0x5
+
+#ifdef __cplusplus
+}
+#endif
+
 namespace qhwc {
 
 bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
@@ -245,6 +265,15 @@
         ctx->mMDPDownscaleEnabled = true;
     }
 
+    // Initialize gpu perfomance hint related parameters
+    property_get("sys.hwc.gpu_perf_mode", value, "0");
+    ctx->mGPUHintInfo.mGpuPerfModeEnable = atoi(value)? true : false;
+
+    ctx->mGPUHintInfo.mEGLDisplay = NULL;
+    ctx->mGPUHintInfo.mEGLContext = NULL;
+    ctx->mGPUHintInfo.mPrevCompositionGLES = false;
+    ctx->mGPUHintInfo.mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
+
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
 }
@@ -1981,6 +2010,78 @@
     return true;
 }
 
+bool isGLESComp(hwc_context_t *ctx,
+                     hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+    for(int index = 0; index < numAppLayers; index++) {
+        hwc_layer_1_t* layer = &(list->hwLayers[index]);
+        if(layer->compositionType == HWC_FRAMEBUFFER)
+            return true;
+    }
+    return false;
+}
+
+void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
+    struct gpu_hint_info *gpuHint = &ctx->mGPUHintInfo;
+    if(!gpuHint->mGpuPerfModeEnable)
+        return;
+    /* Set the GPU hint flag to high for MIXED/GPU composition only for
+       first frame after MDP -> GPU/MIXED mode transition. Set the GPU
+       hint to default if the previous composition is GPU or current GPU
+       composition is due to idle fallback */
+    if(!gpuHint->mEGLDisplay || !gpuHint->mEGLContext) {
+        gpuHint->mEGLDisplay = eglGetCurrentDisplay();
+        if(!gpuHint->mEGLDisplay) {
+            ALOGW("%s Warning: EGL current display is NULL", __FUNCTION__);
+            return;
+        }
+        gpuHint->mEGLContext = eglGetCurrentContext();
+        if(!gpuHint->mEGLContext) {
+            ALOGW("%s Warning: EGL current context is NULL", __FUNCTION__);
+            return;
+        }
+    }
+    if(isGLESComp(ctx, list)) {
+        if(!gpuHint->mPrevCompositionGLES && !MDPComp::isIdleFallback()) {
+            EGLint attr_list[] = {EGL_GPU_HINT_1,
+                                  EGL_GPU_LEVEL_3,
+                                  EGL_NONE };
+            if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_3) &&
+                !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
+                                    gpuHint->mEGLContext, attr_list)) {
+                ALOGW("eglGpuPerfHintQCOM failed for Built in display");
+            } else {
+                gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_3;
+                gpuHint->mPrevCompositionGLES = true;
+            }
+        } else {
+            EGLint attr_list[] = {EGL_GPU_HINT_1,
+                                  EGL_GPU_LEVEL_0,
+                                  EGL_NONE };
+            if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
+                !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
+                                    gpuHint->mEGLContext, attr_list)) {
+                ALOGW("eglGpuPerfHintQCOM failed for Built in display");
+            } else {
+                gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
+            }
+        }
+    } else {
+        /* set the GPU hint flag to default for MDP composition */
+        EGLint attr_list[] = {EGL_GPU_HINT_1,
+                              EGL_GPU_LEVEL_0,
+                              EGL_NONE };
+        if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
+                !eglGpuPerfHintQCOM(gpuHint->mEGLDisplay,
+                                    gpuHint->mEGLContext, attr_list)) {
+            ALOGW("eglGpuPerfHintQCOM failed for Built in display");
+        } else {
+            gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
+        }
+        gpuHint->mPrevCompositionGLES = false;
+    }
+}
+
 void BwcPM::setBwc(const hwc_rect_t& crop,
             const hwc_rect_t& dst, const int& transform,
             ovutils::eMdpFlags& mdpFlags) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index b4b5232..ad023ad 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -30,6 +30,8 @@
 #include <utils/String8.h>
 #include "qdMetaData.h"
 #include <overlayUtils.h>
+#include <EGL/egl.h>
+
 
 #define ALIGN_TO(x, align)     (((x) + ((align)-1)) & ~((align)-1))
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
@@ -341,6 +343,12 @@
 
 bool isDisplaySplit(hwc_context_t* ctx, int dpy);
 
+// Set the GPU hint flag to high for MIXED/GPU composition only for
+// first frame after MDP to GPU/MIXED mode transition.
+// Set the GPU hint to default if the current composition type is GPU
+// due to idle fallback or MDP composition.
+void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list);
+
 // Inline utility functions
 static inline bool isSkipLayer(const hwc_layer_1_t* l) {
     return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
@@ -439,6 +447,20 @@
     ANIMATION_STARTED,
 };
 
+// Structure holds the information about the GPU hint.
+struct gpu_hint_info {
+    // system level flag to enable gpu_perf_mode
+    bool mGpuPerfModeEnable;
+    // Stores the current GPU performance mode DEFAULT/HIGH
+    bool mCurrGPUPerfMode;
+    // true if previous composition used GPU
+    bool mPrevCompositionGLES;
+    // Stores the EGLContext of current process
+    EGLContext mEGLContext;
+    // Stores the EGLDisplay of current process
+    EGLDisplay mEGLDisplay;
+};
+
 // -----------------------------------------------------------------------------
 // HWC context
 // This structure contains overall state
@@ -502,6 +524,7 @@
     // Downscale feature switch, set via system the property
     // sys.hwc.mdp_downscale_enabled
     bool mMDPDownscaleEnabled;
+    struct gpu_hint_info mGPUHintInfo;
 };
 
 namespace qhwc {