hwc: Add support for external-only layers

Add support for different types of external-only layers
EXTERNAL_ONLY: General purpose
EXTERNAL_BLOCK: Blocks the display of other ext-only layers
EXTERNAL_CC: Used for closed captions with videos.

Change-Id: I9cc7b9a1dbf1085194725474d6a4d1094e27a0c8
Acked-by: Saurabh Shah <saurshah@codeaurora.org>
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 05d033e..51f1e00 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -9,8 +9,14 @@
                                  libqdutils libhardware_legacy libdl libmemalloc
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"hwcomposer\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_SRC_FILES               :=  hwc.cpp hwc_video.cpp hwc_utils.cpp \
-                                  hwc_uimirror.cpp hwc_external.cpp \
-                                  hwc_uevents.cpp hwc_copybit.cpp \
-                                  hwc_mdpcomp.cpp
+LOCAL_SRC_FILES               := hwc.cpp          \
+                                 hwc_video.cpp    \
+                                 hwc_utils.cpp    \
+                                 hwc_uimirror.cpp \
+                                 hwc_external.cpp \
+                                 hwc_uevents.cpp  \
+                                 hwc_copybit.cpp  \
+                                 hwc_mdpcomp.cpp  \
+                                 hwc_extonly.cpp
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 13d6274..ad84d25 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -32,6 +32,7 @@
 #include "hwc_copybit.h"
 #include "hwc_external.h"
 #include "hwc_mdpcomp.h"
+#include "hwc_extonly.h"
 
 using namespace qhwc;
 
@@ -81,10 +82,16 @@
     return 0;
 
     if (LIKELY(list)) {
+        //reset for this draw round
+        VideoOverlay::reset();
+        ExtOnly::reset();
+
         getLayerStats(ctx, list);
         if(VideoOverlay::prepare(ctx, list)) {
             ctx->overlayInUse = true;
             //Nothing here
+        } else if(ExtOnly::prepare(ctx, list)) {
+            ctx->overlayInUse = true;
         } else if(UIMirrorOverlay::prepare(ctx, list)) {
             ctx->overlayInUse = true;
         } else if(MDPComp::configure(dev, list)) {
@@ -156,6 +163,7 @@
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     if (LIKELY(list)) {
         VideoOverlay::draw(ctx, list);
+        ExtOnly::draw(ctx, list);
         CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur);
         MDPComp::draw(ctx, list);
         EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
diff --git a/libhwcomposer/hwc_extonly.cpp b/libhwcomposer/hwc_extonly.cpp
new file mode 100644
index 0000000..77a96b6
--- /dev/null
+++ b/libhwcomposer/hwc_extonly.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * 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 "hwc_extonly.h"
+#include "hwc_external.h"
+#include "hwc_qbuf.h"
+
+namespace qhwc {
+
+#define EXTONLY_DEBUG 0
+
+//Static Members
+ovutils::eOverlayState ExtOnly::sState = ovutils::OV_CLOSED;
+int ExtOnly::sExtCount = 0;
+int ExtOnly::sExtIndex = -1;
+bool ExtOnly::sIsExtBlock = false;
+bool ExtOnly::sIsModeOn = false;
+
+//Cache stats, figure out the state, config overlay
+bool ExtOnly::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
+    sIsModeOn = false;
+    if(!ctx->mMDP.hasOverlay) {
+       ALOGD_IF(EXTONLY_DEBUG,"%s, this hw doesnt support overlay",
+            __FUNCTION__);
+       return false;
+    }
+    if(sExtIndex == -1) {
+        return false;
+    }
+    chooseState(ctx);
+    //if the state chosen above is CLOSED, skip this block.
+    if(sState != ovutils::OV_CLOSED) {
+        hwc_layer_t *extLayer = &list->hwLayers[sExtIndex];
+        if(configure(ctx, extLayer)) {
+            markFlags(extLayer);
+            sIsModeOn = true;
+        }
+    }
+
+    ALOGD_IF(EXTONLY_DEBUG, "%s: stats: extCount = %d, extIndex = %d,"
+            "IsExtBlock = %d, IsModeOn = %d",
+            __func__, sExtCount, sExtIndex,
+            sIsExtBlock, sIsModeOn);
+
+    return sIsModeOn;
+}
+
+void ExtOnly::chooseState(hwc_context_t *ctx) {
+    ALOGD_IF(EXTONLY_DEBUG, "%s: old state = %s", __FUNCTION__,
+            ovutils::getStateString(sState));
+
+    ovutils::eOverlayState newState = ovutils::OV_CLOSED;
+
+    if(sExtCount > 0 &&
+        ctx->mExtDisplay->getExternalDisplay()) {
+            newState = ovutils::OV_DUAL_DISP;
+    }
+
+    sState = newState;
+    ALOGD_IF(EXTONLY_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
+            ovutils::getStateString(sState));
+}
+
+void ExtOnly::markFlags(hwc_layer_t *layer) {
+    switch(sState) {
+        case ovutils::OV_DUAL_DISP:
+            layer->compositionType = HWC_OVERLAY;
+            break;
+        default:
+            break;
+    }
+}
+
+bool ExtOnly::configure(hwc_context_t *ctx, hwc_layer_t *layer) {
+
+    overlay::Overlay& ov = *(ctx->mOverlay);
+    ov.setState(sState);
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
+    ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
+    ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
+    ovutils::PipeArgs parg(mdpFlags,
+            info,
+            ovutils::ZORDER_0,
+            isFgFlag,
+            ovutils::ROT_FLAG_DISABLED);
+    ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
+    ov.setSource(pargs, ovutils::OV_PIPE0);
+
+    hwc_rect_t sourceCrop = layer->sourceCrop;
+    // x,y,w,h
+    ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
+            sourceCrop.right - sourceCrop.left,
+            sourceCrop.bottom - sourceCrop.top);
+    ov.setCrop(dcrop, ovutils::OV_PIPE0);
+
+    ov.setTransform(0, ovutils::OV_PIPE0);
+
+    //Setting position same as crop
+    //FIXME stretch to full screen
+    ov.setPosition(dcrop, ovutils::OV_PIPE0);
+
+    if (!ov.commit(ovutils::OV_PIPE0)) {
+        ALOGE("%s: commit fails", __FUNCTION__);
+        return false;
+    }
+    return true;
+}
+
+bool ExtOnly::draw(hwc_context_t *ctx, hwc_layer_list_t *list)
+{
+    if(!sIsModeOn || sExtIndex == -1) {
+        return true;
+    }
+
+    private_handle_t *hnd = (private_handle_t *)
+            list->hwLayers[sExtIndex].handle;
+
+    // Lock this buffer for read.
+    ctx->qbuf->lockAndAdd(hnd);
+    bool ret = true;
+    overlay::Overlay& ov = *(ctx->mOverlay);
+    ovutils::eOverlayState state = ov.getState();
+
+    switch (state) {
+        case ovutils::OV_DUAL_DISP:
+            // Play external
+            if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
+                ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
+                ret = false;
+            }
+            // Wait for external vsync to be done
+            if (!ov.waitForVsync(ovutils::OV_PIPE0)) {
+                ALOGE("%s: waitForVsync failed for external", __FUNCTION__);
+                ret = false;
+            }
+            break;
+        default:
+            ALOGE("%s Unused state %s", __FUNCTION__,
+                    ovutils::getStateString(state));
+            break;
+    }
+
+    return ret;
+}
+
+}; //namespace qhwc
diff --git a/libhwcomposer/hwc_extonly.h b/libhwcomposer/hwc_extonly.h
new file mode 100644
index 0000000..26d5fb9
--- /dev/null
+++ b/libhwcomposer/hwc_extonly.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * 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_EXTONLY_H
+#define HWC_EXTONLY_H
+
+#include <overlay.h>
+#include "hwc_utils.h"
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace qhwc {
+//Feature for using overlay to display external-only layers on HDTV
+class ExtOnly {
+public:
+    //Sets up members and prepares overlay if conditions are met
+    static bool prepare(hwc_context_t *ctx, hwc_layer_list_t *list);
+    //Draws layer if this feature is on
+    static bool draw(hwc_context_t *ctx, hwc_layer_list_t *list);
+    //Receives data from hwc
+    static void setStats(int extCount, int extIndex, bool isExtBlock);
+    //resets values
+    static void reset();
+private:
+    //Choose an appropriate overlay state based on conditions
+    static void chooseState(hwc_context_t *ctx);
+    //Configures overlay
+    static bool configure(hwc_context_t *ctx, hwc_layer_t *layer);
+    //Marks layer flags if this feature is used
+    static void markFlags(hwc_layer_t *layer);
+    //returns ext-only count
+    static int getExtCount();
+
+    //The chosen overlay state.
+    static ovutils::eOverlayState sState;
+    //Number of ext-only layers in this drawing round. Used for stats/debugging.
+    //This does not reflect the closed caption layer count even though its
+    //ext-only.
+    static int sExtCount;
+    //Index of ext-only layer. If there are 2 such layers with 1 marked as BLOCK
+    //then this will hold the index of BLOCK layer.
+    static int sExtIndex;
+    //Flags if ext-only layer is BLOCK, which means only this layer (sExtIndex)
+    //is displayed even if other ext-only layers are present to block their
+    //content. This is used for stats / debugging only.
+    static bool sIsExtBlock;
+    //Flags if this feature is on.
+    static bool sIsModeOn;
+};
+
+inline void ExtOnly::setStats(int extCount, int extIndex, bool isExtBlock) {
+    sExtCount = extCount;
+    sExtIndex = extIndex;
+    sIsExtBlock = isExtBlock;
+}
+
+inline int ExtOnly::getExtCount() { return sExtCount; }
+inline void ExtOnly::reset() {
+    sExtCount = 0;
+    sExtIndex = -1;
+    sIsExtBlock = false;
+    sIsModeOn = false;
+    sState = ovutils::OV_CLOSED;
+}
+
+}; //namespace qhwc
+
+#endif //HWC_EXTONLY_H
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index dd890a9..8bc8bfc 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -23,6 +23,7 @@
 #include "hwc_copybit.h"
 #include "hwc_external.h"
 #include "hwc_mdpcomp.h"
+#include "hwc_extonly.h"
 
 namespace qhwc {
 
@@ -107,18 +108,32 @@
     int yuvLayerIndex = -1;
     bool isYuvLayerSkip = false;
     int skipCount = 0;
+    int ccLayerIndex = -1; //closed caption
+    int extLayerIndex = -1; //ext-only or block except closed caption
+    int extCount = 0; //ext-only except closed caption
+    bool isExtBlockPresent = false; //is BLOCK layer present
 
     for (size_t i = 0; i < list->numHwLayers; i++) {
         private_handle_t *hnd =
             (private_handle_t *)list->hwLayers[i].handle;
 
-        if (isYuvBuffer(hnd)) {
+        if (UNLIKELY(isYuvBuffer(hnd))) {
             yuvCount++;
             yuvLayerIndex = i;
             //Animating
             if (isSkipLayer(&list->hwLayers[i])) {
                 isYuvLayerSkip = true;
             }
+        } else if(UNLIKELY(isExtCC(hnd))) {
+            ccLayerIndex = i;
+        } else if(UNLIKELY(isExtBlock(hnd))) {
+            extCount++;
+            extLayerIndex = i;
+            isExtBlockPresent = true;
+        } else if(UNLIKELY(isExtOnly(hnd))) {
+            extCount++;
+            //If BLOCK layer present, dont cache index, display BLOCK only.
+            if(isExtBlockPresent == false) extLayerIndex = i;
         } else if (isSkipLayer(&list->hwLayers[i])) { //Popups
             //If video layer is below a skip layer
             if(yuvLayerIndex != -1 && yuvLayerIndex < (ssize_t)i) {
@@ -128,7 +143,9 @@
         }
     }
 
-    VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip);
+    VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip,
+            ccLayerIndex);
+    ExtOnly::setStats(extCount, extLayerIndex, isExtBlockPresent);
     CopyBit::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip);
     MDPComp::setStats(skipCount);
 
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 9ce0815..71c1f73 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -90,6 +90,21 @@
     return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
 }
 
+//Return true if buffer is for external display only
+static inline bool isExtOnly(const private_handle_t* hnd) {
+    return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY));
+}
+
+//Return true if buffer is for external display only with a BLOCK flag.
+static inline bool isExtBlock(const private_handle_t* hnd) {
+    return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK));
+}
+
+//Return true if buffer is for external display only with a Close Caption flag.
+static inline bool isExtCC(const private_handle_t* hnd) {
+    return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_CC));
+}
+
 // Initialize uevent thread
 void init_uevent_thread(hwc_context_t* ctx);
 
diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp
index a0ae331..4fb88d7 100644
--- a/libhwcomposer/hwc_video.cpp
+++ b/libhwcomposer/hwc_video.cpp
@@ -29,8 +29,9 @@
 ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED;
 int VideoOverlay::sYuvCount = 0;
 int VideoOverlay::sYuvLayerIndex = -1;
+bool VideoOverlay::sIsYuvLayerSkip = false;
+int VideoOverlay::sCCLayerIndex = -1;
 bool VideoOverlay::sIsModeOn = false;
-bool VideoOverlay::sIsLayerSkip = false;
 
 //Cache stats, figure out the state, config overlay
 bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
@@ -45,15 +46,21 @@
     chooseState(ctx);
     //if the state chosen above is CLOSED, skip this block.
     if(sState != ovutils::OV_CLOSED) {
-        if(configure(ctx, &list->hwLayers[sYuvLayerIndex])) {
+        hwc_layer_t *yuvLayer = &list->hwLayers[sYuvLayerIndex];
+        hwc_layer_t *ccLayer = NULL;
+        if(sCCLayerIndex != -1)
+            ccLayer = &list->hwLayers[sCCLayerIndex];
+
+        if(configure(ctx, yuvLayer, ccLayer)) {
             markFlags(&list->hwLayers[sYuvLayerIndex]);
             sIsModeOn = true;
         }
     }
 
     ALOGD_IF(VIDEO_DEBUG, "%s: stats: yuvCount = %d, yuvIndex = %d,"
-            "IsModeOn = %d, IsSkipLayer = %d", __FUNCTION__, sYuvCount,
-            sYuvLayerIndex, sIsModeOn, sIsLayerSkip);
+            "IsYuvLayerSkip = %d, ccLayerIndex = %d, IsModeOn = %d",
+            __FUNCTION__, sYuvCount, sYuvLayerIndex,
+            sIsYuvLayerSkip, sCCLayerIndex, sIsModeOn);
 
     return sIsModeOn;
 }
@@ -63,14 +70,13 @@
             ovutils::getStateString(sState));
 
     ovutils::eOverlayState newState = ovutils::OV_CLOSED;
-    //TODO check if device supports overlay and hdmi
 
     //Support 1 video layer
     if(sYuvCount == 1) {
         //Skip on primary, display on ext.
-        if(sIsLayerSkip && ctx->mExtDisplay->getExternalDisplay()) {
+        if(sIsYuvLayerSkip && ctx->mExtDisplay->getExternalDisplay()) {
             newState = ovutils::OV_2D_VIDEO_ON_TV;
-        } else if(sIsLayerSkip) { //skip on primary, no ext
+        } else if(sIsYuvLayerSkip) { //skip on primary, no ext
             newState = ovutils::OV_CLOSED;
         } else if(ctx->mExtDisplay->getExternalDisplay()) {
             //display on both
@@ -228,8 +234,49 @@
     return true;
 }
 
-bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *yuvLayer)
-{
+bool configExtCC(hwc_context_t *ctx, hwc_layer_t *layer) {
+    if(layer == NULL)
+        return true;
+
+    overlay::Overlay& ov = *(ctx->mOverlay);
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
+    ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
+    ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
+    ovutils::PipeArgs parg(mdpFlags,
+            info,
+            ovutils::ZORDER_1,
+            isFgFlag,
+            ovutils::ROT_FLAG_DISABLED);
+    ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
+    ov.setSource(pargs, ovutils::OV_PIPE2);
+
+    hwc_rect_t sourceCrop = layer->sourceCrop;
+    // x,y,w,h
+    ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
+            sourceCrop.right - sourceCrop.left,
+            sourceCrop.bottom - sourceCrop.top);
+    //Only for External
+    ov.setCrop(dcrop, ovutils::OV_PIPE2);
+
+    // FIXME: Use source orientation for TV when source is portrait
+    //Only for External
+    ov.setTransform(0, ovutils::OV_PIPE2);
+
+    //Setting position same as crop
+    //FIXME stretch to full screen
+    ov.setPosition(dcrop, ovutils::OV_PIPE2);
+
+    if (!ov.commit(ovutils::OV_PIPE2)) {
+        ALOGE("%s: commit fails", __FUNCTION__);
+        return false;
+    }
+    return true;
+}
+
+bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *yuvLayer,
+        hwc_layer_t *ccLayer) {
+
     bool ret = true;
     if (LIKELY(ctx->mOverlay)) {
         overlay::Overlay& ov = *(ctx->mOverlay);
@@ -241,10 +288,12 @@
                 break;
             case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
                 ret &= configExtVid(ctx, yuvLayer);
+                ret &= configExtCC(ctx, ccLayer);
                 ret &= configPrimVid(ctx, yuvLayer);
                 break;
             case ovutils::OV_2D_VIDEO_ON_TV:
                 ret &= configExtVid(ctx, yuvLayer);
+                ret &= configExtCC(ctx, ccLayer);
                 break;
             default:
                 return false;
@@ -262,11 +311,18 @@
         return true;
     }
 
-    private_handle_t *hnd =
-            (private_handle_t *)list->hwLayers[sYuvLayerIndex].handle;
+    private_handle_t *hnd = (private_handle_t *)
+            list->hwLayers[sYuvLayerIndex].handle;
+
+    private_handle_t *cchnd = NULL;
+    if(sCCLayerIndex != -1) {
+        cchnd = (private_handle_t *)list->hwLayers[sCCLayerIndex].handle;
+        ctx->qbuf->lockAndAdd(cchnd);
+    }
 
     // Lock this buffer for read.
     ctx->qbuf->lockAndAdd(hnd);
+
     bool ret = true;
     overlay::Overlay& ov = *(ctx->mOverlay);
     ovutils::eOverlayState state = ov.getState();
@@ -278,6 +334,12 @@
                 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
                 ret = false;
             }
+            //Play CC on external
+            if (cchnd && !ov.queueBuffer(cchnd->fd, cchnd->offset,
+                        ovutils::OV_PIPE2)) {
+                ALOGE("%s: queueBuffer failed for cc external", __FUNCTION__);
+                ret = false;
+            }
             // Play primary
             if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
                 ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
@@ -302,11 +364,18 @@
                 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
                 ret = false;
             }
+            //Play CC on external
+            if (cchnd && !ov.queueBuffer(cchnd->fd, cchnd->offset,
+                        ovutils::OV_PIPE2)) {
+                ALOGE("%s: queueBuffer failed for cc external", __FUNCTION__);
+                ret = false;
+            }
             // Wait for external vsync to be done
             if (!ov.waitForVsync(ovutils::OV_PIPE1)) {
                 ALOGE("%s: waitForVsync failed for external", __FUNCTION__);
                 ret = false;
             }
+            break;
         default:
             ALOGE("%s Unused state %s", __FUNCTION__,
                     ovutils::getStateString(state));
diff --git a/libhwcomposer/hwc_video.h b/libhwcomposer/hwc_video.h
index c6c6c22..62a32a9 100644
--- a/libhwcomposer/hwc_video.h
+++ b/libhwcomposer/hwc_video.h
@@ -30,12 +30,16 @@
     //Draws layer if this feature is on
     static bool draw(hwc_context_t *ctx, hwc_layer_list_t *list);
     //Receives data from hwc
-    static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip);
+    static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip,
+            int ccLayerIndex);
+    //resets values
+    static void reset();
 private:
     //Choose an appropriate overlay state based on conditions
     static void chooseState(hwc_context_t *ctx);
-    //Configures overlay
-    static bool configure(hwc_context_t *ctx, hwc_layer_t *layer);
+    //Configures overlay for video prim and ext
+    static bool configure(hwc_context_t *ctx, hwc_layer_t *yuvlayer,
+            hwc_layer_t *ccLayer);
     //Marks layer flags if this feature is used
     static void markFlags(hwc_layer_t *layer);
     //returns yuv count
@@ -48,20 +52,30 @@
     //Index of YUV layer, relevant only if count is 1
     static int sYuvLayerIndex;
     //Flags if a yuv layer is animating or below something that is animating
-    static bool sIsLayerSkip;
+    static bool sIsYuvLayerSkip;
+    //Holds the closed caption layer index, -1 by default
+    static int sCCLayerIndex;
     //Flags if this feature is on.
     static bool sIsModeOn;
 };
 
 inline void VideoOverlay::setStats(int yuvCount, int yuvLayerIndex,
-        bool isYuvLayerSkip) {
+        bool isYuvLayerSkip, int ccLayerIndex) {
     sYuvCount = yuvCount;
     sYuvLayerIndex = yuvLayerIndex;
-    sIsLayerSkip = isYuvLayerSkip;
+    sIsYuvLayerSkip = isYuvLayerSkip;
+    sCCLayerIndex = ccLayerIndex;
 }
 
 inline int VideoOverlay::getYuvCount() { return sYuvCount; }
-
+inline void VideoOverlay::reset() {
+    sYuvCount = 0;
+    sYuvLayerIndex = -1;
+    sIsYuvLayerSkip = false;
+    sCCLayerIndex = -1;
+    sIsModeOn = false;
+    sState = ovutils::OV_CLOSED;
+}
 }; //namespace qhwc
 
 #endif //HWC_VIDEO_H