drm local preview: add primary plane and page flip mode to improve
stability and display fps. Primary mode as default display mode, and
use cmd to point at overlay mode:
    ./test-device-manager -f YUYV -m dma -d video -e overlay -p
diff --git a/cl_kernel/kernel_csc_yuyvtorgba.cl b/cl_kernel/kernel_csc_yuyvtorgba.cl
new file mode 100644
index 0000000..9531ae8
--- /dev/null
+++ b/cl_kernel/kernel_csc_yuyvtorgba.cl
@@ -0,0 +1,25 @@
+/*
+ * function: kernel_csc_yuyvtorgba
+ * input:    image2d_t as read only
+ * output:   image2d_t as write only
+ */
+
+"__kernel void kernel_csc_yuyvtorgba (__read_only image2d_t input, __write_only image2d_t output)        "
+"{                                                                                             "
+"    int x = get_global_id (0);                                                            "
+"    int y = get_global_id (1);                                                             "
+"    sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;  "
+"    float4 pixel_in1 = read_imagef(input, sampler, (int2)(x,y));                                          "
+"    float4 pixel_out1,pixel_out2;    "
+"    pixel_out1.x = pixel_in1.x + 1.13983 * (pixel_in1.w - 0.5);    "
+"    pixel_out1.y = pixel_in1.x - 0.39465 * (pixel_in1.y - 0.5) - 0.5806 * (pixel_in1.w - 0.5);    "
+"    pixel_out1.z = pixel_in1.x + 2.03211 * (pixel_in1.y - 0.5);    "
+"    pixel_out1.w = 0.0;    "
+"    pixel_out2.x = pixel_in1.z + 1.13983 * (pixel_in1.w - 0.5);    "
+"    pixel_out2.y = pixel_in1.z - 0.39465 * (pixel_in1.y - 0.5) - 0.5806 * (pixel_in1.w - 0.5);    "
+"    pixel_out2.z = pixel_in1.z + 2.03211 * (pixel_in1.y - 0.5);    "
+"    pixel_out2.w = 0.0;    "
+"    write_imagef(output, (int2)(2*x,y), pixel_out1);                                                        "
+"    write_imagef(output, (int2)(2*x+1,y), pixel_out2);                                                        "
+"}                                                                                             "
+
diff --git a/tests/test-device-manager.cpp b/tests/test-device-manager.cpp
index 25b4f5c..51f1260 100644
--- a/tests/test-device-manager.cpp
+++ b/tests/test-device-manager.cpp
@@ -28,6 +28,7 @@
 #endif
 #if HAVE_LIBCL
 #include "cl_3a_image_processor.h"
+#include "cl_csc_image_processor.h"
 #endif
 #if HAVE_LIBDRM
 #include "drm_display.h"
@@ -81,6 +82,10 @@
         _enable_display = value;
     }
 
+    void set_display_mode(DrmDisplayMode mode) {
+        _display->set_display_mode (mode);
+    }
+
 protected:
     virtual void handle_message (SmartPtr<XCamMessage> &msg);
     virtual void handle_buffer (SmartPtr<VideoBuffer> &buf);
@@ -242,7 +247,9 @@
             "\t -d cap_mode   specify capture mode\n"
             "\t               cap_mode select from [video, still], default is [video]\n"
             "\t -i frame_save specify the frame count to save, default is 0 which means endless\n"
-            "\t -p           preview on local display\n"
+            "\t -p preview on local display\n"
+            "\t -e display_mode    preview mode\n"
+            "\t                select from [primary, overlay], default is [primary]\n"
             "\t -h            help\n"
             , bin_name
             , DEFAULT_SAVE_FILE_NAME);
@@ -257,7 +264,9 @@
     SmartPtr<IspController> isp_controller;
     SmartPtr<X3aAnalyzer> analyzer;
     SmartPtr<ImageProcessor> isp_processor;
+    SmartPtr<CLCscImageProcessor> cl_csc_proccessor;
     AnalyzerType  analyzer_type = AnalyzerTypeSimple;
+    DrmDisplayMode display_mode = DRM_DISPLAY_MODE_PRIMARY;
 #if HAVE_LIBDRM
     SmartPtr<DrmDisplay> drm_disp = DrmDisplay::instance();
 #endif
@@ -273,7 +282,7 @@
     uint32_t capture_mode = V4L2_CAPTURE_MODE_VIDEO;
     uint32_t pixel_format = V4L2_PIX_FMT_NV12;
 
-    while ((opt =  getopt(argc, argv, "sca:n:m:f:d:pi:h")) != -1) {
+    while ((opt =  getopt(argc, argv, "sca:n:m:f:d:pi:e:h")) != -1) {
         switch (opt) {
         case 'a': {
             if (!strcmp (optarg, "dynamic"))
@@ -330,6 +339,17 @@
         case 'p':
             need_display = true;
             break;
+        case 'e': {
+            if (!strcmp (optarg, "primary"))
+                display_mode = DRM_DISPLAY_MODE_PRIMARY;
+            else if (!strcmp (optarg, "overlay"))
+                display_mode = DRM_DISPLAY_MODE_OVERLAY;
+            else {
+                print_help (bin_name);
+                return -1;
+            }
+            break;
+        }
         case 'i':
             device_manager->set_frame_save(atoi(optarg));
             break;
@@ -343,9 +363,10 @@
         }
     }
 
-    if (need_display)
+    if (need_display) {
         device_manager->enable_display (true);
-
+        device_manager->set_display_mode (display_mode);
+    }
     if (!device.ptr ())  {
         if (capture_mode == V4L2_CAPTURE_MODE_STILL)
             device = new AtomispDevice (CAPTURE_DEVICE_STILL);
@@ -421,6 +442,11 @@
 
     XCAM_ASSERT (isp_processor.ptr ());
     device_manager->add_image_processor (isp_processor);
+    if ((display_mode == DRM_DISPLAY_MODE_PRIMARY) && need_display && (!have_cl_processor)) {
+        cl_csc_proccessor = new CLCscImageProcessor();
+        XCAM_ASSERT (cl_csc_proccessor.ptr ());
+        device_manager->add_image_processor (cl_csc_proccessor);
+    }
 
 #if HAVE_LIBCL
     if (have_cl_processor) {
diff --git a/xcore/Makefile.am b/xcore/Makefile.am
index 722a371..38f0188 100644
--- a/xcore/Makefile.am
+++ b/xcore/Makefile.am
@@ -104,6 +104,7 @@
 	cl_image_handler.cpp     \
 	cl_image_processor.cpp   \
 	cl_3a_image_processor.cpp      \
+	cl_csc_image_processor.cpp    \
 	cl_3a_stats_calculator.cpp     \
 	cl_demo_handler.cpp      \
 	cl_blc_handler.cpp       \
diff --git a/xcore/cl_csc_handler.cpp b/xcore/cl_csc_handler.cpp
index aab7533..765687d 100644
--- a/xcore/cl_csc_handler.cpp
+++ b/xcore/cl_csc_handler.cpp
@@ -78,7 +78,9 @@
         work_size.global[1] = video_info.height / 2;
         arg_count = 4;
     }
-    else if ((video_info.format == XCAM_PIX_FMT_LAB) || (video_info.format == V4L2_PIX_FMT_RGBA32)) {
+    else if ((video_info.format == XCAM_PIX_FMT_LAB)
+             || (video_info.format == V4L2_PIX_FMT_RGBA32)
+             || (video_info.format == V4L2_PIX_FMT_YUYV)) {
         work_size.global[0] = video_info.width;
         work_size.global[1] = video_info.height;
         arg_count = 2;
@@ -102,6 +104,7 @@
         _output_format = XCAM_PIX_FMT_LAB;
         break;
     case CL_CSC_TYPE_RGBA64TORGBA:
+    case CL_CSC_TYPE_YUYVTORGBA:
         _output_format = V4L2_PIX_FMT_RGBA32;
         break;
     default:
@@ -165,6 +168,10 @@
 #include "kernel_csc_rgba64torgba.cl"
     XCAM_CL_KERNEL_FUNC_END;
 
+    XCAM_CL_KERNEL_FUNC_SOURCE_BEGIN(kernel_csc_yuyvtorgba)
+#include "kernel_csc_yuyvtorgba.cl"
+    XCAM_CL_KERNEL_FUNC_END;
+
 
     if (type == CL_CSC_TYPE_RGBATONV12) {
         csc_kernel = new CLCscImageKernel (context, "kernel_csc_rgbatonv12");
@@ -178,6 +185,10 @@
         csc_kernel = new CLCscImageKernel (context, "kernel_csc_rgba64torgba");
         ret = csc_kernel->load_from_source (kernel_csc_rgba64torgba_body, strlen (kernel_csc_rgba64torgba_body));
     }
+    else if (type == CL_CSC_TYPE_YUYVTORGBA) {
+        csc_kernel = new CLCscImageKernel (context, "kernel_csc_yuyvtorgba");
+        ret = csc_kernel->load_from_source (kernel_csc_yuyvtorgba_body, strlen (kernel_csc_yuyvtorgba_body));
+    }
 
     XCAM_FAIL_RETURN (
         WARNING,
diff --git a/xcore/cl_csc_handler.h b/xcore/cl_csc_handler.h
index b3dcfe9..98d8ae5 100644
--- a/xcore/cl_csc_handler.h
+++ b/xcore/cl_csc_handler.h
@@ -32,6 +32,7 @@
     CL_CSC_TYPE_RGBATONV12,
     CL_CSC_TYPE_RGBATOLAB,
     CL_CSC_TYPE_RGBA64TORGBA,
+    CL_CSC_TYPE_YUYVTORGBA,
 };
 
 class CLCscImageKernel
diff --git a/xcore/cl_csc_image_processor.cpp b/xcore/cl_csc_image_processor.cpp
new file mode 100644
index 0000000..ee3bbf4
--- /dev/null
+++ b/xcore/cl_csc_image_processor.cpp
@@ -0,0 +1,58 @@
+/*
+ * cl_3a_image_processor.cpp - CL 3A image processor
+ *
+ *  Copyright (c) 2015 Intel Corporation
+ *
+ * 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.
+ *
+ * Author: wangfei <feix.w.wang@intel.com>
+ */
+#include "cl_csc_image_processor.h"
+#include "cl_context.h"
+#include "cl_csc_handler.h"
+
+
+namespace XCam {
+
+CLCscImageProcessor::CLCscImageProcessor ()
+    : CLImageProcessor ("CLCscImageProcessor")
+{
+    XCAM_LOG_DEBUG ("CLCscImageProcessor constructed");
+}
+
+CLCscImageProcessor::~CLCscImageProcessor ()
+{
+    XCAM_LOG_DEBUG ("CLCscImageProcessor destructed");
+}
+
+XCamReturn
+CLCscImageProcessor::create_handlers ()
+{
+    SmartPtr<CLImageHandler> image_handler;
+    SmartPtr<CLContext> context = get_cl_context ();
+
+    XCAM_ASSERT (context.ptr ());
+
+    /* color space conversion */
+    image_handler = create_cl_csc_image_handler (context, CL_CSC_TYPE_YUYVTORGBA);
+    _csc = image_handler.dynamic_cast_ptr<CLCscImageHandler> ();
+    XCAM_FAIL_RETURN (
+        WARNING,
+        _csc .ptr (),
+        XCAM_RETURN_ERROR_CL,
+        "CLCscImageProcessor create csc handler failed");
+    add_handler (image_handler);
+    return XCAM_RETURN_NO_ERROR;
+}
+
+};
diff --git a/xcore/cl_csc_image_processor.h b/xcore/cl_csc_image_processor.h
new file mode 100644
index 0000000..f44fdab
--- /dev/null
+++ b/xcore/cl_csc_image_processor.h
@@ -0,0 +1,49 @@
+/*
+ * cl_3a_image_processor.h - CL 3A image processor
+ *
+ *  Copyright (c) 2015 Intel Corporation
+ *
+ * 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.
+ *
+ * Author: wangfei <feix.w.wang@intel.com>
+ */
+
+#ifndef XCAM_CL_CSC_IMAGE_PROCESSOR_H
+#define XCAM_CL_CSC_IMAGE_PROCESSOR_H
+
+#include "xcam_utils.h"
+#include "cl_image_processor.h"
+#include "stats_callback_interface.h"
+
+namespace XCam {
+
+class CLCscImageHandler;
+
+class CLCscImageProcessor
+    : public CLImageProcessor
+{
+
+public:
+    explicit CLCscImageProcessor ();
+    virtual ~CLCscImageProcessor ();
+
+private:
+    virtual XCamReturn create_handlers ();
+    XCAM_DEAD_COPY (CLCscImageProcessor);
+
+private:
+    SmartPtr<CLCscImageHandler>        _csc;
+};
+
+};
+#endif //XCAM_CL_CSC_IMAGE_PROCESSOR_H
diff --git a/xcore/cl_image_processor.cpp b/xcore/cl_image_processor.cpp
index 83afbcd..c8f624e 100644
--- a/xcore/cl_image_processor.cpp
+++ b/xcore/cl_image_processor.cpp
@@ -24,6 +24,7 @@
 #include "drm_display.h"
 #include "cl_demo_handler.h"
 #include "cl_blc_handler.h"
+#include "cl_csc_handler.h"
 
 
 namespace XCam {
diff --git a/xcore/drm_display.cpp b/xcore/drm_display.cpp
index ff709ca..fffd280 100644
--- a/xcore/drm_display.cpp
+++ b/xcore/drm_display.cpp
@@ -48,6 +48,7 @@
     : _module(NULL)
     , _fd (-1)
     , _buf_manager (NULL)
+    , _display_mode (DRM_DISPLAY_MODE_PRIMARY)
     , _crtc_index (-1)
     , _crtc_id (0)
     , _con_id (0)
@@ -133,6 +134,7 @@
         if(_connector->connection == DRM_MODE_CONNECTED) {
             _con_id = res->connectors[i];
             _encoder_id = res->encoders[i];
+            _mode = *_connector->modes;
         }
         drmModeFreeConnector(_connector);
     }
@@ -227,8 +229,8 @@
                      "failed to get plane with required format %s", strerror(errno));
 
     drmModeFreeResources(resource);
-
-    _is_render_inited = true;
+    if (_display_mode ==  DRM_DISPLAY_MODE_OVERLAY)
+        _is_render_inited = true;
     return XCAM_RETURN_NO_ERROR;
 }
 
@@ -323,6 +325,23 @@
 }
 
 XCamReturn
+DrmDisplay::set_crtc (const FB &fb)
+{
+    XCamReturn ret = XCAM_RETURN_NO_ERROR;
+    uint32_t fb_handle = fb.fb_handle;
+    //uint32_t index = fb.index;
+
+    if( !_is_render_inited) {
+        ret = (XCamReturn) drmModeSetCrtc(_fd,  _crtc_id, fb_handle, 0,
+                                          0, &_con_id, 1, &_mode);
+        XCAM_FAIL_RETURN(ERROR, ret == XCAM_RETURN_NO_ERROR, XCAM_RETURN_ERROR_IOCTL,
+                         "failed to set crct via drm: %s", strerror(errno));
+        _is_render_inited = true;
+    }
+    return ret;
+}
+
+XCamReturn
 DrmDisplay::set_plane (const FB &fb)
 {
     XCamReturn ret = XCAM_RETURN_NO_ERROR;
@@ -361,20 +380,37 @@
     XCAM_FAIL_RETURN(ERROR, ret == XCAM_RETURN_NO_ERROR, XCAM_RETURN_ERROR_IOCTL,
                      "failed on page flip: %s", strerror(errno));
 
+    drmEventContext evctx;
+    struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+    fd_set fds;
+    memset(&evctx, 0, sizeof evctx);
+    evctx.version = DRM_EVENT_CONTEXT_VERSION;
+    evctx.vblank_handler = NULL;
+    //evctx.page_flip_handler = page_flip_handler;
+    FD_ZERO(&fds);
+    FD_SET(_fd, &fds);
+    select(_fd + 1, &fds, NULL, NULL, &timeout);
+    drmHandleEvent(_fd, &evctx);
+
     return XCAM_RETURN_NO_ERROR;
 }
 
 XCamReturn
 DrmDisplay::render_buffer(SmartPtr<VideoBuffer> &buf)
 {
+    XCamReturn ret = XCAM_RETURN_NO_ERROR;
     FBMap::iterator iter = _buf_fb_handles.find (buf.ptr ());
     XCAM_FAIL_RETURN(
         ERROR,
         iter != _buf_fb_handles.end (),
         XCAM_RETURN_ERROR_PARAM,
         "buffer not register on framebuf");
-
-    XCamReturn ret = _plane_id ? set_plane(iter->second) : page_flip(iter->second);
+    if(_display_mode == DRM_DISPLAY_MODE_OVERLAY)
+        ret = _plane_id ? set_plane(iter->second) : page_flip(iter->second);
+    else if(_display_mode == DRM_DISPLAY_MODE_PRIMARY) {
+        ret = set_crtc (iter->second);
+        ret = page_flip (iter->second);
+    }
     _display_buf = buf;
 
     return ret;
diff --git a/xcore/drm_display.h b/xcore/drm_display.h
index 609c4da..f0c2b2c 100644
--- a/xcore/drm_display.h
+++ b/xcore/drm_display.h
@@ -50,6 +50,12 @@
 class DrmBoBufferPool;
 class DrmBoBuffer;
 
+enum DrmDisplayMode {
+    DRM_DISPLAY_MODE_NONE = 0,
+    DRM_DISPLAY_MODE_PRIMARY,
+    DRM_DISPLAY_MODE_OVERLAY,
+};
+
 class DrmDisplay {
     friend class DrmBoBufferPool;
     friend class CLBoBufferPool;
@@ -97,6 +103,11 @@
         const enum v4l2_buf_type buf_type);
     SmartPtr<DrmBoBuffer> convert_to_drm_bo_buf (SmartPtr<DrmDisplay> &self, SmartPtr<VideoBuffer> &buf_in);
 
+    bool set_display_mode(DrmDisplayMode mode) {
+        _display_mode = mode;
+        return true;
+    };
+
 private:
     DrmDisplay (const char* module = NULL);
 
@@ -107,6 +118,7 @@
     XCamReturn get_connector(drmModeRes *res);
     XCamReturn get_plane();
     XCamReturn set_plane(const FB &fb);
+    XCamReturn set_crtc(const FB &fb);
     XCamReturn page_flip(const FB &fb);
 
 private:
@@ -115,12 +127,13 @@
     char *_module;
     int _fd;
     drm_intel_bufmgr *_buf_manager;
-
+    DrmDisplayMode _display_mode;
     int _crtc_index;
     unsigned int _crtc_id;
     unsigned int _con_id;
     unsigned int _encoder_id;
     unsigned int _plane_id;
+    drmModeModeInfo _mode;
     drmModeConnector *_connector;
     bool _is_render_inited;