add initial files for exynos driver base
authorBoram Park <boram1288.park@samsung.com>
Wed, 2 Jul 2014 03:48:28 +0000 (12:48 +0900)
committerBoram Park <boram1288.park@samsung.com>
Wed, 2 Jul 2014 07:35:01 +0000 (16:35 +0900)
Change-Id: Ia41b04770b5fc912223d2ae781baea6fc9b573eb

59 files changed:
Makefile.am
autogen.sh
configure.ac
lib/exynos_drv.so [deleted file]
man/Makefile.am [new file with mode: 0644]
man/exynos.man [new file with mode: 0644]
packaging/xf86-video-exynos.spec [deleted file]
src/Makefile.am [new file with mode: 0644]
src/accel/sec_accel.h [new file with mode: 0644]
src/accel/sec_dri2.c [new file with mode: 0644]
src/accel/sec_exa.c [new file with mode: 0644]
src/accel/sec_exa_g2d.c [new file with mode: 0644]
src/accel/sec_exa_sw.c [new file with mode: 0644]
src/crtcconfig/sec_crtc.c [new file with mode: 0644]
src/crtcconfig/sec_crtc.h [new file with mode: 0644]
src/crtcconfig/sec_display.c [new file with mode: 0644]
src/crtcconfig/sec_display.h [new file with mode: 0644]
src/crtcconfig/sec_layer.c [new file with mode: 0644]
src/crtcconfig/sec_layer.h [new file with mode: 0644]
src/crtcconfig/sec_output.c [new file with mode: 0644]
src/crtcconfig/sec_output.h [new file with mode: 0644]
src/crtcconfig/sec_plane.c [new file with mode: 0644]
src/crtcconfig/sec_plane.h [new file with mode: 0644]
src/crtcconfig/sec_prop.c [new file with mode: 0644]
src/crtcconfig/sec_prop.h [new file with mode: 0644]
src/crtcconfig/sec_xberc.c [new file with mode: 0644]
src/crtcconfig/sec_xberc.h [new file with mode: 0644]
src/debug/sec_drmmode_dump.c [new file with mode: 0644]
src/debug/sec_drmmode_dump.h [new file with mode: 0644]
src/g2d/fimg2d.c [new file with mode: 0644]
src/g2d/fimg2d.h [new file with mode: 0644]
src/g2d/fimg2d_reg.h [new file with mode: 0644]
src/g2d/util_g2d.c [new file with mode: 0644]
src/ipp/sec_converter.c [new file with mode: 0644]
src/ipp/sec_converter.h [new file with mode: 0644]
src/ipp/sec_drm_ipp.c [new file with mode: 0644]
src/ipp/sec_drm_ipp.h [new file with mode: 0644]
src/ipp/sec_wb.c [new file with mode: 0644]
src/ipp/sec_wb.h [new file with mode: 0644]
src/memory/sec_memory_flush.c [new file with mode: 0644]
src/memory/sec_memory_flush.h [new file with mode: 0644]
src/neon/copy_area.c [new file with mode: 0644]
src/neon/memcpy_neon.s [new file with mode: 0644]
src/neon/neonmem.h [new file with mode: 0644]
src/sec.c [new file with mode: 0644]
src/sec.h [new file with mode: 0644]
src/util/sec_util.c [new file with mode: 0644]
src/util/sec_util.h [new file with mode: 0644]
src/xv/sec_video.c [new file with mode: 0644]
src/xv/sec_video.h [new file with mode: 0644]
src/xv/sec_video_display.c [new file with mode: 0644]
src/xv/sec_video_display.h [new file with mode: 0644]
src/xv/sec_video_fourcc.h [new file with mode: 0644]
src/xv/sec_video_tvout.c [new file with mode: 0644]
src/xv/sec_video_tvout.h [new file with mode: 0644]
src/xv/sec_video_types.h [new file with mode: 0644]
src/xv/sec_video_virtual.c [new file with mode: 0644]
src/xv/sec_video_virtual.h [new file with mode: 0644]
src/xv/xv_types.h [new file with mode: 0644]

index 3d1efd3..bdeb5b7 100644 (file)
@@ -1,3 +1,22 @@
-exynos_drvdir = @moduledir@/drivers
-exynos_drv_DATA = $(top_srcdir)/lib/exynos_drv.so
+#  Copyright 2005 Adam Jackson.
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  on the rights to use, copy, modify, merge, publish, distribute, sub
+#  license, and/or sell copies of the Software, and to permit persons to whom
+#  the Software is furnished to do so, subject to the following conditions:
+#
+#  The above copyright notice and this permission notice (including the next
+#  paragraph) shall be included in all copies or substantial portions of the
+#  Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+#  ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+#  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+#  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+AUTOMAKE_OPTIONS = foreign
+SUBDIRS = src 
index 218197d..904cd67 100755 (executable)
@@ -9,4 +9,4 @@ cd $srcdir
 autoreconf -v --install || exit 1
 cd $ORIGDIR || exit $?
 
-#$srcdir/configure --enable-maintainer-mode "$@"
+$srcdir/configure --enable-maintainer-mode "$@"
index 7362082..c161211 100644 (file)
@@ -1,12 +1,8 @@
-#                                               -*- Autoconf -*-
-# Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
-
-# Checks for programs.
-AC_PROG_INSTALL
-AC_PROG_MAKE_SET
+AC_INIT([xf86-video-exynos], 0.2.0,
+        [https://bugs.tizen.org/jira],
+        [xf86-video-exynos])
 
 AC_CONFIG_SRCDIR([Makefile.am])
 AM_CONFIG_HEADER([config.h])
@@ -20,14 +16,77 @@ AM_MAINTAINER_MODE
 AC_DISABLE_STATIC
 AC_PROG_LIBTOOL
 AC_PROG_CC
+AM_PROG_AS
+
+AH_TOP([#include "xorg-server.h"])
 
 AC_ARG_WITH(xorg-module-dir,
             AC_HELP_STRING([--with-xorg-module-dir=DIR],
                            [Default xorg module directory [[default=$libdir/xorg/modules]]]),
-                          [moduledir="$withval"],
-                          [moduledir="$libdir/xorg/modules"])
+                                                  [moduledir="$withval"],
+                                                  [moduledir="$libdir/xorg/modules"])
+
+AC_ARG_ENABLE(pciaccess,
+             AS_HELP_STRING([--enable-pciaccess],
+                             [Enable use of libpciaccess (default: disabled)]),
+                            [PCIACCESS=$enableval], [PCIACCESS=no])
+
+# Checks for extensions
+XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
+XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
+XORG_DRIVER_CHECK_EXT(XV, videoproto)
+
+# Checks for pkg-config packages
+PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.99.901 xproto fontsproto $REQUIRED_MODULES])
+sdkdir=$(pkg-config --variable=sdkdir xorg-server)
+
+# check the conditions
+EXYNOS_CFALGS=""
+EXYNOS_LIBS=""
+
+PKG_CHECK_MODULES(XDBG, xdbg)
+PKG_CHECK_MODULES(DRM, libdrm)
+PKG_CHECK_MODULES(LIBTBM, libtbm)
+PKG_CHECK_MODULES(UDEV, [libudev], [udev=yes], [udev=no])
+if test x"$udev" = xyes; then
+       AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection])
+fi
+
+EXYNOS_CFLAGS="$EXYNOS_CFLAGS $XDBG_CFLAGS"
+EXYNOS_LIBS="$EXYNOS_LIBS $XDBG_LIBS"
 
+EXYNOS_CFLAGS="$EXYNOS_CFLAGS $DRM_CFLAGS $LIBTBM_CFLAGS "
+EXYNOS_LIBS="$EXYNOS_LIBS $DRM_LIBS $LIBTBM_LIBS "
+
+EXYNOS_CFLAGS="$EXYNOS_CFLAGS $UDEV_CFALGS "
+EXYNOS_LIBS="$EXYNOS_LIBS $UDEV_LIBS "
+
+AM_CONDITIONAL(PCIACCESS, [test "x$PCIACCESS" = xyes])
+if test "x$PCIACCESS" = xyes; then
+    AC_DEFINE(PCIACCESS, 1, [Use libpciaccess])
+    PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
+    XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS "
+fi
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_HEADER_STDC
+
+AC_SUBST([EXYNOS_CFLAGS])
+AC_SUBST([EXYNOS_LIBS])
+
+AC_SUBST([XORG_CFLAGS])
 AC_SUBST([moduledir])
 
-AC_CONFIG_FILES([Makefile])
-AC_OUTPUT
+DRIVER_NAME=exynos
+AC_SUBST([DRIVER_NAME])
+
+XORG_MANPAGE_SECTIONS
+XORG_RELEASE_VERSION
+
+AC_OUTPUT([
+       Makefile
+       src/Makefile
+       man/Makefile
+])
diff --git a/lib/exynos_drv.so b/lib/exynos_drv.so
deleted file mode 100755 (executable)
index df4bf86..0000000
Binary files a/lib/exynos_drv.so and /dev/null differ
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644 (file)
index 0000000..bf7ec17
--- /dev/null
@@ -0,0 +1,59 @@
+# $Id$
+#
+# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# 
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation.
+# 
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+# 
+# Except as contained in this notice, the name of the copyright holders shall
+# not be used in advertising or otherwise to promote the sale, use or
+# other dealings in this Software without prior written authorization
+# from the copyright holders.
+# 
+
+drivermandir = $(DRIVER_MAN_DIR)
+
+driverman_PRE = @DRIVER_NAME@.man
+
+driverman_DATA = $(driverman_PRE:man=@DRIVER_MAN_SUFFIX@)
+
+EXTRA_DIST = @DRIVER_NAME@.man
+
+CLEANFILES = $(driverman_DATA)
+
+SED = sed
+
+# Strings to replace in man pages
+XORGRELSTRING = @PACKAGE_STRING@
+  XORGMANNAME = X Version 11
+
+MAN_SUBSTS = \
+       -e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
+       -e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
+       -e 's|__xservername__|Xorg|g' \
+       -e 's|__xconfigfile__|xorg.conf|g' \
+       -e 's|__projectroot__|$(prefix)|g' \
+       -e 's|__appmansuffix__|$(APP_MAN_SUFFIX)|g' \
+       -e 's|__drivermansuffix__|$(DRIVER_MAN_SUFFIX)|g' \
+       -e 's|__adminmansuffix__|$(ADMIN_MAN_SUFFIX)|g' \
+       -e 's|__miscmansuffix__|$(MISC_MAN_SUFFIX)|g' \
+       -e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g'
+
+SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
+
+.man.$(DRIVER_MAN_SUFFIX):
+       sed $(MAN_SUBSTS) < $< > $@
diff --git a/man/exynos.man b/man/exynos.man
new file mode 100644 (file)
index 0000000..aed60ce
--- /dev/null
@@ -0,0 +1,63 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/fbdev/fbdev.man,v 1.2 2001/01/27 18:20:47 dawes Exp $ 
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH FBDEV __drivermansuffix__ __vendorversion__
+.SH NAME
+fbdev \- video driver for framebuffer device
+.SH SYNOPSIS
+.nf
+.B "Section \*qDevice\*q"
+.BI "  Identifier \*q"  devname \*q
+.B  "  Driver \*qfbdev\*q"
+.BI "  BusID  \*qpci:" bus : dev : func \*q
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B fbdev
+is an __xservername__ driver for framebuffer devices.  This is a non-accelerated
+driver, the following framebuffer depths are supported: 8, 15, 16, 24.
+All visual types are supported for depth 8, and TrueColor visual is
+supported for the other depths.  Multi-head configurations are supported.
+.SH SUPPORTED HARDWARE
+The 
+.B fbdev
+driver supports all hardware where a framebuffer driver is available.
+fbdev uses the os-specific submodule fbdevhw(__drivermansuffix__) to talk
+to the kernel
+device driver.  Currently a fbdevhw module is available for linux.
+.SH CONFIGURATION DETAILS
+Please refer to __xconfigfile__(__filemansuffix__) for general configuration
+details.  This section only covers configuration details specific to
+this driver.
+.PP
+For this driver it is not required to specify modes in the screen 
+section of the config file.  The
+.B fbdev
+driver can pick up the currently used video mode from the framebuffer 
+driver and will use it if there are no video modes configured.
+.PP
+For PCI boards you might have to add a BusID line to the Device
+section.  See above for a sample line.  You can use \*q\__xservername__
+-scanpci\*q
+to figure out the correct values.
+.PP
+The following driver 
+.B Options
+are supported:
+.TP
+.BI "Option \*qfbdev\*q \*q" string \*q
+The framebuffer device to use. Default: /dev/fb0.
+.TP
+.BI "Option \*qShadowFB\*q \*q" boolean \*q
+Enable or disable use of the shadow framebuffer layer.  Default: on.
+.TP
+.BI "Option \*qRotate\*q \*q" string \*q
+Enable rotation of the display. The supported values are "CW" (clockwise,
+90 degrees), "UD" (upside down, 180 degrees) and "CCW" (counter clockwise,
+270 degrees). Implies use of the shadow framebuffer layer.   Default: off.
+.SH "SEE ALSO"
+__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__),
+X(__miscmansuffix__), fbdevhw(__drivermansuffix__)
+.SH AUTHORS
+Authors include: Gerd Knorr, Michel D\(:anzer, Geert Uytterhoeven
diff --git a/packaging/xf86-video-exynos.spec b/packaging/xf86-video-exynos.spec
deleted file mode 100644 (file)
index 90818a8..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-Name:       xf86-video-exynos
-Summary:    X.Org X server driver for exynos
-Version:    0.2.93
-Release:    1
-ExclusiveArch:  %arm
-Group:      System/X Hardware Support
-License:    Samsung
-Source0:    %{name}-%{version}.tar.gz
-
-
-%description
-This package provides the driver for the Samsung display device exynos
-
-
-%prep
-%setup -q
-
-
-%build
-
-%reconfigure
-
-make %{?jobs:-j%jobs}
-
-%install
-rm -rf %{buildroot}
-%make_install
-
-%files
-%defattr(-,root,root,-)
-%{_libdir}/xorg/modules/drivers/*.so
-
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..e293a9a
--- /dev/null
@@ -0,0 +1,71 @@
+AM_CFLAGS = -I@top_srcdir@/src @XORG_CFLAGS@ @EXYNOS_CFLAGS@
+exynos_drv_la_LTLIBRARIES = exynos_drv.la
+#exynos_drv_la_LDFLAGS = -module -avoid-version @EXYNOS_LIBS@
+exynos_drv_la_LDFLAGS = -module -avoid-version
+exynos_drv_la_LIBADD = @EXYNOS_LIBS@
+exynos_drv_ladir = @moduledir@/drivers
+
+# common
+exynos_drv_la_SOURCES = \
+       sec.c
+
+# crtcconfig
+exynos_drv_la_SOURCES += \
+       crtcconfig/sec_crtc.c \
+       crtcconfig/sec_output.c \
+       crtcconfig/sec_plane.c \
+       crtcconfig/sec_layer.c \
+       crtcconfig/sec_prop.c \
+       crtcconfig/sec_xberc.c \
+       crtcconfig/sec_display.c
+AM_CFLAGS += -I@top_srcdir@/src/crtcconfig
+
+# accel
+exynos_drv_la_SOURCES += \
+       accel/sec_exa.c \
+       accel/sec_exa_sw.c \
+       accel/sec_dri2.c
+AM_CFLAGS += -I@top_srcdir@/src/accel
+
+# xv
+exynos_drv_la_SOURCES += \
+       xv/sec_video_tvout.c \
+       xv/sec_video_virtual.c \
+       xv/sec_video_display.c \
+       xv/sec_video.c
+AM_CFLAGS += -I@top_srcdir@/src/xv
+
+# util
+exynos_drv_la_SOURCES += \
+       util/sec_util.c 
+AM_CFLAGS += -I@top_srcdir@/src/util
+
+# debug
+exynos_drv_la_SOURCES += \
+       debug/sec_drmmode_dump.c
+AM_CFLAGS += -I@top_srcdir@/src/debug
+
+# memory flush
+#exynos_drv_la_SOURCES += \
+#      memory/sec_memory_flush.c
+#AM_CFLAGS += -I@top_srcdir@/src/memory
+
+# neon
+exynos_drv_la_SOURCES += \
+       neon/memcpy_neon.s \
+       neon/copy_area.c
+AM_CFLAGS += -I@top_srcdir@/src/neon
+
+# ipp
+exynos_drv_la_SOURCES += \
+       ipp/sec_drm_ipp.c \
+       ipp/sec_converter.c \
+       ipp/sec_wb.c
+AM_CFLAGS += -I@top_srcdir@/src/ipp
+
+# g2d
+exynos_drv_la_SOURCES += \
+        accel/sec_exa_g2d.c \
+        g2d/fimg2d.c \
+        g2d/util_g2d.c
+AM_CFLAGS += -I@top_srcdir@/src/g2d
diff --git a/src/accel/sec_accel.h b/src/accel/sec_accel.h
new file mode 100644 (file)
index 0000000..f9808a3
--- /dev/null
@@ -0,0 +1,155 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef _SEC_ACCEL_H_
+#define _SEC_ACCEL_H_ 1
+
+#include <exa.h>
+#include <dri2.h>
+#include <list.h>
+#include <picture.h>
+#include <xf86drm.h>
+#include <tbm_bufmgr.h>
+#include <damage.h>
+
+#include "sec_layer.h"
+
+/* exa driver private infomation */
+typedef struct _secExaPriv SECExaPriv, *SECExaPrivPtr;
+#define SECEXAPTR(p) ((SECExaPrivPtr)((p)->pExaPriv))
+
+/* pixmap usage hint */
+#define CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK  0x100
+#define CREATE_PIXMAP_USAGE_FB              0x101
+#define CREATE_PIXMAP_USAGE_SUB_FB          0x202
+#define CREATE_PIXMAP_USAGE_DRI2_BACK       0x404
+#define CREATE_PIXMAP_USAGE_XVIDEO          0x808
+
+typedef struct
+{
+    int usage_hint;
+    long size;
+
+    /* buffer object */
+    tbm_bo bo;
+    pointer pPixData;   /*text glyphs or SHM-PutImage*/
+
+    int isFrameBuffer;
+    int isSubFramebuffer;
+
+    SECLayer *ovl_layer;
+
+    /* for exa operation */
+    void* exaOpInfo;
+
+    /* dump count */
+    int dump_cnt;
+
+    /* Last update SBC */
+    XID owner;
+    CARD64 sbc;
+} SECPixmapPriv;
+
+/* exa driver private infomation */
+struct _secExaPriv
+{
+    ExaDriverPtr pExaDriver;
+
+    int flip_backbufs;
+};
+
+/* type of the frame event */
+typedef enum _dri2FrameEventType
+{
+    DRI2_NONE,
+    DRI2_SWAP,
+    DRI2_FLIP,
+    DRI2_BLIT,
+    DRI2_FB_BLIT,
+    DRI2_WAITMSC,
+} DRI2FrameEventType;
+
+/* dri2 frame event information */
+typedef struct _dri2FrameEvent
+{
+    DRI2FrameEventType type;
+    XID drawable_id;
+    unsigned int client_idx;
+    ClientPtr pClient;
+    int frame;
+
+    /* for swaps & flips only */
+    DRI2SwapEventPtr event_complete;
+    void *event_data;
+    DRI2BufferPtr pFrontBuf;
+    DRI2BufferPtr pBackBuf;
+
+    /* pending flip event */
+    int crtc_pipe;
+    void *pCrtc;
+    struct _dri2FrameEvent *pPendingEvent;
+    struct xorg_list crtc_pending_link;
+
+    /* for SwapRegion */
+    RegionPtr pRegion;
+} DRI2FrameEventRec, *DRI2FrameEventPtr;
+
+/**************************************************************************
+ * EXA
+ **************************************************************************/
+/* EXA */
+Bool secExaInit                 (ScreenPtr pScreen);
+void secExaDeinit               (ScreenPtr pScreen);
+Bool secExaPrepareAccess        (PixmapPtr pPix, int index);
+void secExaFinishAccess         (PixmapPtr pPix, int index);
+Bool secExaMigratePixmap        (PixmapPtr pPix, tbm_bo bo);
+void secExaScreenCountFps       (ScreenPtr pScreen); /* count fps */
+void secExaScreenLock           (ScreenPtr pScreen, int enable);
+int  secExaScreenAsyncSwap      (ScreenPtr pScreen, int enable);
+int  secExaScreenSetScrnPixmap  (ScreenPtr pScreen);
+tbm_bo secExaPixmapGetBo    (PixmapPtr pPix);
+
+/* sw EXA */
+Bool secExaSwInit   (ScreenPtr pScreen, ExaDriverPtr pExaDriver);
+void secExaSwDeinit (ScreenPtr pScreen);
+Bool secExaG2dInit   (ScreenPtr pScreen, ExaDriverPtr pExaDriver);
+void secExaG2dDeinit (ScreenPtr pScreen);
+
+
+/**************************************************************************
+ * DRI2
+ **************************************************************************/
+/* DRI2 */
+Bool secDri2Init              (ScreenPtr pScreen);
+void secDri2Deinit            (ScreenPtr pScreen);
+void secDri2FrameEventHandler (unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, void *event_data);
+void secDri2FlipEventHandler  (unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, void *event_data, Bool flip_failed);
+
+#endif /* _SEC_ACCEL_H_ */
diff --git a/src/accel/sec_dri2.c b/src/accel/sec_dri2.c
new file mode 100644 (file)
index 0000000..da3255e
--- /dev/null
@@ -0,0 +1,1987 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2001 VA Linux Systems Inc., Fremont, California.
+Copyright Â© 2002 by David Dawes
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+#include <poll.h>
+
+#include "X11/Xatom.h"
+#include "xorg-server.h"
+#include "xf86.h"
+#include "dri2.h"
+#include "damage.h"
+#include "windowstr.h"
+#include "sec.h"
+#include "sec_accel.h"
+#include "sec_display.h"
+#include "sec_crtc.h"
+#include "sec_util.h"
+#include "sec_crtc.h"
+#include "sec_xberc.h"
+
+#define DRI2_BUFFER_TYPE_WINDOW 0x0
+#define DRI2_BUFFER_TYPE_PIXMAP 0x1
+#define DRI2_BUFFER_TYPE_FB     0x2
+
+typedef union{
+    unsigned int flags;
+    struct {
+        unsigned int type:1;
+        unsigned int is_framebuffer:1;
+        unsigned int is_viewable:1;
+        unsigned int is_reused:1;
+        unsigned int idx_reuse:3;
+    }data;
+}DRI2BufferFlags;
+
+#define DRI2_GET_NEXT_IDX(idx, max) (((idx+1) % (max)))
+
+/* if a window is mapped and realized (viewable) */
+#define IS_VIEWABLE(pDraw) \
+    ((pDraw->type == DRAWABLE_PIXMAP)?TRUE:(Bool)(((WindowPtr) pDraw)->viewable))
+
+/* dri2 buffer private infomation */
+typedef struct _dri2BufferPriv
+{
+    int       refcnt;
+    int       attachment;
+    PixmapPtr pPixmap;
+    ScreenPtr pScreen;
+
+    /* pixmap of the backbuffer */
+    int pipe;
+    Bool canFlip;
+    int num_buf;
+    int avail_idx; /* next available index of the back pixmap, -1 means not to be available */
+    int cur_idx;   /* current index of the back pixmap, -1 means not to be available */
+    int free_idx;  /* free index of the back pixmap, -1 means not to be available */
+    PixmapPtr *pBackPixmaps;
+
+    /* flip buffers */
+    ClientPtr    pClient;
+    DRI2FrameEventPtr pFlipEvent;
+} DRI2BufferPrivRec, *DRI2BufferPrivPtr;
+
+/* prototypes */
+static void SECDri2CopyRegion (DrawablePtr pDraw, RegionPtr pRegion,
+                               DRI2BufferPtr pDstBuf, DRI2BufferPtr pSrcBuf);
+static void SECDri2DestroyBuffer (DrawablePtr pDraw, DRI2BufferPtr pBuf);
+
+static PixmapPtr _initBackBufPixmap     (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip);
+static void      _deinitBackBufPixmap   (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip);
+static void      _exchangeBackBufPixmap (DRI2BufferPtr pBackBuf);
+static PixmapPtr _reuseBackBufPixmap    (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip, int *reues);
+static void      _disuseBackBufPixmap   (DRI2BufferPtr pBackBuf, DRI2FrameEventPtr pEvent);
+
+static unsigned int
+_getName (PixmapPtr pPix)
+{
+    SECPixmapPriv *pExaPixPriv = NULL;
+
+    if (pPix == NULL)
+        return 0;
+
+    pExaPixPriv = exaGetPixmapDriverPrivate (pPix);
+    if (pExaPixPriv == NULL)
+        return 0;
+
+    if (pExaPixPriv->bo == NULL)
+    {
+        if(pExaPixPriv->isFrameBuffer)
+            return (unsigned int)ROOT_FB_ADDR;
+        else
+            return 0;
+    }
+
+    return tbm_bo_export (pExaPixPriv->bo);
+}
+
+/* initialize the pixmap of the backbuffer */
+static PixmapPtr
+_initBackBufPixmap (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR(pScrn);
+    SECExaPrivPtr pExaPriv = SECEXAPTR (pSec);
+    DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate;
+    unsigned int usage_hint = CREATE_PIXMAP_USAGE_DRI2_BACK;
+    PixmapPtr pPixmap = NULL;
+    int pipe = -1;
+
+    /* if a drawable can be flip, check whether the flip buffer is available */
+    if (canFlip)
+    {
+        usage_hint = CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK;
+        pipe = secDisplayDrawablePipe (pDraw);
+        if (pipe != -1)
+        {
+            /* get the flip pixmap from crtc */
+            pPixmap = secCrtcGetFreeFlipPixmap (pScrn, pipe, pDraw, usage_hint);
+            if (!pPixmap)
+            {
+                /* fail to get a  flip pixmap from crtc */
+                canFlip = FALSE;
+                XDBG_WARNING(MDRI2, "fail to get a  flip pixmap from crtc\n");
+            }
+        }
+        else
+        {
+            /* pipe is -1 */
+            canFlip = FALSE;
+            XDBG_WARNING(MDRI2, "pipe is -1");
+        }
+    }
+
+    /* if canflip is false, get the dri2_back pixmap */
+    if (!canFlip)
+    {
+        pPixmap = (*pScreen->CreatePixmap) (pScreen,
+                                            pDraw->width,
+                                            pDraw->height,
+                                            pDraw->depth,
+                                            usage_hint);
+        XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL);
+#if USE_XDBG
+        xDbgLogPListDrawAddRefPixmap (pDraw, pPixmap);
+#endif
+    }
+
+    if (canFlip)
+    {
+        pBackBufPriv->num_buf = pExaPriv->flip_backbufs;
+        pBackBufPriv->pBackPixmaps = calloc (pBackBufPriv->num_buf, sizeof (void*));
+    }
+    else
+    {
+        pBackBufPriv->num_buf = 1; /* num of backbuffer for swap/blit */
+        pBackBufPriv->pBackPixmaps = calloc (pBackBufPriv->num_buf, sizeof (void*));
+    }
+
+    pBackBufPriv->pBackPixmaps[0] = pPixmap;
+    pBackBufPriv->canFlip = canFlip;
+    pBackBufPriv->avail_idx = 0;
+    pBackBufPriv->free_idx = 0;
+    pBackBufPriv->cur_idx = 0;
+    pBackBufPriv->pipe = pipe;
+
+    return pPixmap;
+}
+
+/* deinitialize the pixmap of the backbuffer */
+static void
+_deinitBackBufPixmap (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip)
+{
+    DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate;
+    ScreenPtr pScreen = pBackBufPriv->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    int i;
+    int pipe = -1;
+
+    for (i = 0; i < pBackBufPriv->num_buf; i++)
+    {
+        if (pBackBufPriv->pBackPixmaps)
+        {
+            if(pBackBufPriv->pBackPixmaps[i])
+            {
+                if (canFlip)
+                {
+                    /* have to release the flip pixmap */
+                    pipe = pBackBufPriv->pipe;
+                    if (pipe != -1)
+                        secCrtcRelAllFlipPixmap (pScrn, pipe);
+                    else
+                        XDBG_WARNING(MDRI2, "pipe is -1\n");
+                }
+                else
+                {
+#if USE_XDBG
+                    xDbgLogPListDrawRemoveRefPixmap (pDraw, pBackBufPriv->pBackPixmaps[i]);
+#endif
+                    (*pScreen->DestroyPixmap) (pBackBufPriv->pBackPixmaps[i]);
+            }
+                pBackBufPriv->pBackPixmaps[i] = NULL;
+                pBackBufPriv->pPixmap = NULL;
+            }
+            free(pBackBufPriv->pBackPixmaps);
+            pBackBufPriv->pBackPixmaps = NULL;
+        }
+    }
+}
+
+/* increase the next available index of the backbuffer */
+static void
+_exchangeBackBufPixmap (DRI2BufferPtr pBackBuf)
+{
+    DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate;
+
+     /* increase avail_idx when buffers exchange */
+    pBackBufPriv->avail_idx = DRI2_GET_NEXT_IDX(pBackBufPriv->avail_idx, pBackBufPriv->num_buf);
+}
+
+/* return the next available pixmap of the backbuffer */
+static PixmapPtr
+_reuseBackBufPixmap (DRI2BufferPtr pBackBuf, DrawablePtr pDraw, Bool canFlip, int *reues)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate;
+    PixmapPtr pPixmap = NULL;
+    int avail_idx = pBackBufPriv->avail_idx;
+    unsigned int usage_hint = CREATE_PIXMAP_USAGE_DRI2_BACK;
+    int pipe = -1;
+
+    if (pBackBufPriv->canFlip != canFlip)
+    {
+        /* flip buffer -> swap buffer */
+        if (pBackBufPriv->canFlip && !canFlip)
+        {
+            /* return the next available pixmap */
+            _deinitBackBufPixmap (pBackBuf, pDraw, pBackBufPriv->canFlip);
+            pPixmap = _initBackBufPixmap(pBackBuf, pDraw, canFlip);
+            XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL);
+            return pPixmap;
+        }
+
+        /* swap buffer -> flip buffer */
+        if (!pBackBufPriv->canFlip && canFlip)
+        {
+            pipe = secDisplayDrawablePipe (pDraw);
+            if (pipe != -1)
+            {
+                /* return the next available pixmap */
+                _deinitBackBufPixmap (pBackBuf, pDraw, pBackBufPriv->canFlip);
+                pPixmap = _initBackBufPixmap(pBackBuf, pDraw, canFlip);
+                XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL);
+                return pPixmap;
+            }
+            else
+            {
+                canFlip = FALSE;
+                XDBG_WARNING (MDRI2, "pipe is -1\n");
+            }
+        }
+    }
+
+    /* set the next available pixmap */
+    /* if pBackPixmap is available, reuse it */
+    if (pBackBufPriv->pBackPixmaps[avail_idx])
+    {
+        if (canFlip)
+        {
+            usage_hint = CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK;
+            pipe = secDisplayDrawablePipe (pDraw);
+            if (pipe != -1)
+            {
+                if (avail_idx != pBackBufPriv->cur_idx)
+                {
+                    /* get the flip pixmap from crtc */
+                    pBackBufPriv->pBackPixmaps[avail_idx] = secCrtcGetFreeFlipPixmap (pScrn, pipe, pDraw, usage_hint);
+                    if (!pBackBufPriv->pBackPixmaps[avail_idx])
+                    {
+                        /* fail to get a  flip pixmap from crtc */
+                        XDBG_WARNING(MDRI2, "@@[reuse]: draw(0x%x) fail to get a flip pixmap from crtc to reset the index of pixmap\n",
+                                     (unsigned int)pDraw->id);
+
+                        _deinitBackBufPixmap (pBackBuf, pDraw, pBackBufPriv->canFlip);
+                        pPixmap = _initBackBufPixmap(pBackBuf, pDraw, FALSE);
+                        XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL);
+                        *reues = 0;
+                        return pPixmap;
+                    }
+                    pBackBufPriv->cur_idx = avail_idx;
+                }
+             }
+             else
+             {
+                 XDBG_WARNING (MDRI2, "pipe is -1(%d)\n", pipe);
+                 return NULL;
+             }
+        }
+        else
+        {
+            if (avail_idx != pBackBufPriv->cur_idx)
+            {
+                pBackBufPriv->cur_idx = avail_idx;
+            }
+        }
+
+        *reues = 1;
+    }
+    else
+    {
+        if (canFlip)
+        {
+            usage_hint = CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK;
+            pipe = secDisplayDrawablePipe (pDraw);
+            if (pipe != -1)
+            {
+                if (avail_idx != pBackBufPriv->cur_idx)
+                {
+                     /* get the flip pixmap from crtc */
+                    pBackBufPriv->pBackPixmaps[avail_idx] = secCrtcGetFreeFlipPixmap (pScrn, pipe, pDraw, usage_hint);
+                    if (!pBackBufPriv->pBackPixmaps[avail_idx])
+                    {
+                        /* fail to get a  flip pixmap from crtc */
+                        XDBG_WARNING(MDRI2, "@@[initial set]: draw(0x%x) fail to get a flip pixmap from crtc to generate and to set the next available pixmap.\n",
+                                     (unsigned int)pDraw->id);
+
+                        _deinitBackBufPixmap (pBackBuf, pDraw, TRUE);
+                        pPixmap = _initBackBufPixmap(pBackBuf, pDraw, FALSE);
+                        XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL);
+                        *reues = 0;
+                        return pPixmap;
+                    }
+                    pBackBufPriv->cur_idx = avail_idx;
+                }
+            }
+        }
+        else
+        {
+            if (avail_idx != pBackBufPriv->cur_idx)
+            {
+
+                pBackBufPriv->pBackPixmaps[avail_idx] = (*pScreen->CreatePixmap) (pScreen,
+                        pDraw->width,
+                        pDraw->height,
+                        pDraw->depth,
+                        usage_hint);
+                XDBG_RETURN_VAL_IF_FAIL(pBackBufPriv->pBackPixmaps[avail_idx] != NULL, NULL);
+                pBackBufPriv->cur_idx = avail_idx;
+#if USE_XDBG
+                xDbgLogPListDrawAddRefPixmap (pDraw, pPixmap);
+#endif
+            }
+        }
+
+        *reues = 0;
+    }
+    pPixmap = pBackBufPriv->pBackPixmaps[avail_idx];
+
+    pBackBufPriv->canFlip = canFlip;
+
+    return pPixmap;
+}
+
+static void
+_disuseBackBufPixmap (DRI2BufferPtr pBackBuf, DRI2FrameEventPtr pEvent)
+{
+    DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate;
+    ScreenPtr pScreen = pBackBufPriv->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+    if (pEvent->type == DRI2_FLIP)
+    {
+        secCrtcRelFlipPixmap (pScrn, pEvent->crtc_pipe,
+                pBackBufPriv->pBackPixmaps[pBackBufPriv->free_idx]);
+
+        /* increase free_idx when buffers destory or when frame is deleted */
+        pBackBufPriv->free_idx = DRI2_GET_NEXT_IDX(pBackBufPriv->free_idx, pBackBufPriv->num_buf);
+    }
+}
+
+static void
+_setDri2Property (DrawablePtr pDraw)
+{
+    if(pDraw->type == DRAWABLE_WINDOW)
+    {
+        static Atom atom_use_dri2= 0;
+        static int use = 1;
+
+        if(!atom_use_dri2)
+        {
+            atom_use_dri2 = MakeAtom ("X_WIN_USE_DRI2", 14, TRUE);
+        }
+
+        dixChangeWindowProperty (serverClient,
+                                 (WindowPtr)pDraw, atom_use_dri2, XA_CARDINAL, 32,
+                                 PropModeReplace, 1, &use, TRUE);
+    }
+}
+
+static unsigned int
+_getBufferFlag (DrawablePtr pDraw, Bool canFlip)
+{
+    DRI2BufferFlags flag;
+    flag.flags = 0;
+
+    switch (pDraw->type)
+    {
+    case DRAWABLE_WINDOW:
+        flag.data.type = DRI2_BUFFER_TYPE_WINDOW;
+        break;
+    case DRAWABLE_PIXMAP:
+        flag.data.type = DRI2_BUFFER_TYPE_PIXMAP;
+        break;
+    }
+
+    if (IS_VIEWABLE(pDraw))
+    {
+        flag.data.is_viewable = 1;
+    }
+
+    if (canFlip)
+    {
+        flag.data.is_framebuffer = 1;
+    }
+
+    return flag.flags;
+}
+
+static inline PixmapPtr
+_getPixmapFromDrawable (DrawablePtr pDraw)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    PixmapPtr pPix;
+
+    if (pDraw->type == DRAWABLE_WINDOW)
+        pPix = (*pScreen->GetWindowPixmap) ((WindowPtr) pDraw);
+    else
+        pPix = (PixmapPtr) pDraw;
+
+    return pPix;
+}
+
+/* Can this drawable be page flipped? */
+static Bool
+_canFlip (DrawablePtr pDraw)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR(pScrn);
+    WindowPtr pWin, pRoot;
+    PixmapPtr pWinPixmap, pRootPixmap;
+    int ret;
+
+    if (pDraw->type == DRAWABLE_PIXMAP)
+        return FALSE;
+
+    pRoot = pScreen->root;
+    pRootPixmap = pScreen->GetWindowPixmap (pRoot);
+    pWin = (WindowPtr) pDraw;
+    pWinPixmap = pScreen->GetWindowPixmap (pWin);
+    if (pRootPixmap != pWinPixmap)
+        return FALSE;
+
+    if (!IS_VIEWABLE(pDraw))
+        return FALSE;
+
+    ret = secFbFindBo(pSec->pFb,
+                      pDraw->x, pDraw->y, pDraw->width, pDraw->height,
+                      NULL, NULL);
+    if (ret != rgnSAME)
+        return FALSE;
+
+    return TRUE;
+}
+
+static DRI2FrameEventType
+_getSwapType (DrawablePtr pDraw, DRI2BufferPtr pFrontBuf,
+              DRI2BufferPtr pBackBuf)
+{
+    DRI2BufferPrivPtr pFrontBufPriv;
+    DRI2BufferPrivPtr pBackBufPriv;
+    PixmapPtr pFrontPix;
+    PixmapPtr pBackPix;
+    SECPixmapPriv *pFrontExaPixPriv = NULL;
+    SECPixmapPriv *pBackExaPixPriv = NULL;
+    DRI2FrameEventType swap_type = DRI2_NONE;
+
+    if (!pFrontBuf || !pBackBuf)
+        return DRI2_NONE;
+
+    /* if a buffer is not viewable at DRI2GetBuffers, return none */
+    if (!IS_VIEWABLE(pDraw))
+    {
+        //XDBG_WARNING(MDRI2, "DRI2_NONE: window is not viewable.(%d,%d)\n", pDraw->width, pDraw->height);
+        return DRI2_NONE;
+    }
+
+    pFrontBufPriv = pFrontBuf->driverPrivate;
+    pBackBufPriv = pBackBuf->driverPrivate;
+    pFrontPix = pFrontBufPriv->pPixmap;
+    pBackPix = pBackBufPriv->pPixmap;
+    if (!pFrontPix || !pBackPix)
+    {
+        XDBG_WARNING(MDRI2, "Warning: pFrontPix or pBackPix is null.(DRI2_NONE)\n");
+        return DRI2_NONE;
+    }
+
+    pFrontExaPixPriv = exaGetPixmapDriverPrivate (pFrontBufPriv->pPixmap);
+    pBackExaPixPriv = exaGetPixmapDriverPrivate (pBackBufPriv->pPixmap);
+    if (!pFrontExaPixPriv || !pBackExaPixPriv)
+    {
+        XDBG_WARNING(MDRI2, "Warning: pFrontPixPriv or pBackPixPriv is null.(DRI2_NONE)\n");
+        return DRI2_NONE;
+    }
+
+
+    /* Check Exchange */
+    if (pFrontBufPriv->canFlip == 1)
+    {
+        if(pBackBufPriv->canFlip == 1)
+        {
+            swap_type = DRI2_FLIP;
+
+            if (!_canFlip(pDraw))
+            {
+                ErrorF ("@@@ [%10.3f] %lx : flip to blit\n", GetTimeInMillis()/1000.0, pDraw->id);
+                swap_type = DRI2_BLIT;
+            }
+        }
+        else
+        {
+            XDBG_WARNING (MDRI2, "DRI2_FB_BLIT: Front(%d) Back(%d) \n",
+                          pFrontBufPriv->canFlip, pBackBufPriv->canFlip);
+            swap_type = DRI2_FB_BLIT;
+        }
+    }
+    else
+    {
+        if (pFrontExaPixPriv->isFrameBuffer == 1)
+        {
+            //XDBG_WARNING (MDRI2, "DRI2_FB_BLIT: Front(%d) Back(%d) : front is framebuffer \n",
+            //               pFrontBufPriv->canFlip, pBackBufPriv->canFlip);
+            swap_type = DRI2_FB_BLIT;
+        }
+        else
+        {
+            if (pFrontPix->drawable.width == pBackPix->drawable.width &&
+                pFrontPix->drawable.height == pBackPix->drawable.height &&
+                pFrontPix->drawable.bitsPerPixel == pBackPix->drawable.bitsPerPixel)
+            {
+                swap_type = DRI2_SWAP;
+            }
+            else
+            {
+                swap_type = DRI2_BLIT;
+            }
+        }
+    }
+
+    return swap_type;
+}
+
+static void
+_referenceBufferPriv (DRI2BufferPtr pBuf)
+{
+    if (pBuf)
+    {
+        DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate;
+        pBufPriv->refcnt++;
+    }
+}
+
+static void
+_unreferenceBufferPriv (DRI2BufferPtr pBuf)
+{
+    if (pBuf)
+    {
+        DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate;
+        pBufPriv->refcnt--;
+    }
+}
+
+static Bool
+_resetBufPixmap (DrawablePtr pDraw, DRI2BufferPtr pBuf)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate;
+    PixmapPtr pPix = NULL, pNewPix=NULL, pOldPix=NULL;
+    Bool canFlip = FALSE;
+    int reuse = 0;
+
+    canFlip = _canFlip (pDraw);
+
+    if (pBufPriv->attachment == DRI2BufferFrontLeft)
+    {
+        pPix = _getPixmapFromDrawable (pDraw);
+        if (pPix != pBufPriv->pPixmap ||
+            ((DRI2BufferFlags)pBuf->flags).data.is_viewable != IS_VIEWABLE(pDraw))
+        {
+            pOldPix = pBufPriv->pPixmap;
+
+            /* reset the pixmap and the name of the buffer */
+            pNewPix = _getPixmapFromDrawable (pDraw);
+            pPix->refcnt++;
+            pBufPriv->canFlip = canFlip;
+
+            /* Destroy Old buffer */
+            if (pOldPix)
+            {
+                (*pScreen->DestroyPixmap) (pOldPix);
+            }
+        }
+        else
+        {
+            pBufPriv->canFlip = canFlip;
+            return FALSE;
+        }
+    }
+    else
+    {
+        pNewPix = _reuseBackBufPixmap(pBuf, pDraw, canFlip, &reuse);
+        if (pNewPix == NULL)
+        {
+            XDBG_WARNING (MDRI2, "Error pixmap is null\n", pipe);
+            return FALSE;
+        }
+
+        if (reuse)
+        {
+            pBufPriv->pPixmap = pNewPix;
+            return FALSE;
+        }
+    }
+
+    pBufPriv->pPixmap = pNewPix;
+
+    pBuf->name = _getName (pNewPix);
+    pBuf->flags = _getBufferFlag(pDraw, canFlip);
+
+    XDBG_TRACE (MDRI2,"id:0x%x(%d) can_flip:%d attach:%d, name:%d, flags:0x%x geo(%dx%d+%d+%d)\n",
+                pDraw->id, pDraw->type,
+                pBufPriv->canFlip,
+                pBuf->attachment, pBuf->name, pBuf->flags,
+                pDraw->width, pDraw->height, pDraw->x, pDraw->y);
+
+    return TRUE;
+}
+
+static void
+_generateDamage (DrawablePtr pDraw, DRI2FrameEventPtr pFrameEvent)
+{
+    BoxRec box;
+    RegionRec region;
+
+    if (pFrameEvent->pRegion)
+    {
+        /* translate the regions with drawable */
+        BoxPtr pBox = RegionRects(pFrameEvent->pRegion);
+        int nBox = RegionNumRects(pFrameEvent->pRegion);
+
+        while (nBox--)
+        {
+            box.x1 = pBox->x1;
+            box.y1 = pBox->y1;
+            box.x2 = pBox->x2;
+            box.y2 = pBox->y2;
+           XDBG_DEBUG(MDRI2,"Damage Region[%d]: (x1, y1, x2, y2) = (%d,%d,%d,%d) \n ",
+                   nBox, box.x1, box.x2, box.y1, box.y2);
+            RegionInit (&region, &box, 0);
+            DamageDamageRegion (pDraw, &region);
+            pBox++;
+        }
+    }
+    else
+    {
+
+        box.x1 = pDraw->x;
+        box.y1 = pDraw->y;
+        box.x2 = box.x1 + pDraw->width;
+        box.y2 = box.y1 + pDraw->height;
+        RegionInit (&region, &box, 0);
+        DamageDamageRegion (pDraw, &region);
+    }
+}
+
+static void
+_blitBuffers (DrawablePtr pDraw, DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf)
+{
+    BoxRec box;
+    RegionRec region;
+
+    box.x1 = 0;
+    box.y1 = 0;
+    box.x2 = pDraw->width;
+    box.y2 = pDraw->height;
+    REGION_INIT (pScreen, &region, &box, 0);
+
+    SECDri2CopyRegion (pDraw, &region, pFrontBuf, pBackBuf);
+}
+
+static void
+_exchangeBuffers (DrawablePtr pDraw, DRI2FrameEventType type,
+                  DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+    DRI2BufferPrivPtr pFrontBufPriv = pFrontBuf->driverPrivate;
+    DRI2BufferPrivPtr pBackBufPriv = pBackBuf->driverPrivate;
+    SECPixmapPriv *pFrontExaPixPriv = exaGetPixmapDriverPrivate (pFrontBufPriv->pPixmap);
+    SECPixmapPriv *pBackExaPixPriv = exaGetPixmapDriverPrivate (pBackBufPriv->pPixmap);
+
+    if(pFrontBufPriv->canFlip != pBackBufPriv->canFlip)
+    {
+        XDBG_WARNING (MDRI2, "Cannot exchange buffer(0x%x): Front(%d, canFlip:%d), Back(%d, canFlip:%d)\n",
+                      (unsigned int)pDraw->id, pFrontBuf->name, pFrontBufPriv->canFlip,
+                      pBackBuf->name, pBackBufPriv->canFlip);
+
+        return;
+    }
+
+    /* exchange the buffers
+     * 1. exchange the bo of the exa pixmap private
+     * 2. get the name of the front buffer (the name of the back buffer will get next DRI2GetBuffers.)
+     */
+    if (pFrontBufPriv->canFlip)
+    {
+        XDBG_RETURN_IF_FAIL(NULL != secFbSwapBo(pSec->pFb, pBackExaPixPriv->bo));
+        pFrontBuf->name = _getName (pFrontBufPriv->pPixmap);
+    }
+    else
+    {
+        tbm_bo_swap(pFrontExaPixPriv->bo, pBackExaPixPriv->bo);
+        pFrontBuf->name = _getName (pFrontBufPriv->pPixmap);
+    }
+
+    /*Exchange pixmap owner and sbc*/
+    {
+        XID owner;
+        CARD64 sbc;
+
+        owner = pFrontExaPixPriv->owner;
+        sbc = pFrontExaPixPriv->sbc;
+
+        pFrontExaPixPriv->owner = pBackExaPixPriv->owner;
+        pFrontExaPixPriv->sbc = pBackExaPixPriv->sbc;
+
+        pBackExaPixPriv->owner = owner;
+        pBackExaPixPriv->sbc = sbc;
+    }
+
+    /* exchange the index of the available buffer*/
+    _exchangeBackBufPixmap(pBackBuf);
+}
+
+static DRI2FrameEventPtr
+_newFrame (ClientPtr pClient, DrawablePtr pDraw,
+           DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf,
+           DRI2SwapEventPtr swap_func, void *data, RegionPtr pRegion)
+{
+    DRI2FrameEventPtr pFrameEvent = NULL;
+    DRI2FrameEventType swap_type = DRI2_NONE;
+
+    /* check and get the swap_type */
+    swap_type = _getSwapType (pDraw, pFrontBuf, pBackBuf);
+    if (swap_type == DRI2_NONE)
+        return NULL;
+
+    pFrameEvent = calloc (1, sizeof (DRI2FrameEventRec));
+    if (!pFrameEvent)
+        return NULL;
+
+    pFrameEvent->type = swap_type;
+    pFrameEvent->drawable_id = pDraw->id;
+    pFrameEvent->client_idx = pClient->index;
+    pFrameEvent->pClient = pClient;
+    pFrameEvent->event_complete = swap_func;
+    pFrameEvent->event_data = data;
+    pFrameEvent->pFrontBuf = pFrontBuf;
+    pFrameEvent->pBackBuf = pBackBuf;
+
+    if (pRegion)
+    {
+        pFrameEvent->pRegion = RegionCreate(RegionExtents(pRegion),
+                                            RegionNumRects(pRegion));
+        if (!RegionCopy(pFrameEvent->pRegion, pRegion))
+        {
+            RegionDestroy(pFrameEvent->pRegion);
+            pFrameEvent->pRegion = NULL;
+        }
+    }
+    else
+    {
+        pFrameEvent->pRegion = NULL;
+    }
+
+    _referenceBufferPriv (pFrontBuf);
+    _referenceBufferPriv (pBackBuf);
+
+    return pFrameEvent;
+}
+
+static void
+_swapFrame (DrawablePtr pDraw, DRI2FrameEventPtr pFrameEvent)
+{
+    switch (pFrameEvent->type)
+    {
+    case DRI2_FLIP:
+        _generateDamage (pDraw, pFrameEvent);
+        break;
+    case DRI2_SWAP:
+        _exchangeBuffers (pDraw, pFrameEvent->type,
+                          pFrameEvent->pFrontBuf, pFrameEvent->pBackBuf);
+        _generateDamage (pDraw, pFrameEvent);
+        break;
+    case DRI2_BLIT:
+    case DRI2_FB_BLIT:
+        /* copy the region from back buffer to front buffer */
+        _blitBuffers (pDraw, pFrameEvent->pFrontBuf, pFrameEvent->pBackBuf);
+        break;
+    default:
+        /* Unknown type */
+        XDBG_WARNING (MDRI2, "%s: unknown swap_type received\n", __func__);
+        _generateDamage (pDraw, pFrameEvent);
+        break;
+    }
+}
+
+static void
+_deleteFrame (DrawablePtr pDraw, DRI2FrameEventPtr pEvent)
+{
+    /* some special case */
+    DRI2BufferPrivPtr pFrontBufPriv;
+    DRI2BufferPrivPtr pBackBufPriv;
+
+    if (pEvent->pBackBuf && pEvent->pFrontBuf)
+    {
+        pFrontBufPriv = pEvent->pFrontBuf->driverPrivate;
+        pBackBufPriv = pEvent->pBackBuf->driverPrivate;
+
+        /*
+        * Even though pFrontBufPriv->canFlip and pBackBufPriv->canFlip is 1, pEvent->type can have DRI2_BLIT.
+        * When it requests SECDri2ScheduleSwapWithRegion(), _canFlip(pDraw) is FALSE. So it has DRI2_BLIT type.
+        * In this case we should change pEvent->type to DRI2_FLIP. So we can call secCrtcRelFlipPixmap() for pEvent->pBackBuf
+        */
+        if( (pFrontBufPriv->canFlip == 1) && (pBackBufPriv->canFlip == 1) )
+        {
+            pEvent->type = DRI2_FLIP;
+        }
+    }
+
+    if (pEvent->pBackBuf)
+    {
+        /* disuse the backbuffer */
+        _disuseBackBufPixmap(pEvent->pBackBuf, pEvent);
+
+        SECDri2DestroyBuffer (pDraw, pEvent->pBackBuf);
+    }
+
+    if (pEvent->pFrontBuf)
+    {
+        SECDri2DestroyBuffer (pDraw, pEvent->pFrontBuf);
+    }
+
+    if (pEvent->pRegion)
+    {
+        RegionDestroy(pEvent->pRegion);
+    }
+
+    free (pEvent);
+    pEvent = NULL;
+}
+
+static void
+_asyncSwapBuffers (ClientPtr pClient, DrawablePtr pDraw, DRI2FrameEventPtr pFrameEvent)
+{
+    XDBG_DEBUG(MDRI2,"id:0x%x(%d) Client:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n",
+               (unsigned int)pDraw->id, pDraw->type,
+               pClient->index,
+               pFrameEvent->pFrontBuf->attachment, pFrameEvent->pFrontBuf->name, pFrameEvent->pFrontBuf->flags,
+               pFrameEvent->pBackBuf->attachment, pFrameEvent->pBackBuf->name, pFrameEvent->pBackBuf->flags);
+
+    _swapFrame (pDraw, pFrameEvent);
+
+    switch (pFrameEvent->type)
+    {
+    case DRI2_SWAP:
+        DRI2SwapComplete (pClient, pDraw, 0, 0, 0,
+                          DRI2_EXCHANGE_COMPLETE,
+                          pFrameEvent->event_complete, pFrameEvent->event_data);
+        break;
+    case DRI2_FLIP:
+        _exchangeBuffers (pDraw, pFrameEvent->type, pFrameEvent->pFrontBuf, pFrameEvent->pBackBuf);
+        DRI2SwapComplete (pClient, pDraw, 0, 0, 0,
+                          DRI2_FLIP_COMPLETE,
+                          pFrameEvent->event_complete, pFrameEvent->event_data);
+        break;
+    case DRI2_BLIT:
+    case DRI2_FB_BLIT:
+        DRI2SwapComplete (pClient, pDraw, 0, 0, 0,
+                          DRI2_BLIT_COMPLETE,
+                          pFrameEvent->event_complete, pFrameEvent->event_data);
+        break;
+    default:
+        DRI2SwapComplete (pClient, pDraw, 0, 0, 0,
+                          0,
+                          pFrameEvent->event_complete, pFrameEvent->event_data);
+        break;
+    }
+}
+
+static Bool
+_doPageFlip (DrawablePtr pDraw, int crtc_pipe, xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn =  xf86Screens[pScreen->myNum];
+    DRI2BufferPrivPtr pBackBufPriv = pEvent->pBackBuf->driverPrivate;
+    SECPixmapPriv *pBackExaPixPriv = exaGetPixmapDriverPrivate (pBackBufPriv->pPixmap);
+
+    /* Reset buffer position */
+    secRenderBoSetPos(pBackExaPixPriv->bo, pDraw->x, pDraw->y);
+
+    if (!secModePageFlip (pScrn, NULL, pEvent, crtc_pipe, pBackExaPixPriv->bo))
+    {
+        XDBG_WARNING (MDRI2, "fail to secModePageFlip\n");
+        return FALSE;
+    }
+    else
+    {
+        XDBG_DEBUG (MDRI2,"doPageFlip id:0x%x(%d) Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), "
+                "Back(attach:%d, name:%d, flag:0x%x )\n",
+                (unsigned int)pDraw->id, pDraw->type,
+                pEvent->pClient->index, crtc_pipe,
+                pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, pEvent->pFrontBuf->flags,
+                pEvent->pBackBuf->attachment, pEvent->pBackBuf->name, pEvent->pBackBuf->flags);
+
+        _exchangeBuffers (pDraw, pEvent->type, pEvent->pFrontBuf, pEvent->pBackBuf);
+    }
+
+    return TRUE;
+}
+
+
+static Bool
+_scheduleFlip (DrawablePtr pDraw, DRI2FrameEventPtr pEvent, Bool bFlipChain)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn =  xf86Screens[pScreen->myNum];
+    xf86CrtcPtr pCrtc = NULL;
+    SECCrtcPrivPtr pCrtcPriv = NULL;
+    BoxRec box;
+
+    /* main crtc for this drawable shall finally deliver pageflip event */
+    int crtc_pipe = secDisplayDrawablePipe (pDraw);
+
+    box.x1 = pDraw->x;
+    box.y1 = pDraw->y;
+    box.x2 = box.x1 + pDraw->width;
+    box.y2 = box.y1 + pDraw->height;
+    pCrtc = secModeCoveringCrtc (pScrn, &box, NULL, NULL);
+
+    if (!pCrtc)
+    {
+        XDBG_WARNING(MDRI2, "fail to get a crtc from a drawable\n");
+        DRI2SwapComplete (pEvent->pClient, pDraw, 0, 0, 0, DRI2_FLIP_COMPLETE,
+                pEvent->event_complete, pEvent->event_data);
+        _deleteFrame (pDraw, pEvent);
+        return FALSE;
+    }
+
+    pEvent->pCrtc = (void*)pCrtc;
+    pEvent->crtc_pipe = crtc_pipe;
+
+    pCrtcPriv = pCrtc->driver_private;
+
+    DRI2BufferPrivPtr pBackBufPriv = pEvent->pBackBuf->driverPrivate;
+
+    if (secCrtcIsFlipping(pCrtc) || pBackBufPriv->pFlipEvent)
+    {
+        /* Set the pending filp frame_event to the back buffer
+         * if the previous flip frmae_event is not completed.
+         */
+        if (pBackBufPriv->pFlipEvent)
+        {
+            if (pBackBufPriv->pFlipEvent->pPendingEvent)
+            {
+                XDBG_WARNING(MDRI2, "waring : pPendingEvent exist.\n");
+                return FALSE;
+            }
+            pBackBufPriv->pFlipEvent->pPendingEvent = pEvent;
+        }
+
+        if ( pCrtcPriv->is_fb_blit_flipping || !bFlipChain)
+        {
+            secCrtcAddPendingFlip (pCrtc, pEvent);
+            return TRUE;
+        }
+    }
+
+    if (!_doPageFlip (pDraw, crtc_pipe, pCrtc, pEvent))
+        XDBG_WARNING (MDRI2, "_doPageflip failed\n");
+    else
+    {
+        /* set the flip frame_event */
+        pBackBufPriv->pFlipEvent = pEvent;
+        DRI2SwapComplete (pEvent->pClient, pDraw, 0, 0, 0, DRI2_FLIP_COMPLETE,
+                pEvent->event_complete, pEvent->event_data);
+    }
+
+    return TRUE;
+}
+
+static void
+_saveDrawable (DrawablePtr pDraw, DRI2BufferPtr pBackBuf, DRI2FrameEventType swap_type)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR(pScrn);
+    char *type[5] = {"none", "swap", "flip", "blit", "fbblit"};
+    char file[128];
+    PixmapPtr pPix;
+    DRI2BufferPrivPtr pBackBufPriv;
+    SECPixmapPriv *pExaPixPriv;
+
+    if (!pSec->dump_info)
+        return;
+
+    XDBG_RETURN_IF_FAIL (pDraw != NULL);
+    XDBG_RETURN_IF_FAIL (pBackBuf != NULL);
+
+    pPix = _getPixmapFromDrawable (pDraw);
+    XDBG_RETURN_IF_FAIL (pPix != NULL);
+    pBackBufPriv = pBackBuf->driverPrivate;
+    XDBG_RETURN_IF_FAIL (pBackBufPriv != NULL);
+    pExaPixPriv = exaGetPixmapDriverPrivate (pPix);
+    XDBG_RETURN_IF_FAIL (pExaPixPriv != NULL);
+
+    snprintf (file, sizeof(file), "%03d_%s_%lx_%03d.%s",
+              pSec->flip_cnt, type[swap_type], pDraw->id, pExaPixPriv->dump_cnt,
+              pSec->dump_type);
+
+    if (!strcmp (pSec->dump_type, "raw"))
+    {
+        Bool need_finish = FALSE;
+        SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pBackBufPriv->pPixmap);
+        int size;
+
+        if (!privPixmap->bo)
+        {
+            need_finish = TRUE;
+            secExaPrepareAccess (pBackBufPriv->pPixmap, EXA_PREPARE_DEST);
+            XDBG_RETURN_IF_FAIL (privPixmap->bo != NULL);
+        }
+        size = tbm_bo_size (privPixmap->bo);
+        secUtilDoDumpRaws (pSec->dump_info, &privPixmap->bo, &size, 1, file);
+
+        if (need_finish)
+            secExaFinishAccess (pBackBufPriv->pPixmap, EXA_PREPARE_DEST);
+    }
+    else
+        secUtilDoDumpPixmaps (pSec->dump_info, pBackBufPriv->pPixmap, file);
+
+    XDBG_DEBUG (MSEC, "dump done\n");
+
+    pExaPixPriv->dump_cnt++;
+}
+
+static void
+_SendSyncDrawDoneMessage(ScreenPtr screen, ClientPtr client, DrawablePtr pDraw)
+{
+    XDBG_RETURN_IF_FAIL (screen != NULL);
+    XDBG_RETURN_IF_FAIL (client != NULL);
+    XDBG_RETURN_IF_FAIL (pDraw != NULL);
+
+    static Atom sync_draw_done = None;
+    xEvent event;
+    DeviceIntPtr dev = PickPointer(client);
+
+    if (sync_draw_done == None)
+        sync_draw_done = MakeAtom ("_E_COMP_SYNC_DRAW_DONE", strlen ("_E_COMP_SYNC_DRAW_DONE"), TRUE);
+
+    memset (&event, 0, sizeof (xEvent));
+    event.u.u.type = ClientMessage;
+    event.u.u.detail = 32;
+    event.u.clientMessage.u.l.type = sync_draw_done;
+    event.u.clientMessage.u.l.longs0 = pDraw->id; // window id
+    event.u.clientMessage.u.l.longs1 = 1; // version
+    event.u.clientMessage.u.l.longs2 = pDraw->width; // window's width
+    event.u.clientMessage.u.l.longs3 = pDraw->height; // window's height
+
+    XDBG_DEBUG(MDRI2, "client=%d pDraw->id=%x width=%d height=%d\n", client->index, pDraw->id, pDraw->width, pDraw->height);
+
+    DeliverEventsToWindow(dev, screen->root, &event, 1, SubstructureRedirectMask | SubstructureNotifyMask, NullGrab);
+}
+
+static DRI2BufferPtr
+SECDri2CreateBuffer (DrawablePtr pDraw, unsigned int attachment, unsigned int format)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    DRI2BufferPtr pBuf = NULL;
+    DRI2BufferPrivPtr pBufPriv = NULL;
+    PixmapPtr pPix = NULL;
+    Bool canFlip = FALSE;
+
+    /* create dri2 buffer */
+    pBuf = calloc (1, sizeof (DRI2BufferRec));
+    if (pBuf == NULL)
+        goto fail;
+
+    /* create dri2 buffer private */
+    pBufPriv = calloc (1, sizeof (DRI2BufferPrivRec));
+    if (pBufPriv == NULL)
+        goto fail;
+
+    /* check canFlip */
+    canFlip = _canFlip (pDraw);
+
+    pBuf->driverPrivate = pBufPriv;
+    pBuf->format = format;
+    pBuf->flags = _getBufferFlag (pDraw, canFlip);
+
+    /* check the attachments */
+    if (attachment == DRI2BufferFrontLeft)
+    {
+        pPix = _getPixmapFromDrawable (pDraw);
+        pPix->refcnt++;
+        pBufPriv->canFlip = canFlip;
+    }
+    else
+    {
+        switch (attachment)
+        {
+        case DRI2BufferDepth:
+        case DRI2BufferDepthStencil:
+        case DRI2BufferFakeFrontLeft:
+        case DRI2BufferFakeFrontRight:
+        case DRI2BufferBackRight:
+        case DRI2BufferBackLeft:
+            pPix = _initBackBufPixmap (pBuf, pDraw, canFlip);
+            if (pPix == NULL)
+            {
+                goto fail;
+            }
+            break;
+        default:
+            XDBG_ERROR(MDRI2, "Unsupported attachmemt:%d\n", attachment);
+            goto fail;
+            break;
+        }
+
+        //Set DRI2 property for selective-composite mode
+        _setDri2Property (pDraw);
+    }
+
+    pBuf->cpp = pPix->drawable.bitsPerPixel / 8;
+    pBuf->attachment = attachment;
+    pBuf->pitch = pPix->devKind;
+    pBuf->name = _getName (pPix);
+    if (pBuf->name == 0)
+    {
+        goto fail;
+    }
+
+    pBufPriv->refcnt = 1;
+    pBufPriv->attachment = attachment;
+    pBufPriv->pPixmap = pPix;
+    pBufPriv->pScreen = pScreen;
+
+    XDBG_DEBUG(MDRI2, "id:0x%x(%d) attach:%d, name:%d, flags:0x%x, flip:%d geo(%dx%d+%d+%d)\n",
+               pDraw->id, pDraw->type,
+               pBuf->attachment, pBuf->name, pBuf->flags, pBufPriv->canFlip,
+               pDraw->width, pDraw->height, pDraw->x, pDraw->y);
+
+    return pBuf;
+fail:
+    XDBG_WARNING(MDRI2, "Failed: id:0x%x(%d) attach:%d,geo(%dx%d+%d+%d)\n",
+                 pDraw->id, pDraw->type, attachment, pDraw->width, pDraw->height, pDraw->x, pDraw->y);
+    if (pPix)
+    {
+#if USE_XDBG
+        xDbgLogPListDrawRemoveRefPixmap (pDraw, pPix);
+#endif
+        (*pScreen->DestroyPixmap) (pPix);
+    }
+    if (pBufPriv)
+        free (pBufPriv);
+    if (pBuf)
+        free (pBuf);
+    return NULL;
+}
+
+static void
+SECDri2DestroyBuffer (DrawablePtr pDraw, DRI2BufferPtr pBuf)
+{
+    ScreenPtr pScreen = NULL;
+    DRI2BufferPrivPtr pBufPriv = NULL;
+
+    if (pBuf == NULL)
+        return;
+
+    pBufPriv = pBuf->driverPrivate;
+    pScreen = pBufPriv->pScreen;
+
+    _unreferenceBufferPriv(pBuf);
+
+    if (pBufPriv->refcnt == 0)
+    {
+        XDBG_DEBUG(MDRI2, "DestroyBuffer(%d:0x%x) name:%d flip:%d\n",
+                   pDraw?pDraw->type:0,
+                   pDraw?(unsigned int)pDraw->id:0,
+                   pBuf->name,
+                   pBufPriv->canFlip);
+
+        if (pBuf->attachment == DRI2BufferFrontLeft)
+        {
+            (*pScreen->DestroyPixmap) (pBufPriv->pPixmap);
+        }
+        else
+        {
+            _deinitBackBufPixmap(pBuf, pDraw, pBufPriv->canFlip);
+        }
+
+        pBufPriv->pPixmap = NULL;
+        free (pBufPriv);
+        free (pBuf);
+    }
+}
+
+static void
+SECDri2CopyRegion (DrawablePtr pDraw, RegionPtr pRegion,
+                   DRI2BufferPtr pDstBuf, DRI2BufferPtr pSrcBuf)
+{
+    DRI2BufferPrivPtr pSrcBufPriv = pSrcBuf->driverPrivate;
+    DRI2BufferPrivPtr pDstBufPriv = pDstBuf->driverPrivate;
+    ScreenPtr pScreen = pDraw->pScreen;
+    RegionPtr pCopyClip;
+    GCPtr pGc;
+
+    DrawablePtr pSrcDraw = (pSrcBufPriv->attachment == DRI2BufferFrontLeft)
+                           ? pDraw : &pSrcBufPriv->pPixmap->drawable;
+    DrawablePtr pDstDraw = (pDstBufPriv->attachment == DRI2BufferFrontLeft)
+                           ? pDraw : &pDstBufPriv->pPixmap->drawable;
+
+    pGc = GetScratchGC (pDstDraw->depth, pScreen);
+    if (!pGc)
+        return;
+
+    XDBG_DEBUG(MDRI2,"CopyRegion(%d,0x%x) Dst(attach:%d, name:%d, flag:0x%x), Src(attach:%d, name:%d, flag:0x%x)\n",
+               pDraw->type, (unsigned int)pDraw->id,
+               pDstBuf->attachment, pDstBuf->name, pDstBuf->flags,
+               pSrcBuf->attachment, pSrcBuf->name, pSrcBuf->flags);
+
+    pCopyClip = REGION_CREATE (pScreen, NULL, 0);
+    REGION_COPY (pScreen, pCopyClip, pRegion);
+    (*pGc->funcs->ChangeClip) (pGc, CT_REGION, pCopyClip, 0);
+    ValidateGC (pDstDraw, pGc);
+
+    /* Wait for the scanline to be outside the region to be copied */
+    /* [TODO] Something Do ??? */
+
+    /* It's important that this copy gets submitted before the
+    * direct rendering client submits rendering for the next
+    * frame, but we don't actually need to submit right now.  The
+    * client will wait for the DRI2CopyRegion reply or the swap
+    * buffer event before rendering, and we'll hit the flush
+    * callback chain before those messages are sent.  We submit
+    * our batch buffers from the flush callback chain so we know
+    * that will happen before the client tries to render
+    * again. */
+
+    (*pGc->ops->CopyArea) (pSrcDraw, pDstDraw,
+                           pGc,
+                           0, 0,
+                           pDraw->width, pDraw->height,
+                           0, 0);
+    (*pGc->funcs->DestroyClip) (pGc);
+    FreeScratchGC (pGc);
+}
+
+
+/*
+ * ScheduleSwap is responsible for requesting a DRM vblank event for the
+ * appropriate frame.
+ *
+ * In the case of a blit (e.g. for a windowed swap) or buffer exchange,
+ * the vblank requested can simply be the last queued swap frame + the swap
+ * interval for the drawable.
+ *
+ * In the case of a page flip, we request an event for the last queued swap
+ * frame + swap interval - 1, since we'll need to queue the flip for the frame
+ * immediately following the received event.
+ *
+ * The client will be blocked if it tries to perform further GL commands
+ * after queueing a swap, though in the Intel case after queueing a flip, the
+ * client is free to queue more commands; they'll block in the kernel if
+ * they access buffers busy with the flip.
+ *
+ * When the swap is complete, the driver should call into the server so it
+ * can send any swap complete events that have been requested.
+ */
+static int
+SECDri2ScheduleSwapWithRegion (ClientPtr pClient, DrawablePtr pDraw,
+                     DRI2BufferPtr pFrontBuf, DRI2BufferPtr pBackBuf,
+                     CARD64 *target_msc, CARD64 divisor,    CARD64 remainder,
+                     DRI2SwapEventPtr swap_func, void *data, RegionPtr pRegion)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+    int pipe = 0; /* default */
+    int flip = 0;
+    DRI2FrameEventPtr pFrameEvent = NULL;
+    DRI2FrameEventType swap_type = DRI2_SWAP;
+    CARD64 current_msc;
+    CARD64 ust, msc;
+
+    pFrameEvent = _newFrame (pClient, pDraw, pFrontBuf, pBackBuf, swap_func, data, pRegion);
+    if (!pFrameEvent)
+    {
+        DRI2SwapComplete (pClient, pDraw, 0, 0, 0, 0, swap_func, data);
+        return TRUE;
+    }
+
+    /* Set frame count to back*/
+    {
+        PixmapPtr pPix;
+        SECPixmapPriv *pExaPixPriv = NULL;
+        DRI2BufferPrivPtr pBufPriv = pBackBuf->driverPrivate;
+        CARD64 sbc;
+        unsigned int pending;
+
+        pPix = pBufPriv->pBackPixmaps[pBufPriv->cur_idx];
+        pExaPixPriv = exaGetPixmapDriverPrivate (pPix);
+        DRI2GetSBC(pDraw, &sbc, &pending);
+        pExaPixPriv->owner = pDraw->id;
+        pExaPixPriv->sbc = sbc+pending;
+    }
+
+
+    swap_type = pFrameEvent->type;
+
+    XDBG_DEBUG (MSEC, "dump_mode(%x) dump_xid(0x%x:0x%x) swap_type(%d)\n",
+                pSec->dump_mode, pSec->dump_xid, pDraw->id, swap_type);
+
+    if ((pSec->dump_mode & XBERC_DUMP_MODE_DRAWABLE) &&
+        (swap_type != DRI2_NONE && swap_type != DRI2_WAITMSC) &&
+        (pSec->dump_xid == 0 || pSec->dump_xid == pDraw->id))
+        _saveDrawable (pDraw, pBackBuf, swap_type);
+
+    /* If lcd is off status, SwapBuffers do not consider the vblank sync.
+     * The client that launches after lcd is off wants to render the frame
+     * on the fly.
+     */
+    if (pSec->isLcdOff == TRUE ||
+        pSec->useAsyncSwap == TRUE)
+    {
+        _asyncSwapBuffers (pClient, pDraw, pFrameEvent);
+        _SendSyncDrawDoneMessage(pScreen, pClient, pDraw);
+        _deleteFrame (pDraw, pFrameEvent);
+        return TRUE;
+    }
+
+    pipe = secDisplayDrawablePipe (pDraw);
+
+    /* check if the pipe is -1 */
+    if (pipe == -1)
+    {
+        /* if swap_type is DRI2_FLIP, fall into the async swap */
+        if (swap_type == DRI2_FLIP)
+        {
+            XDBG_WARNING(MDRI2, "Warning: flip pipe is -1 \n");
+            _asyncSwapBuffers (pClient, pDraw, pFrameEvent);
+            _SendSyncDrawDoneMessage(pScreen, pClient, pDraw);
+            _deleteFrame (pDraw, pFrameEvent);
+            return TRUE;
+        }
+    }
+
+    /* Truncate to match kernel interfaces; means occasional overflow
+     * misses, but that's generally not a big deal */
+    *target_msc &= 0xffffffff;
+    divisor &= 0xffffffff;
+    remainder &= 0xffffffff;
+
+    /* Get current count */
+    if (!secDisplayGetCurMSC (pScrn, pipe, &ust, &msc))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
+                    "fail to get current_msc\n");
+        goto blit_fallback;
+    }
+    current_msc = msc;
+
+    /* Flips need to be submitted one frame before */
+    if (swap_type == DRI2_FLIP)
+    {
+        flip = 1;
+    }
+
+    /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
+     * Do it early, so handling of different timing constraints
+     * for divisor, remainder and msc vs. target_msc works.
+     */
+    if (*target_msc > 0)
+        *target_msc -= flip;
+
+    /*
+     * If divisor is zero, or current_msc is smaller than target_msc
+     * we just need to make sure target_msc passes before initiating
+     * the swap.
+     */
+    if (divisor == 0 || current_msc < *target_msc)
+    {
+        /* If target_msc already reached or passed, set it to
+         * current_msc to ensure we return a reasonable value back
+         * to the caller. This makes swap_interval logic more robust.
+         */
+        if (current_msc >= *target_msc)
+            *target_msc = current_msc;
+
+        if (!secDisplayVBlank (pScrn, pipe, target_msc, flip, VBLANK_INFO_SWAP, pFrameEvent))
+        {
+            xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "fail to Vblank\n");
+            goto blit_fallback;
+        }
+
+        pFrameEvent->frame = (unsigned int )*target_msc;
+
+        XDBG_DEBUG(MDRI2,"id:0x%x(%d) SwapType:%d Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), "
+                   "Back(attach:%d, name:%d, flag:0x%x )\n",
+                   (unsigned int)pDraw->id, pDraw->type,
+                   swap_type, pClient->index, pipe,
+                   pFrontBuf->attachment, pFrontBuf->name, pFrontBuf->flags,
+                   pBackBuf->attachment, pBackBuf->name, pBackBuf->flags);
+
+        if (pFrameEvent->pRegion)
+        {
+            BoxPtr pBox = RegionRects(pFrameEvent->pRegion);
+            int nBox = RegionNumRects(pFrameEvent->pRegion);
+
+            while (nBox--)
+            {
+                   XDBG_DEBUG(MDRI2,"Region[%d]: (x1, y1, x2, y2) = (%d,%d,%d,%d) \n ",
+                           nBox, pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+                   pBox++;
+            }
+        }
+
+        _swapFrame (pDraw, pFrameEvent);
+        _SendSyncDrawDoneMessage(pScreen, pClient, pDraw);
+
+        return TRUE;
+    }
+
+    /*
+     * If we get here, target_msc has already passed or we don't have one,
+     * and we need to queue an event that will satisfy the divisor/remainder
+     * equation.
+     */
+    *target_msc = current_msc - (current_msc % divisor) +
+                           remainder;
+
+    /*
+     * If the calculated deadline vbl.request.sequence is smaller than
+     * or equal to current_msc, it means we've passed the last point
+     * when effective onset frame seq could satisfy
+     * seq % divisor == remainder, so we need to wait for the next time
+     * this will happen.
+
+     * This comparison takes the 1 frame swap delay in pageflipping mode
+     * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay
+     * if we are blitting/exchanging instead of flipping.
+     */
+    if (*target_msc <= current_msc)
+        *target_msc += divisor;
+
+    /* Account for 1 frame extra pageflip delay if flip > 0 */
+    *target_msc -= flip;
+
+    if (!secDisplayVBlank (pScrn, pipe, target_msc, flip, VBLANK_INFO_SWAP, pFrameEvent))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "fail to Vblank\n");
+        goto blit_fallback;
+    }
+
+    pFrameEvent->frame = *target_msc;
+
+    XDBG_DEBUG(MDRI2,"ScaduleSwap_ex(%d,0x%x) SwapType:%d Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n",
+               pDraw->type, (unsigned int)pDraw->id,
+               swap_type, pClient->index, pipe,
+               pFrontBuf->attachment, pFrontBuf->name, pFrontBuf->flags,
+               pBackBuf->attachment, pBackBuf->name, pBackBuf->flags);
+
+    _swapFrame (pDraw, pFrameEvent);
+    _SendSyncDrawDoneMessage(pScreen, pClient, pDraw);
+
+    return TRUE;
+
+blit_fallback:
+    XDBG_WARNING(MDRI2,"blit_fallback(%d,0x%x) SwapType:%d Client:%d pipe:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n",
+                 pDraw->type, (unsigned int)pDraw->id,
+                 swap_type, pClient->index, pipe,
+                 pFrontBuf->attachment, pFrontBuf->name, pFrontBuf->flags,
+                 pBackBuf->attachment, pBackBuf->name, pBackBuf->flags);
+
+    _blitBuffers (pDraw, pFrontBuf, pBackBuf);
+
+    DRI2SwapComplete (pClient, pDraw, 0, 0, 0, DRI2_BLIT_COMPLETE, swap_func, data);
+    _SendSyncDrawDoneMessage(pScreen, pClient, pDraw);
+
+    if (pFrameEvent)
+    {
+        _deleteFrame (pDraw, pFrameEvent);
+    }
+    *target_msc = 0; /* offscreen, so zero out target vblank count */
+    return TRUE;
+}
+
+
+/*
+ * Get current frame count and frame count timestamp, based on drawable's
+ * crtc.
+ */
+static int
+SECDri2GetMSC (DrawablePtr pDraw, CARD64 *ust, CARD64 *msc)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    int pipe;
+
+    pipe = secDisplayDrawablePipe (pDraw);
+
+    /* Get current count */
+    if (!secDisplayGetCurMSC (pScrn, pipe, ust, msc))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
+                    "fail to get current_msc\n");
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*
+ * Request a DRM event when the requested conditions will be satisfied.
+ *
+ * We need to handle the event and ask the server to wake up the client when
+ * we receive it.
+ */
+static int
+SECDri2ScheduleWaitMSC (ClientPtr pClient, DrawablePtr pDraw,
+                        CARD64 target_msc, CARD64 divisor, CARD64 remainder)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    DRI2FrameEventPtr wait_info = NULL;
+    CARD64 current_msc;
+    CARD64 ust, msc;
+
+    int pipe = 0;
+
+    /* Truncate to match kernel interfaces; means occasional overflow
+     * misses, but that's generally not a big deal */
+    target_msc &= 0xffffffff;
+    divisor &= 0xffffffff;
+    remainder &= 0xffffffff;
+
+    /* Drawable not visible, return immediately */
+    pipe = secDisplayDrawablePipe (pDraw);
+    if (pipe == -1)
+        goto out_complete;
+
+    wait_info = calloc (1, sizeof (DRI2FrameEventRec));
+    if (!wait_info)
+        goto out_complete;
+
+    wait_info->drawable_id = pDraw->id;
+    wait_info->pClient = pClient;
+    wait_info->type = DRI2_WAITMSC;
+
+    /* Get current count */
+    if (!secDisplayGetCurMSC (pScrn, pipe, &ust, &msc))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
+                    "fail to get current_msc\n");
+        goto out_complete;
+    }
+    current_msc = msc;
+
+    /*
+     * If divisor is zero, or current_msc is smaller than target_msc,
+     * we just need to make sure target_msc passes  before waking up the
+     * client.
+     */
+    if (divisor == 0 || current_msc < target_msc)
+    {
+        /* If target_msc already reached or passed, set it to
+         * current_msc to ensure we return a reasonable value back
+         * to the caller. This keeps the client from continually
+         * sending us MSC targets from the past by forcibly updating
+         * their count on this call.
+         */
+        if (current_msc >= target_msc)
+            target_msc = current_msc;
+
+        /* flip is 1 to avoid to set DRM_VBLANK_NEXTONMISS */
+        if (!secDisplayVBlank (pScrn, pipe, &target_msc, 1, VBLANK_INFO_SWAP, wait_info))
+        {
+            xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "fail to Vblank\n");
+            goto out_complete;
+        }
+
+        wait_info->frame = target_msc - 1; /* reply qeuenct is +1 in secDisplayVBlank */
+        DRI2BlockClient (pClient, pDraw);
+        return TRUE;
+    }
+
+    /*
+     * If we get here, target_msc has already passed or we don't have one,
+     * so we queue an event that will satisfy the divisor/remainder equation.
+     */
+    target_msc = current_msc - (current_msc % divisor) +
+                           remainder;
+
+    /*
+     * If calculated remainder is larger than requested remainder,
+     * it means we've passed the last point where
+     * seq % divisor == remainder, so we need to wait for the next time
+     * that will happen.
+     */
+    if ((current_msc % divisor) >= remainder)
+        target_msc += divisor;
+
+    /* flip is 1 to avoid to set DRM_VBLANK_NEXTONMISS */
+    if (!secDisplayVBlank (pScrn, pipe, &target_msc, 1, VBLANK_INFO_SWAP, wait_info))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "fail to Vblank\n");
+        goto out_complete;
+    }
+
+    wait_info->frame = target_msc - 1; /* reply qeuenct is +1 in secDisplayVBlank */
+    DRI2BlockClient (pClient, pDraw);
+
+    return TRUE;
+
+out_complete:
+    free(wait_info);
+    DRI2WaitMSCComplete (pClient, pDraw, target_msc, 0, 0);
+    return TRUE;
+}
+
+static int
+SECDri2AuthMagic (int fd, uint32_t magic)
+{
+    int ret;
+    ret = drmAuthMagic (fd, (drm_magic_t) magic);
+
+    XDBG_TRACE(MDRI2, "AuthMagic: %d\n", ret);
+
+    return ret;
+}
+
+static void
+SECDri2ReuseBufferNotify (DrawablePtr pDraw, DRI2BufferPtr pBuf)
+{
+    DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate;
+
+    if(!_resetBufPixmap(pDraw, pBuf))
+    {
+        DRI2BufferFlags *flags = (DRI2BufferFlags*)&pBuf->flags;
+
+        pBuf->name = _getName(pBufPriv->pPixmap);
+        flags->flags = _getBufferFlag(pDraw, pBufPriv->canFlip);
+        flags->data.is_reused = 1;
+
+        /*Set reuse index*/
+        if (pBuf->attachment != DRI2BufferFrontLeft)
+        {
+            DRI2BufferPrivPtr pBufPriv = pBuf->driverPrivate;
+            PixmapPtr pPix;
+            SECPixmapPriv *pExaPixPriv = NULL;
+            CARD64 sbc;
+            unsigned int pending;
+
+            pPix = pBufPriv->pBackPixmaps[pBufPriv->cur_idx];
+            pExaPixPriv = exaGetPixmapDriverPrivate (pPix);
+
+            DRI2GetSBC(pDraw, &sbc, &pending);
+            /*Get current count */
+            if(pExaPixPriv->owner == pDraw->id)
+            {
+                unsigned int idx_reuse = sbc+pending - pExaPixPriv->sbc + 1;
+                if(idx_reuse > pBufPriv->num_buf + 1)
+                {
+                   flags->data.idx_reuse = 0;
+                }
+                else
+                {
+                   flags->data.idx_reuse = idx_reuse;
+                }
+            }
+            else
+            {
+                flags->data.idx_reuse = 0;
+            }
+        }
+        else
+        {
+            flags->data.idx_reuse = 0;
+        }
+    }
+
+    XDBG_DEBUG(MDRI2, "id:0x%x(%d) attach:%d, name:%d, flags:0x%x, flip:%d, geo(%dx%d+%d+%d)\n",
+               pDraw->id, pDraw->type,
+               pBuf->attachment, pBuf->name, pBuf->flags, pBufPriv->canFlip,
+               pDraw->width, pDraw->height, pDraw->x, pDraw->y);
+}
+
+static void
+_secDri2ProcessPending (xf86CrtcPtr pCrtc, ScreenPtr pScreen,
+                         unsigned int frame, unsigned int tv_sec, unsigned int tv_usec)
+{
+    DRI2BufferPrivPtr pBackBufPriv = NULL;
+    DrawablePtr pCrtcPendingDraw = NULL;
+    DRI2FrameEventPtr pCrtcPendingFlip = NULL;
+
+    pCrtcPendingFlip = secCrtcGetFirstPendingFlip (pCrtc);
+    if (pCrtcPendingFlip)
+    {
+        ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+        SECPtr pSec = SECPTR (pScrn);
+
+        secCrtcRemovePendingFlip (pCrtc, pCrtcPendingFlip);
+
+        if (pCrtcPendingFlip->drawable_id)
+            dixLookupDrawable (&pCrtcPendingDraw, pCrtcPendingFlip->drawable_id,
+                           serverClient, M_ANY, DixWriteAccess);
+        if (!pCrtcPendingDraw)
+        {
+            XDBG_WARNING (MDRI2, "pCrtcPendingDraw is null.\n");
+            _deleteFrame (pCrtcPendingDraw, pCrtcPendingFlip);
+            return;
+        }
+        else
+        {
+            if(pSec->isLcdOff)
+            {
+                XDBG_WARNING (MDRI2, "LCD OFF : Request a pageflip pending even if the lcd is off.\n");
+
+                _exchangeBuffers(pCrtcPendingDraw, DRI2_FLIP, pCrtcPendingFlip->pFrontBuf, pCrtcPendingFlip->pBackBuf);
+
+                DRI2SwapComplete (pCrtcPendingFlip->pClient, pCrtcPendingDraw,
+                                  frame, tv_sec, tv_usec,
+                                  0, pCrtcPendingFlip->event_complete,
+                                  pCrtcPendingFlip->event_data);
+
+                pBackBufPriv = pCrtcPendingFlip->pBackBuf->driverPrivate;
+                pBackBufPriv->pFlipEvent = NULL;
+                _deleteFrame (pCrtcPendingDraw, pCrtcPendingFlip);
+            }
+            else
+            {
+                if(!_scheduleFlip (pCrtcPendingDraw, pCrtcPendingFlip, TRUE))
+                {
+                    XDBG_WARNING (MDRI2, "fail to _scheduleFlip in secDri2FlipEventHandler\n");
+                }
+            }
+        }
+    }
+
+}
+
+void
+secDri2FlipEventHandler (unsigned int frame, unsigned int tv_sec,
+                         unsigned int tv_usec, void *event_data, Bool flip_failed)
+{
+    DRI2FrameEventPtr pEvent = event_data;
+    DRI2BufferPrivPtr pBackBufPriv = pEvent->pBackBuf->driverPrivate;
+    ScreenPtr pScreen = pBackBufPriv->pScreen;
+    DrawablePtr pDraw = NULL;
+    ClientPtr pClient = pEvent->pClient;
+    xf86CrtcPtr pCrtc = (xf86CrtcPtr) pEvent->pCrtc;
+
+    if (pEvent->drawable_id)
+        dixLookupDrawable (&pDraw, pEvent->drawable_id, serverClient, M_ANY, DixWriteAccess);
+    if (!pDraw)
+    {
+        XDBG_WARNING (MDRI2,"pDraw is null... Client:%d pipe:%d "
+                   "Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n",
+                   pClient->index, pBackBufPriv->pipe,
+                   pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, pEvent->pFrontBuf->flags,
+                   pEvent->pBackBuf->attachment, pEvent->pBackBuf->name, pEvent->pBackBuf->flags);
+        _secDri2ProcessPending (pCrtc, pScreen, frame, tv_sec, tv_usec);
+        _deleteFrame (pDraw, pEvent);
+        return;
+    }
+
+    XDBG_TRACE (MDRI2,"FlipEvent(%d,0x%x) Client:%d pipe:%d "
+               "Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n",
+               pDraw->type, (unsigned int)pDraw->id, pClient->index, pBackBufPriv->pipe,
+               pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, pEvent->pFrontBuf->flags,
+               pEvent->pBackBuf->attachment, pEvent->pBackBuf->name, pEvent->pBackBuf->flags);
+
+    /* check the failure of the pageflip */
+    if (flip_failed)
+    {
+        _exchangeBuffers(pDraw, DRI2_FLIP, pEvent->pFrontBuf, pEvent->pBackBuf);
+
+        DRI2SwapComplete (pEvent->pClient, pDraw, frame, tv_sec, tv_usec,
+                0, pEvent->event_complete, pEvent->event_data);
+        _deleteFrame (pDraw, pEvent);
+        return;
+    }
+
+    assert (pBackBufPriv->pFlipEvent == pEvent);
+    pBackBufPriv->pFlipEvent = NULL;
+    _deleteFrame (pDraw, pEvent);
+
+    /* get the next pending flip event */
+    _secDri2ProcessPending (pCrtc, pScreen, frame, tv_sec, tv_usec);
+
+}
+
+void
+secDri2FrameEventHandler (unsigned int frame, unsigned int tv_sec,
+                          unsigned int tv_usec, void *event_data)
+{
+    DRI2FrameEventPtr pEvent = event_data;
+    DrawablePtr pDraw = NULL;
+    int status;
+
+    status = dixLookupDrawable (&pDraw, pEvent->drawable_id, serverClient,
+                                M_ANY, DixWriteAccess);
+    if (status != Success)
+    {
+        XDBG_WARNING(MDRI2,"drawable is not found\n");
+
+        _deleteFrame (NULL, pEvent);
+        return;
+    }
+
+    XDBG_RETURN_IF_FAIL(pEvent->pFrontBuf != NULL);
+    XDBG_RETURN_IF_FAIL(pEvent->pBackBuf != NULL);
+
+    switch (pEvent->type)
+    {
+    case DRI2_FLIP:
+        if(!_scheduleFlip (pDraw, pEvent, FALSE))
+            XDBG_WARNING(MDRI2, "pageflip fails.\n");
+        return;
+        break;
+    case DRI2_SWAP:
+        DRI2SwapComplete (pEvent->pClient, pDraw, frame, tv_sec, tv_usec,
+                          DRI2_EXCHANGE_COMPLETE, pEvent->event_complete, pEvent->event_data);
+        break;
+    case DRI2_BLIT:
+    case DRI2_FB_BLIT:
+        DRI2SwapComplete (pEvent->pClient, pDraw, frame, tv_sec, tv_usec,
+                          DRI2_BLIT_COMPLETE, pEvent->event_complete, pEvent->event_data);
+        break;
+    case DRI2_NONE:
+        DRI2SwapComplete (pEvent->pClient, pDraw, frame, tv_sec, tv_usec,
+                          0, pEvent->event_complete, pEvent->event_data);
+        break;
+    case DRI2_WAITMSC:
+        DRI2WaitMSCComplete (pEvent->pClient, pDraw, frame, tv_sec, tv_usec);
+        break;
+    default:
+        /* Unknown type */
+        break;
+    }
+
+    XDBG_DEBUG (MDRI2,"FrameEvent(%d,0x%x) SwapType:%d Front(attach:%d, name:%d, flag:0x%x), Back(attach:%d, name:%d, flag:0x%x)\n",
+                pDraw->type, (unsigned int)pDraw->id, pEvent->type,
+                pEvent->pFrontBuf->attachment, pEvent->pFrontBuf->name, pEvent->pFrontBuf->flags,
+                pEvent->pBackBuf->attachment, pEvent->pBackBuf->name, pEvent->pBackBuf->flags);
+
+
+    _deleteFrame (pDraw, pEvent);
+}
+
+
+Bool secDri2Init (ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+    SECExaPrivPtr pExaPriv = SECEXAPTR (pSec);
+    DRI2InfoRec info;
+    int ret;
+    const char *driverNames[1];
+
+    info.driverName = "exynos-drm";
+    info.deviceName = pSec->drm_device_name;
+    info.version = 106;
+    info.fd = pSec->drm_fd;
+    info.CreateBuffer = SECDri2CreateBuffer;
+    info.DestroyBuffer = SECDri2DestroyBuffer;
+    info.CopyRegion = SECDri2CopyRegion;
+    info.ScheduleSwap = NULL;
+    info.GetMSC = SECDri2GetMSC;
+    info.ScheduleWaitMSC = SECDri2ScheduleWaitMSC;
+    info.AuthMagic = SECDri2AuthMagic;
+    info.ReuseBufferNotify = SECDri2ReuseBufferNotify;
+    info.SwapLimitValidate = NULL;
+    /* added in version 7 */
+    info.GetParam = NULL;
+
+    /* added in version 8 */
+    /* AuthMagic callback which passes extra context */
+    /* If this is NULL the AuthMagic callback is used */
+    /* If this is non-NULL the AuthMagic callback is ignored */
+    info.AuthMagic2 = NULL;
+
+    /* added in version 9 */
+    info.CreateBuffer2 = NULL;
+    info.DestroyBuffer2 = NULL;
+    info.CopyRegion2 = NULL;
+
+    /* add in for Tizen extension */
+    info.ScheduleSwapWithRegion = SECDri2ScheduleSwapWithRegion;
+
+    info.Wait = NULL;
+    info.numDrivers = 1;
+    info.driverNames = driverNames;
+    driverNames[0] = info.driverName;
+
+    ret = DRI2ScreenInit (pScreen, &info);
+    if (ret == FALSE)
+    {
+        return FALSE;
+    }
+
+    /* set the number of the flip back buffers */
+    pExaPriv->flip_backbufs = pSec->flip_bufs - 1;
+
+    //xDbgLogSetLevel (MDRI2, 0);
+    return ret;
+}
+
+void secDri2Deinit (ScreenPtr pScreen)
+{
+    DRI2CloseScreen (pScreen);
+}
diff --git a/src/accel/sec_exa.c b/src/accel/sec_exa.c
new file mode 100644 (file)
index 0000000..c62ede5
--- /dev/null
@@ -0,0 +1,664 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include "sec.h"
+#include "sec_accel.h"
+#include "sec_display.h"
+#include "sec_crtc.h"
+#include <X11/Xatom.h>
+#include "windowstr.h"
+#include "fbpict.h"
+#include "sec_util.h"
+#include "sec_converter.h"
+
+static void
+_setScreenRotationProperty (ScrnInfoPtr pScrn)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    ScreenPtr pScreen = pScrn->pScreen;
+    Atom atom_screen_rotaion;
+    WindowPtr pWin = pScreen->root;
+    int rc;
+    atom_screen_rotaion = MakeAtom ("X_SCREEN_ROTATION", 17, TRUE);
+    unsigned int rotation = (unsigned int) pSec->rotate;
+
+    rc = dixChangeWindowProperty (serverClient,
+                                  pWin, atom_screen_rotaion, XA_CARDINAL, 32,
+                                  PropModeReplace, 1, &rotation, FALSE);
+       if (rc != Success)
+        XDBG_ERROR (MEXAS, "failed : set X_SCREEN_ROTATION to %d\n", rotation);
+}
+
+static void
+_secExaBlockHandler (pointer blockData, OSTimePtr pTimeout,
+                     pointer pReadmask)
+{
+    ScreenPtr pScreen = screenInfo.screens[0];
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+    /* add screen rotation property to the root window */
+    _setScreenRotationProperty (pScrn);
+
+    RemoveBlockAndWakeupHandlers (_secExaBlockHandler /*blockHandler*/,
+                                  (void*)NULL /*wakeupHandler*/,
+                                  (void*)NULL /*blockData*/);
+}
+
+static void
+SECExaWaitMarker (ScreenPtr pScreen, int marker)
+{
+}
+
+static Bool
+SECExaPrepareAccess (PixmapPtr pPix, int index)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+    SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPix);
+    int opt = TBM_OPTION_READ;
+    tbm_bo_handle bo_handle;
+
+    XDBG_RETURN_VAL_IF_FAIL((privPixmap != NULL), FALSE);
+    if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB &&
+        privPixmap->bo == NULL)
+    {
+        privPixmap->bo = secRenderBoRef(pSec->pFb->default_bo);
+        XDBG_RETURN_VAL_IF_FAIL((privPixmap->bo != NULL), FALSE);
+        XDBG_TRACE(MEXAS, " FRAMEBUFFER\n");
+    }
+    else
+    {
+        XDBG_TRACE(MEXAS, "\n");
+    }
+
+    if(privPixmap->bo)
+    {
+        if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST)
+            opt |= TBM_OPTION_WRITE;
+
+        bo_handle = tbm_bo_map(privPixmap->bo, TBM_DEVICE_CPU, opt);
+        pPix->devPrivate.ptr = bo_handle.ptr;
+    }
+    else
+    {
+        if(privPixmap->pPixData)
+        {
+            pPix->devPrivate.ptr = privPixmap->pPixData;
+        }
+    }
+
+    XDBG_DEBUG (MEXA, "pix:%p index:%d hint:%d ptr:%p\n",
+                pPix, index, pPix->usage_hint, pPix->devPrivate.ptr);
+    return TRUE;
+}
+
+static void
+SECExaFinishAccess (PixmapPtr pPix, int index)
+{
+    XDBG_TRACE(MEXAS, "\n");
+    if (!pPix)
+        return;
+
+    SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix);
+
+    if(privPixmap == NULL)
+        return;
+
+    if (privPixmap->bo)
+        tbm_bo_unmap (privPixmap->bo);
+
+    if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB)
+    {
+        secRenderBoUnref(privPixmap->bo);
+        privPixmap->bo = NULL;
+    }
+
+    if (pPix->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY)
+        secLayerUpdate (secLayerFind (LAYER_OUTPUT_LCD, LAYER_UPPER));
+
+    pPix->devPrivate.ptr = NULL;
+    XDBG_DEBUG (MEXA, "pix:%p index:%d hint:%d ptr:%p\n",
+                pPix, index, pPix->usage_hint, pPix->devPrivate.ptr);
+}
+
+static void *
+SECExaCreatePixmap (ScreenPtr pScreen, int size, int align)
+{
+    SECPixmapPriv *privPixmap = calloc (1, sizeof (SECPixmapPriv));
+
+    return privPixmap;
+}
+
+static void
+SECExaDestroyPixmap (ScreenPtr pScreen, void *driverPriv)
+{
+    XDBG_RETURN_IF_FAIL (driverPriv != NULL);
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+
+    SECPixmapPriv *privPixmap = (SECPixmapPriv*)driverPriv;
+
+    XDBG_TRACE (MEXA, "DESTROY_PIXMAP : usage_hint:0x%x\n", privPixmap->usage_hint);
+
+    switch(privPixmap->usage_hint)
+    {
+    case CREATE_PIXMAP_USAGE_FB:
+        pSec->pix_fb = pSec->pix_fb - privPixmap->size;
+        secRenderBoUnref (privPixmap->bo);
+        privPixmap->bo = NULL;
+        break;
+    case CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK:
+        pSec->pix_dri2_flip_back = pSec->pix_dri2_flip_back - privPixmap->size;
+        secRenderBoUnref (privPixmap->bo);
+        privPixmap->bo = NULL;
+        break;
+    case CREATE_PIXMAP_USAGE_SUB_FB:
+        /* TODO ???? */
+        pSec->pix_sub_fb = pSec->pix_sub_fb - privPixmap->size;
+        privPixmap->bo = NULL;
+        break;
+    case CREATE_PIXMAP_USAGE_OVERLAY:
+        /* TODO ???? */
+        pSec->pix_overlay = pSec->pix_overlay - privPixmap->size;
+        secRenderBoUnref (privPixmap->bo);
+        privPixmap->bo = NULL;
+
+        if (privPixmap->ovl_layer)
+        {
+            secLayerUnref (privPixmap->ovl_layer);
+            privPixmap->ovl_layer = NULL;
+        }
+
+        pSec->ovl_drawable = NULL;
+
+        SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+        xf86CrtcPtr pCrtc = secCrtcGetAtGeometry (pScrn, 0, 0,
+                                                  pSecMode->main_lcd_mode.hdisplay,
+                                                  pSecMode->main_lcd_mode.vdisplay);
+        secCrtcOverlayRef (pCrtc, FALSE);
+
+        break;
+    case CREATE_PIXMAP_USAGE_DRI2_BACK:
+        pSec->pix_dri2_back = pSec->pix_dri2_back - privPixmap->size;
+        tbm_bo_unref (privPixmap->bo);
+        privPixmap->bo = NULL;
+        break;
+    case CREATE_PIXMAP_USAGE_BACKING_PIXMAP:
+        pSec->pix_backing_pixmap = pSec->pix_backing_pixmap - privPixmap->size;
+        tbm_bo_unref (privPixmap->bo);
+        privPixmap->bo = NULL;
+        break;
+    default:
+        pSec->pix_normal = pSec->pix_normal - privPixmap->size;
+        tbm_bo_unref (privPixmap->bo);
+        privPixmap->bo = NULL;
+        break;
+    }
+
+    /* free pixmap private */
+    free (privPixmap);
+}
+
+static Bool
+SECExaModifyPixmapHeader (PixmapPtr pPixmap, int width, int height,
+                          int depth, int bitsPerPixel, int devKind, pointer pPixData)
+{
+    XDBG_RETURN_VAL_IF_FAIL(pPixmap, FALSE);
+
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+    SECPixmapPriv * privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPixmap);
+    long lSizeInBytes;
+
+    /* set the default headers of the pixmap */
+    miModifyPixmapHeader (pPixmap, width, height, depth, bitsPerPixel,
+                          devKind, pPixData);
+
+    /* screen pixmap : set a framebuffer pixmap */
+    if (pPixData == (void*)ROOT_FB_ADDR)
+    {
+        lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind;
+        pSec->pix_fb = pSec->pix_fb + lSizeInBytes;
+        pPixmap->usage_hint = CREATE_PIXMAP_USAGE_FB;
+        privPixmap->usage_hint = pPixmap->usage_hint;
+        privPixmap->isFrameBuffer = TRUE;
+        privPixmap->bo = NULL;
+        privPixmap->size = lSizeInBytes;
+
+        XDBG_TRACE (MEXA, "CREATE_PIXMAP_FB(%p) : (x,y,w,h)=(%d,%d,%d,%d)\n",
+                    pPixmap, pPixmap->drawable.x, pPixmap->drawable.y, width, height);
+
+        return TRUE;
+    }
+
+    if(pPixmap->usage_hint == CREATE_PIXMAP_USAGE_SUB_FB)
+    {
+        lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind;
+        pSec->pix_sub_fb = pSec->pix_sub_fb + lSizeInBytes;
+
+        pPixmap->devPrivate.ptr = NULL;
+        privPixmap->usage_hint = pPixmap->usage_hint;
+        privPixmap->isSubFramebuffer = TRUE;
+        privPixmap->bo = (tbm_bo)pPixData;
+        privPixmap->size = lSizeInBytes;
+
+        XDBG_TRACE (MEXA, "CREATE_PIXMAP_SUB_FB(%p) : (x,y,w,h)=(%d,%d,%d,%d)\n",
+                    pPixmap, pPixmap->drawable.x, pPixmap->drawable.y, width, height);
+
+        return TRUE;
+    }
+    else if(pPixmap->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY)
+    {
+        SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+        SECLayer *layer;
+        SECVideoBuf *vbuf;
+        int width, height;
+
+        lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind;
+        pSec->pix_overlay = pSec->pix_overlay + lSizeInBytes;
+
+        privPixmap->usage_hint = pPixmap->usage_hint;
+        privPixmap->size = lSizeInBytes;
+
+        pSec->ovl_drawable = &pPixmap->drawable;
+
+        /* change buffer if needed. */
+        xf86CrtcPtr pCrtc = secCrtcGetAtGeometry (pScrn, 0, 0,
+                                                  pSecMode->main_lcd_mode.hdisplay,
+                                                  pSecMode->main_lcd_mode.vdisplay);
+        secCrtcOverlayRef (pCrtc, TRUE);
+
+        layer = secLayerFind (LAYER_OUTPUT_LCD, LAYER_UPPER);
+        XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
+
+        vbuf = secLayerGetBuffer (layer);
+        XDBG_RETURN_VAL_IF_FAIL (vbuf != NULL, FALSE);
+
+        width = vbuf->width;
+        height = vbuf->height;
+
+        if (width != pSecMode->main_lcd_mode.hdisplay || height != pSecMode->main_lcd_mode.vdisplay)
+        {
+            XDBG_ERROR (MEXA, "layer size(%d,%d) should be (%dx%d). pixmap(%d,%d %dx%d)\n",
+                        width, height, pSecMode->main_lcd_mode.hdisplay, pSecMode->main_lcd_mode.vdisplay,
+                        pPixmap->screen_x, pPixmap->screen_y, pPixmap->drawable.width, pPixmap->drawable.height);
+            return FALSE;
+        }
+
+        privPixmap->bo = secRenderBoRef (vbuf->bo[0]);
+
+        privPixmap->ovl_layer = secLayerRef (layer);
+
+        XDBG_TRACE (MEXA, "CREATE_PIXMAP_OVERLAY(%p) : (x,y,w,h)=(%d,%d,%d,%d)\n",
+                    pPixmap, pPixmap->drawable.x, pPixmap->drawable.y, width, height);
+
+        return TRUE;
+    }
+    else if(pPixmap->usage_hint == CREATE_PIXMAP_USAGE_XVIDEO)
+    {
+        SECCvtProp prop = {0,};
+        tbm_bo old_bo = privPixmap->bo;
+
+        prop.id = FOURCC_RGB32;
+        prop.width = width;
+        prop.height = height;
+        prop.crop.width = width;
+        prop.crop.height = height;
+
+        secCvtEnsureSize (NULL, &prop);
+
+        privPixmap->bo = secRenderBoCreate(pScrn, prop.width, prop.height);
+        if (!privPixmap->bo)
+        {
+            XDBG_ERROR (MEXA, "Error: cannot create a xvideo buffer\n");
+            privPixmap->bo = old_bo;
+            return FALSE;
+        }
+
+        pPixmap->devKind = prop.width * 4;
+
+        lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind;
+        pSec->pix_dri2_flip_back = pSec->pix_dri2_flip_back + lSizeInBytes;
+
+        privPixmap->usage_hint = pPixmap->usage_hint;
+        privPixmap->isFrameBuffer = FALSE;
+        privPixmap->size = lSizeInBytes;
+
+        XDBG_TRACE (MEXA, "CREATE_PIXMAP_USAGE_XVIDEO(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n",
+                    pPixmap, privPixmap->bo, pPixmap->drawable.x, pPixmap->drawable.y, width, height);
+
+        if (old_bo)
+            tbm_bo_unref (old_bo);
+
+        return TRUE;
+    }
+    else if(pPixmap->usage_hint == CREATE_PIXMAP_USAGE_DRI2_FLIP_BACK)
+    {
+        privPixmap->bo = secRenderBoCreate(pScrn, width, height);
+        if (!privPixmap->bo)
+        {
+            XDBG_ERROR (MEXA, "Error: cannot create a back flip buffer\n");
+            return FALSE;
+        }
+        lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind;
+        pSec->pix_dri2_flip_back = pSec->pix_dri2_flip_back + lSizeInBytes;
+
+        privPixmap->usage_hint = pPixmap->usage_hint;
+        privPixmap->isFrameBuffer = TRUE;
+        privPixmap->size = lSizeInBytes;
+
+        XDBG_TRACE (MEXA, "CREATE_PIXMAP_DRI2_FLIP_BACK(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n",
+                    pPixmap, privPixmap->bo, pPixmap->drawable.x, pPixmap->drawable.y, width, height);
+
+        return TRUE;
+    }
+    else if (pPixmap->usage_hint == CREATE_PIXMAP_USAGE_DRI2_BACK)
+    {
+        lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind;
+        privPixmap->usage_hint = pPixmap->usage_hint;
+
+        privPixmap->bo = tbm_bo_alloc (pSec->tbm_bufmgr, lSizeInBytes, TBM_BO_DEFAULT);
+        if (privPixmap->bo == NULL)
+        {
+            XDBG_ERROR(MEXA, "Error on allocating BufferObject. size:%d\n",lSizeInBytes);
+            return FALSE;
+        }
+        pSec->pix_dri2_back = pSec->pix_dri2_back + lSizeInBytes;
+        privPixmap->size = lSizeInBytes;
+
+        XDBG_TRACE (MEXA, "CREATE_PIXMAP_USAGE_DRI2_BACK(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n",
+                    pPixmap, privPixmap->bo,
+                    pPixmap->drawable.x, pPixmap->drawable.y, width, height);
+
+        return TRUE;
+
+    }
+    else if (pPixmap->usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP)
+    {
+        lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind;
+        privPixmap->usage_hint = pPixmap->usage_hint;
+
+        privPixmap->bo = tbm_bo_alloc (pSec->tbm_bufmgr, lSizeInBytes, TBM_BO_DEFAULT);
+        if (privPixmap->bo == NULL)
+        {
+            XDBG_ERROR(MEXA, "Error on allocating BufferObject. size:%d\n",lSizeInBytes);
+            return FALSE;
+        }
+        pSec->pix_backing_pixmap = pSec->pix_backing_pixmap + lSizeInBytes;
+        privPixmap->size = lSizeInBytes;
+
+        XDBG_TRACE (MEXA, "CREATE_PIXMAP_USAGE_BACKING_PIXMAP(%p) : bo:%p (x,y,w,h)=(%d,%d,%d,%d)\n",
+                    pPixmap, privPixmap->bo,
+                    pPixmap->drawable.x, pPixmap->drawable.y, width, height);
+
+        return TRUE;
+
+    }
+
+    if(privPixmap->bo != NULL)
+    {
+        tbm_bo_unref (privPixmap->bo);
+        privPixmap->bo = NULL;
+    }
+
+    lSizeInBytes = pPixmap->drawable.height * pPixmap->devKind;
+    privPixmap->usage_hint = pPixmap->usage_hint;
+
+    /* pPixData is also set for text glyphs or SHM-PutImage */
+    if (pPixData)
+    {
+        privPixmap->pPixData = pPixData;
+        /*
+        privPixmap->bo = tbm_bo_attach(pSec->tbm_bufmgr,
+                                           NULL,
+                                           TBM_MEM_USERPTR,
+                                           lSizeInBytes, (unsigned int)pPixData);
+        */
+    }
+    else
+    {
+        /* create the pixmap private memory */
+        if (lSizeInBytes && privPixmap->bo == NULL)
+        {
+            privPixmap->bo = tbm_bo_alloc (pSec->tbm_bufmgr, lSizeInBytes, TBM_BO_DEFAULT);
+            if (privPixmap->bo == NULL)
+            {
+                XDBG_ERROR(MEXA, "Error on allocating BufferObject. size:%d\n",lSizeInBytes);
+                return FALSE;
+            }
+        }
+        pSec->pix_normal = pSec->pix_normal + lSizeInBytes;
+    }
+
+    XDBG_TRACE (MEXA, "CREATE_PIXMAP_NORMAL(%p) : bo:%p, pPixData:%p (%dx%d+%d+%d)\n",
+                pPixmap, privPixmap->bo, pPixData,
+                width, height,
+                pPixmap->drawable.x, pPixmap->drawable.y);
+
+    return TRUE;
+}
+
+static Bool
+SECExaPixmapIsOffscreen (PixmapPtr pPix)
+{
+    return TRUE;
+}
+
+Bool
+secExaInit (ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    ExaDriverPtr pExaDriver;
+    SECPtr pSec = SECPTR (pScrn);
+    SECExaPrivPtr pExaPriv;
+    unsigned int cpp = 4;
+
+    /* allocate the pExaPriv private */
+    pExaPriv = calloc (1, sizeof (*pExaPriv));
+    if (pExaPriv == NULL)
+        return FALSE;
+
+    /* allocate the EXA driver private */
+    pExaDriver = exaDriverAlloc();
+    if (pExaDriver == NULL)
+    {
+        free (pExaPriv);
+        return FALSE;
+    }
+
+    /* version of exa */
+    pExaDriver->exa_major = EXA_VERSION_MAJOR;
+    pExaDriver->exa_minor = EXA_VERSION_MINOR;
+
+    /* setting the memory stuffs */
+    pExaDriver->memoryBase = (void*)ROOT_FB_ADDR;
+    pExaDriver->memorySize = pScrn->videoRam * 1024;
+    pExaDriver->offScreenBase = pScrn->displayWidth * cpp * pScrn->virtualY;
+
+    pExaDriver->maxX = 1 << 16;
+    pExaDriver->maxY = 1 << 16;
+    pExaDriver->pixmapOffsetAlign = 0;
+    pExaDriver->pixmapPitchAlign = 8;
+    pExaDriver->flags = (EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS
+                         |EXA_SUPPORTS_OFFSCREEN_OVERLAPS
+                         |EXA_SUPPORTS_PREPARE_AUX);
+
+    pExaDriver->WaitMarker = SECExaWaitMarker;
+    pExaDriver->PrepareAccess = SECExaPrepareAccess;
+    pExaDriver->FinishAccess = SECExaFinishAccess;
+
+    pExaDriver->CreatePixmap = SECExaCreatePixmap;
+    pExaDriver->DestroyPixmap = SECExaDestroyPixmap;
+    pExaDriver->ModifyPixmapHeader = SECExaModifyPixmapHeader;
+    pExaDriver->PixmapIsOffscreen = SECExaPixmapIsOffscreen;
+
+    /* call init function */
+    if (pSec->is_sw_exa)
+    {
+        if (secExaSwInit (pScreen, pExaDriver))
+        {
+            XDBG_INFO (MEXA, "Initialized SEC SW_EXA acceleration OK !\n");
+        }
+        else
+        {
+            free (pExaPriv);
+            free (pExaDriver);
+            FatalError ("Failed to initialize SW_EXA\n");
+            return FALSE;
+        }
+    }
+    else
+    {
+        if (secExaG2dInit (pScreen, pExaDriver))
+        {
+            XDBG_INFO (MEXA, "Initialized SEC HW_EXA acceleration OK !\n");
+        }
+        else
+        {
+            free (pExaPriv);
+            free (pExaDriver);
+            FatalError ("Failed to initialize HW_EXA\n");
+            return FALSE;
+        }
+    }
+
+    /* exa driver init with exa driver private */
+    if (exaDriverInit (pScreen, pExaDriver))
+    {
+        pExaPriv->pExaDriver = pExaDriver;
+        pSec->pExaPriv = pExaPriv;
+    }
+    else
+    {
+        free (pExaDriver);
+        free (pExaPriv);
+        FatalError ("Failed to initialize EXA...exaDriverInit\n");
+        return FALSE;
+    }
+
+    /* block handler */
+    RegisterBlockAndWakeupHandlers (_secExaBlockHandler /*blockHandler*/,
+                                    NULL /*wakeupHandler*/,
+                                    NULL /*blockData*/);
+
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO
+                , "EXA driver is Loaded successfully\n");
+
+    return TRUE;
+}
+
+void
+secExaDeinit (ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+
+    /* call Fini function */
+    if (pSec->is_sw_exa)
+    {
+        secExaSwDeinit (pScreen);
+        XDBG_INFO (MEXA, "Finish SW EXA acceleration.\n");
+    }
+
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO
+                , "EXA driver is UnLoaded successfully\n");
+}
+
+Bool
+secExaPrepareAccess (PixmapPtr pPix, int index)
+{
+    return SECExaPrepareAccess (pPix, index);
+}
+
+void
+secExaFinishAccess (PixmapPtr pPix, int index)
+{
+    SECExaFinishAccess (pPix, index);
+}
+
+int
+secExaScreenAsyncSwap (ScreenPtr pScreen, int enable)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+
+    if(enable == -1)
+        return pSec->useAsyncSwap;
+
+    if ( enable == 1)
+        pSec->useAsyncSwap = TRUE;
+    else
+        pSec->useAsyncSwap = FALSE;
+
+    return pSec->useAsyncSwap;
+}
+
+int
+secExaScreenSetScrnPixmap (ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    PixmapPtr pPix = (*pScreen->GetScreenPixmap) (pScreen);
+    unsigned int pitch = pScrn->virtualX * 4;
+    (*pScreen->ModifyPixmapHeader) (pPix, pScrn->virtualX, pScrn->virtualY,
+                                    -1, -1, pitch, (void*)ROOT_FB_ADDR);
+    pScrn->displayWidth = pitch / 4;
+    return 1;
+}
+
+Bool
+secExaMigratePixmap (PixmapPtr pPix, tbm_bo bo)
+{
+    SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPix);
+
+    tbm_bo_unref (privPixmap->bo);
+    privPixmap->bo = tbm_bo_ref(bo);
+
+    return TRUE;
+}
+
+tbm_bo
+secExaPixmapGetBo (PixmapPtr pPix)
+{
+    tbm_bo bo = NULL;
+    SECPixmapPriv *pExaPixPriv = NULL;
+
+    if (pPix == NULL)
+        return 0;
+
+    pExaPixPriv = exaGetPixmapDriverPrivate (pPix);
+    if (pExaPixPriv == NULL)
+        return 0;
+
+    bo = pExaPixPriv->bo;
+
+    return bo;
+}
diff --git a/src/accel/sec_exa_g2d.c b/src/accel/sec_exa_g2d.c
new file mode 100644 (file)
index 0000000..d4e7e58
--- /dev/null
@@ -0,0 +1,1724 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "sec.h"
+#include "sec_accel.h"
+#include "sec_util.h"
+#include "sec_layer.h"
+#include "exa.h"
+#include "fbpict.h"
+#include "neonmem.h"
+#include "g2d/fimg2d.h"
+
+#define DO(x)   ((x.bDo==DO_DRAW_NONE)?"SKIP": \
+                            ((x.bDo==DO_DRAW_SW)?"SW":"HW"))
+
+#define PIXINFO(pPixmap)       if(pPixmap) { \
+                                                    XDBG_TRACE(MEXAH, "%s:%p(0x%x) %dx%d depth:%d(%d) pitch:%d\n", \
+                                                                #pPixmap,    \
+                                                                pPixmap, ID(pPixmap), \
+                                                                pPixmap->drawable.width, pPixmap->drawable.height, \
+                                                                pPixmap->drawable.depth, \
+                                                                pPixmap->drawable.bitsPerPixel, \
+                                                                pPixmap->devKind); \
+                                                }
+
+#define PICINFO(pPic)       if(pPic) { \
+                                                    XDBG_TRACE(MEXAH, "%s, draw:%p, repeat:%d(%d), ca:%d, srcPict:%p\n", \
+                                                                #pPic,    \
+                                                                pPic->pDrawable,  \
+                                                                pPic->repeat, pPic->repeatType, \
+                                                                pPic->componentAlpha, \
+                                                                pPic->pSourcePict); \
+                                                    if(pPic->transform) { \
+                                                        XDBG_TRACE("EXA2D", "\t0x%08x  0x%08x 0x%08x\n", \
+                                                                    pPic->transform->matrix[0][0], \
+                                                                    pPic->transform->matrix[0][1], \
+                                                                    pPic->transform->matrix[0][2]); \
+                                                        XDBG_TRACE("EXA2D", "\t0x%08x  0x%08x 0x%08x\n", \
+                                                                    pPic->transform->matrix[1][0], \
+                                                                    pPic->transform->matrix[1][1], \
+                                                                    pPic->transform->matrix[1][2]); \
+                                                        XDBG_TRACE("EXA2D", "\t0x%08x  0x%08x 0x%08x\n", \
+                                                                    pPic->transform->matrix[1][0], \
+                                                                    pPic->transform->matrix[1][1], \
+                                                                    pPic->transform->matrix[1][2]); \
+                                                    }\
+                                                }
+
+typedef struct
+{
+    BoxRec  pos;
+    PixmapPtr pixmap;
+    tbm_bo bo;
+
+    unsigned int access_device; /*TBM_DEVICE_XXX*/
+    unsigned int access_data;   /*pointer or gem*/
+    G2dImage* imgG2d;
+} ExaOpBuf;
+
+typedef struct
+{
+    int refcnt;
+    int opt;
+    int num;
+    int isSame;
+
+    ExaOpBuf buf[5];
+} ExaOpInfo;
+
+typedef struct
+{
+    BoxRec box;
+    int state;            /*state of region*/
+
+    struct xorg_list link;
+
+    ExaOpBuf *pSrc;
+    ExaOpBuf *pMask;
+    ExaOpBuf *pDst;
+} ExaBox;
+
+enum{
+    DO_DRAW_NONE,
+    DO_DRAW_SW,
+    DO_DRAW_HW
+};
+
+typedef struct
+{
+    char bDo;
+
+    int alu;
+    Pixel planemask;
+    Pixel fg;
+    PixmapPtr pixmap;
+
+    int x,y,w,h;
+    GCPtr pGC;
+    ExaOpInfo* pOpDst;
+    struct xorg_list opBox;
+} OpSolid;
+
+typedef struct
+{
+    char bDo;
+
+    Pixel pm;
+    int alu;
+    int reverse;
+    int upsidedown;
+    PixmapPtr pSrcPix;
+    PixmapPtr pDstPix;
+
+    /*copy param*/
+    int srcX;
+    int srcY;
+    int dstX;
+    int dstY;
+    int width, height;
+
+    ExaOpInfo* pOpDst;
+    ExaOpInfo* pOpSrc;
+    struct xorg_list opBox;
+} OpCopy;
+
+typedef struct
+{
+    char bDo;
+
+    int op;
+    PicturePtr pSrcPicture;
+    PicturePtr pMaskPicture;
+    PicturePtr pDstPicture;
+    PixmapPtr pSrcPixmap;
+    PixmapPtr pMaskPixmap;
+    PixmapPtr pDstPixmap;
+
+    /*copy param*/
+    int srcX, srcY;
+    int maskX, maskY;
+    int dstX, dstY;
+    int width, height;
+
+    char srcRepeat;
+    char srcRotate;
+    double srcScaleX;
+    double srcScaleY;
+
+    char maskRepeat;
+    char maskRotate;
+    double maskScaleX;
+    double maskScaleY;
+
+    ExaOpInfo* pOpSrc;
+    ExaOpInfo* pOpMask;
+    ExaOpInfo* pOpDst;
+    struct xorg_list opBox;
+} OpComposite;
+
+typedef struct
+{
+    char bDo;
+
+    PixmapPtr pDst;
+    int x,y,w,h;
+    char* src;
+    int src_pitch;
+
+    G2dImage* imgSrc;
+    ExaOpInfo* pOpDst;
+    struct xorg_list opBox;
+} OpUTS;
+
+typedef struct
+{
+    char bDo;
+
+    PixmapPtr pSrc;
+    int x,y,w,h;
+    char* dst;
+    int dst_pitch;
+
+    G2dImage* imgDst;
+    ExaOpInfo* pOpSrc;
+    struct xorg_list opBox;
+} OpDFS;
+
+typedef void (* DoDrawProcPtr) (PixmapPtr pPix, Bool isPart,
+                                int x, int y,
+                                int clip_x, int clip_y,
+                                int w, int h, void* data);
+
+typedef void (* DoDrawProcPtrEx) (ExaBox* box, void* data);
+
+static ExaOpInfo OpInfo[EXA_NUM_PREPARE_INDICES];
+static OpSolid gOpSolid;
+static OpCopy gOpCopy;
+static OpComposite gOpComposite;
+static OpUTS gOpUTS;
+static OpDFS gOpDFS;
+
+ExaBox* _g2dBoxAdd (struct xorg_list *l, BoxPtr b1, BoxPtr b2)
+{
+    ExaBox* rgn;
+
+    rgn = calloc (1, sizeof (ExaBox));
+    rgn->state = secUtilBoxIntersect (&rgn->box, b1, b2);
+    if (rgnOUT == rgn->state)
+    {
+        free (rgn);
+        return NULL;
+    }
+
+    xorg_list_add (&rgn->link, l);
+    return rgn;
+}
+
+void _g2dBoxMerge (struct xorg_list *l, struct xorg_list* b, struct xorg_list* t)
+{
+    ExaBox *b1, *b2;
+    ExaBox* r=NULL;
+
+    xorg_list_for_each_entry (b1, b, link)
+    {
+        xorg_list_for_each_entry (b2, t, link)
+        {
+            r = _g2dBoxAdd (l, &b1->box, &b2->box);
+            if (r)
+            {
+                r->pSrc = b1->pSrc ? b1->pSrc : b2->pSrc;
+                r->pMask= b1->pMask ? b1->pMask : b2->pMask;
+                r->pDst = b1->pDst ? b1->pDst : b2->pDst;
+            }
+        }
+    }
+}
+
+void _g2dBoxMove (struct xorg_list* l, int tx, int ty)
+{
+    ExaBox *b;
+
+    xorg_list_for_each_entry (b, l, link)
+    {
+        secUtilBoxMove (&b->box, tx, ty);
+    }
+}
+
+void _g2dBoxRemoveAll (struct xorg_list* l)
+{
+    ExaBox *ref, *next;
+
+    xorg_list_for_each_entry_safe (ref, next, l, link)
+    {
+        xorg_list_del (&ref->link);
+        free (ref);
+    }
+}
+
+int _g2dBoxIsOne (struct xorg_list* l)
+{
+    if (l->next != l)
+    {
+        if (l->next == l->prev)
+            return 1;
+        else
+            return -1;
+    }
+
+    return 0;
+}
+
+void _g2dBoxPrint (ExaBox* sb1, const char* name)
+{
+    ExaBox *b;
+
+    xorg_list_for_each_entry (b, &sb1->link, link)
+    {
+        XDBG_DEBUG (MEXAS, "[%s] %d,%d - %d,%d\n", name,
+                b->box.x1, b->box.y1, b->box.x2, b->box.y2);
+    }
+}
+
+static pixman_bool_t
+_g2d_check_within_epsilon (pixman_fixed_t a,
+                pixman_fixed_t b,
+                pixman_fixed_t epsilon)
+{
+    pixman_fixed_t t = a - b;
+
+    if (t < 0)
+        t = -t;
+
+    return t <= epsilon;
+}
+
+static Bool
+_g2d_check_picture(PicturePtr pPicture, char *rot90, double *scaleX, double *scaleY, char* repeat)
+{
+    struct pixman_transform* t;
+
+#define EPSILON (pixman_fixed_t) (2)
+
+#define IS_SAME(a, b) (_g2d_check_within_epsilon (a, b, EPSILON))
+#define IS_ZERO(a)    (_g2d_check_within_epsilon (a, 0, EPSILON))
+#define IS_ONE(a)     (_g2d_check_within_epsilon (a, F (1), EPSILON))
+#define IS_UNIT(a)                          \
+                                    (_g2d_check_within_epsilon (a, F (1), EPSILON) ||  \
+                                    _g2d_check_within_epsilon (a, F (-1), EPSILON) || \
+                                    IS_ZERO (a))
+#define IS_INT(a)    (IS_ZERO (pixman_fixed_frac (a)))
+
+/*RepeatNormal*/
+
+    if(pPicture == NULL)
+    {
+        return TRUE;
+    }
+
+    if(pPicture->repeat)
+    {
+        switch(pPicture->repeatType)
+        {
+        case RepeatNormal:
+            *repeat = G2D_REPEAT_MODE_REPEAT;
+            break;
+        case RepeatPad:
+            *repeat = G2D_REPEAT_MODE_PAD;
+            break;
+        case RepeatReflect:
+            *repeat = G2D_REPEAT_MODE_REFLECT;
+            break;
+        default:
+            *repeat = G2D_REPEAT_MODE_NONE;
+            break;
+        }
+    }
+    else
+    {
+        *repeat = G2D_REPEAT_MODE_NONE;
+    }
+
+    if(pPicture->transform == NULL)
+    {
+        *rot90 = 0;
+        *scaleX = 1.0;
+        *scaleY = 1.0;
+        return TRUE;
+    }
+
+    t= pPicture->transform;
+
+    if(!IS_ZERO(t->matrix[0][0]) && IS_ZERO(t->matrix[0][1]) && IS_ZERO(t->matrix[1][0]) && !IS_ZERO(t->matrix[1][1]))
+    {
+        *rot90 = FALSE;
+        *scaleX = pixman_fixed_to_double(t->matrix[0][0]);
+        *scaleY = pixman_fixed_to_double(t->matrix[1][1]);
+    }
+    else if(IS_ZERO(t->matrix[0][0]) && !IS_ZERO(t->matrix[0][1]) && !IS_ZERO(t->matrix[1][0]) && IS_ZERO(t->matrix[1][1]))
+    {
+        /* FIMG2D 90 => PIXMAN 270 */
+        *rot90 = TRUE;
+        *scaleX = pixman_fixed_to_double(t->matrix[0][1]);
+        *scaleY = pixman_fixed_to_double(t->matrix[1][0]*-1);
+    }
+    else
+    {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static Bool
+_g2dIsSupport(PixmapPtr pPix, Bool forMask)
+{
+    SECPixmapPriv *privPixmap;
+
+    if(!pPix) return TRUE;
+
+    if(!forMask && pPix->drawable.depth < 8)
+        return FALSE;
+
+    privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix);
+    if(!privPixmap->isFrameBuffer && !privPixmap->bo)
+        return FALSE;
+
+    return TRUE;
+}
+
+static G2dImage*
+_g2dGetImageFromPixmap(PixmapPtr pPix, unsigned int gem)
+{
+    G2dImage* img;
+    G2dColorKeyMode mode;
+
+    if(gem == 0)
+    {
+        gem = (unsigned int)pPix->devPrivate.ptr;
+    }
+
+    XDBG_RETURN_VAL_IF_FAIL((pPix != NULL && gem != 0), NULL);
+
+    switch(pPix->drawable.depth)
+    {
+    case 32:
+        mode = G2D_COLOR_FMT_ARGB8888|G2D_ORDER_AXRGB;
+        break;
+    case 24:
+        mode = G2D_COLOR_FMT_XRGB8888|G2D_ORDER_AXRGB;
+        break;
+    case 16:
+        mode = G2D_COLOR_FMT_RGB565|G2D_ORDER_AXRGB;
+        break;
+    case 8:
+        mode = G2D_COLOR_FMT_A8|G2D_ORDER_AXRGB;
+        break;
+    case 1:
+        mode = G2D_COLOR_FMT_A1|G2D_ORDER_AXRGB;
+        break;
+    default:
+        XDBG_ERROR(MEXA, "Unsupport format depth:%d(%d),pitch:%d \n",
+                   pPix->drawable.depth, pPix->drawable.bitsPerPixel, pPix->devKind);
+        return NULL;
+    }
+
+    img = g2d_image_create_bo(mode,
+                                            pPix->drawable.width,
+                                            pPix->drawable.height,
+                                            gem,
+                                            pPix->devKind);
+
+    return img;
+}
+
+static ExaOpInfo* _g2dPrepareAccess (PixmapPtr pPix, int index, unsigned int device)
+{
+    ScreenPtr pScreen = pPix->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+    SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix);
+    ExaOpInfo* op = &OpInfo[index];
+    int opt = TBM_OPTION_READ;
+    int i;
+    tbm_bo *bos;
+    tbm_bo_handle bo_handle;
+    SECFbBoDataPtr bo_data;
+    int num_bo;
+    int ret;
+
+    XDBG_RETURN_VAL_IF_FAIL ((privPixmap != NULL), NULL);
+
+    if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST)
+        opt |= TBM_OPTION_WRITE;
+
+    /* Check mapped */
+    if (privPixmap->exaOpInfo)
+    {
+        op = (ExaOpInfo*)privPixmap->exaOpInfo;
+        op->refcnt++;
+        XDBG_TRACE (MEXAH, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
+                    pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
+        return op;
+    }
+
+    /*Set buffer info*/
+    memset (op, 0x00, sizeof (ExaOpInfo));
+    op->refcnt = 1;
+    op->opt = opt;
+    op->isSame = 0;
+
+    if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB)
+    {
+        ret = secFbFindBo (pSec->pFb,
+                           pPix->drawable.x, pPix->drawable.y,
+                           pPix->drawable.width, pPix->drawable.height,
+                           &num_bo, &bos);
+        XDBG_TRACE (MEXAH,"FB  ret:%d num_pix:%d, %dx%d+%d+%d\n",
+                    ret, num_bo,
+                    pPix->drawable.width, pPix->drawable.height,
+                    pPix->drawable.x, pPix->drawable.y);
+
+        if (ret == rgnSAME && num_bo == 1)
+        {
+            op->num = 1;
+            op->isSame = 1;
+
+            op->buf[0].pixmap = pPix;
+            op->buf[0].bo = bos[0];
+            op->buf[0].pos.x1 = 0;
+            op->buf[0].pos.y1 = 0;
+            op->buf[0].pos.x2 = pPix->drawable.width;
+            op->buf[0].pos.y2 = pPix->drawable.height;
+
+            op->buf[0].access_device = device;
+            bo_handle = tbm_bo_map (op->buf[0].bo, device, op->opt);
+            op->buf[0].access_data = bo_handle.u32;
+            op->buf[0].pixmap->devPrivate.ptr = (pointer)op->buf[0].access_data;
+            if(device == TBM_DEVICE_2D)
+            {
+                op->buf[0].imgG2d = _g2dGetImageFromPixmap(op->buf[0].pixmap,
+                                                                                            op->buf[0].access_data);
+            }
+        }
+        else
+        {
+            op->num = num_bo;
+            op->isSame = 0;
+
+            for (i = 0; i < num_bo; i++)
+            {
+                tbm_bo_get_user_data (bos[i], TBM_BO_DATA_FB, (void**)&bo_data);
+                op->buf[i].pixmap = secRenderBoGetPixmap (pSec->pFb, bos[i]);
+                op->buf[i].bo = bos[i];
+                op->buf[i].pos = bo_data->pos;
+
+                op->buf[i].access_device = device;
+                bo_handle = tbm_bo_map (op->buf[i].bo, device, op->opt);
+                op->buf[i].access_data = bo_handle.u32;
+                op->buf[i].pixmap->devPrivate.ptr = (pointer)op->buf[i].access_data;
+                if(device == TBM_DEVICE_2D)
+                {
+                    op->buf[i].imgG2d = _g2dGetImageFromPixmap(op->buf[i].pixmap,
+                                                                                                op->buf[i].access_data);
+                }
+            }
+
+            if (bos)
+                free (bos);
+        }
+    }
+    else
+    {
+        op->num = 1;
+        op->isSame = 1;
+
+        op->buf[0].pixmap = pPix;
+        op->buf[0].bo = privPixmap->bo;
+        op->buf[0].pos.x1 = 0;
+        op->buf[0].pos.y1 = 0;
+        op->buf[0].pos.x2 = pPix->drawable.width;
+        op->buf[0].pos.y2 = pPix->drawable.height;
+
+        op->buf[0].access_device = device;
+        if (privPixmap->bo)
+        {
+            bo_handle = tbm_bo_map (op->buf[0].bo, device, op->opt);
+            op->buf[0].access_data =  bo_handle.u32;
+            if(device == TBM_DEVICE_2D)
+            {
+                op->buf[0].imgG2d = _g2dGetImageFromPixmap(op->buf[0].pixmap, op->buf[0].access_data);
+            }
+        }
+        else
+        {
+            op->buf[0].access_data = (unsigned int)privPixmap->pPixData;
+            op->buf[0].imgG2d = NULL;
+        }
+        op->buf[0].pixmap->devPrivate.ptr = (pointer)op->buf[0].access_data;
+    }
+
+    privPixmap->exaOpInfo = op;
+
+    XDBG_TRACE (MEXAH, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
+                pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
+    return op;
+}
+
+static void _g2dFinishAccess (PixmapPtr pPix, int index)
+{
+    XDBG_RETURN_IF_FAIL (pPix!=NULL);
+
+    SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix);
+    ExaOpInfo* op;
+    int i;
+
+    XDBG_RETURN_IF_FAIL (privPixmap!=NULL);
+    XDBG_RETURN_IF_FAIL (privPixmap->exaOpInfo!=NULL);
+
+    op = (ExaOpInfo*)privPixmap->exaOpInfo;
+    op->refcnt --;
+
+    if (op->refcnt == 0)
+    {
+        for (i=0; i<op->num; i++)
+        {
+            if(op->buf[i].bo)
+            {
+                tbm_bo_unmap(op->buf[i].bo);
+                op->buf[i].bo = NULL;
+            }
+
+            if(op->buf[i].pixmap)
+            {
+                op->buf[i].pixmap->devPrivate.ptr = NULL;
+                op->buf[i].pixmap = NULL;
+            }
+
+            if(op->buf[i].imgG2d)
+            {
+                g2d_image_free(op->buf[i].imgG2d);
+                op->buf[i].imgG2d = NULL;
+            }
+
+            op->buf[i].access_data = (unsigned int)NULL;
+        }
+
+        privPixmap->exaOpInfo = NULL;
+    }
+
+    if (pPix->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY)
+        secLayerUpdate (secLayerFind (LAYER_OUTPUT_LCD, LAYER_UPPER));
+
+    XDBG_TRACE (MEXAH, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
+                pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
+}
+
+void
+_g2dDoDraw (struct xorg_list *l, DoDrawProcPtrEx do_draw, void* data)
+{
+    ExaBox *box;
+    xorg_list_for_each_entry (box, l, link)
+    {
+        do_draw (box, data);
+    }
+}
+
+static void
+_g2dDoSolid (ExaBox* box, void* data)
+{
+    XDBG_TRACE (MEXAH, "[%s] (%d,%d), (%d,%d) off(%d,%d)\n",
+                DO(gOpSolid),
+                box->box.x1,
+                box->box.y1,
+                box->box.x2,
+                box->box.y2,
+                gOpSolid.x,
+                gOpSolid.y);
+
+    if(gOpSolid.bDo == DO_DRAW_SW)
+    {
+        fbFill (&box->pDst->pixmap->drawable,
+                gOpSolid.pGC,
+                box->box.x1 + gOpSolid.x - box->pDst->pos.x1,
+                box->box.y1 + gOpSolid.y - box->pDst->pos.y1,
+                box->box.x2- box->box.x1,
+                box->box.y2- box->box.y1);
+    }
+    else
+    {
+        util_g2d_fill_alu(box->pDst->imgG2d,
+                box->box.x1 + gOpSolid.x - box->pDst->pos.x1,
+                box->box.y1 + gOpSolid.y - box->pDst->pos.y1,
+                box->box.x2- box->box.x1,
+                box->box.y2- box->box.y1,
+                gOpSolid.fg,
+                (G2dAlu)gOpSolid.alu);
+    }
+}
+
+static void
+_g2dDoCopy (ExaBox* box, void* data)
+{
+    CARD8 alu = gOpCopy.alu;
+    FbBits pm = gOpCopy.pm;
+    FbBits *src;
+    FbStride srcStride;
+    int        srcBpp;
+    FbBits *dst;
+    FbStride dstStride;
+    int        dstBpp;
+    _X_UNUSED int      srcXoff, srcYoff;
+    _X_UNUSED int      dstXoff, dstYoff;
+    int srcX, srcY, dstX, dstY, width, height;
+
+    XDBG_TRACE (MEXAH, "[%s] box(%d,%d),(%d,%d) src(%d,%d) dst(%d,%d)\n",
+                DO(gOpCopy),
+                box->box.x1,
+                box->box.y1,
+                box->box.x2,
+                box->box.y2,
+                gOpCopy.srcX,
+                gOpCopy.srcY);
+
+    srcX = gOpCopy.srcX + box->box.x1 - box->pSrc->pos.x1;
+    srcY = gOpCopy.srcY + box->box.y1 - box->pSrc->pos.y1;
+    dstX = gOpCopy.dstX + box->box.x1 - box->pDst->pos.x1;
+    dstY = gOpCopy.dstY + box->box.y1 - box->pDst->pos.y1;
+    width = box->box.x2 - box->box.x1;
+    height = box->box.y2 - box->box.y1;
+
+    if(gOpCopy.bDo == DO_DRAW_SW)
+    {
+        fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
+        fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+        /* temp fix : do right things later */
+        if (!src || !dst)
+        {
+            return;
+        }
+
+        if (pm != FB_ALLONES ||
+                alu != GXcopy ||
+                gOpCopy.reverse ||
+                gOpCopy.upsidedown ||
+                !pixman_blt ((uint32_t *)src, (uint32_t *)dst,
+                             srcStride,
+                             dstStride,
+                             srcBpp, dstBpp,
+                             srcX, srcY, dstX, dstY, width, height))
+        {
+            fbBlt (src + srcY * srcStride,
+                   srcStride,
+                   srcX * srcBpp,
+
+                   dst + dstY * dstStride,
+                   dstStride,
+                   dstX * dstBpp,
+
+                   width * dstBpp,
+                   height,
+
+                   alu,
+                   pm,
+                   dstBpp,
+
+                   gOpCopy.reverse,
+                   gOpCopy.upsidedown);
+        }
+    }
+    else
+    {
+        util_g2d_copy_alu(box->pSrc->imgG2d,
+                                        box->pDst->imgG2d,
+                                        srcX, srcY,
+                                        dstX, dstY,
+                                        width, height,
+                                        gOpCopy.alu);
+    }
+}
+
+static void
+_g2dDoComposite (ExaBox* box, void* data)
+{
+
+    if (box->state == rgnPART)
+    {
+        XDBG_RETURN_IF_FAIL (gOpComposite.pSrcPicture->transform == NULL);
+        XDBG_RETURN_IF_FAIL (gOpComposite.pMaskPicture &&
+                             gOpComposite.pMaskPicture->transform == NULL);
+    }
+
+    if (gOpComposite.bDo == DO_DRAW_SW)
+    {
+        PicturePtr     pDstPicture;
+        pixman_image_t *src, *mask, *dest;
+        int src_xoff, src_yoff, msk_xoff, msk_yoff;
+        FbBits *bits;
+        FbStride stride;
+        int bpp;
+
+        pDstPicture = gOpComposite.pDstPicture;
+
+        src = image_from_pict (gOpComposite.pSrcPicture, FALSE, &src_xoff, &src_yoff);
+        mask = image_from_pict (gOpComposite.pMaskPicture, FALSE, &msk_xoff, &msk_yoff);
+
+        fbGetPixmapBitsData (box->pDst->pixmap, bits, stride, bpp);
+        dest = pixman_image_create_bits (pDstPicture->format,
+                                         box->pDst->pixmap->drawable.width,
+                                         box->pDst->pixmap->drawable.height,
+                                         (uint32_t *)bits, stride * sizeof (FbStride));
+
+        pixman_image_composite (gOpComposite.op,
+                                src, mask, dest,
+                                gOpComposite.srcX + box->box.x1,
+                                gOpComposite.srcY + box->box.y1,
+                                gOpComposite.maskX + box->box.x1,
+                                gOpComposite.maskY + box->box.y1,
+                                gOpComposite.dstX + box->box.x1 - box->pDst->pos.x1,
+                                gOpComposite.dstY + box->box.y1 - box->pDst->pos.y1,
+                                box->box.x2 - box->box.x1,
+                                box->box.y2 - box->box.y1);
+
+        free_pixman_pict (gOpComposite.pSrcPicture, src);
+        free_pixman_pict (gOpComposite.pMaskPicture, mask);
+        pixman_image_unref (dest);
+    }
+    else
+    {
+        util_g2d_composite (gOpComposite.op,
+                                    box->pSrc->imgG2d,
+                                    box->pMask ? box->pMask->imgG2d:NULL,
+                                    box->pDst->imgG2d,
+                                    gOpComposite.srcX + box->box.x1,
+                                    gOpComposite.srcY + box->box.y1,
+                                    gOpComposite.maskX + box->box.x1,
+                                    gOpComposite.maskY + box->box.y1,
+                                    gOpComposite.dstX + box->box.x1 - box->pDst->pos.x1,
+                                    gOpComposite.dstY + box->box.y1 - box->pDst->pos.y1,
+                                    box->box.x2 - box->box.x1,
+                                    box->box.y2 - box->box.y1);
+    }
+}
+
+static void
+_g2dDoUploadToScreen (ExaBox* box, void* data)
+{
+    int             dstX, dstY;
+    int             width, height;
+
+    dstX = gOpUTS.x + box->box.x1 - box->pDst->pos.x1;
+    dstY = gOpUTS.y + box->box.y1 - box->pDst->pos.y1;
+    width = box->box.x2 - box->box.x1;
+    height = box->box.y2 - box->box.y1;
+
+    if(gOpUTS.bDo == DO_DRAW_SW)
+    {
+        FbBits *dst;
+        FbStride       dstStride;
+        int            dstBpp;
+        _X_UNUSED int          dstXoff, dstYoff;
+        int              srcStride;
+
+        fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+
+        srcStride = gOpUTS.src_pitch/sizeof (uint32_t);
+
+        XDBG_TRACE (MEXAH, "src(%p, %d) %d,%d,%d,%d\n",
+                    gOpUTS.src, srcStride, dstX, dstY, width, height);
+
+        if (!pixman_blt ((uint32_t *)gOpUTS.src,
+                         (uint32_t *)dst,
+                         srcStride,
+                         dstStride,
+                         dstBpp, dstBpp,
+                         box->box.x1, box->box.y1,
+                         dstX, dstY,
+                         width, height))
+        {
+            fbBlt ((FbBits*) ((FbBits*)gOpUTS.src),
+                   srcStride,
+                   box->box.x1,
+
+                   dst + dstY * dstStride,
+                   dstStride,
+                   dstX,
+
+                   width,
+                   height,
+
+                   GXcopy,
+                   ~0,
+                   dstBpp,
+
+                   0,
+                   0);
+        }
+    }
+    else
+    {
+        util_g2d_copy(gOpUTS.imgSrc,
+                            box->pDst->imgG2d,
+                            box->box.x1, box->box.y1,
+                            dstX, dstY,
+                            width, height);
+    }
+}
+
+static void
+_g2dDoDownladFromScreen (ExaBox* box, void* data)
+{
+    int             srcX, srcY;
+    int             width, height;
+    int             dstStride;
+
+    dstStride = gOpDFS.dst_pitch/sizeof (uint32_t);
+    srcX = gOpDFS.x + box->box.x1 - box->pSrc->pos.x1;
+    srcY = gOpDFS.y + box->box.y1 - box->pSrc->pos.y1;
+    width = box->box.x2 - box->box.x1;
+    height = box->box.y2 - box->box.y1;
+
+    XDBG_TRACE (MEXAH, "dst(%p, %d) %d,%d,%d,%d\n",
+                gOpDFS.dst, dstStride, srcX, srcY, width, height);
+
+    if(gOpDFS.bDo == DO_DRAW_SW)
+    {
+        FbBits *src;
+        FbStride       srcStride;
+        int            srcBpp;
+        _X_UNUSED int          srcXoff, srcYoff;
+
+        fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
+
+        if (!pixman_blt ((uint32_t *)src,
+                         (uint32_t *)gOpDFS.dst,
+                         srcStride,
+                         dstStride,
+                         srcBpp, srcBpp,
+                         srcX, srcY,
+                         box->box.x1, box->box.y1,
+                         width, height))
+        {
+            fbBlt (src + srcY * srcStride,
+                   srcStride,
+                   srcX,
+
+                   (FbBits*) ((FbBits*)gOpDFS.dst),
+                   dstStride,
+                   box->box.x1,
+
+                   width,
+                   height,
+
+                   GXcopy,
+                   ~0,
+                   srcBpp,
+
+                   0,
+                   0);
+        }
+    }
+    else
+    {
+        util_g2d_copy (box->pSrc->imgG2d,
+                                gOpDFS.imgDst,
+                                srcX, srcY,
+                                box->box.x1, box->box.y1,
+                                width, height);
+    }
+}
+
+static Bool
+SECExaG2dPrepareSolid (PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
+{
+    ScreenPtr pScreen = pPixmap->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    ChangeGCVal tmpval[3];
+
+    XDBG_TRACE (MEXAH, "\n");
+    memset (&gOpSolid, 0x00, sizeof (gOpSolid));
+
+    /* Put ff at the alpha bits when transparency is set to xv */
+    if (pPixmap->drawable.depth == 24)
+        fg = fg | (~ (pScrn->mask.red|pScrn->mask.green|pScrn->mask.blue));
+
+    gOpSolid.alu = alu;
+    gOpSolid.fg = fg;
+    gOpSolid.planemask = planemask;
+    gOpSolid.pixmap = pPixmap;
+
+    if (!_g2dIsSupport(pPixmap, 0))
+    {
+        gOpSolid.pOpDst = _g2dPrepareAccess (pPixmap,
+                                                                        EXA_PREPARE_DEST,
+                                                                        TBM_DEVICE_CPU);
+        XDBG_GOTO_IF_FAIL (gOpSolid.pOpDst, bail);
+
+        gOpSolid.pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
+        tmpval[0].val = alu;
+        tmpval[1].val = planemask;
+        tmpval[2].val = fg;
+        ChangeGC (NullClient, gOpSolid.pGC, GCFunction|GCPlaneMask|GCForeground, tmpval);
+        ValidateGC (&pPixmap->drawable, gOpSolid.pGC);
+
+        gOpSolid.bDo = DO_DRAW_SW;
+    }
+    else
+    {
+        gOpSolid.pOpDst = _g2dPrepareAccess (pPixmap,
+                                                                        EXA_PREPARE_DEST,
+                                                                        TBM_DEVICE_2D);
+        XDBG_GOTO_IF_FAIL (gOpSolid.pOpDst, bail);
+        gOpSolid.bDo = DO_DRAW_HW;
+    }
+
+    return TRUE;
+
+bail:
+    XDBG_TRACE (MEXAH, "FAIL: pix:%p hint:%d, num_pix:%d\n",
+                pPixmap, index, pPixmap->usage_hint, gOpSolid.pOpDst->num);
+    gOpSolid.bDo = DO_DRAW_NONE;
+    gOpSolid.pGC = NULL;
+
+    return TRUE;
+}
+
+
+static void
+SECExaG2dSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
+{
+    XDBG_TRACE (MEXAH, " (%d,%d), (%d,%d)\n", x1,y1,x2,y2);
+    XDBG_TRACE (MEXAH, "%s\n", DO(gOpSolid));
+    if (gOpSolid.bDo == DO_DRAW_NONE) return;
+
+    gOpSolid.x = x1;
+    gOpSolid.y = y1;
+    gOpSolid.w = x2-x1;
+    gOpSolid.h = y2-y1;
+
+    if (gOpSolid.pOpDst->isSame)
+    {
+        ExaBox box;
+
+        box.state = rgnIN;
+        box.box.x1 = 0;
+        box.box.y1 = 0;
+        box.box.x2 = x2-x1;
+        box.box.y2 = y2-y1;
+        box.pDst = &gOpSolid.pOpDst->buf[0];
+        _g2dDoSolid (&box, NULL);
+    }
+    else
+    {
+        int i;
+        ExaBox *box;
+        BoxRec b;
+
+        /*Init box list*/
+        xorg_list_init (&gOpSolid.opBox);
+
+        b.x1 = x1;
+        b.y1 = y1;
+        b.x2 = x2;
+        b.y2 = y2;
+
+        for (i=0; i<gOpSolid.pOpDst->num; i++)
+        {
+            box = _g2dBoxAdd (&gOpSolid.opBox,
+                             &gOpSolid.pOpDst->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pDst = &gOpSolid.pOpDst->buf[i];
+            }
+        }
+        _g2dBoxMove (&gOpSolid.opBox, -x1, -y1);
+
+        /* Call solid function */
+        _g2dDoDraw (&gOpSolid.opBox,
+                   _g2dDoSolid, NULL);
+
+        /*Remove box list*/
+        _g2dBoxRemoveAll (&gOpSolid.opBox);
+    }
+}
+
+static void
+SECExaG2dDoneSolid (PixmapPtr pPixmap)
+{
+    XDBG_TRACE (MEXAH, "\n");
+
+    if (gOpSolid.bDo)
+        g2d_exec();
+
+    if (gOpSolid.pGC)
+    {
+        FreeScratchGC (gOpSolid.pGC);
+        gOpSolid.pGC = NULL;
+    }
+
+    if (gOpSolid.pixmap)
+        _g2dFinishAccess (gOpSolid.pixmap, EXA_PREPARE_DEST);
+}
+
+static Bool
+SECExaG2dPrepareCopy (PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
+                     int dx, int dy, int alu, Pixel planemask)
+{
+    int num_dst_pix = -1;
+    int num_src_pix = -1;
+    unsigned int draw_type = DO_DRAW_HW;
+    unsigned int access_device = TBM_DEVICE_2D;
+
+    XDBG_TRACE (MEXAH, "\n");
+    memset (&gOpCopy, 0x00, sizeof (gOpCopy));
+
+    gOpCopy.alu = alu;
+    gOpCopy.pm = planemask;
+    gOpCopy.reverse = (dx == 1)?0:1;
+    gOpCopy.upsidedown = (dy == 1)?0:1;
+    gOpCopy.pDstPix = pDstPixmap;
+    gOpCopy.pSrcPix = pSrcPixmap;
+
+    /* Check capability */
+    if(!_g2dIsSupport(pSrcPixmap, 0) ||
+        !_g2dIsSupport(pDstPixmap, 0) ||
+        gOpCopy.reverse ||
+        gOpCopy.upsidedown)
+    {
+        draw_type = DO_DRAW_SW;
+        access_device = TBM_DEVICE_CPU;
+    }
+
+    gOpCopy.pOpDst = _g2dPrepareAccess (pDstPixmap, EXA_PREPARE_DEST, access_device);
+    XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail);
+    gOpCopy.pOpSrc = _g2dPrepareAccess (pSrcPixmap, EXA_PREPARE_SRC, access_device);
+    XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail);
+
+    gOpCopy.bDo = draw_type;
+
+    return TRUE;
+
+bail:
+    XDBG_TRACE (MEXAH, "FAIL\n");
+    XDBG_TRACE (MEXAH, "   SRC pix:%p, index:%d, hint:%d, num_pix:%d\n",
+                pSrcPixmap, index, pSrcPixmap->usage_hint, num_src_pix);
+    XDBG_TRACE (MEXAH, "   DST pix:%p, index:%d, hint:%d, num_pix:%d\n",
+                pDstPixmap, index, pDstPixmap->usage_hint, num_dst_pix);
+    gOpCopy.bDo = DO_DRAW_NONE;
+
+    return TRUE;
+}
+
+
+static void
+SECExaG2dCopy (PixmapPtr pDstPixmap, int srcX, int srcY,
+              int dstX, int dstY, int width, int height)
+{
+    XDBG_TRACE (MEXAH, "%s\n", DO(gOpCopy));
+    XDBG_TRACE (MEXAH, "src(%d,%d) dst(%d,%d) %dx%d\n",
+                srcX, srcY, dstX, dstY, width, height);
+
+    if (gOpSolid.bDo == FALSE) return;
+
+    gOpCopy.srcX = srcX;
+    gOpCopy.srcY = srcY;
+    gOpCopy.dstX = dstX;
+    gOpCopy.dstY = dstY;
+    gOpCopy.width = width;
+    gOpCopy.height = height;
+
+    if (gOpCopy.pOpSrc->isSame && gOpCopy.pOpDst->isSame)
+    {
+        ExaBox box;
+
+        box.state = rgnIN;
+        box.box.x1 = 0;
+        box.box.y1 = 0;
+        box.box.x2 = width;
+        box.box.y2 = height;
+        box.pDst = &gOpCopy.pOpDst->buf[0];
+        box.pSrc = &gOpCopy.pOpSrc->buf[0];
+        _g2dDoCopy (&box, NULL);
+    }
+    else
+    {
+        int i;
+        struct xorg_list lSrc, lDst;
+        ExaBox *box;
+        BoxRec b;
+
+        //Set Dest
+        b.x1 = dstX;
+        b.y1 = dstY;
+        b.x2 = dstX + width;
+        b.y2 = dstY + height;
+        xorg_list_init (&lDst);
+        for (i=0; i<gOpCopy.pOpDst->num; i++)
+        {
+            box = _g2dBoxAdd (&lDst,
+                             &gOpCopy.pOpDst->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pDst = &gOpCopy.pOpDst->buf[i];
+            }
+        }
+        _g2dBoxMove (&lDst, -dstX, -dstY);
+
+        //Set Src
+        b.x1 = srcX;
+        b.y1 = srcY;
+        b.x2 = srcX + width;
+        b.y2 = srcY + height;
+
+        xorg_list_init (&lSrc);
+        for (i=0; i<gOpCopy.pOpSrc->num; i++)
+        {
+            box = _g2dBoxAdd (&lSrc,
+                             &gOpCopy.pOpSrc->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pSrc = &gOpCopy.pOpSrc->buf[i];
+            }
+        }
+        _g2dBoxMove (&lSrc, -srcX, -srcY);
+
+        //Merge and call copy
+        xorg_list_init (&gOpCopy.opBox);
+        _g2dBoxMerge (&gOpCopy.opBox, &lSrc, &lDst);
+        _g2dDoDraw (&gOpCopy.opBox,
+                   _g2dDoCopy, NULL);
+
+        //Remove box list
+        _g2dBoxRemoveAll (&lSrc);
+        _g2dBoxRemoveAll (&lDst);
+        _g2dBoxRemoveAll (&gOpCopy.opBox);
+    }
+}
+
+static void
+SECExaG2dDoneCopy (PixmapPtr pDstPixmap)
+{
+    XDBG_TRACE (MEXAH, "\n");
+    if (gOpCopy.bDo == DO_DRAW_HW)
+        g2d_exec();
+
+    if (gOpCopy.pDstPix)
+        _g2dFinishAccess (gOpCopy.pDstPix, EXA_PREPARE_DEST);
+    if (gOpCopy.pSrcPix)
+        _g2dFinishAccess (gOpCopy.pSrcPix, EXA_PREPARE_SRC);
+}
+
+static Bool
+SECExaG2dCheckComposite (int op, PicturePtr pSrcPicture,
+                        PicturePtr pMaskPicture, PicturePtr pDstPicture)
+{
+    return TRUE;
+}
+
+static Bool
+SECExaG2dPrepareComposite (int op, PicturePtr pSrcPicture,
+                          PicturePtr pMaskPicture, PicturePtr pDstPicture,
+                          PixmapPtr pSrcPixmap,
+                          PixmapPtr pMaskPixmap, PixmapPtr pDstPixmap)
+{
+    XDBG_GOTO_IF_FAIL (pDstPixmap, bail);
+    XDBG_GOTO_IF_FAIL (pSrcPicture && pDstPicture, bail);
+
+    unsigned int draw_type = DO_DRAW_HW;
+    unsigned int access_device = TBM_DEVICE_2D;
+
+    XDBG_TRACE (MEXAH, "\n");
+    memset (&gOpComposite, 0x00, sizeof (gOpComposite));
+
+    gOpComposite.op = op;
+    gOpComposite.pDstPicture = pDstPicture;
+    gOpComposite.pSrcPicture = pSrcPicture;
+    gOpComposite.pMaskPicture = pMaskPicture;
+    gOpComposite.pSrcPixmap = pSrcPixmap;
+    gOpComposite.pMaskPixmap = pMaskPixmap;
+    gOpComposite.pDstPixmap = pDstPixmap;
+
+    if (!_g2dIsSupport(pSrcPixmap, 0) ||
+        !_g2dIsSupport(pDstPixmap, 0) ||
+        !_g2dIsSupport(pMaskPixmap, 1))
+    {
+        draw_type = DO_DRAW_SW;
+    }
+
+    if (!_g2d_check_picture(pSrcPicture,
+                                    &gOpComposite.srcRotate,
+                                    &gOpComposite.srcScaleX,
+                                    &gOpComposite.srcScaleY,
+                                    &gOpComposite.srcRepeat) ||
+         !_g2d_check_picture(pMaskPicture,
+                                    &gOpComposite.maskRotate,
+                                    &gOpComposite.maskScaleX,
+                                    &gOpComposite.maskScaleY,
+                                    &gOpComposite.maskRepeat))
+    {
+        draw_type = DO_DRAW_SW;
+    }
+
+    if(draw_type == DO_DRAW_SW)
+    {
+        access_device = TBM_DEVICE_CPU;
+    }
+
+    gOpComposite.pOpDst = _g2dPrepareAccess (pDstPixmap,
+                                                                            EXA_PREPARE_DEST,
+                                                                            access_device);
+
+    if (pSrcPixmap)
+    {
+        gOpComposite.pOpSrc = _g2dPrepareAccess (pSrcPixmap,
+                                                                                EXA_PREPARE_SRC,
+                                                                                access_device);
+        XDBG_GOTO_IF_FAIL (gOpComposite.pOpSrc->num == 1, bail);
+    }
+
+    if (pMaskPixmap)
+    {
+        gOpComposite.pOpMask = _g2dPrepareAccess (pMaskPixmap,
+                                                                                    EXA_PREPARE_MASK,
+                                                                                    access_device);
+        XDBG_GOTO_IF_FAIL (gOpComposite.pOpMask->num == 1, bail);
+    }
+
+    if(draw_type == DO_DRAW_HW)
+    {
+        G2dImage *imgSrc = NULL, *imgMask = NULL;
+
+        if(pSrcPicture)
+        {
+            if(gOpComposite.pOpSrc == NULL)
+            {
+                gOpComposite.pOpSrc = &OpInfo[EXA_PREPARE_SRC];
+                gOpComposite.pOpSrc->buf[0].imgG2d =
+                            g2d_image_create_solid((unsigned int)gOpComposite.pSrcPicture->pSourcePict->solidFill.color);
+            }
+
+            imgSrc = gOpComposite.pOpSrc->buf[0].imgG2d;
+        }
+
+
+        if(pMaskPicture)
+        {
+            if(gOpComposite.pOpMask == NULL)
+            {
+                gOpComposite.pOpMask = &OpInfo[EXA_PREPARE_MASK];
+                gOpComposite.pOpMask->buf[0].imgG2d =
+                            g2d_image_create_solid((unsigned int)gOpComposite.pSrcPicture->pSourcePict->solidFill.color);
+            }
+
+            imgMask = gOpComposite.pOpMask->buf[0].imgG2d;
+        }
+
+        /*Set Repeat*/
+        imgSrc->repeat_mode = gOpComposite.srcRepeat;
+
+        /*Set Rotate */
+        imgSrc->rotate_90 = gOpComposite.srcRotate;
+        imgSrc->xDir = (gOpComposite.srcScaleX < 0.0);
+        imgSrc->yDir = (gOpComposite.srcScaleY < 0.0);
+
+        /*Set Scale*/
+        if(((gOpComposite.srcScaleX != 1.0 && gOpComposite.srcScaleX != -1.0) ||
+            (gOpComposite.srcScaleY != 1.0 && gOpComposite.srcScaleY != -1.0)))
+        {
+            imgSrc->xscale = G2D_DOUBLE_TO_FIXED(gOpComposite.srcScaleX);
+            imgSrc->yscale = G2D_DOUBLE_TO_FIXED(gOpComposite.srcScaleY);
+            imgSrc->scale_mode = G2D_SCALE_MODE_BILINEAR;
+        }
+
+        if(imgMask)
+        {
+            /*Set Repeat*/
+            imgMask->repeat_mode = gOpComposite.maskRepeat;
+
+            /*Set Rotate */
+            imgMask->rotate_90 = gOpComposite.maskRotate;
+            imgMask->xDir = (gOpComposite.maskScaleX < 0.0);
+            imgMask->yDir = (gOpComposite.maskScaleY < 0.0);
+
+            /*Set Scale*/
+            if(((gOpComposite.maskScaleX != 1.0 && gOpComposite.maskScaleX != -1.0) ||
+                (gOpComposite.maskScaleY != 1.0 && gOpComposite.maskScaleY != -1.0)))
+            {
+                imgMask->xscale = G2D_DOUBLE_TO_FIXED(gOpComposite.maskScaleX);
+                imgMask->yscale = G2D_DOUBLE_TO_FIXED(gOpComposite.maskScaleY);
+                imgMask->scale_mode = G2D_SCALE_MODE_BILINEAR;
+            }
+        }
+    }
+
+    gOpComposite.bDo = draw_type;
+
+    return TRUE;
+
+bail:
+    XDBG_TRACE (MEXAH, "FAIL: op%d\n", op);
+    XDBG_TRACE (MEXAH, "   SRC picture:%p pix:%p\n", pSrcPicture, pSrcPixmap);
+    XDBG_TRACE (MEXAH, "   MASK picture:%p pix:%p\n", pMaskPicture, pMaskPixmap);
+    XDBG_TRACE (MEXAH, "   DST picture:%p pix:%p\n", pDstPicture, pDstPixmap);
+
+    gOpComposite.bDo = DO_DRAW_NONE;
+
+    return TRUE;
+}
+
+static void
+SECExaG2dComposite (PixmapPtr pDstPixmap, int srcX, int srcY,
+                   int maskX, int maskY, int dstX, int dstY,
+                   int width, int height)
+{
+    XDBG_TRACE (MEXAH, "%s\n", DO(gOpComposite));
+    XDBG_TRACE (MEXAH, "s(%d,%d), m(%d,%d) d(%d,%d) %dx%d\n",
+                srcX, srcY,
+                maskX, maskY,
+                dstX, dstY,
+                width, height);
+    if (gOpComposite.bDo == DO_DRAW_NONE) return;
+
+    gOpComposite.srcX = srcX;
+    gOpComposite.srcY = srcY;
+    gOpComposite.maskX = maskX;
+    gOpComposite.maskY = maskY;
+    gOpComposite.dstX = dstX;
+    gOpComposite.dstY = dstY;
+    gOpComposite.width = width;
+    gOpComposite.height = height;
+
+    if (gOpComposite.pOpDst->isSame)
+    {
+        ExaBox box;
+
+        box.state = rgnIN;
+        box.box.x1 = 0;
+        box.box.y1 = 0;
+        box.box.x2 = width;
+        box.box.y2 = height;
+        box.pDst = &gOpComposite.pOpDst->buf[0];
+        box.pSrc = &gOpComposite.pOpSrc->buf[0];
+        box.pMask = (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL;
+
+        _g2dDoComposite (&box, NULL);
+    }
+    else
+    {
+        int i;
+        ExaBox *box;
+        BoxRec b;
+
+        /*Init box list*/
+        xorg_list_init (&gOpComposite.opBox);
+
+        b.x1 = dstX;
+        b.y1 = dstY;
+        b.x2 = dstX+width;
+        b.y2 = dstY+height;
+
+        for (i=0; i<gOpComposite.pOpDst->num; i++)
+        {
+            box = _g2dBoxAdd (&gOpComposite.opBox,
+                             &gOpComposite.pOpDst->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pDst = &gOpComposite.pOpDst->buf[i];
+                box->pSrc = &gOpComposite.pOpSrc->buf[0];
+                box->pMask= (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL;
+            }
+        }
+        _g2dBoxMove (&gOpComposite.opBox, -dstX, -dstY);
+
+        /* Call solid function */
+        _g2dDoDraw (&gOpComposite.opBox,
+                   _g2dDoComposite, NULL);
+
+        /*Remove box list*/
+        _g2dBoxRemoveAll (&gOpComposite.opBox);
+    }
+}
+
+/* done composite : sw done composite, not using pvr2d */
+static void
+SECExaG2dDoneComposite (PixmapPtr pDst)
+{
+    XDBG_TRACE (MEXAH, "\n");
+
+    if(gOpComposite.bDo == DO_DRAW_HW)
+        g2d_exec();
+
+    if (gOpComposite.pDstPixmap != NULL)
+        _g2dFinishAccess (gOpComposite.pDstPixmap, EXA_PREPARE_DEST);
+
+    if (gOpComposite.pSrcPixmap != NULL)
+        _g2dFinishAccess (gOpComposite.pSrcPixmap, EXA_PREPARE_SRC);
+    else if (gOpComposite.pOpSrc)
+    {
+        g2d_image_free (gOpComposite.pOpSrc->buf[0].imgG2d);
+        gOpComposite.pOpSrc->buf[0].imgG2d = NULL;
+    }
+
+    if (gOpComposite.pMaskPixmap != NULL)
+        _g2dFinishAccess (gOpComposite.pMaskPixmap, EXA_PREPARE_MASK);
+    else if (gOpComposite.pOpMask != NULL)
+    {
+        g2d_image_free (gOpComposite.pOpMask->buf[0].imgG2d);
+        gOpComposite.pOpMask->buf[0].imgG2d = NULL;
+    }
+}
+
+static Bool
+SECExaG2dUploadToScreen (PixmapPtr pDst, int x, int y, int w, int h,
+                        char *src, int src_pitch)
+{
+    XDBG_RETURN_VAL_IF_FAIL (src!=NULL, TRUE);
+    XDBG_TRACE (MEXAH, "src(%p, %d) %d,%d,%d,%d\n", src, src_pitch, x,y,w,h);
+
+    gOpUTS.pDst = pDst;
+    gOpUTS.x = x;
+    gOpUTS.y = y;
+    gOpUTS.w = w;
+    gOpUTS.h = h;
+    gOpUTS.src = src;
+    gOpUTS.src_pitch = src_pitch;
+
+    if(_g2dIsSupport(pDst, FALSE))
+    {
+        gOpUTS.pOpDst = _g2dPrepareAccess (pDst,
+                                                                    EXA_PREPARE_DEST,
+                                                                    TBM_DEVICE_2D);
+        gOpUTS.imgSrc = g2d_image_create_data (gOpUTS.pOpDst->buf[0].imgG2d->color_mode,
+                                                                    w, h, (void*)src, src_pitch);
+        gOpUTS.bDo = DO_DRAW_HW;
+    }
+    else
+    {
+        gOpUTS.pOpDst = _g2dPrepareAccess (pDst,
+                                                                    EXA_PREPARE_DEST,
+                                                                    TBM_DEVICE_CPU);
+        gOpUTS.imgSrc = NULL;
+        gOpUTS.bDo = DO_DRAW_SW;
+    }
+
+    XDBG_TRACE (MEXAH, "%s\n", DO(gOpUTS));
+    if (gOpUTS.pOpDst->isSame)
+    {
+        ExaBox box;
+
+        box.box.x1 = 0;
+        box.box.y1 = 0;
+        box.box.x2 = w;
+        box.box.y2 = h;
+        box.state = rgnIN;
+        box.pDst = &gOpUTS.pOpDst->buf[0];
+        _g2dDoUploadToScreen (&box, NULL);
+    }
+    else
+    {
+        int i;
+        ExaBox *box;
+        BoxRec b;
+
+        /*Init box list*/
+        xorg_list_init (&gOpUTS.opBox);
+
+        b.x1 = x;
+        b.y1 = y;
+        b.x2 = x+w;
+        b.y2 = y+h;
+
+        for (i=0; i<gOpUTS.pOpDst->num; i++)
+        {
+            box = _g2dBoxAdd (&gOpUTS.opBox,
+                             &gOpUTS.pOpDst->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pDst = &gOpUTS.pOpDst->buf[i];
+            }
+        }
+        _g2dBoxMove (&gOpUTS.opBox, -x, -y);
+
+        /* Call solid function */
+        _g2dDoDraw (&gOpUTS.opBox,
+                   _g2dDoUploadToScreen, NULL);
+
+        /*Remove box list*/
+        _g2dBoxRemoveAll (&gOpUTS.opBox);
+    }
+
+    if(gOpUTS.bDo == DO_DRAW_HW)
+        g2d_exec();
+
+    _g2dFinishAccess (pDst, EXA_PREPARE_DEST);
+    if(gOpUTS.imgSrc)
+    {
+        g2d_image_free(gOpUTS.imgSrc);
+    }
+    return TRUE;
+}
+
+
+
+static Bool
+SECExaG2dDownloadFromScreen (PixmapPtr pSrc, int x, int y, int w, int h,
+                            char *dst, int dst_pitch)
+{
+    XDBG_RETURN_VAL_IF_FAIL (dst!=NULL, TRUE);
+    XDBG_TRACE (MEXAH, "dst(%p, %d) %d,%d,%d,%d\n", dst, dst_pitch, x,y,w,h);
+
+    gOpDFS.pSrc = pSrc;
+    gOpDFS.x = x;
+    gOpDFS.y = y;
+    gOpDFS.w = w;
+    gOpDFS.h = h;
+    gOpDFS.dst = dst;
+    gOpDFS.dst_pitch = dst_pitch;
+
+    if(_g2dIsSupport(pSrc, FALSE))
+    {
+        gOpDFS.pOpSrc = _g2dPrepareAccess (pSrc,
+                                                                    EXA_PREPARE_DEST,
+                                                                    TBM_DEVICE_2D);
+        gOpDFS.imgDst = g2d_image_create_data (gOpDFS.pOpSrc->buf[0].imgG2d->color_mode,
+                                                                    w, h, (void*)dst, dst_pitch);
+        gOpDFS.bDo = DO_DRAW_HW;
+    }
+    else
+    {
+        gOpDFS.pOpSrc = _g2dPrepareAccess (pSrc,
+                                                                    EXA_PREPARE_DEST,
+                                                                    TBM_DEVICE_CPU);
+        gOpDFS.imgDst = NULL;
+        gOpDFS.bDo = DO_DRAW_SW;
+    }
+
+    XDBG_TRACE (MEXAH, "%s\n", DO(gOpDFS));
+    if (gOpDFS.pOpSrc->isSame)
+    {
+        ExaBox box;
+
+        box.box.x1 = 0;
+        box.box.y1 = 0;
+        box.box.x2 = w;
+        box.box.y2 = h;
+        box.state = rgnIN;
+        box.pSrc = &gOpDFS.pOpSrc->buf[0];
+        _g2dDoDownladFromScreen (&box, NULL);
+    }
+    else
+    {
+        int i;
+        ExaBox *box;
+        BoxRec b;
+
+        /*Init box list*/
+        xorg_list_init (&gOpDFS.opBox);
+
+        b.x1 = x;
+        b.y1 = y;
+        b.x2 = x+w;
+        b.y2 = y+h;
+
+        for (i=0; i<gOpDFS.pOpSrc->num; i++)
+        {
+            box = _g2dBoxAdd (&gOpDFS.opBox,
+                             &gOpDFS.pOpSrc->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pSrc = &gOpDFS.pOpSrc->buf[i];
+            }
+        }
+        _g2dBoxMove (&gOpDFS.opBox, -x, -y);
+
+        /* Call solid function */
+        _g2dDoDraw (&gOpDFS.opBox,
+                   _g2dDoDownladFromScreen, NULL);
+
+        /*Remove box list*/
+        _g2dBoxRemoveAll (&gOpDFS.opBox);
+    }
+
+    if(gOpDFS.bDo == DO_DRAW_HW)
+        g2d_exec();
+
+    _g2dFinishAccess (pSrc, EXA_PREPARE_SRC);
+    if(gOpDFS.imgDst)
+    {
+        g2d_image_free(gOpDFS.imgDst);
+    }
+    return TRUE;
+}
+
+Bool secExaG2dInit (ScreenPtr pScreen, ExaDriverPtr pExaDriver)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+
+    if(!g2d_init (pSec->drm_fd))
+    {
+        XDBG_WARNING (MEXA, "[EXAG2D] fail to g2d_init(%d)\n", pSec->drm_fd);
+    }
+
+    pExaDriver->PrepareSolid = SECExaG2dPrepareSolid;
+    pExaDriver->Solid = SECExaG2dSolid;
+    pExaDriver->DoneSolid = SECExaG2dDoneSolid;
+
+    pExaDriver->PrepareCopy = SECExaG2dPrepareCopy;
+    pExaDriver->Copy = SECExaG2dCopy;
+    pExaDriver->DoneCopy = SECExaG2dDoneCopy;
+
+    pExaDriver->CheckComposite = SECExaG2dCheckComposite;
+    pExaDriver->PrepareComposite = SECExaG2dPrepareComposite;
+    pExaDriver->Composite = SECExaG2dComposite;
+    pExaDriver->DoneComposite = SECExaG2dDoneComposite;
+
+    pExaDriver->UploadToScreen = SECExaG2dUploadToScreen;
+    pExaDriver->DownloadFromScreen = SECExaG2dDownloadFromScreen;
+
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO
+                , "Succeed to Initialize G2D EXA\n");
+
+    return TRUE;
+}
+
+void secExaG2dDeinit (ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO
+                , "Succeed to finish SW EXA\n");
+}
diff --git a/src/accel/sec_exa_sw.c b/src/accel/sec_exa_sw.c
new file mode 100644 (file)
index 0000000..1093c05
--- /dev/null
@@ -0,0 +1,1263 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "sec.h"
+#include "sec_accel.h"
+#include "sec_util.h"
+#include "sec_layer.h"
+#include "exa.h"
+#include "fbpict.h"
+#include "neonmem.h"
+
+typedef struct
+{
+    BoxRec  pos;
+    PixmapPtr pixmap;
+    tbm_bo bo;
+    void* addr;
+} ExaOpBuf;
+
+typedef struct
+{
+    int refcnt;
+    int opt;
+    int num;
+    int isSame;
+
+    ExaOpBuf buf[5];
+} ExaOpInfo;
+
+typedef struct
+{
+    BoxRec box;
+    int state;            /*state of region*/
+
+    struct xorg_list link;
+
+    ExaOpBuf *pSrc;
+    ExaOpBuf *pMask;
+    ExaOpBuf *pDst;
+} ExaBox;
+
+typedef struct
+{
+    Bool bDo;
+
+    int alu;
+    Pixel planemask;
+    Pixel fg;
+    PixmapPtr pixmap;
+
+    int x,y,w,h;
+    GCPtr pGC;
+    ExaOpInfo* pOpDst;
+    struct xorg_list opBox;
+} OpSolid;
+
+typedef struct
+{
+    Bool bDo;
+    Pixel pm;
+    int alu;
+    int reverse;
+    int upsidedown;
+    PixmapPtr pSrcPix;
+    PixmapPtr pDstPix;
+
+    /*copy param*/
+    int srcX;
+    int srcY;
+    int dstX;
+    int dstY;
+    int width, height;
+
+    ExaOpInfo* pOpDst;
+    ExaOpInfo* pOpSrc;
+    struct xorg_list opBox;
+} OpCopy;
+
+typedef struct
+{
+    Bool bDo;
+    int op;
+
+    PicturePtr pSrcPicture;
+    PicturePtr pMaskPicture;
+    PicturePtr pDstPicture;
+    PixmapPtr pSrcPixmap;
+    PixmapPtr pMaskPixmap;
+    PixmapPtr pDstPixmap;
+
+    /*copy param*/
+    int srcX, srcY;
+    int maskX, maskY;
+    int dstX, dstY;
+    int width, height;
+
+    ExaOpInfo* pOpSrc;
+    ExaOpInfo* pOpMask;
+    ExaOpInfo* pOpDst;
+    struct xorg_list opBox;
+} OpComposite;
+
+typedef struct
+{
+    Bool bDo;
+
+    PixmapPtr pDst;
+    int x,y,w,h;
+    char* src;
+    int src_pitch;
+
+    ExaOpInfo* pOpDst;
+    struct xorg_list opBox;
+} OpUTS;
+
+typedef struct
+{
+    Bool bDo;
+
+    PixmapPtr pSrc;
+    int x,y,w,h;
+    char* dst;
+    int dst_pitch;
+
+    ExaOpInfo* pOpSrc;
+    struct xorg_list opBox;
+} OpDFS;
+
+typedef void (* DoDrawProcPtr) (PixmapPtr pPix, Bool isPart,
+                                int x, int y,
+                                int clip_x, int clip_y,
+                                int w, int h, void* data);
+
+typedef void (* DoDrawProcPtrEx) (ExaBox* box, void* data);
+
+static ExaOpInfo OpInfo[EXA_NUM_PREPARE_INDICES];
+static OpSolid gOpSolid;
+static OpCopy gOpCopy;
+static OpComposite gOpComposite;
+static OpUTS gOpUTS;
+static OpDFS gOpDFS;
+
+ExaBox* _swBoxAdd (struct xorg_list *l, BoxPtr b1, BoxPtr b2)
+{
+    ExaBox* rgn;
+
+    rgn = calloc (1, sizeof (ExaBox));
+    rgn->state = secUtilBoxIntersect (&rgn->box, b1, b2);
+    if (rgnOUT == rgn->state)
+    {
+        free (rgn);
+        return NULL;
+    }
+
+    xorg_list_add (&rgn->link, l);
+    return rgn;
+}
+
+void _swBoxMerge (struct xorg_list *l, struct xorg_list* b, struct xorg_list* t)
+{
+    ExaBox *b1, *b2;
+    ExaBox* r=NULL;
+
+    xorg_list_for_each_entry (b1, b, link)
+    {
+        xorg_list_for_each_entry (b2, t, link)
+        {
+            r = _swBoxAdd (l, &b1->box, &b2->box);
+            if (r)
+            {
+                r->pSrc = b1->pSrc ? b1->pSrc : b2->pSrc;
+                r->pMask= b1->pMask ? b1->pMask : b2->pMask;
+                r->pDst = b1->pDst ? b1->pDst : b2->pDst;
+            }
+        }
+    }
+}
+
+void _swBoxMove (struct xorg_list* l, int tx, int ty)
+{
+    ExaBox *b;
+
+    xorg_list_for_each_entry (b, l, link)
+    {
+        secUtilBoxMove (&b->box, tx, ty);
+    }
+}
+
+void _swBoxRemoveAll (struct xorg_list* l)
+{
+    ExaBox *ref, *next;
+
+    xorg_list_for_each_entry_safe (ref, next, l, link)
+    {
+        xorg_list_del (&ref->link);
+        free (ref);
+    }
+}
+
+int _swBoxIsOne (struct xorg_list* l)
+{
+    if (l->next != l)
+    {
+        if (l->next == l->prev)
+            return 1;
+        else
+            return -1;
+    }
+
+    return 0;
+}
+
+void _swBoxPrint (ExaBox* sb1, const char* name)
+{
+    ExaBox *b;
+
+    xorg_list_for_each_entry (b, &sb1->link, link)
+    {
+        XDBG_DEBUG (MEXA, "[%s] %d,%d - %d,%d\n", name,
+                b->box.x1, b->box.y1, b->box.x2, b->box.y2);
+    }
+}
+
+static ExaOpInfo* _swPrepareAccess (PixmapPtr pPix, int index)
+{
+    ScreenPtr pScreen = pPix->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+    SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix);
+    ExaOpInfo* op = &OpInfo[index];
+    int opt = TBM_OPTION_READ;
+    int i;
+    tbm_bo *bos;
+    tbm_bo_handle bo_handle;
+    SECFbBoDataPtr bo_data;
+    int num_bo;
+    int ret;
+
+    XDBG_RETURN_VAL_IF_FAIL ((privPixmap != NULL), NULL);
+
+    if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST)
+        opt |= TBM_OPTION_WRITE;
+
+    /* Check mapped */
+    if (privPixmap->exaOpInfo)
+    {
+        op = (ExaOpInfo*)privPixmap->exaOpInfo;
+        op->refcnt++;
+        XDBG_TRACE (MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
+                    pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
+        return op;
+    }
+
+    /*Set buffer info*/
+    memset (op, 0x00, sizeof (ExaOpInfo));
+    op->refcnt = 1;
+    op->opt = opt;
+    op->isSame = 0;
+
+    if (pPix->usage_hint == CREATE_PIXMAP_USAGE_FB)
+    {
+        ret = secFbFindBo (pSec->pFb,
+                           pPix->drawable.x, pPix->drawable.y,
+                           pPix->drawable.width, pPix->drawable.height,
+                           &num_bo, &bos);
+        XDBG_TRACE (MEXAS,"FB  ret:%d num_pix:%d, %dx%d+%d+%d\n",
+                    ret, num_bo,
+                    pPix->drawable.width, pPix->drawable.height,
+                    pPix->drawable.x, pPix->drawable.y);
+
+        if (ret == rgnSAME && num_bo == 1)
+        {
+            op->num = 1;
+            op->isSame = 1;
+
+            op->buf[0].pixmap = pPix;
+            op->buf[0].bo = bos[0];
+            bo_handle = tbm_bo_map (op->buf[0].bo, TBM_DEVICE_CPU, op->opt);
+            op->buf[0].addr = bo_handle.ptr;
+            op->buf[0].pixmap->devPrivate.ptr = op->buf[0].addr;
+            op->buf[0].pos.x1 = 0;
+            op->buf[0].pos.y1 = 0;
+            op->buf[0].pos.x2 = pPix->drawable.width;
+            op->buf[0].pos.y2 = pPix->drawable.height;
+        }
+        else
+        {
+            op->num = num_bo;
+            op->isSame = 0;
+
+            for (i = 0; i < num_bo; i++)
+            {
+                tbm_bo_get_user_data (bos[i], TBM_BO_DATA_FB, (void**)&bo_data);
+                op->buf[i].pixmap = secRenderBoGetPixmap (pSec->pFb, bos[i]);
+                op->buf[i].bo = bos[i];
+                bo_handle = tbm_bo_map (bos[i], TBM_DEVICE_CPU, op->opt);
+                op->buf[i].addr = bo_handle.ptr;
+                op->buf[i].pixmap->devPrivate.ptr = op->buf[i].addr;
+                op->buf[i].pos = bo_data->pos;
+            }
+        }
+
+        if (bos)
+        {
+            free (bos);
+            bos=NULL;
+        }
+    }
+    else
+    {
+        op->num = 1;
+        op->isSame = 1;
+
+        op->buf[0].pixmap = pPix;
+        if (privPixmap->bo)
+        {
+            op->buf[0].bo = privPixmap->bo;
+            bo_handle = tbm_bo_map (op->buf[0].bo, TBM_DEVICE_CPU, op->opt);
+            op->buf[0].addr = bo_handle.ptr;
+        }
+        else
+        {
+            op->buf[0].bo = privPixmap->bo;
+            op->buf[0].addr = privPixmap->pPixData;
+        }
+        op->buf[0].pixmap->devPrivate.ptr = op->buf[0].addr;
+        op->buf[0].pos.x1 = 0;
+        op->buf[0].pos.y1 = 0;
+        op->buf[0].pos.x2 = pPix->drawable.width;
+        op->buf[0].pos.y2 = pPix->drawable.height;
+    }
+
+    privPixmap->exaOpInfo = op;
+
+    XDBG_TRACE (MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
+                pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
+    return op;
+}
+
+static void _swFinishAccess (PixmapPtr pPix, int index)
+{
+    XDBG_RETURN_IF_FAIL (pPix!=NULL);
+
+    SECPixmapPriv *privPixmap = (SECPixmapPriv*)exaGetPixmapDriverPrivate (pPix);
+    ExaOpInfo* op;
+    int i;
+
+    XDBG_RETURN_IF_FAIL (privPixmap!=NULL);
+    XDBG_RETURN_IF_FAIL (privPixmap->exaOpInfo!=NULL);
+
+    op = (ExaOpInfo*)privPixmap->exaOpInfo;
+    op->refcnt --;
+
+    if (op->refcnt == 0)
+    {
+        for (i=0; i < op->num; i++)
+        {
+            if (op->buf[i].bo)
+            {
+                tbm_bo_unmap (op->buf[i].bo);
+
+                if( index == EXA_PREPARE_DEST && pPix->usage_hint == CREATE_PIXMAP_USAGE_FB )
+                {
+                    // In this case, DEST is framebuffer. It is updated by CPU.
+                    // After that LCD will use this buffer.
+                    // So we should call cache op!!
+                    tbm_bo_map(op->buf[i].bo, TBM_DEVICE_3D, TBM_OPTION_READ);
+                    tbm_bo_unmap(op->buf[i].bo);
+
+                    ScreenPtr pScreen;
+                    pScreen = pPix->drawable.pScreen;
+
+                    if( pScreen != NULL )
+                    {
+                        ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+                        SECPtr pSec = SECPTR(pScrn);
+
+                        pSec->is_fb_touched = TRUE;
+                    }
+                }
+                op->buf[i].bo = NULL;
+            }
+
+            if (op->buf[i].pixmap)
+            {
+                op->buf[i].pixmap->devPrivate.ptr = NULL;
+                op->buf[i].pixmap = NULL;
+            }
+            op->buf[i].addr = NULL;
+        }
+
+        privPixmap->exaOpInfo = NULL;
+    }
+
+    if (pPix->usage_hint == CREATE_PIXMAP_USAGE_OVERLAY)
+        secLayerUpdate (secLayerFind (LAYER_OUTPUT_LCD, LAYER_UPPER));
+
+    XDBG_TRACE (MEXAS, "pix:%p index:%d hint:%d ptr:%p ref:%d\n",
+                pPix, index, pPix->usage_hint, pPix->devPrivate.ptr, op->refcnt);
+}
+
+void
+_swDoDraw (struct xorg_list *l, DoDrawProcPtrEx do_draw, void* data)
+{
+    ExaBox *box;
+    xorg_list_for_each_entry (box, l, link)
+    {
+        do_draw (box, data);
+    }
+}
+
+static void
+_swDoSolid (ExaBox* box, void* data)
+{
+    XDBG_TRACE (MEXAS, "(%d,%d), (%d,%d) off(%d,%d)\n",
+                box->box.x1,
+                box->box.y1,
+                box->box.x2,
+                box->box.y2,
+                gOpSolid.x,
+                gOpSolid.y);
+
+    fbFill (&box->pDst->pixmap->drawable,
+            gOpSolid.pGC,
+            box->box.x1 + gOpSolid.x - box->pDst->pos.x1,
+            box->box.y1 + gOpSolid.y - box->pDst->pos.y1,
+            box->box.x2- box->box.x1,
+            box->box.y2- box->box.y1);
+}
+
+static void
+_swDoCopy (ExaBox* box, void* data)
+{
+    CARD8 alu = gOpCopy.alu;
+    FbBits pm = gOpCopy.pm;
+    FbBits *src;
+    FbStride srcStride;
+    int        srcBpp;
+    FbBits *dst;
+    FbStride dstStride;
+    int        dstBpp;
+    _X_UNUSED int      srcXoff, srcYoff;
+    _X_UNUSED int      dstXoff, dstYoff;
+    int srcX, srcY, dstX, dstY, width, height;
+
+    XDBG_TRACE (MEXAS, "box(%d,%d),(%d,%d) src(%d,%d) dst(%d,%d)\n",
+                box->box.x1,
+                box->box.y1,
+                box->box.x2,
+                box->box.y2,
+                gOpCopy.srcX,
+                gOpCopy.srcY);
+
+    srcX = gOpCopy.srcX + box->box.x1 - box->pSrc->pos.x1;
+    srcY = gOpCopy.srcY + box->box.y1 - box->pSrc->pos.y1;
+    dstX = gOpCopy.dstX + box->box.x1 - box->pDst->pos.x1;
+    dstY = gOpCopy.dstY + box->box.y1 - box->pDst->pos.y1;
+    width = box->box.x2 - box->box.x1;
+    height = box->box.y2 - box->box.y1;
+
+    fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
+    fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+    /* temp fix : do right things later */
+    if (!src || !dst)
+    {
+        return;
+    }
+
+    if (pm != FB_ALLONES ||
+            alu != GXcopy ||
+            gOpCopy.reverse ||
+            gOpCopy.upsidedown ||
+            !pixman_blt ((uint32_t *)src, (uint32_t *)dst,
+                         srcStride,
+                         dstStride,
+                         srcBpp, dstBpp,
+                         srcX, srcY, dstX, dstY, width, height))
+    {
+        fbBlt (src + srcY * srcStride,
+               srcStride,
+               srcX * srcBpp,
+
+               dst + dstY * dstStride,
+               dstStride,
+               dstX * dstBpp,
+
+               width * dstBpp,
+               height,
+
+               alu,
+               pm,
+               dstBpp,
+
+               gOpCopy.reverse,
+               gOpCopy.upsidedown);
+    }
+}
+
+static void
+_swDoComposite (ExaBox* box, void* data)
+{
+    PicturePtr pDstPicture;
+    pixman_image_t *src, *mask, *dest;
+    int src_xoff, src_yoff, msk_xoff, msk_yoff;
+    FbBits *bits;
+    FbStride stride;
+    int bpp;
+
+    if (box->state == rgnPART)
+    {
+        XDBG_RETURN_IF_FAIL (gOpComposite.pSrcPicture->transform == NULL);
+        XDBG_RETURN_IF_FAIL (gOpComposite.pMaskPicture &&
+                             gOpComposite.pMaskPicture->transform == NULL);
+    }
+
+    pDstPicture = gOpComposite.pDstPicture;
+
+    src = image_from_pict (gOpComposite.pSrcPicture, FALSE, &src_xoff, &src_yoff);
+    mask = image_from_pict (gOpComposite.pMaskPicture, FALSE, &msk_xoff, &msk_yoff);
+
+    fbGetPixmapBitsData (box->pDst->pixmap, bits, stride, bpp);
+    dest = pixman_image_create_bits (pDstPicture->format,
+                                     box->pDst->pixmap->drawable.width,
+                                     box->pDst->pixmap->drawable.height,
+                                     (uint32_t *)bits, stride * sizeof (FbStride));
+
+    pixman_image_composite (gOpComposite.op,
+                            src, mask, dest,
+                            gOpComposite.srcX + box->box.x1,
+                            gOpComposite.srcY + box->box.y1,
+                            gOpComposite.maskX + box->box.x1,
+                            gOpComposite.maskY + box->box.y1,
+                            gOpComposite.dstX + box->box.x1 - box->pDst->pos.x1,
+                            gOpComposite.dstY + box->box.y1 - box->pDst->pos.y1,
+                            box->box.x2 - box->box.x1,
+                            box->box.y2 - box->box.y1);
+
+    free_pixman_pict (gOpComposite.pSrcPicture, src);
+    free_pixman_pict (gOpComposite.pMaskPicture, mask);
+    pixman_image_unref (dest);
+}
+
+static void
+_swDoUploadToScreen (ExaBox* box, void* data)
+{
+    FbBits     *dst;
+    FbStride   dstStride;
+    int                dstBpp;
+    _X_UNUSED int              dstXoff, dstYoff;
+    int              srcStride;
+    int             dstX, dstY;
+    int             width, height;
+
+    fbGetDrawable (&box->pDst->pixmap->drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+
+    srcStride = gOpUTS.src_pitch/sizeof (uint32_t);
+    dstX = gOpUTS.x + box->box.x1 - box->pDst->pos.x1;
+    dstY = gOpUTS.y + box->box.y1 - box->pDst->pos.y1;
+    width = box->box.x2 - box->box.x1;
+    height = box->box.y2 - box->box.y1;
+
+    XDBG_TRACE (MEXAS, "src(%p, %d) %d,%d,%d,%d\n",
+                gOpUTS.src, srcStride, dstX, dstY, width, height);
+
+    if(dstBpp < 8)
+    {
+        XDBG_WARNING(MEXAS, "dstBpp:%d\n", dstBpp);
+        return;
+    }
+
+    if (!pixman_blt ((uint32_t *)gOpUTS.src,
+                     (uint32_t *)dst,
+                     srcStride,
+                     dstStride,
+                     dstBpp, dstBpp,
+                     box->box.x1, box->box.y1,
+                     dstX, dstY,
+                     width, height))
+    {
+        unsigned char *pDst, *pSrc;
+        int dst_pitch, src_pitch, cpp;
+
+        pDst = (unsigned char*)dst;
+        pSrc = (unsigned char*)gOpUTS.src;
+        cpp = dstBpp / 8;
+        src_pitch = gOpUTS.src_pitch;
+        dst_pitch = box->pDst->pixmap->devKind;
+
+        pSrc += box->box.y1 * src_pitch + box->box.x1 * cpp;
+        pDst += dstY * dst_pitch + dstX * cpp;
+
+        for (; height > 0; height--) {
+            memcpy(pDst, pSrc, width * cpp);
+            pDst += dst_pitch;
+            pSrc += src_pitch;
+        }
+    }
+}
+
+static void
+_swDoDownladFromScreen (ExaBox* box, void* data)
+{
+    FbBits     *src;
+    FbStride   srcStride;
+    int                srcBpp;
+    _X_UNUSED int              srcXoff, srcYoff;
+    int              dstStride;
+    int             srcX, srcY;
+    int             width, height;
+
+    fbGetDrawable (&box->pSrc->pixmap->drawable, src, srcStride, srcBpp, srcXoff, srcYoff);
+
+    dstStride = gOpDFS.dst_pitch/sizeof (uint32_t);
+    srcX = gOpDFS.x + box->box.x1 - box->pSrc->pos.x1;
+    srcY = gOpDFS.y + box->box.y1 - box->pSrc->pos.y1;
+    width = box->box.x2 - box->box.x1;
+    height = box->box.y2 - box->box.y1;
+
+    XDBG_TRACE (MEXAS, "dst(%p, %d) %d,%d,%d,%d\n",
+                gOpDFS.dst, dstStride, srcX, srcY, width, height);
+
+    if(srcBpp < 8)
+    {
+        XDBG_WARNING(MEXAS, "srcBpp:%d\n", srcBpp);
+        return;
+    }
+
+    if (!pixman_blt ((uint32_t *)src,
+                     (uint32_t *)gOpDFS.dst,
+                     srcStride,
+                     dstStride,
+                     srcBpp, srcBpp,
+                     srcX, srcY,
+                     box->box.x1, box->box.y1,
+                     width, height))
+    {
+        unsigned char *pDst, *pSrc;
+        int dst_pitch, src_pitch, cpp;
+
+        pDst = (unsigned char*)gOpDFS.dst;
+        pSrc = (unsigned char*)src;
+        cpp = srcBpp / 8;
+        src_pitch = box->pSrc->pixmap->devKind;
+        dst_pitch = gOpDFS.dst_pitch;
+
+        pSrc += srcY * src_pitch + srcX * cpp;
+        pDst += box->box.y1 * dst_pitch + box->box.x1 * cpp;
+
+        for (; height > 0; height--) {
+            memcpy(pDst, pSrc, width * cpp);
+            pDst += dst_pitch;
+            pSrc += src_pitch;
+        }
+    }
+}
+
+static Bool
+SECExaSwPrepareSolid (PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
+{
+    ScreenPtr pScreen = pPixmap->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    ChangeGCVal tmpval[3];
+
+    XDBG_TRACE (MEXAS, "\n");
+    memset (&gOpSolid, 0x00, sizeof (gOpSolid));
+
+    /* Put ff at the alpha bits when transparency is set to xv */
+    if (pPixmap->drawable.depth == 24)
+        fg = fg | (~ (pScrn->mask.red|pScrn->mask.green|pScrn->mask.blue));
+    gOpSolid.alu = alu;
+    gOpSolid.fg = fg;
+    gOpSolid.planemask = planemask;
+    gOpSolid.pixmap = pPixmap;
+
+    gOpSolid.pOpDst = _swPrepareAccess (pPixmap, EXA_PREPARE_DEST);
+    XDBG_GOTO_IF_FAIL (gOpSolid.pOpDst, bail);
+    gOpSolid.pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
+
+    tmpval[0].val = alu;
+    tmpval[1].val = planemask;
+    tmpval[2].val = fg;
+    ChangeGC (NullClient, gOpSolid.pGC, GCFunction|GCPlaneMask|GCForeground, tmpval);
+    ValidateGC (&pPixmap->drawable, gOpSolid.pGC);
+
+    gOpSolid.bDo = TRUE;
+
+    return TRUE;
+
+bail:
+    XDBG_TRACE (MEXAS, "FAIL: pix:%p hint:%d, num_pix:%d\n",
+                pPixmap, index, pPixmap->usage_hint, gOpSolid.pOpDst->num);
+    gOpSolid.bDo = FALSE;
+    gOpSolid.pGC = NULL;
+
+    return TRUE;
+}
+
+
+static void
+SECExaSwSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
+{
+    XDBG_TRACE (MEXAS, " (%d,%d), (%d,%d)\n", x1,y1,x2,y2);
+    if (gOpSolid.bDo == FALSE) return;
+
+    gOpSolid.x = x1;
+    gOpSolid.y = y1;
+    gOpSolid.w = x2-x1;
+    gOpSolid.h = y2-y1;
+
+    if (gOpSolid.pOpDst->isSame)
+    {
+        ExaBox box;
+
+        box.state = rgnIN;
+        box.box.x1 = 0;
+        box.box.y1 = 0;
+        box.box.x2 = x2-x1;
+        box.box.y2 = y2-y1;
+        box.pDst = &gOpSolid.pOpDst->buf[0];
+        _swDoSolid (&box, NULL);
+    }
+    else
+    {
+        int i;
+        ExaBox *box;
+        BoxRec b;
+
+        /*Init box list*/
+        xorg_list_init (&gOpSolid.opBox);
+
+        b.x1 = x1;
+        b.y1 = y1;
+        b.x2 = x2;
+        b.y2 = y2;
+
+        for (i=0; i<gOpSolid.pOpDst->num; i++)
+        {
+            box = _swBoxAdd (&gOpSolid.opBox,
+                             &gOpSolid.pOpDst->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pDst = &gOpSolid.pOpDst->buf[i];
+            }
+        }
+        _swBoxMove (&gOpSolid.opBox, -x1, -y1);
+
+        /* Call solid function */
+        _swDoDraw (&gOpSolid.opBox,
+                   _swDoSolid, NULL);
+
+        /*Remove box list*/
+        _swBoxRemoveAll (&gOpSolid.opBox);
+    }
+}
+
+static void
+SECExaSwDoneSolid (PixmapPtr pPixmap)
+{
+    XDBG_TRACE (MEXAS, "\n");
+    if (gOpSolid.pGC)
+    {
+        FreeScratchGC (gOpSolid.pGC);
+        gOpSolid.pGC = NULL;
+    }
+
+    if (gOpSolid.pixmap)
+        _swFinishAccess (gOpSolid.pixmap, EXA_PREPARE_DEST);
+}
+
+static Bool
+SECExaSwPrepareCopy (PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
+                     int dx, int dy, int alu, Pixel planemask)
+{
+    int num_dst_pix = -1;
+    int num_src_pix = -1;
+
+    XDBG_TRACE (MEXAS, "\n");
+    memset (&gOpCopy, 0x00, sizeof (gOpCopy));
+
+    gOpCopy.alu = alu;
+    gOpCopy.pm = planemask;
+    gOpCopy.reverse = (dx == 1)?0:1;
+    gOpCopy.upsidedown = (dy == 1)?0:1;
+    gOpCopy.pDstPix = pDstPixmap;
+    gOpCopy.pSrcPix = pSrcPixmap;
+
+    gOpCopy.pOpDst = _swPrepareAccess (pDstPixmap, EXA_PREPARE_DEST);
+    XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail);
+    gOpCopy.pOpSrc = _swPrepareAccess (pSrcPixmap, EXA_PREPARE_SRC);
+    XDBG_GOTO_IF_FAIL (gOpCopy.pOpDst, bail);
+
+    gOpCopy.bDo = TRUE;
+
+    return TRUE;
+
+bail:
+    XDBG_TRACE (MEXAS, "FAIL\n");
+    XDBG_TRACE (MEXAS, "   SRC pix:%p, index:%d, hint:%d, num_pix:%d\n",
+                pSrcPixmap, index, pSrcPixmap->usage_hint, num_src_pix);
+    XDBG_TRACE (MEXAS, "   DST pix:%p, index:%d, hint:%d, num_pix:%d\n",
+                pDstPixmap, index, pDstPixmap->usage_hint, num_dst_pix);
+    gOpCopy.bDo = FALSE;
+
+    return TRUE;
+}
+
+
+static void
+SECExaSwCopy (PixmapPtr pDstPixmap, int srcX, int srcY,
+              int dstX, int dstY, int width, int height)
+{
+    XDBG_TRACE (MEXAS, "src(%d,%d) dst(%d,%d) %dx%d\n",
+                srcX, srcY, dstX, dstY, width, height);
+
+    if (gOpSolid.bDo == FALSE) return;
+
+    gOpCopy.srcX = srcX;
+    gOpCopy.srcY = srcY;
+    gOpCopy.dstX = dstX;
+    gOpCopy.dstY = dstY;
+    gOpCopy.width = width;
+    gOpCopy.height = height;
+
+    if (gOpCopy.pOpSrc->isSame && gOpCopy.pOpDst->isSame)
+    {
+        ExaBox box;
+
+        box.state = rgnIN;
+        box.box.x1 = 0;
+        box.box.y1 = 0;
+        box.box.x2 = width;
+        box.box.y2 = height;
+        box.pDst = &gOpCopy.pOpDst->buf[0];
+        box.pSrc = &gOpCopy.pOpSrc->buf[0];
+        _swDoCopy (&box, NULL);
+    }
+    else
+    {
+        int i;
+        struct xorg_list lSrc, lDst;
+        ExaBox *box;
+        BoxRec b;
+
+        //Set Dest
+        b.x1 = dstX;
+        b.y1 = dstY;
+        b.x2 = dstX + width;
+        b.y2 = dstY + height;
+        xorg_list_init (&lDst);
+        for (i=0; i<gOpCopy.pOpDst->num; i++)
+        {
+            box = _swBoxAdd (&lDst,
+                             &gOpCopy.pOpDst->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pDst = &gOpCopy.pOpDst->buf[i];
+            }
+        }
+        _swBoxMove (&lDst, -dstX, -dstY);
+
+        //Set Src
+        b.x1 = srcX;
+        b.y1 = srcY;
+        b.x2 = srcX + width;
+        b.y2 = srcY + height;
+
+        xorg_list_init (&lSrc);
+        for (i=0; i<gOpCopy.pOpSrc->num; i++)
+        {
+            box = _swBoxAdd (&lSrc,
+                             &gOpCopy.pOpSrc->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pSrc = &gOpCopy.pOpSrc->buf[i];
+            }
+        }
+        _swBoxMove (&lSrc, -srcX, -srcY);
+
+        //Merge and call copy
+        xorg_list_init (&gOpCopy.opBox);
+        _swBoxMerge (&gOpCopy.opBox, &lSrc, &lDst);
+        _swDoDraw (&gOpCopy.opBox,
+                   _swDoCopy, NULL);
+
+        //Remove box list
+        _swBoxRemoveAll (&lSrc);
+        _swBoxRemoveAll (&lDst);
+        _swBoxRemoveAll (&gOpCopy.opBox);
+    }
+}
+
+static void
+SECExaSwDoneCopy (PixmapPtr pDstPixmap)
+{
+    XDBG_TRACE (MEXAS, "\n");
+
+    if (gOpCopy.pDstPix)
+        _swFinishAccess (gOpCopy.pDstPix, EXA_PREPARE_DEST);
+    if (gOpCopy.pSrcPix)
+        _swFinishAccess (gOpCopy.pSrcPix, EXA_PREPARE_SRC);
+}
+
+static Bool
+SECExaSwCheckComposite (int op, PicturePtr pSrcPicture,
+                        PicturePtr pMaskPicture, PicturePtr pDstPicture)
+{
+    return TRUE;
+}
+
+static Bool
+SECExaSwPrepareComposite (int op, PicturePtr pSrcPicture,
+                          PicturePtr pMaskPicture, PicturePtr pDstPicture,
+                          PixmapPtr pSrcPixmap,
+                          PixmapPtr pMaskPixmap, PixmapPtr pDstPixmap)
+{
+    XDBG_TRACE (MEXAS, "\n");
+    memset (&gOpComposite, 0x00, sizeof (gOpComposite));
+    XDBG_GOTO_IF_FAIL (pDstPixmap != NULL, bail);
+
+    gOpComposite.op = op;
+    gOpComposite.pDstPicture = pDstPicture;
+    gOpComposite.pSrcPicture = pSrcPicture;
+    gOpComposite.pMaskPicture = pMaskPicture;
+    gOpComposite.pSrcPixmap = pSrcPixmap;
+    gOpComposite.pMaskPixmap = pMaskPixmap;
+    gOpComposite.pDstPixmap = pDstPixmap;
+
+    gOpComposite.pOpDst = _swPrepareAccess (pDstPixmap, EXA_PREPARE_DEST);
+
+    if (pSrcPixmap)
+    {
+        gOpComposite.pOpSrc = _swPrepareAccess (pSrcPixmap, EXA_PREPARE_SRC);
+        XDBG_GOTO_IF_FAIL (gOpComposite.pOpSrc->num == 1, bail);
+    }
+
+    if (pMaskPixmap)
+    {
+        gOpComposite.pOpMask = _swPrepareAccess (pMaskPixmap, EXA_PREPARE_MASK);
+        XDBG_GOTO_IF_FAIL (gOpComposite.pOpMask->num == 1, bail);
+    }
+
+    gOpComposite.bDo = TRUE;
+
+    return TRUE;
+
+bail:
+    XDBG_TRACE (MEXAS, "FAIL: op%d\n", op);
+    XDBG_TRACE (MEXAS, "   SRC picture:%p pix:%p\n", pSrcPicture, pSrcPixmap);
+    XDBG_TRACE (MEXAS, "   MASK picture:%p pix:%p\n", pMaskPicture, pMaskPixmap);
+    XDBG_TRACE (MEXAS, "   DST picture:%p pix:%p\n", pDstPicture, pDstPixmap);
+
+    gOpComposite.bDo = FALSE;
+
+    return TRUE;
+}
+
+static void
+SECExaSwComposite (PixmapPtr pDstPixmap, int srcX, int srcY,
+                   int maskX, int maskY, int dstX, int dstY,
+                   int width, int height)
+{
+    XDBG_TRACE (MEXAS, "s(%d,%d), m(%d,%d) d(%d,%d) %dx%d\n",
+                srcX, srcY,
+                maskX, maskY,
+                dstX, dstY,
+                width, height);
+    if (!gOpComposite.bDo) return;
+
+    gOpComposite.srcX = srcX;
+    gOpComposite.srcY = srcY;
+    gOpComposite.maskX = maskX;
+    gOpComposite.maskY = maskY;
+    gOpComposite.dstX = dstX;
+    gOpComposite.dstY = dstY;
+    gOpComposite.width = width;
+    gOpComposite.height = height;
+
+    if (gOpComposite.pOpDst->isSame)
+    {
+        ExaBox box;
+
+        box.state = rgnIN;
+        box.box.x1 = 0;
+        box.box.y1 = 0;
+        box.box.x2 = width;
+        box.box.y2 = height;
+        box.pDst = &gOpComposite.pOpDst->buf[0];
+        box.pSrc = (gOpComposite.pOpSrc)? (&gOpComposite.pOpSrc->buf[0]):NULL;
+        box.pSrc = (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL;
+
+        _swDoComposite (&box, NULL);
+    }
+    else
+    {
+        int i;
+        ExaBox *box;
+        BoxRec b;
+
+        /*Init box list*/
+        xorg_list_init (&gOpComposite.opBox);
+
+        b.x1 = dstX;
+        b.y1 = dstY;
+        b.x2 = dstX+width;
+        b.y2 = dstY+height;
+
+        for (i=0; i<gOpComposite.pOpDst->num; i++)
+        {
+            box = _swBoxAdd (&gOpComposite.opBox,
+                             &gOpComposite.pOpDst->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pDst = &gOpComposite.pOpDst->buf[i];
+                box->pSrc = (gOpComposite.pOpSrc)? (&gOpComposite.pOpSrc->buf[0]):NULL;
+                box->pMask= (gOpComposite.pOpMask)? (&gOpComposite.pOpMask->buf[0]):NULL;
+            }
+        }
+        _swBoxMove (&gOpComposite.opBox, -dstX, -dstY);
+
+        /* Call solid function */
+        _swDoDraw (&gOpComposite.opBox,
+                   _swDoComposite, NULL);
+
+        /*Remove box list*/
+        _swBoxRemoveAll (&gOpComposite.opBox);
+    }
+}
+
+/* done composite : sw done composite, not using pvr2d */
+static void
+SECExaSwDoneComposite (PixmapPtr pDst)
+{
+    XDBG_TRACE (MEXAS, "\n");
+    if (gOpComposite.pDstPixmap != NULL)
+        _swFinishAccess (gOpComposite.pDstPixmap, EXA_PREPARE_DEST);
+    if (gOpComposite.pSrcPixmap != NULL)
+        _swFinishAccess (gOpComposite.pSrcPixmap, EXA_PREPARE_SRC);
+    if (gOpComposite.pMaskPixmap != NULL)
+        _swFinishAccess (gOpComposite.pMaskPixmap, EXA_PREPARE_MASK);
+}
+
+static Bool
+SECExaSwUploadToScreen (PixmapPtr pDst, int x, int y, int w, int h,
+                        char *src, int src_pitch)
+{
+    XDBG_RETURN_VAL_IF_FAIL (src!=NULL, TRUE);
+    XDBG_TRACE (MEXAS, "src(%p, %d) %d,%d,%d,%d\n", src, src_pitch, x,y,w,h);
+    XDBG_TRACE (MEXAS, "\tdst depth:%d, bpp:%d, pitch:%d, %dx%d\n",
+                pDst->drawable.depth, pDst->drawable.bitsPerPixel, pDst->devKind,
+                pDst->drawable.width, pDst->drawable.height);
+
+    gOpUTS.pDst = pDst;
+    gOpUTS.x = x;
+    gOpUTS.y = y;
+    gOpUTS.w = w;
+    gOpUTS.h = h;
+    gOpUTS.src = src;
+    gOpUTS.src_pitch = src_pitch;
+    gOpUTS.pOpDst = _swPrepareAccess (pDst, EXA_PREPARE_DEST);
+
+    if (gOpUTS.pOpDst->isSame)
+    {
+        ExaBox box;
+
+        box.box.x1 = 0;
+        box.box.y1 = 0;
+        box.box.x2 = w;
+        box.box.y2 = h;
+        box.state = rgnIN;
+        box.pDst = &gOpUTS.pOpDst->buf[0];
+        _swDoUploadToScreen (&box, NULL);
+    }
+    else
+    {
+        int i;
+        ExaBox *box;
+        BoxRec b;
+
+        /*Init box list*/
+        xorg_list_init (&gOpUTS.opBox);
+
+        b.x1 = x;
+        b.y1 = y;
+        b.x2 = x+w;
+        b.y2 = y+h;
+
+        for (i=0; i<gOpUTS.pOpDst->num; i++)
+        {
+            box = _swBoxAdd (&gOpUTS.opBox,
+                             &gOpUTS.pOpDst->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pDst = &gOpUTS.pOpDst->buf[i];
+            }
+        }
+        _swBoxMove (&gOpUTS.opBox, -x, -y);
+
+        /* Call solid function */
+        _swDoDraw (&gOpUTS.opBox,
+                   _swDoUploadToScreen, NULL);
+
+        /*Remove box list*/
+        _swBoxRemoveAll (&gOpUTS.opBox);
+    }
+
+    _swFinishAccess (pDst, EXA_PREPARE_DEST);
+    return TRUE;
+}
+
+
+
+static Bool
+SECExaSwDownloadFromScreen (PixmapPtr pSrc, int x, int y, int w, int h,
+                            char *dst, int dst_pitch)
+{
+    XDBG_RETURN_VAL_IF_FAIL (dst!=NULL, TRUE);
+    XDBG_TRACE (MEXAS, "dst(%p, %d) %d,%d,%d,%d\n", dst, dst_pitch, x,y,w,h);
+
+    gOpDFS.pSrc = pSrc;
+    gOpDFS.x = x;
+    gOpDFS.y = y;
+    gOpDFS.w = w;
+    gOpDFS.h = h;
+    gOpDFS.dst = dst;
+    gOpDFS.dst_pitch = dst_pitch;
+    gOpDFS.pOpSrc = _swPrepareAccess (pSrc, EXA_PREPARE_SRC);
+
+    if (gOpDFS.pOpSrc->isSame)
+    {
+        ExaBox box;
+
+        box.box.x1 = 0;
+        box.box.y1 = 0;
+        box.box.x2 = w;
+        box.box.y2 = h;
+        box.state = rgnIN;
+        box.pSrc = &gOpDFS.pOpSrc->buf[0];
+        _swDoDownladFromScreen (&box, NULL);
+    }
+    else
+    {
+        int i;
+        ExaBox *box;
+        BoxRec b;
+
+        /*Init box list*/
+        xorg_list_init (&gOpDFS.opBox);
+
+        b.x1 = x;
+        b.y1 = y;
+        b.x2 = x+w;
+        b.y2 = y+h;
+
+        for (i=0; i<gOpDFS.pOpSrc->num; i++)
+        {
+            box = _swBoxAdd (&gOpDFS.opBox,
+                             &gOpDFS.pOpSrc->buf[i].pos,
+                             &b);
+            if (box)
+            {
+                box->pSrc = &gOpDFS.pOpSrc->buf[i];
+            }
+        }
+        _swBoxMove (&gOpDFS.opBox, -x, -y);
+
+        /* Call solid function */
+        _swDoDraw (&gOpDFS.opBox,
+                   _swDoDownladFromScreen, NULL);
+
+        /*Remove box list*/
+        _swBoxRemoveAll (&gOpDFS.opBox);
+    }
+
+    _swFinishAccess (pSrc, EXA_PREPARE_SRC);
+    return TRUE;
+}
+
+int SECExaMarkSync(ScreenPtr pScreen)
+{
+    XDBG_RETURN_VAL_IF_FAIL (pScreen != NULL, TRUE);
+    int ret=0;
+
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR(pScrn);
+
+    if( pSec && pSec->is_fb_touched == TRUE )
+    {
+        XDBG_TRACE(MEXAS, "UpdateRequest to the display!\n");
+
+        ret = secDisplayUpdateRequest(pScrn);
+        pSec->is_fb_touched = FALSE;
+    }
+
+    return ret;
+}
+
+Bool secExaSwInit (ScreenPtr pScreen, ExaDriverPtr pExaDriver)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+    pExaDriver->PrepareSolid = SECExaSwPrepareSolid;
+    pExaDriver->Solid = SECExaSwSolid;
+    pExaDriver->DoneSolid = SECExaSwDoneSolid;
+
+    pExaDriver->PrepareCopy = SECExaSwPrepareCopy;
+    pExaDriver->Copy = SECExaSwCopy;
+    pExaDriver->DoneCopy = SECExaSwDoneCopy;
+
+    pExaDriver->CheckComposite = SECExaSwCheckComposite;
+    pExaDriver->PrepareComposite = SECExaSwPrepareComposite;
+    pExaDriver->Composite = SECExaSwComposite;
+    pExaDriver->DoneComposite = SECExaSwDoneComposite;
+
+    pExaDriver->UploadToScreen = SECExaSwUploadToScreen;
+    pExaDriver->DownloadFromScreen = SECExaSwDownloadFromScreen;
+
+    pExaDriver->MarkSync = SECExaMarkSync;
+
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO
+                , "Succeed to Initialize SW EXA\n");
+
+    return TRUE;
+}
+
+void secExaSwDeinit (ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO
+                , "Succeed to finish SW EXA\n");
+}
diff --git a/src/crtcconfig/sec_crtc.c b/src/crtcconfig/sec_crtc.c
new file mode 100644 (file)
index 0000000..abe2f61
--- /dev/null
@@ -0,0 +1,2750 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011-2012 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <poll.h>
+
+#include <xace.h>
+#include <xacestr.h>
+#include <xorgVersion.h>
+#include <tbm_bufmgr.h>
+#include <xf86Crtc.h>
+#include <xf86DDC.h>
+#include <xf86cmap.h>
+#include <xf86Xinput.h>
+#include <exevents.h>
+#include <list.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/dpmsconst.h>
+#include <exynos_drm.h>
+#include "sec.h"
+#include "sec_util.h"
+#include "sec_crtc.h"
+#include "sec_output.h"
+#include "sec_plane.h"
+#include "sec_layer.h"
+#include "sec_accel.h"
+#include "sec_drm_ipp.h"
+#include "fimg2d.h"
+
+static void _cursorRegisterBlockHandler (xf86CrtcPtr pCrtc);
+static void _cursorUnregisterBlockHandler (xf86CrtcPtr pCrtc);
+static void _cursorShow (xf86CrtcPtr pCrtc);
+static void _cursorMove (xf86CrtcPtr pCrtc, int x, int y);
+static void _cursorDrawCursor (xf86CrtcPtr pCrtc);
+
+static Atom atom_rotate_root_angle;
+static Atom atom_relative_device_exist;
+
+static int
+_overlayGetXMoveOffset (xf86CrtcPtr pCrtc, int x)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode;
+    int offset = 0;
+
+    if (pCrtcPriv->pipe != 0)
+        return 0;
+
+    offset = x + SEC_CURSOR_W - pSecMode->main_lcd_mode.hdisplay;
+
+    return (offset > 0) ? offset : 0;
+}
+
+static Bool
+_overlayEnsureBuffer (xf86CrtcPtr pCrtc, Bool move_layer)
+{
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode;
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    if (move_layer)
+    {
+        if (!pCrtcPriv->ovl_vbuf_cursor)
+        {
+            pCrtcPriv->ovl_vbuf_cursor = secUtilAllocVideoBuffer (pCrtc->scrn, FOURCC_RGB32,
+                                                                  SEC_CURSOR_W, SEC_CURSOR_H,
+                                                                  FALSE, TRUE, FALSE);
+            XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->ovl_vbuf_cursor != NULL, FALSE);
+            XDBG_TRACE (MCRS, "[%p] ovl_vbuf_cursor(%p) %dx%d created. \n", pCrtc,
+                        pCrtcPriv->ovl_vbuf_cursor, SEC_CURSOR_W, SEC_CURSOR_H);
+        }
+    }
+    else
+    {
+        if (!pCrtcPriv->ovl_vbuf_pixmap)
+        {
+            pCrtcPriv->ovl_vbuf_pixmap = secUtilAllocVideoBuffer (pCrtc->scrn, FOURCC_RGB32,
+                                                                  pSecMode->main_lcd_mode.hdisplay,
+                                                                  pSecMode->main_lcd_mode.vdisplay,
+                                                                  FALSE, TRUE, FALSE);
+            XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->ovl_vbuf_pixmap != NULL, FALSE);
+            XDBG_TRACE (MCRS, "[%p] ovl_vbuf_pixmap(%p) %dx%d created. \n", pCrtc, pCrtcPriv->ovl_vbuf_pixmap,
+                        pSecMode->main_lcd_mode.hdisplay, pSecMode->main_lcd_mode.vdisplay);
+        }
+    }
+
+    return TRUE;
+}
+
+static Bool
+_overlayEnsureLayer (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    int connector_type;
+    SECLayerOutput output = LAYER_OUTPUT_LCD;
+    SECLayer *layer;
+
+    if (pCrtcPriv->ovl_layer)
+        return TRUE;
+
+    connector_type = secCrtcGetConnectType (pCrtc);
+
+    if (connector_type == DRM_MODE_CONNECTOR_LVDS ||
+        connector_type == DRM_MODE_CONNECTOR_Unknown)
+    {
+        output = LAYER_OUTPUT_LCD;
+    }
+    else if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+             connector_type == DRM_MODE_CONNECTOR_HDMIB ||
+             connector_type == DRM_MODE_CONNECTOR_VIRTUAL)
+    {
+        output = LAYER_OUTPUT_EXT;
+    }
+    else
+    {
+        XDBG_NEVER_GET_HERE (MDISP);
+        return FALSE;
+    }
+
+    layer = secLayerFind (output, LAYER_UPPER);
+    XDBG_RETURN_VAL_IF_FAIL (layer == NULL, FALSE);
+
+    pCrtcPriv->ovl_layer = secLayerCreate (pCrtc->scrn, output, LAYER_UPPER);
+    XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->ovl_layer != NULL, FALSE);
+
+    XDBG_TRACE (MCRS, "[%p] ovl_layer(%p) created. \n", pCrtc, pCrtcPriv->ovl_layer);
+
+    return TRUE;
+}
+
+static Bool
+_overlaySelectBuffer (xf86CrtcPtr pCrtc, Bool move_layer)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode;
+
+    if (!_overlayEnsureLayer (pCrtc))
+        return FALSE;
+
+    if (!_overlayEnsureBuffer (pCrtc, move_layer))
+        return FALSE;
+
+    if (move_layer)
+    {
+        if (secLayerGetBuffer (pCrtcPriv->ovl_layer) == pCrtcPriv->ovl_vbuf_cursor)
+            return TRUE;
+
+        secLayerFreezeUpdate (pCrtcPriv->ovl_layer, TRUE);
+        _cursorDrawCursor (pCrtc);
+        secLayerSetBuffer (pCrtcPriv->ovl_layer, pCrtcPriv->ovl_vbuf_cursor);
+        secLayerFreezeUpdate (pCrtcPriv->ovl_layer, FALSE);
+
+        int offset = _overlayGetXMoveOffset (pCrtc, pCrtcPriv->cursor_win_x);
+        _cursorMove (pCrtc, pCrtcPriv->cursor_win_x - offset, pCrtcPriv->cursor_win_y);
+
+        XDBG_TRACE (MCRS, "[%p] Set ovl_vbuf_cursor. \n", pCrtc);
+    }
+    else
+    {
+        xRectangle rect = {0,};
+
+        if (secLayerGetBuffer (pCrtcPriv->ovl_layer) == pCrtcPriv->ovl_vbuf_pixmap)
+            return TRUE;
+
+        rect.width = pSecMode->main_lcd_mode.hdisplay;
+        rect.height = pSecMode->main_lcd_mode.vdisplay;
+        secLayerFreezeUpdate (pCrtcPriv->ovl_layer, TRUE);
+        secLayerSetBuffer (pCrtcPriv->ovl_layer, pCrtcPriv->ovl_vbuf_pixmap);
+        secLayerFreezeUpdate (pCrtcPriv->ovl_layer, FALSE);
+
+        secLayerSetRect (pCrtcPriv->ovl_layer, &rect, &rect);
+
+        XDBG_TRACE (MCRS, "[%p] Set ovl_vbuf_pixmap. \n", pCrtc);
+    }
+
+    return TRUE;
+}
+
+static Bool
+_cursorEnsureCursorImage(xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECPtr pSec = SECPTR (pCrtc->scrn);
+
+    int x, y, cursor_x, cursor_y;
+    int win_x, win_y;
+    int rotate;
+    int tx = 0, ty = 0;
+    double c, s;
+    pixman_transform_t t;
+
+    x = pCrtcPriv->cursor_pos_x;
+    y = pCrtcPriv->cursor_pos_y;
+
+    //Determine cursor image transform
+    rotate = secUtilRotateAdd (pSec->rotate, pCrtcPriv->user_rotate);
+
+    //Transform cursor position and screen size
+    switch (pSec->rotate)
+    {
+    case RR_Rotate_0:
+    default:
+        cursor_x = x;
+        cursor_y = y;
+        break;
+    case RR_Rotate_90:
+        cursor_x = y;
+        cursor_y = pCrtc->scrn->virtualX-1 - x;
+        break;
+    case RR_Rotate_180:
+        cursor_x = pCrtc->scrn->virtualX-1 - x;
+        cursor_y = pCrtc->scrn->virtualY-1 - y;
+        break;
+    case RR_Rotate_270:
+        cursor_x =  pCrtc->scrn->virtualY-1 - y;
+        cursor_y = x;
+        break;
+    }
+
+    switch (rotate)
+    {
+    case RR_Rotate_0:
+    default:
+        c = 1.0;
+        s = 0.0;
+        win_x = cursor_x;
+        win_y = cursor_y;
+        break;
+    case RR_Rotate_90:
+        c = 0.0;
+        s = 1.0;
+        tx = SEC_CURSOR_W;
+        ty = 0;
+
+        win_x = cursor_x;
+        win_y = cursor_y - SEC_CURSOR_W;
+        break;
+    case RR_Rotate_180:
+        c = -1.0;
+        s = 0.0;
+        tx = SEC_CURSOR_W;
+        ty = SEC_CURSOR_H;
+
+        win_x = cursor_x  - SEC_CURSOR_W;
+        win_y = cursor_y - SEC_CURSOR_H;
+        break;
+    case RR_Rotate_270:
+        c = 0.0;
+        s = -1.0;
+        tx = 0;
+        ty = SEC_CURSOR_H;
+
+        win_x = cursor_x - SEC_CURSOR_H;
+        win_y = cursor_y;
+        break;
+    }
+
+    pCrtcPriv->cursor_win_x = win_x;
+    pCrtcPriv->cursor_win_y = win_y;
+
+    if(pCrtcPriv->cursor_image == NULL)
+    {
+        XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->backup_image != NULL, FALSE);
+
+        XDBG_DEBUG (MCRS, "[%p] (%d + %d) => %d \n", pCrtc,
+                    pSec->rotate, pCrtcPriv->user_rotate, rotate);
+
+        if(rotate == RR_Rotate_0)
+        {
+            pCrtcPriv->cursor_image = pCrtcPriv->backup_image;
+            pixman_image_ref(pCrtcPriv->cursor_image);
+        }
+        else
+        {
+            //Clear cursor image
+            pCrtcPriv->cursor_image = pixman_image_create_bits (PIXMAN_a8r8g8b8
+                                      , SEC_CURSOR_W, SEC_CURSOR_H
+                                      , NULL
+                                      , 0);
+
+            //Copy Cursor image
+            pixman_transform_init_rotate (&t, pixman_double_to_fixed (c), pixman_double_to_fixed (s));
+            pixman_transform_translate (&t, NULL, pixman_int_to_fixed (tx), pixman_int_to_fixed (ty));
+            pixman_image_set_transform (pCrtcPriv->backup_image, &t);
+            pixman_image_composite (PIXMAN_OP_SRC
+                                    , pCrtcPriv->backup_image
+                                    , NULL
+                                    , pCrtcPriv->cursor_image
+                                    , 0, 0, 0, 0, 0, 0, SEC_CURSOR_W, SEC_CURSOR_H);
+            pixman_transform_init_rotate (&t, pixman_double_to_fixed (1.0), pixman_double_to_fixed (0.0));
+            pixman_image_set_transform (pCrtcPriv->backup_image, &t);
+        }
+    }
+
+    return TRUE;
+}
+
+static Bool
+_cursorEnsureCanvas (xf86CrtcPtr pCrtc, SECVideoBuf *vbuf, int width, int height)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    tbm_bo_handle bo_handle;
+
+    if (pCrtcPriv->ovl_canvas)
+        return TRUE;
+
+    if (!_overlayEnsureBuffer (pCrtc, pCrtcPriv->move_layer))
+        return FALSE;
+
+    XDBG_RETURN_VAL_IF_FAIL (vbuf != NULL, FALSE);
+
+    bo_handle = tbm_bo_get_handle (vbuf->bo[0], TBM_DEVICE_CPU);
+    XDBG_RETURN_VAL_IF_FAIL (bo_handle.ptr != NULL, FALSE);
+
+    pCrtcPriv->ovl_canvas = pixman_image_create_bits (PIXMAN_a8r8g8b8,
+                                                      width, height,
+                                                      (uint32_t *)bo_handle.ptr,
+                                                      width * 4);
+
+    XDBG_TRACE (MCRS, "[%p] ovl_canvas(%p) %dx%d created.\n", pCrtc,
+                pCrtcPriv->ovl_canvas, width, height);
+
+    return TRUE;
+}
+
+static Bool
+_cursorEnsureSavedImage (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    if (pCrtcPriv->saved_image)
+        return TRUE;
+
+    pCrtcPriv->saved_image = pixman_image_create_bits (PIXMAN_a8r8g8b8,
+                                                       SEC_CURSOR_W, SEC_CURSOR_H,
+                                                       NULL,
+                                                       0);
+    XDBG_TRACE (MCRS, "[%p] saved_image(%p) %dx%d created.\n", pCrtc,
+                pCrtcPriv->saved_image, SEC_CURSOR_W, SEC_CURSOR_H);
+
+    return TRUE;
+}
+
+static void
+_cursorSaveImage (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode;
+
+    XDBG_RETURN_IF_FAIL (pCrtcPriv->move_layer == FALSE);
+
+    _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_pixmap,
+                         pSecMode->main_lcd_mode.hdisplay,
+                         pSecMode->main_lcd_mode.vdisplay);
+
+    _cursorEnsureSavedImage (pCrtc);
+
+    pixman_image_composite (PIXMAN_OP_SRC,
+                            pCrtcPriv->ovl_canvas,
+                            NULL,
+                            pCrtcPriv->saved_image,
+                            pCrtcPriv->cursor_win_x, pCrtcPriv->cursor_win_y,
+                            0, 0,
+                            0, 0,
+                            SEC_CURSOR_W, SEC_CURSOR_H);
+
+    pCrtcPriv->saved_box.x1 = pCrtcPriv->cursor_win_x;
+    pCrtcPriv->saved_box.y1 = pCrtcPriv->cursor_win_y;
+    pCrtcPriv->saved_box.x2 = pCrtcPriv->cursor_win_x+SEC_CURSOR_W;
+    pCrtcPriv->saved_box.y2 = pCrtcPriv->cursor_win_y+SEC_CURSOR_H;
+
+    XDBG_DEBUG (MCRS, "[%p] (%d,%d %dx%d) saved. \n", pCrtc,
+                pCrtcPriv->cursor_win_x, pCrtcPriv->cursor_win_y,
+                SEC_CURSOR_W, SEC_CURSOR_H);
+}
+
+static void
+_cursorRestoreImage (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    if (!pCrtcPriv->saved_image || !pCrtcPriv->ovl_canvas)
+        return;
+
+    pixman_image_composite (PIXMAN_OP_SRC,
+                            pCrtcPriv->saved_image,
+                            NULL,
+                            pCrtcPriv->ovl_canvas,
+                            0, 0, 0, 0,
+                            pCrtcPriv->saved_box.x1, pCrtcPriv->saved_box.y1,
+                            SEC_CURSOR_W, SEC_CURSOR_H);
+
+    if (pCrtcPriv->ovl_layer && secLayerIsVisible (pCrtcPriv->ovl_layer))
+        secLayerUpdate (pCrtcPriv->ovl_layer);
+
+    XDBG_DEBUG (MCRS, "[%p] (%d,%d %dx%d) restored. \n", pCrtc,
+                pCrtcPriv->saved_box.x1, pCrtcPriv->saved_box.y1,
+                SEC_CURSOR_W, SEC_CURSOR_H);
+}
+
+static void
+_cursorDrawCursor (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    int x, y;
+
+    XDBG_RETURN_IF_FAIL (pCrtcPriv->ovl_canvas != NULL);
+    XDBG_RETURN_IF_FAIL (pCrtcPriv->cursor_image != NULL);
+
+    if (pCrtcPriv->move_layer)
+    {
+        /* clear */
+        pixman_color_t color = {0,};
+        pixman_rectangle16_t rect = {0, 0, SEC_CURSOR_W, SEC_CURSOR_H};
+        pixman_image_fill_rectangles (PIXMAN_OP_CLEAR, pCrtcPriv->ovl_canvas,
+                                      &color, 1, &rect);
+
+        x = _overlayGetXMoveOffset (pCrtc, pCrtcPriv->cursor_win_x);
+        y = 0;
+    }
+    else
+    {
+        x = pCrtcPriv->cursor_win_x;
+        y = pCrtcPriv->cursor_win_y;
+    }
+
+    pixman_image_composite (PIXMAN_OP_OVER,
+                            pCrtcPriv->cursor_image,
+                            NULL,
+                            pCrtcPriv->ovl_canvas,
+                            0, 0, 0, 0, x, y,
+                            SEC_CURSOR_W, SEC_CURSOR_H);
+
+    XDBG_DEBUG (MCRS, "[%p] (%d,%d %dx%d) drawn. \n", pCrtc,
+                x, y, SEC_CURSOR_W, SEC_CURSOR_H);
+
+    secUtilCacheFlush (pCrtc->scrn);
+
+    if (pCrtcPriv->ovl_layer && secLayerIsVisible (pCrtcPriv->ovl_layer))
+        secLayerUpdate (pCrtcPriv->ovl_layer);
+}
+
+static void
+_cursorReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
+{
+    xf86CrtcPtr pCrtc = (xf86CrtcPtr)closure;
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECPtr pSec = SECPTR (pCrtc->scrn);
+
+    if (pCrtcPriv->move_layer)
+        return;
+
+    if(!pSec->enableCursor || !pCrtcPriv->cursor_show)
+        return;
+
+    if (RegionContainsRect (pRegion, &pCrtcPriv->saved_box) != rgnOUT)
+    {
+        XDBG_TRACE (MCRS, "[%p] \n", pCrtc);
+        pCrtcPriv->need_cursor_update = TRUE;
+        _cursorRestoreImage(pCrtc);
+        _cursorRegisterBlockHandler (pCrtc);
+    }
+}
+
+static void
+_cursorDamageDestroy(DamagePtr pDamage, void *closure)
+{
+    xf86CrtcPtr pCrtc = (xf86CrtcPtr)closure;
+    SECPtr pSec = SECPTR (pCrtc->scrn);
+
+    if (!pSec->ovl_damage)
+        return;
+
+    pSec->ovl_damage = NULL;
+}
+
+static void
+_cursorBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
+{
+    xf86CrtcPtr pCrtc = (xf86CrtcPtr)data;
+    SECPtr pSec = SECPTR (pCrtc->scrn);
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    XDBG_RETURN_IF_FAIL (pCrtcPriv->move_layer == FALSE);
+
+    if(pSec->ovl_drawable)
+    {
+        if(pSec->ovl_damage == NULL)
+        {
+            pSec->ovl_damage = DamageCreate((DamageReportFunc)_cursorReportDamage,
+                                            (DamageDestroyFunc)_cursorDamageDestroy,
+                                            DamageReportRawRegion,
+                                            TRUE, pCrtc->scrn->pScreen, pCrtc);
+            DamageRegister(pSec->ovl_drawable, pSec->ovl_damage);
+        }
+    }
+    else
+    {
+        if(pSec->ovl_damage)
+        {
+            DamageDestroy(pSec->ovl_damage);
+            pSec->ovl_damage = NULL;
+        }
+    }
+
+    XDBG_DEBUG (MCRS, "[%p] enable(%d) cursor_show(%d) need_update(%d) show(%d) \n", pCrtc,
+                pSec->enableCursor, pCrtcPriv->cursor_show,
+                pCrtcPriv->need_cursor_update, pCrtcPriv->cursor_show);
+
+    if(pSec->enableCursor && pCrtcPriv->need_cursor_update)
+    {
+        SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode;
+
+        _cursorEnsureCursorImage (pCrtc);
+        _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_pixmap,
+                             pSecMode->main_lcd_mode.hdisplay,
+                             pSecMode->main_lcd_mode.vdisplay);
+
+        _cursorSaveImage (pCrtc);
+
+        /*Draw Cursor*/
+        if(pCrtcPriv->cursor_show)
+            _cursorDrawCursor (pCrtc);
+
+        _overlaySelectBuffer (pCrtc, pCrtcPriv->move_layer);
+        _cursorMove (pCrtc, pCrtcPriv->cursor_win_x, pCrtcPriv->cursor_win_y);
+
+        pCrtcPriv->need_cursor_update = FALSE;
+    }
+
+    if (!secLayerIsVisible (pCrtcPriv->ovl_layer))
+        secLayerShow (pCrtcPriv->ovl_layer);
+
+    if(!pSec->enableCursor || !pCrtcPriv->cursor_show || !pCrtcPriv->need_cursor_update)
+        _cursorUnregisterBlockHandler (pCrtc);
+}
+
+static Bool
+_cursorSetPointerDeviceRotate (DeviceIntPtr dev, int rotate)
+{
+#define EVDEV_PROP_INVERT_AXES "Evdev Axis Inversion" /* BOOL, 2 values [x, y], 1 inverts axis */
+#define EVDEV_PROP_SWAP_AXES "Evdev Axes Swap" /* BOOL */
+
+    int swap = 0;
+    char inv[2];
+
+    static Atom swap_axes=0;
+    static Atom invert_axes=0;
+    int rc;
+
+    if (!dev) return FALSE;
+
+    XDBG_TRACE (MCRS, "device %s (valuator:%p)\n",
+                dev->name, dev->valuator);
+
+    if (!swap_axes)
+        swap_axes = MakeAtom (EVDEV_PROP_SWAP_AXES, strlen (EVDEV_PROP_SWAP_AXES), TRUE);
+
+    if (!invert_axes)
+        invert_axes = MakeAtom (EVDEV_PROP_INVERT_AXES, strlen (EVDEV_PROP_INVERT_AXES), TRUE);
+
+    switch (rotate)
+    {
+    case RR_Rotate_0:
+        swap = 0;
+        inv[0] = 0;
+        inv[1] = 0;
+        break;
+    case RR_Rotate_90:
+        swap = 1;
+        inv[0] = 0;
+        inv[1] = 1;
+        break;
+    case RR_Rotate_180:
+        swap = 0;
+        inv[0] = 1;
+        inv[1] = 1;
+        break;
+    case RR_Rotate_270:
+        swap = 1;
+        inv[0] = 1;
+        inv[1] = 0;
+        break;
+    default:
+        XDBG_ERROR (MCRS, "Error.. cursor_rotate:%d\n", rotate);
+        return FALSE;
+    }
+
+    XDBG_TRACE (MCRS, "%s change(swap:%d, inv:%d,%d rotate:%d)\n", dev->name, swap, inv[0], inv[1], rotate);
+    rc = XIChangeDeviceProperty (dev, swap_axes, XA_INTEGER, 8,
+                                 PropModeReplace, 1, &swap, TRUE);
+    if (rc != Success)
+    {
+        XDBG_ERROR (MCRS, "Fail change swap(%s , swap:%d)\n", dev->name, swap);
+    }
+
+    rc = XIChangeDeviceProperty (dev, invert_axes, XA_INTEGER, 8,
+                                 PropModeReplace, 2,
+                                 inv, TRUE);
+    if (rc != Success)
+    {
+        XDBG_ERROR (MCRS, "Fail change invert(%s , invert:%d,%d)\n", dev->name, inv[0], inv[1]);
+    }
+
+    return TRUE;
+}
+
+static Bool
+_cursorFindRelativeDevice (xf86CrtcPtr pCrtc)
+{
+    InputInfoPtr localDevices;
+    DeviceIntPtr dev;
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    XDBG_TRACE (MCRS, "[%p]  \n", pCrtc);
+
+    localDevices = xf86FirstLocalDevice();
+    while (localDevices)
+    {
+        dev= localDevices->dev;
+        _cursorSetPointerDeviceRotate (dev, pCrtcPriv->user_rotate);
+        localDevices = localDevices->next;
+    }
+
+    return TRUE;
+}
+
+static void
+_cursorRotateHook (CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+    ScrnInfoPtr pScrn = (ScrnInfoPtr) unused;
+    xf86CrtcPtr pCrtc = xf86CompatCrtc (pScrn);
+    XacePropertyAccessRec *rec = (XacePropertyAccessRec*)calldata;
+    PropertyPtr pProp = *rec->ppProp;
+    Atom name = pProp->propertyName;
+
+    /* Don't care about the new content check */
+    if (rec->pWin != pScrn->pScreen->root)        //Check Rootwindow
+        return;
+
+    if (name == atom_rotate_root_angle
+            && (rec->access_mode & DixWriteAccess))
+    {
+        int rotate_degree = *(int*)pProp->data;
+
+        XDBG_TRACE (MCRS, "[%p] Change root angle(%d)\n", pCrtc, rotate_degree);
+        secCrtcCursorRotate (pCrtc, secUtilDegreeToRotate (rotate_degree));
+    }
+
+    if (name == atom_relative_device_exist
+            && (rec->access_mode & DixWriteAccess))
+    {
+        int exist = *(int*)pProp->data;
+        if (exist)
+        {
+            _cursorFindRelativeDevice (pCrtc);
+            XDBG_TRACE (MCRS, "[%p] Change device exist(%d)\n", pCrtc, exist);
+        }
+    }
+
+    return;
+}
+
+static void
+_cursorRegisterBlockHandler (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    XDBG_RETURN_IF_FAIL (pCrtcPriv->move_layer == FALSE);
+
+    if (pCrtcPriv->registered_block_handler)
+        return;
+
+    XDBG_DEBUG (MCRS, "[%p] \n", pCrtc);
+
+    RegisterBlockAndWakeupHandlers (_cursorBlockHandler,
+                                    (WakeupHandlerProcPtr)NoopDDA, pCrtc);
+
+    pCrtcPriv->registered_block_handler = TRUE;
+}
+
+static void
+_cursorUnregisterBlockHandler (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    if (!pCrtcPriv->registered_block_handler)
+        return;
+
+    XDBG_DEBUG (MCRS, "[%p] \n", pCrtc);
+
+    RemoveBlockAndWakeupHandlers (_cursorBlockHandler,
+                                  (WakeupHandlerProcPtr)NoopDDA, pCrtc);
+
+    pCrtcPriv->registered_block_handler = FALSE;
+}
+
+static void
+_cursorMove (xf86CrtcPtr pCrtc, int x, int y)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    if (!pCrtcPriv->move_layer)
+        return;
+
+    if (pCrtcPriv->ovl_layer)
+    {
+        xRectangle src = {0,};
+        xRectangle dst = {0,};
+
+        src.width = SEC_CURSOR_W;
+        src.height = SEC_CURSOR_H;
+
+        dst.x = x;
+        dst.y = y;
+        dst.width = SEC_CURSOR_W;
+        dst.height = SEC_CURSOR_H;
+
+        XDBG_DEBUG (MCRS, "[%p] to (%d,%d)\n", pCrtc, x, y);
+
+        secLayerSetRect (pCrtcPriv->ovl_layer, &src, &dst);
+    }
+}
+
+static void
+_cursorInit (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    XDBG_TRACE (MCRS, "[%p] \n", pCrtc);
+
+    //Damage Create
+    if (!pCrtcPriv->move_layer)
+        _cursorRegisterBlockHandler (pCrtc);
+}
+
+static int
+_cursorDestroy (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    XDBG_TRACE (MCRS, "[%p]  \n", pCrtc);
+
+    if(pCrtcPriv->saved_image)
+    {
+        pixman_image_unref(pCrtcPriv->saved_image);
+        pCrtcPriv->saved_image = NULL;
+    }
+
+    if(pCrtcPriv->cursor_image)
+    {
+        pixman_image_unref(pCrtcPriv->cursor_image);
+        pCrtcPriv->cursor_image = NULL;
+    }
+
+    if(pCrtcPriv->ovl_canvas)
+    {
+        XDBG_TRACE (MCRS, "[%p] ovl_canvas(%p) destroy.\n", pCrtc, pCrtcPriv->ovl_canvas);
+        pixman_image_unref(pCrtcPriv->ovl_canvas);
+        pCrtcPriv->ovl_canvas = NULL;
+        pCrtcPriv->need_draw_cursor = TRUE;
+    }
+
+    if (pCrtcPriv->ovl_layer)
+    {
+        XDBG_TRACE (MCRS, "[%p] ovl_layer(%p) destroy.\n", pCrtc, pCrtcPriv->ovl_layer);
+        secLayerUnref (pCrtcPriv->ovl_layer);
+        pCrtcPriv->ovl_layer = NULL;
+    }
+
+    return TRUE;
+}
+
+static void
+_cursorShow (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECPtr pSec = SECPTR (pCrtc->scrn);
+
+    if(!pSec->enableCursor)
+        return;
+
+    if (pCrtcPriv->ovl_layer && !secLayerTurnStatus (pCrtcPriv->ovl_layer))
+        secLayerTurn (pCrtcPriv->ovl_layer, TRUE, FALSE);
+
+    XDBG_TRACE (MCRS, "[%p] user_rotate(%d)\n", pCrtc, pCrtcPriv->user_rotate);
+
+    if (pCrtcPriv->move_layer)
+    {
+        _overlayEnsureBuffer (pCrtc, pCrtcPriv->move_layer);
+        _overlayEnsureLayer (pCrtc);
+
+        _cursorEnsureCursorImage (pCrtc);
+        _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_cursor,
+                             SEC_CURSOR_W, SEC_CURSOR_H);
+        _cursorDrawCursor (pCrtc);
+
+        _overlaySelectBuffer (pCrtc, pCrtcPriv->move_layer);
+
+        int offset = _overlayGetXMoveOffset (pCrtc, pCrtcPriv->cursor_win_x);
+        _cursorMove (pCrtc, pCrtcPriv->cursor_win_x - offset, pCrtcPriv->cursor_win_y);
+
+        if (!secLayerIsVisible (pCrtcPriv->ovl_layer))
+            secLayerShow (pCrtcPriv->ovl_layer);
+    }
+    else
+    {
+        pCrtcPriv->need_cursor_update = TRUE;
+        _cursorRestoreImage(pCrtc);
+        _cursorRegisterBlockHandler (pCrtc);
+    }
+}
+
+static void
+_cursorHide (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    XDBG_TRACE (MCRS, "[%p] \n", pCrtc);
+
+    if (pCrtcPriv->move_layer)
+    {
+        if (pCrtcPriv->ovl_layer && secLayerIsVisible (pCrtcPriv->ovl_layer))
+            secLayerHide (pCrtcPriv->ovl_layer);
+    }
+    else
+    {
+        _cursorRestoreImage (pCrtc);
+
+        if (pCrtcPriv->need_off && !pCrtcPriv->cursor_show)
+        {
+            if (pCrtcPriv->ovl_layer && secLayerIsVisible (pCrtcPriv->ovl_layer))
+                secLayerHide (pCrtcPriv->ovl_layer);
+            return;
+        }
+    }
+
+    if (pCrtcPriv->ovl_layer && secLayerTurnStatus (pCrtcPriv->ovl_layer))
+    {
+        Bool turnoff = FALSE;
+
+        if (pCrtcPriv->ref_overlay && pCrtcPriv->need_off)
+            turnoff = TRUE;
+        if (!pCrtcPriv->ref_overlay)
+            turnoff = TRUE;
+
+        if (turnoff)
+            _cursorDestroy (pCrtc);
+    }
+
+    pCrtcPriv->cursor_old_offset = 0;
+    pCrtcPriv->need_cursor_update = TRUE;
+}
+
+static Bool
+_cursorEnable (xf86CrtcPtr pCrtc, Bool enable)
+{
+    ScrnInfoPtr pScrn = pCrtc->scrn;
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    if (!pCrtcPriv->cursor_show)
+        return FALSE;
+
+    XDBG_TRACE (MCRS, "[%p] enable(%d) \n", pCrtc, enable);
+
+    if (enable)
+    {
+        _cursorShow (pCrtc);
+
+        if (pCrtc == xf86CompatCrtc (pScrn))
+        {
+            PropertyPtr rotate_prop;
+
+            /* Set Current Root Rotation */
+            rotate_prop = secUtilGetWindowProperty (pScrn->pScreen->root,
+                                                    "_E_ILLUME_ROTATE_ROOT_ANGLE");
+            if (rotate_prop)
+            {
+                int rotate = secUtilDegreeToRotate (*(int*)rotate_prop->data);
+                pCrtcPriv->user_rotate = rotate;
+
+                //Send swap property to relative input device
+                _cursorFindRelativeDevice (pCrtc);
+            }
+        }
+
+        /* Hook for window rotate */
+        atom_rotate_root_angle = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE"
+                                           , strlen ("_E_ILLUME_ROTATE_ROOT_ANGLE"), FALSE);
+        atom_relative_device_exist = MakeAtom ("X Mouse Exist"
+                                               , strlen ("X Mouse Exist"), TRUE);
+
+        if (atom_rotate_root_angle != None)
+        {
+            if (!XaceRegisterCallback (XACE_PROPERTY_ACCESS, _cursorRotateHook, pScrn))
+                XDBG_ERROR (MCRS, "[%p] Fail XaceRegisterCallback:XACE_PROPERTY_ACCESS\n", pCrtc);
+
+            XDBG_TRACE (MCRS, "[%p] Hook property : _E_ILLUME_ROTATE_ROOT_ANGLE\n", pCrtc);
+        }
+        else
+            XDBG_TRACE (MCRS, "[%p] Cannot find _E_ILLUME_ROTATE_ROOT_ANGLE\n", pCrtc);
+    }
+    else
+    {
+        XaceDeleteCallback (XACE_PROPERTY_ACCESS, _cursorRotateHook, pScrn);
+
+        _cursorHide (pCrtc);
+    }
+
+    pCrtcPriv->cursor_old_offset = 0;
+
+    return TRUE;
+}
+
+static Bool
+_cursorRotate (xf86CrtcPtr pCrtc, int rotate)
+{
+    SECPtr pSec = SECPTR (pCrtc->scrn);
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    if (pCrtcPriv->user_rotate == rotate)
+        return TRUE;
+
+    if (!pCrtcPriv->cursor_show)
+        return TRUE;
+
+    XDBG_TRACE (MCRS, "[%p] rotate(%d) \n", pCrtc, rotate);
+
+    pCrtcPriv->user_rotate = rotate;
+
+    if (pSec->enableCursor && pCrtcPriv->cursor_show)
+    {
+        //Send swap property to relative input device
+        _cursorFindRelativeDevice (pCrtc);
+
+        if(pCrtcPriv->cursor_image)
+        {
+            pixman_image_unref(pCrtcPriv->cursor_image);
+            pCrtcPriv->cursor_image = NULL;
+        }
+
+        if (pCrtcPriv->move_layer)
+        {
+            _overlayEnsureBuffer (pCrtc, pCrtcPriv->move_layer);
+            _overlayEnsureLayer (pCrtc);
+
+            _cursorEnsureCursorImage (pCrtc);
+            _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_cursor,
+                                 SEC_CURSOR_W, SEC_CURSOR_H);
+            _cursorDrawCursor (pCrtc);
+
+            int offset = _overlayGetXMoveOffset (pCrtc, pCrtcPriv->cursor_win_x);
+            _cursorMove (pCrtc, pCrtcPriv->cursor_win_x - offset, pCrtcPriv->cursor_win_y);
+        }
+        else
+        {
+            pCrtcPriv->need_cursor_update = TRUE;
+            _cursorRestoreImage(pCrtc);
+            _cursorRegisterBlockHandler (pCrtc);
+        }
+    }
+
+    pCrtcPriv->cursor_old_offset = 0;
+
+    return TRUE;
+}
+
+static Bool
+_cursorChangeStatus (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECPtr pSec = SECPTR (pCrtc->scrn);
+    int new_value;
+
+    if (pCrtcPriv->ref_overlay && !pCrtcPriv->need_off)
+        new_value = FALSE;
+    else
+        new_value = TRUE;
+
+    XDBG_TRACE (MCRS, "[%p] ref(%d) off(%d) value(%d=>%d) cursor(%d,%d) \n", pCrtc,
+                pCrtcPriv->ref_overlay, pCrtcPriv->need_off, pCrtcPriv->move_layer,
+                new_value, pCrtcPriv->cursor_show, pSec->enableCursor);
+
+    /* layer off if needed */
+    if (!pSec->enableCursor && pCrtcPriv->ovl_layer && secLayerTurnStatus (pCrtcPriv->ovl_layer))
+    {
+        Bool turnoff = FALSE;
+
+        if (pCrtcPriv->ref_overlay && pCrtcPriv->need_off)
+            turnoff = TRUE;
+        if (!pCrtcPriv->ref_overlay)
+            turnoff = TRUE;
+
+        if (turnoff)
+        {
+            _cursorDestroy (pCrtc);
+            return TRUE;
+        }
+    }
+
+    /* layer on if needed */
+    if (pCrtcPriv->ovl_layer && !secLayerTurnStatus (pCrtcPriv->ovl_layer))
+        if (pSec->enableCursor || (pCrtcPriv->ref_overlay && !pCrtcPriv->need_off))
+            secLayerTurn (pCrtcPriv->ovl_layer, TRUE, FALSE);
+
+    if (pCrtcPriv->move_layer == new_value)
+        return TRUE;
+
+    pCrtcPriv->move_layer = new_value;
+
+    if(pCrtcPriv->ovl_canvas)
+    {
+        XDBG_TRACE (MCRS, "[%p] ovl_canvas(%p) destroy.\n", pCrtc, pCrtcPriv->ovl_canvas);
+        pixman_image_unref(pCrtcPriv->ovl_canvas);
+        pCrtcPriv->ovl_canvas = NULL;
+        pCrtcPriv->need_draw_cursor = TRUE;
+    }
+
+    if (pCrtcPriv->cursor_show)
+        _cursorShow (pCrtc);
+
+    if (new_value && pCrtcPriv->ovl_vbuf_pixmap)
+    {
+        SECModePtr pSecMode = (SECModePtr) SECPTR (pCrtc->scrn)->pSecMode;
+        pixman_image_t *old = pCrtcPriv->ovl_canvas;
+
+        pCrtcPriv->ovl_canvas = NULL;
+
+        _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_pixmap,
+                             pSecMode->main_lcd_mode.hdisplay,
+                             pSecMode->main_lcd_mode.vdisplay);
+
+        _cursorRestoreImage (pCrtc);
+
+        if(pCrtcPriv->ovl_canvas)
+            pixman_image_unref(pCrtcPriv->ovl_canvas);
+
+        pCrtcPriv->ovl_canvas = old;
+    }
+
+    if (!pCrtcPriv->ovl_layer)
+        _overlaySelectBuffer (pCrtc, pCrtcPriv->move_layer);
+
+    if (pCrtcPriv->ovl_layer)
+        if (!secLayerIsVisible (pCrtcPriv->ovl_layer))
+            secLayerShow (pCrtcPriv->ovl_layer);
+
+    return TRUE;
+}
+
+static void
+_flipPixmapInit (xf86CrtcPtr pCrtc)
+{
+    ScrnInfoPtr pScrn = pCrtc->scrn;
+    SECPtr pSec = SECPTR (pScrn);
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    int flip_backbufs = pSec->flip_bufs - 1;
+    int i;
+
+    pCrtcPriv->flip_backpixs.lub = -1;
+    pCrtcPriv->flip_backpixs.num = flip_backbufs;
+
+    pCrtcPriv->flip_backpixs.pix_free = calloc (flip_backbufs, sizeof(void*));
+    for (i = 0; i < flip_backbufs; i++)
+        pCrtcPriv->flip_backpixs.pix_free[i] = TRUE;
+    pCrtcPriv->flip_backpixs.flip_pixmaps = calloc (flip_backbufs, sizeof(void*));
+    pCrtcPriv->flip_backpixs.flip_draws = calloc (flip_backbufs, sizeof(void*));
+}
+
+static void
+_flipPixmapDeinit (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    ScreenPtr pScreen = pCrtc->scrn->pScreen;
+    int i;
+
+    for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++)
+    {
+        pCrtcPriv->flip_backpixs.pix_free[i] = TRUE;
+        if (pCrtcPriv->flip_backpixs.flip_pixmaps[i])
+        {
+#if USE_XDBG
+            if (pCrtcPriv->flip_backpixs.flip_draws[i])
+                xDbgLogPListDrawRemoveRefPixmap (pCrtcPriv->flip_backpixs.flip_draws[i],
+                                                   pCrtcPriv->flip_backpixs.flip_pixmaps[i]);
+#endif
+
+            (*pScreen->DestroyPixmap) (pCrtcPriv->flip_backpixs.flip_pixmaps[i]);
+            pCrtcPriv->flip_backpixs.flip_pixmaps[i] = NULL;
+            pCrtcPriv->flip_backpixs.flip_draws[i] = NULL;
+        }
+    }
+    pCrtcPriv->flip_backpixs.lub = -1;
+}
+
+static xf86CrtcPtr
+_secCrtcGetFromPipe (ScrnInfoPtr pScrn, int pipe)
+{
+    xf86CrtcConfigPtr pXf86CrtcConfig;
+    pXf86CrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
+    xf86CrtcPtr pCrtc = NULL;
+    SECCrtcPrivPtr pCrtcPriv = NULL;
+    int i;
+
+    for (i = 0; i < pXf86CrtcConfig->num_output; i++)
+    {
+        pCrtc = pXf86CrtcConfig->crtc[i];
+        pCrtcPriv = pCrtc->driver_private;
+        if (pCrtcPriv->pipe == pipe)
+        {
+            return pCrtc;
+        }
+    }
+
+    return NULL;
+}
+
+
+static void
+SECCrtcDpms(xf86CrtcPtr pCrtc, int pMode)
+{
+
+}
+
+static Bool
+SECCrtcSetModeMajor(xf86CrtcPtr pCrtc, DisplayModePtr pMode,
+                    Rotation rotation, int x, int y)
+{
+    ScrnInfoPtr pScrn = pCrtc->scrn;
+    SECPtr pSec = SECPTR (pScrn);
+    SECFbPtr pFb = pSec->pFb;
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECModePtr pSecMode = pCrtcPriv->pSecMode;
+    tbm_bo bo = NULL, old_bo = NULL;
+    tbm_bo bo_accessibility[2] = {0,}, old_bo_accessibility[2] = {0,};
+    int saved_x, saved_y;
+    Rotation saved_rotation;
+    DisplayModeRec saved_mode;
+    Bool ret = FALSE;
+
+    XDBG_DEBUG(MDISP,
+               "SetModeMajor pMode:%d cur(%dx%d+%d+%d),rot:%d new(%dx%d+%d+%d),refresh(%f)rot:%d\n",
+               secCrtcID(pCrtcPriv),
+               pCrtc->mode.HDisplay, pCrtc->mode.VDisplay,pCrtc->x, pCrtc->y,
+               pCrtc->rotation,
+               pMode->HDisplay,pMode->VDisplay,x,y,pMode->VRefresh,
+               rotation);
+
+    memcpy (&saved_mode, &pCrtc->mode, sizeof(DisplayModeRec));
+    saved_x = pCrtc->x;
+    saved_y = pCrtc->y;
+    saved_rotation = pCrtc->rotation;
+
+    memcpy (&pCrtc->mode, pMode, sizeof(DisplayModeRec));
+    pCrtc->x = x;
+    pCrtc->y = y;
+    pCrtc->rotation = rotation;
+
+    if (pSec->fake_root)
+        secDisplaySwapModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, pMode);
+    else
+        secDisplayModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, pMode);
+
+    /* accessibility */
+    if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0)
+    {
+        XDBG_GOTO_IF_FAIL (pCrtcPriv->accessibility_front_bo != NULL, fail);
+        XDBG_GOTO_IF_FAIL (pCrtcPriv->accessibility_back_bo != NULL, fail);
+
+        old_bo_accessibility[0] = pCrtcPriv->accessibility_front_bo;
+        old_bo_accessibility[1] = pCrtcPriv->accessibility_back_bo;
+
+        bo_accessibility[0] = secRenderBoCreate (pScrn, pMode->HDisplay, pMode->VDisplay);
+        bo_accessibility[1] = secRenderBoCreate (pScrn, pMode->HDisplay, pMode->VDisplay);
+
+        pCrtcPriv->accessibility_front_bo = bo_accessibility[0];
+        pCrtcPriv->accessibility_back_bo = bo_accessibility[1];
+    }
+
+    /* find bo which covers the requested mode of crtc */
+    old_bo = pCrtcPriv->front_bo;
+    bo = secFbGetBo(pFb, x, y, pMode->HDisplay, pMode->VDisplay, FALSE);
+    XDBG_GOTO_IF_FAIL (bo != NULL, fail);
+    pCrtcPriv->front_bo = bo;
+
+    ret = secCrtcApply(pCrtc);
+    XDBG_GOTO_IF_FAIL (ret == TRUE, fail);
+
+    /* set the default external mode */
+    secDisplayModeToKmode (pCrtc->scrn, &pSecMode->ext_connector_mode, pMode);
+
+   /* accessibility */
+    if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0)
+    {
+        if (ret)
+        {
+            if (old_bo_accessibility[0])
+                secRenderBoUnref (old_bo_accessibility[0]);
+            if (old_bo_accessibility[1])
+                secRenderBoUnref (old_bo_accessibility[1]);
+        } 
+    }
+
+    return ret;
+fail:
+    XDBG_ERROR(MDISP, "Fail crtc apply(crtc_id:%d, rotate:%d, %dx%d+%d+%d\n",
+               secCrtcID(pCrtcPriv), rotation, x, y, pCrtc->mode.HDisplay, pCrtc->mode.VDisplay);
+
+    pCrtcPriv->front_bo = old_bo;
+
+    /* accessibility */
+    if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0)
+    {
+        if (bo_accessibility[0])
+            secRenderBoUnref (bo_accessibility[0]);
+        if (bo_accessibility[1])
+            secRenderBoUnref (bo_accessibility[1]);
+
+        pCrtcPriv->accessibility_front_bo = old_bo_accessibility[0];
+        pCrtcPriv->accessibility_back_bo = old_bo_accessibility[1];
+    }
+
+    if (pSec->fake_root)
+        secDisplaySwapModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, &saved_mode);
+    else
+        secDisplayModeToKmode(pCrtc->scrn, &pCrtcPriv->kmode, &saved_mode);
+
+    memcpy (&pCrtc->mode, &saved_mode, sizeof(DisplayModeRec));
+    pCrtc->x = saved_x;
+    pCrtc->y = saved_y;
+    pCrtc->rotation = saved_rotation;
+
+    return ret;
+}
+
+static void
+SECCrtcSetCursorColors(xf86CrtcPtr pCrtc, int bg, int fg)
+{
+    XDBG_TRACE (MCRS, "[%p]  \n", pCrtc);
+}
+
+static void
+SECCrtcSetCursorPosition (xf86CrtcPtr pCrtc, int x, int y)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECPtr pSec = SECPTR (pCrtc->scrn);
+
+    pCrtcPriv->cursor_pos_x = x;
+    pCrtcPriv->cursor_pos_y = y;
+
+    XDBG_DEBUG (MCRS, "[%p] (%d,%d) \n", pCrtc, x, y);
+
+    if (!pSec->enableCursor)
+        return;
+
+    if (!pCrtcPriv->cursor_show)
+        return;
+
+    if (pCrtcPriv->move_layer)
+    {
+        _cursorEnsureCanvas (pCrtc, pCrtcPriv->ovl_vbuf_cursor,
+                             SEC_CURSOR_W, SEC_CURSOR_H);
+        _cursorEnsureCursorImage (pCrtc);
+
+        int offset = _overlayGetXMoveOffset (pCrtc, pCrtcPriv->cursor_win_x);
+        if (pCrtcPriv->cursor_old_offset != offset)
+        {
+            _cursorDrawCursor (pCrtc);
+            pCrtcPriv->cursor_old_offset = offset;
+        }
+
+        _cursorMove (pCrtc, pCrtcPriv->cursor_win_x - offset, pCrtcPriv->cursor_win_y);
+    }
+    else
+    {
+        /* Draw cursor in block handler */
+        pCrtcPriv->need_cursor_update = TRUE;
+        _cursorRestoreImage(pCrtc);
+        _cursorRegisterBlockHandler (pCrtc);
+    }
+}
+
+static void
+SECCrtcShowCursor (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    XDBG_TRACE (MCRS, "[%p] cursor_show(%d)\n", pCrtc, pCrtcPriv->cursor_show);
+
+    if(pCrtcPriv->cursor_show)
+        return;
+
+    pCrtcPriv->cursor_show = TRUE;
+
+    _cursorShow (pCrtc);
+}
+
+static void
+SECCrtcHideCursor (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    XDBG_TRACE (MCRS, "[%p] cursor_show(%d)\n", pCrtc, pCrtcPriv->cursor_show);
+
+    if(!pCrtcPriv->cursor_show)
+        return;
+
+    pCrtcPriv->cursor_show = FALSE;
+
+    _cursorHide (pCrtc);
+}
+
+static void
+SECCrtcLoadCursorArgb(xf86CrtcPtr pCrtc, CARD32 *image)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    if (image == NULL)
+        return;
+
+    XDBG_TRACE (MCRS, "[%p] image(%p) \n", pCrtc, image);
+
+    if (pCrtcPriv->backup_image)
+        pixman_image_unref (pCrtcPriv->backup_image);
+
+    pCrtcPriv->backup_image = pixman_image_create_bits (PIXMAN_a8r8g8b8
+                                     , SEC_CURSOR_W, SEC_CURSOR_H
+                                     , NULL
+                                     , 0);
+
+    XDBG_RETURN_IF_FAIL (pCrtcPriv->backup_image != NULL);
+
+    memcpy (pixman_image_get_data(pCrtcPriv->backup_image), image, SEC_CURSOR_W * SEC_CURSOR_H * 4);
+
+    if(pCrtcPriv->cursor_image)
+    {
+        pixman_image_unref(pCrtcPriv->cursor_image);
+        pCrtcPriv->cursor_image = NULL;
+    }
+
+    pCrtcPriv->need_cursor_update = TRUE;
+}
+
+
+static void *
+SECCrtcShadowAllocate(xf86CrtcPtr pCrtc, int width, int height)
+{
+#if 0
+    ScrnInfoPtr scrn = pCrtc->scrn;
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECModePtr pSecMode = pCrtcPriv->pSecMode;
+    unsigned long rotate_pitch;
+    uint32_t tiling;
+    int ret;
+
+    pCrtcPriv->rotate_bo = intel_allocate_framebuffer (scrn,
+                           width, height,
+                           pSecMode->cpp,
+                           &rotate_pitch,
+                           &tiling);
+
+    if (!pCrtcPriv->rotate_bo)
+    {
+        xf86DrvMsg (pCrtc->scrn->scrnIndex, X_ERROR,
+                    "Couldn't allocate shadow memory for rotated CRTC\n");
+        return NULL;
+    }
+
+    ret = drmModeAddFB (pSecMode->fd, width, height, pCrtc->scrn->depth,
+                        pCrtc->scrn->bitsPerPixel, rotate_pitch,
+                        pCrtcPriv->rotate_bo->handle,
+                        &pCrtcPriv->rotate_fb_id);
+    if (ret < 0)
+    {
+        ErrorF ("failed to add rotate fb\n");
+        drm_intel_bo_unreference (pCrtcPriv->rotate_bo);
+        return NULL;
+    }
+
+    pCrtcPriv->rotate_pitch = rotate_pitch;
+    return pCrtcPriv->rotate_bo;
+#else
+    return NULL;
+#endif
+}
+
+static PixmapPtr
+SECCrtcShadowCreate(xf86CrtcPtr pCrtc, void *data, int width, int height)
+{
+#if 0
+    ScrnInfoPtr pScrn = pCrtc->scrn;
+    SECPtr pSEC = SECPtr (pScrn);
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    PixmapPtr rotate_pixmap;
+
+    if (!data)
+    {
+        data = SECCrtcShadowAllocate (pCrtc, width, height);
+        if (!data)
+        {
+            xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                        "Couldn't allocate shadow pixmap for rotated CRTC\n");
+            return NULL;
+        }
+    }
+    if (pCrtcPriv->rotate_bo == NULL)
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                    "Couldn't allocate shadow pixmap for rotated CRTC\n");
+        return NULL;
+    }
+
+    rotate_pixmap = GetScratchPixmapHeader (pScrn->pScreen,
+                                            width, height,
+                                            pScrn->depth,
+                                            pScrn->bitsPerPixel,
+                                            pCrtcPriv->rotate_pitch,
+                                            NULL);
+
+    if (rotate_pixmap == NULL)
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                    "Couldn't allocate shadow pixmap for rotated CRTC\n");
+        return NULL;
+    }
+
+//    intel_set_pixmap_bo(rotate_pixmap, pCrtcPriv->rotate_bo);
+
+    pSEC->shadow_present = TRUE;
+
+    return rotate_pixmap;
+#else
+    return NULL;
+#endif
+}
+
+static void
+SECCrtcShadowDestroy(xf86CrtcPtr pCrtc, PixmapPtr rotate_pixmap, void *data)
+{
+#if 0
+    ScrnInfoPtr pScrn = pCrtc->scrn;
+    SECPtr pSEC = SECPtr (pScrn);
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECModePtr pSecMode = pCrtcPriv->mode;
+
+    if (rotate_pixmap)
+    {
+        intel_set_pixmap_bo (rotate_pixmap, NULL);
+        FreeScratchPixmapHeader (rotate_pixmap);
+    }
+
+    if (data)
+    {
+        /* Be sure to sync acceleration before the memory gets
+         * unbound. */
+        drmModeRmFB (pSecMode->fd, pCrtcPriv ->rotate_fb_id);
+        pCrtcPriv ->rotate_fb_id = 0;
+
+        tbm_bo_unreference (pCrtcPriv ->rotate_bo);
+        pCrtcPriv ->rotate_bo = NULL;
+    }
+
+    pSEC->shadow_present = pSEC->use_shadow;
+#else
+    return;
+#endif
+}
+
+static void
+SECCrtcGammaSet(xf86CrtcPtr pCrtc,
+                CARD16 *red, CARD16 *green, CARD16 *blue, int size)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECModePtr pSecMode = pCrtcPriv->pSecMode;
+
+    drmModeCrtcSetGamma(pSecMode->fd, secCrtcID(pCrtcPriv),
+                        size, red, green, blue);
+}
+
+static void
+SECCrtcDestroy(xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    DRI2FrameEventPtr event_ref=NULL, event_next=NULL;
+    xorg_list_for_each_entry_safe (event_ref, event_next, &pCrtcPriv->pending_flips, crtc_pending_link)
+    {
+        free (event_ref);
+    }
+
+    _flipPixmapDeinit (pCrtc);
+
+    _cursorDestroy (pCrtc);
+    _cursorUnregisterBlockHandler (pCrtc);
+
+#if 1
+    if (pCrtcPriv->pFpsDebug)
+    {
+        xDbgLogFpsDebugDestroy (pCrtcPriv->pFpsDebug);
+        pCrtcPriv->pFpsDebug = NULL;
+    }
+#endif
+
+    if (pCrtcPriv->accessibility_front_bo)
+    {
+        secRenderBoUnref (pCrtcPriv->accessibility_front_bo);
+        pCrtcPriv->accessibility_front_bo = NULL;
+    }
+
+    if (pCrtcPriv->accessibility_back_bo)
+    {
+        secRenderBoUnref (pCrtcPriv->accessibility_back_bo);
+        pCrtcPriv->accessibility_back_bo = NULL;
+    }
+
+    if (pCrtcPriv->backup_image)
+    {
+        pixman_image_unref(pCrtcPriv->backup_image);
+        pCrtcPriv->backup_image = NULL;
+    }
+
+    if (pCrtcPriv->ovl_vbuf_cursor)
+    {
+        secUtilVideoBufferUnref (pCrtcPriv->ovl_vbuf_cursor);
+        pCrtcPriv->ovl_vbuf_cursor = NULL;
+    }
+
+    if (pCrtcPriv->ovl_vbuf_pixmap)
+    {
+        secUtilVideoBufferUnref (pCrtcPriv->ovl_vbuf_pixmap);
+        pCrtcPriv->ovl_vbuf_pixmap = NULL;
+    }
+
+    if (pCrtcPriv->ovl_layer)
+    {
+        secLayerUnref (pCrtcPriv->ovl_layer);
+        pCrtcPriv->ovl_layer = NULL;
+    }
+
+    if (pCrtcPriv->mode_crtc)
+        drmModeFreeCrtc (pCrtcPriv->mode_crtc);
+
+    if (pCrtcPriv->front_bo)
+    {
+        pCrtcPriv->front_bo = NULL;
+    }
+
+    if (pCrtcPriv->back_bo)
+    {
+        secRenderBoUnref(pCrtcPriv->back_bo);
+        pCrtcPriv->back_bo = NULL;
+    }
+
+    if( pCrtcPriv->flip_backpixs.pix_free != NULL )
+    {
+        free(pCrtcPriv->flip_backpixs.pix_free);
+        pCrtcPriv->flip_backpixs.pix_free = NULL;
+    }
+
+    if( pCrtcPriv->flip_backpixs.flip_pixmaps != NULL )
+    {
+        free(pCrtcPriv->flip_backpixs.flip_pixmaps);
+        pCrtcPriv->flip_backpixs.flip_pixmaps = NULL;
+    }
+
+    if( pCrtcPriv->flip_backpixs.flip_draws != NULL )
+    {
+        free(pCrtcPriv->flip_backpixs.flip_draws);
+        pCrtcPriv->flip_backpixs.flip_draws = NULL;
+    }
+
+    xorg_list_del (&pCrtcPriv->link);
+    free (pCrtcPriv);
+
+    pCrtc->driver_private = NULL;
+}
+
+static const xf86CrtcFuncsRec sec_crtc_funcs =
+{
+    .dpms = SECCrtcDpms,
+    .set_mode_major = SECCrtcSetModeMajor,
+    .set_cursor_colors = SECCrtcSetCursorColors,
+    .set_cursor_position = SECCrtcSetCursorPosition,
+    .show_cursor = SECCrtcShowCursor,
+    .hide_cursor = SECCrtcHideCursor,
+    .load_cursor_argb = SECCrtcLoadCursorArgb,
+    .shadow_create = SECCrtcShadowCreate,
+    .shadow_allocate = SECCrtcShadowAllocate,
+    .shadow_destroy = SECCrtcShadowDestroy,
+    .gamma_set = SECCrtcGammaSet,
+    .destroy = SECCrtcDestroy,
+};
+
+void
+secCrtcInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num)
+{
+    xf86CrtcPtr pCrtc;
+    SECCrtcPrivPtr pCrtcPriv;
+    SECPtr pSec = SECPTR (pScrn);
+
+//    secLogSetLevel("CRTC", 0);
+
+    pCrtcPriv = calloc (sizeof (SECCrtcPrivRec), 1);
+    if (pCrtcPriv == NULL)
+        return;
+
+    pCrtc = xf86CrtcCreate (pScrn, &sec_crtc_funcs);
+    if (pCrtc == NULL)
+    {
+        free (pCrtcPriv);
+        return;
+    }
+
+    pCrtcPriv->idx = num;
+    pCrtcPriv->mode_crtc = drmModeGetCrtc (pSecMode->fd,
+                                           pSecMode->mode_res->crtcs[num]);
+    pCrtcPriv->move_layer = TRUE;
+    pCrtcPriv->user_rotate = RR_Rotate_0;
+
+    pCrtcPriv->pSecMode = pSecMode;
+    pCrtc->driver_private = pCrtcPriv;
+
+    pCrtcPriv->pipe = num;
+    pCrtcPriv->onoff = TRUE;
+
+    xorg_list_init (&pCrtcPriv->pending_flips);
+
+    pCrtcPriv->pCrtc = pCrtc;
+
+#if 1
+    pCrtcPriv->pFpsDebug = xDbgLogFpsDebugCreate ();
+    if (pCrtcPriv->pFpsDebug == NULL)
+    {
+        free (pCrtcPriv);
+        return;
+    }
+#endif
+
+    if (pSec->enableCursor)
+        _cursorInit (pCrtc);
+
+    _flipPixmapInit (pCrtc);
+
+    xorg_list_add(&(pCrtcPriv->link), &(pSecMode->crtcs));
+}
+
+/* check the crtc is on */
+Bool
+secCrtcOn(xf86CrtcPtr pCrtc)
+{
+    ScrnInfoPtr pScrn = pCrtc->scrn;
+    xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
+    int i;
+
+    if (!pCrtc->enabled)
+        return FALSE;
+
+    /* Kernel manage CRTC status based out output config */
+    for (i = 0; i < pCrtcConfig->num_output; i++)
+    {
+        xf86OutputPtr pOutput = pCrtcConfig->output[i];
+        if (pOutput->crtc == pCrtc &&
+            secOutputDpmsStatus(pOutput) == DPMSModeOn)
+            return TRUE;
+    }
+
+    return TRUE;
+}
+
+Bool
+secCrtcApply(xf86CrtcPtr pCrtc)
+{
+    ScrnInfoPtr pScrn = pCrtc->scrn;
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    SECModePtr pSecMode = pCrtcPriv->pSecMode;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR (pCrtc->scrn);
+    uint32_t *output_ids;
+    int output_count = 0;
+    int fb_id, x, y;
+    int i;
+    Bool ret = FALSE;
+    SECFbBoDataPtr bo_data;
+    tbm_bo bo;
+
+    output_ids = calloc (sizeof (uint32_t), xf86_config->num_output);
+    if (!output_ids)
+        return FALSE;
+
+    for (i = 0; i < xf86_config->num_output; i++)
+    {
+        xf86OutputPtr pOutput = xf86_config->output[i];
+        SECOutputPrivPtr pOutputPriv;
+        if (pOutput->crtc != pCrtc)
+            continue;
+
+        pOutputPriv = pOutput->driver_private;
+
+        /* modify the physical size of monitor */
+        if (!strcmp(pOutput->name, "LVDS1"))
+        {
+            pOutput->mm_width = pOutputPriv->mode_output->mmWidth;
+            pOutput->mm_height = pOutputPriv->mode_output->mmHeight;
+            pOutput->conf_monitor->mon_width = pOutputPriv->mode_output->mmWidth;
+            pOutput->conf_monitor->mon_height = pOutputPriv->mode_output->mmHeight;
+        }
+
+        output_ids[output_count] = pOutputPriv->mode_output->connector_id;
+        output_count++;
+    }
+
+    if (!xf86CrtcRotate (pCrtc))
+        goto done;
+
+    pCrtc->funcs->gamma_set (pCrtc, pCrtc->gamma_red, pCrtc->gamma_green,
+                             pCrtc->gamma_blue, pCrtc->gamma_size);
+
+    /* accessilitity */
+    if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0)
+    {
+        tbm_bo temp;
+        bo = pCrtcPriv->accessibility_back_bo;
+        temp = pCrtcPriv->accessibility_front_bo;
+        pCrtcPriv->accessibility_front_bo = pCrtcPriv->accessibility_back_bo;
+        pCrtcPriv->accessibility_back_bo = temp;
+    }
+    else
+    {
+        bo = pCrtcPriv->front_bo;
+    }
+
+    tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data);
+    x = pCrtc->x-bo_data->pos.x1;
+    y = pCrtc->y-bo_data->pos.y1;
+    fb_id = bo_data->fb_id;
+
+    if (pCrtcPriv->rotate_fb_id)
+    {
+        fb_id = pCrtcPriv->rotate_fb_id;
+        x = 0;
+        y = 0;
+    }
+
+    XDBG_INFO (MDISP, "fb_id,%d name,%s width,%d height,%d, vrefresh,%d, accessibility,%d\n",
+               fb_id, pCrtcPriv->kmode.name, pCrtcPriv->kmode.hdisplay,
+               pCrtcPriv->kmode.vdisplay, pCrtcPriv->kmode.vrefresh, pCrtcPriv->bAccessibility);
+
+    /* turn off the crtc if the same crtc is set already by another display mode
+     * before the set crtcs
+     */
+    secDisplaySetDispSetMode(pScrn, DISPLAY_SET_MODE_OFF);
+
+    if (!pCrtcPriv->onoff)
+        secCrtcTurn (pCrtc, TRUE, FALSE, FALSE);
+
+    /* for cache control */
+    tbm_bo_map (bo, TBM_DEVICE_2D, TBM_OPTION_READ);
+    tbm_bo_unmap (bo);
+
+    ret = drmModeSetCrtc(pSecMode->fd, secCrtcID(pCrtcPriv),
+                         fb_id, x, y, output_ids, output_count,
+                         &pCrtcPriv->kmode);
+    if (ret)
+    {
+        XDBG_INFO (MDISP, "failed to set mode: %s\n", strerror (-ret));
+        ret = FALSE;
+    }
+    else
+    {
+        ret = TRUE;
+
+        /* Force DPMS to On for all outputs, which the kernel will have done
+         * with the mode set. Also, restore the backlight level
+         */
+        for (i = 0; i < xf86_config->num_output; i++)
+        {
+            xf86OutputPtr pOutput = xf86_config->output[i];
+            SECOutputPrivPtr pOutputPriv;
+
+            if (pOutput->crtc != pCrtc)
+                continue;
+
+            pOutputPriv = pOutput->driver_private;
+
+            /* TODO :: soolim :: check this out */
+            secOutputDpmsSet(pOutput, DPMSModeOn);
+            pOutputPriv->dpms_mode = DPMSModeOn;
+
+            /* update mode_encoder */
+            drmModeFreeEncoder (pOutputPriv->mode_encoder);
+            pOutputPriv->mode_encoder =
+                drmModeGetEncoder (pSecMode->fd, pOutputPriv->mode_output->encoders[0]);
+
+            /* set display connector and display set mode */
+            if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+                pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB)
+            {
+                secDisplaySetDispConnMode (pScrn, DISPLAY_CONN_MODE_HDMI);
+                /* TODO : find the display mode */
+                secDisplaySetDispSetMode (pScrn, DISPLAY_SET_MODE_EXT);
+
+                /* should be shown again when crtc on. */
+                secLayerShowAll (pScrn, LAYER_OUTPUT_EXT);
+            }
+            else if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)
+            {
+                secDisplaySetDispConnMode (pScrn, DISPLAY_CONN_MODE_VIRTUAL);
+                /* TODO : find the display mode */
+                secDisplaySetDispSetMode (pScrn, DISPLAY_SET_MODE_EXT);
+
+                /* should be shown again when crtc on. */
+                secLayerShowAll (pScrn, LAYER_OUTPUT_EXT);
+            }
+            else if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS)
+            {
+                /* should be shown again when crtc on. */
+                secLayerShowAll (pScrn, LAYER_OUTPUT_LCD);
+            }
+            else
+                XDBG_NEVER_GET_HERE (MDISP);
+        }
+    }
+
+    secOutputDrmUpdate (pScrn);
+
+    if (pScrn->pScreen)
+        xf86_reload_cursors (pScrn->pScreen);
+
+done:
+    free (output_ids);
+    return ret;
+}
+
+Bool
+secCrtcOverlayNeedOff (xf86CrtcPtr pCrtc, Bool need_off)
+{
+    SECCrtcPrivPtr pCrtcPriv;
+
+    XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE);
+
+    pCrtcPriv = pCrtc->driver_private;
+    XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv != NULL, FALSE);
+
+    pCrtcPriv->need_off = need_off;
+
+    XDBG_TRACE (MCRS, "[%p] need_off(%d) \n", pCrtc, need_off);
+
+    _cursorChangeStatus (pCrtc);
+
+    return TRUE;
+}
+
+Bool
+secCrtcOverlayRef (xf86CrtcPtr pCrtc, Bool refer)
+{
+    SECCrtcPrivPtr pCrtcPriv;
+    XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE);
+
+    pCrtcPriv = pCrtc->driver_private;
+    XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv != NULL, FALSE);
+
+    pCrtcPriv->ref_overlay = refer;
+
+    XDBG_TRACE (MCRS, "[%p] refer(%d) \n", pCrtc, refer);
+
+    _cursorChangeStatus (pCrtc);
+
+    return TRUE;
+}
+
+Bool
+secCrtcCursorEnable (ScrnInfoPtr pScrn, Bool enable)
+{
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+    SECCrtcPrivPtr pCur, pNext;
+
+    xorg_list_for_each_entry_safe (pCur, pNext, &pSecMode->crtcs, link)
+    {
+        xf86CrtcPtr pCrtc = pCur->pCrtc;
+        int connector_type = secCrtcGetConnectType (pCrtc);
+        if (connector_type != DRM_MODE_CONNECTOR_Unknown)
+            _cursorEnable (pCrtc, enable);
+    }
+
+    return TRUE;
+}
+
+Bool
+secCrtcCursorRotate (xf86CrtcPtr pCrtc, int rotate)
+{
+    return _cursorRotate (pCrtc, rotate);
+}
+
+xf86CrtcPtr
+secCrtcGetAtGeometry (ScrnInfoPtr pScrn, int x, int y, int width, int height)
+{
+    BoxRec box;
+
+    XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL);
+
+    box.x1 = x;
+    box.y1 = y;
+    box.x2 = box.x1 + width;
+    box.y2 = box.y1 + height;
+
+    return secModeCoveringCrtc (pScrn, &box, NULL, NULL);
+}
+
+int
+secCrtcGetConnectType (xf86CrtcPtr pCrtc)
+{
+    xf86CrtcConfigPtr pCrtcConfig;
+    int i;
+
+    XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, DRM_MODE_CONNECTOR_Unknown);
+
+    pCrtcConfig = XF86_CRTC_CONFIG_PTR (pCrtc->scrn);
+    XDBG_RETURN_VAL_IF_FAIL (pCrtcConfig != NULL, DRM_MODE_CONNECTOR_Unknown);
+
+    for (i = 0; i < pCrtcConfig->num_output; i++)
+    {
+        xf86OutputPtr pOutput = pCrtcConfig->output[i];
+        SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+
+        if (pOutput->crtc == pCrtc)
+            return pOutputPriv->mode_output->connector_type;
+    }
+
+    return DRM_MODE_CONNECTOR_Unknown;
+}
+
+Bool
+secCrtcIsFlipping (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv;
+
+    XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE);
+    pCrtcPriv = pCrtc->driver_private;
+
+    /* if isFlipping is true, return true */
+    if (pCrtcPriv->is_flipping)
+        return TRUE;
+
+    /* if there is pending_flips in the list, return true */
+    if (!xorg_list_is_empty (&pCrtcPriv->pending_flips))
+        return TRUE;
+
+    return FALSE;
+}
+
+
+DRI2FrameEventPtr
+secCrtcGetPendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent)
+{
+    SECCrtcPrivPtr pCrtcPriv;
+    DRI2FrameEventPtr item=NULL, tmp=NULL;
+
+    XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, NULL);
+    pCrtcPriv = pCrtc->driver_private;
+
+    if (xorg_list_is_empty (&pCrtcPriv->pending_flips))
+        return NULL;
+
+    xorg_list_for_each_entry_safe(item, tmp, &pCrtcPriv->pending_flips, crtc_pending_link)
+    {
+        if (item == pEvent)
+            return item;
+    }
+
+    return NULL;
+}
+
+
+
+DRI2FrameEventPtr
+secCrtcGetFirstPendingFlip (xf86CrtcPtr pCrtc)
+{
+    DRI2FrameEventPtr pEvent = NULL;
+    SECCrtcPrivPtr pCrtcPriv;
+    DRI2FrameEventPtr item=NULL, tmp=NULL;
+
+    XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, NULL);
+    pCrtcPriv = pCrtc->driver_private;
+
+    if (xorg_list_is_empty (&pCrtcPriv->pending_flips))
+        return NULL;
+
+    xorg_list_for_each_entry_safe(item, tmp, &pCrtcPriv->pending_flips, crtc_pending_link)
+    {
+       /* get the last item in the circular list ( last item is at last_item.next==head)*/
+       if (item->crtc_pending_link.next == &pCrtcPriv->pending_flips)
+       {
+           pEvent = item;
+           break;
+       }
+    }
+
+    return pEvent;
+}
+
+void
+secCrtcAddPendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent)
+{
+    SECCrtcPrivPtr pCrtcPriv;
+
+    XDBG_RETURN_IF_FAIL (pCrtc != NULL);
+
+    pCrtcPriv = pCrtc->driver_private;
+
+    xorg_list_add(&(pEvent->crtc_pending_link), &(pCrtcPriv->pending_flips));
+}
+
+void
+secCrtcRemovePendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent)
+{
+    SECCrtcPrivPtr pCrtcPriv;
+    DRI2FrameEventPtr item=NULL, tmp=NULL;
+
+    XDBG_RETURN_IF_FAIL (pCrtc != NULL);
+
+    pCrtcPriv = pCrtc->driver_private;
+
+    if (xorg_list_is_empty (&pCrtcPriv->pending_flips))
+        return;
+
+    xorg_list_for_each_entry_safe(item, tmp, &pCrtcPriv->pending_flips, crtc_pending_link)
+    {
+        if (item == pEvent)
+        {
+            xorg_list_del(&item->crtc_pending_link);
+        }
+    }
+}
+
+static Bool
+_secCrtcExecAccessibilityScaleNegative (xf86CrtcPtr pCrtc, tbm_bo src_bo, tbm_bo dst_bo)
+{
+    XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE);
+
+    SECPtr pSec = SECPTR(pCrtc->scrn);
+
+    if (pSec->isLcdOff)
+    {
+        XDBG_INFO (MDISP, "Accessibility execute : LCD IS OFF\n");
+        return TRUE;
+    }
+
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    XDBG_RETURN_VAL_IF_FAIL(src_bo != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL(dst_bo != NULL, FALSE);
+
+    SECFbBoDataPtr src_bo_data;
+    SECFbBoDataPtr dst_bo_data;
+    G2dColorKeyMode mode;
+    G2dImage *srcImg = NULL, *dstImg = NULL;
+    unsigned int src_bo_w, src_bo_h, src_bo_stride;
+    unsigned int dst_bo_w, dst_bo_h, dst_bo_stride;
+    int src_x, src_y;
+    unsigned int src_w, src_h;
+    int negative = 0;
+    tbm_bo_handle src_bo_handle;
+    tbm_bo_handle dst_bo_handle;
+
+    tbm_bo_get_user_data (src_bo, TBM_BO_DATA_FB, (void * *)&src_bo_data);
+    XDBG_RETURN_VAL_IF_FAIL(src_bo_data != NULL, FALSE);
+
+    tbm_bo_get_user_data (dst_bo, TBM_BO_DATA_FB, (void * *)&dst_bo_data);
+    XDBG_RETURN_VAL_IF_FAIL(dst_bo_data != NULL, FALSE);
+
+    src_bo_w = src_bo_data->pos.x2 - src_bo_data->pos.x1;
+    src_bo_h = src_bo_data->pos.y2 - src_bo_data->pos.y1;
+    src_bo_stride = src_bo_w * 4;
+
+    dst_bo_w = dst_bo_data->pos.x2 - dst_bo_data->pos.x1;
+    dst_bo_h = dst_bo_data->pos.y2 - dst_bo_data->pos.y1;
+    dst_bo_stride = dst_bo_w * 4;
+
+    mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+    src_bo_handle = tbm_bo_map (src_bo, TBM_DEVICE_2D, TBM_OPTION_READ);
+    dst_bo_handle = tbm_bo_map (dst_bo, TBM_DEVICE_2D, TBM_OPTION_WRITE);
+
+    srcImg = g2d_image_create_bo (mode, src_bo_w, src_bo_h, src_bo_handle.u32, src_bo_stride);
+    dstImg = g2d_image_create_bo (mode, dst_bo_w, dst_bo_h, dst_bo_handle.u32, dst_bo_stride);
+
+    if (pCrtcPriv->accessibility_status == ACCESSIBILITY_MODE_NEGATIVE)
+    {
+        negative = 1;
+    }
+
+    if (pCrtcPriv->bScale)
+    {
+        src_x = pCrtcPriv->sx;
+        src_y = pCrtcPriv->sy;
+        src_w = pCrtcPriv->sw;
+        src_h = pCrtcPriv->sh;
+    }
+    else
+    {
+        src_x = 0;
+        src_y = 0;
+        src_w = src_bo_w;
+        src_h = src_bo_h;
+    }
+
+    util_g2d_copy_with_scale(srcImg, dstImg,
+            src_x, src_y, src_w, src_h,
+            0, 0, dst_bo_w, dst_bo_h,
+            negative);
+    g2d_exec ();
+
+    tbm_bo_unmap(src_bo);
+    tbm_bo_unmap(dst_bo);
+
+    g2d_image_free (srcImg);
+    g2d_image_free (dstImg);
+
+    return TRUE;
+}
+
+static Bool
+_secCrtcExecRotate (xf86CrtcPtr pCrtc, tbm_bo src_bo, tbm_bo dst_bo)
+{
+    SECPtr pSec;
+    SECCrtcPrivPtr pCrtcPriv;
+    struct drm_exynos_ipp_queue_buf buf;
+
+    XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE);
+
+    pCrtcPriv = pCrtc->driver_private;
+    XDBG_RETURN_VAL_IF_FAIL(pCrtcPriv->screen_rotate_prop_id > 0, FALSE);
+
+    pSec = SECPTR(pCrtc->scrn);
+    if (pSec->isLcdOff)
+    {
+        XDBG_INFO (MDISP, "screen rotate execute : LCD IS OFF\n");
+        return TRUE;
+    }
+
+    CLEAR (buf);
+    buf.ops_id = EXYNOS_DRM_OPS_SRC;
+    buf.buf_type = IPP_BUF_ENQUEUE;
+    buf.prop_id = pCrtcPriv->screen_rotate_prop_id;
+    buf.handle[0] = (__u32)tbm_bo_get_handle (src_bo, TBM_DEVICE_DEFAULT).u32;
+
+    if (!secDrmIppQueueBuf (pCrtc->scrn, &buf))
+        return FALSE;
+
+    CLEAR (buf);
+    buf.ops_id = EXYNOS_DRM_OPS_DST;
+    buf.buf_type = IPP_BUF_ENQUEUE;
+    buf.prop_id = pCrtcPriv->screen_rotate_prop_id;
+    buf.handle[0] = (__u32)tbm_bo_get_handle (dst_bo, TBM_DEVICE_DEFAULT).u32;
+
+    if (!secDrmIppQueueBuf (pCrtc->scrn, &buf))
+        return FALSE;
+
+    if (pCrtcPriv->screen_rotate_ipp_status == IPP_CTRL_STOP)
+    {
+        struct drm_exynos_ipp_cmd_ctrl ctrl = {0,};
+        ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id;
+        ctrl.ctrl = IPP_CTRL_PLAY;
+        secDrmIppCmdCtrl (pCrtc->scrn, &ctrl);
+        pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_PLAY;
+
+        XDBG_INFO (MDISP, "screen rotate ipp(id:%d) play\n",
+                   pCrtcPriv->screen_rotate_prop_id);
+    }
+    else if (pCrtcPriv->screen_rotate_ipp_status == IPP_CTRL_PAUSE)
+    {
+        struct drm_exynos_ipp_cmd_ctrl ctrl = {0,};
+        ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id;
+        ctrl.ctrl = IPP_CTRL_RESUME;
+        secDrmIppCmdCtrl (pCrtc->scrn, &ctrl);
+        pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_RESUME;
+
+        XDBG_INFO (MDISP, "screen rotate ipp(id:%d) resume\n",
+                   pCrtcPriv->screen_rotate_prop_id);
+    }
+
+    return TRUE;
+}
+
+Bool
+secCrtcExecAccessibility (xf86CrtcPtr pCrtc, tbm_bo src_bo, tbm_bo dst_bo)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    Bool ret = FALSE;
+    CARD32 elapsed = 0;
+    SECPtr pSec = SECPTR(pCrtc->scrn);
+
+    tbm_bo_map(src_bo, TBM_DEVICE_2D, TBM_OPTION_READ);
+    tbm_bo_map(dst_bo, TBM_DEVICE_2D, TBM_OPTION_READ);
+
+    if (pSec->xvperf_mode & XBERC_XVPERF_MODE_ACCESS)
+        elapsed = GetTimeInMillis ();
+
+    if (pCrtcPriv->screen_rotate_degree > 0)
+        ret = _secCrtcExecRotate (pCrtc, src_bo, dst_bo);
+    else if (pCrtcPriv->bAccessibility)
+        ret = _secCrtcExecAccessibilityScaleNegative (pCrtc, src_bo, dst_bo);
+    else
+        XDBG_NEVER_GET_HERE (MDISP);
+
+    if (pSec->xvperf_mode & XBERC_XVPERF_MODE_ACCESS)
+        ErrorF ("Access exec: %3ld ms \n", GetTimeInMillis()-elapsed);
+
+    tbm_bo_unmap(src_bo);
+    tbm_bo_unmap(dst_bo);
+
+    return ret;
+}
+
+Bool
+secCrtcEnableAccessibility (xf86CrtcPtr pCrtc)
+{
+    XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE);
+
+    ScrnInfoPtr pScrn = pCrtc->scrn;
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    /* accessibility and screen rotate can't be enable at the same time */
+    XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->screen_rotate_degree == 0, FALSE);
+
+    int bAccessibility = (pCrtcPriv->accessibility_status | pCrtcPriv->bScale);
+    int width = pCrtc->mode.HDisplay;
+    int height = pCrtc->mode.VDisplay;
+
+    SECLayer *pLayer = NULL;
+    xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pCrtc->scrn);
+    xf86OutputPtr pOutput = NULL;
+    int i;
+    for (i = 0; i < pCrtcConfig->num_output; i++)
+    {
+        xf86OutputPtr pTemp = pCrtcConfig->output[i];
+        if (pTemp->crtc == pCrtc)
+        {
+            pOutput = pTemp;
+            break;
+        }
+    }
+    XDBG_RETURN_VAL_IF_FAIL (pOutput != NULL, FALSE);
+
+    SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+    SECLayerOutput output = LAYER_OUTPUT_LCD;
+
+    if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+        pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown)
+    {
+        output = LAYER_OUTPUT_LCD;
+    }
+    else if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+             pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB ||
+             pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)
+    {
+        output = LAYER_OUTPUT_EXT;
+    }
+    else
+        XDBG_NEVER_GET_HERE (MACCE);
+
+
+    if (bAccessibility)
+    {
+        if (!pCrtcPriv->accessibility_front_bo)
+        {
+            pCrtcPriv->accessibility_front_bo = secRenderBoCreate (pScrn, width, height);
+            XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->accessibility_front_bo != NULL, FALSE);
+        }
+
+        pCrtcPriv->bAccessibility = TRUE;
+
+        /* do accessibility */
+        if (!secCrtcExecAccessibility (pCrtc, pCrtcPriv->front_bo, pCrtcPriv->accessibility_front_bo))
+        {
+            XDBG_ERROR (MDISP, "Accessibility : Fail to execute accessibility\n");
+            secRenderBoUnref(pCrtcPriv->accessibility_front_bo);
+            pCrtcPriv->accessibility_front_bo = NULL;
+            pCrtcPriv->bAccessibility = FALSE;
+            return FALSE;
+        }
+
+        XDBG_INFO (MDISP, "accessibility_status(%d), scale(%d):[sx,sy,sw,sh]=[%d,%d,%d,%d]\n",
+                   pCrtcPriv->accessibility_status,
+                   pCrtcPriv->bScale, pCrtcPriv->sx, pCrtcPriv->sy, pCrtcPriv->sw, pCrtcPriv->sh);
+
+        /* layer update */
+        pLayer = secLayerFind (output, LAYER_UPPER);
+        if (pLayer && secLayerIsVisible (pLayer))
+            secLayerUpdate (pLayer);
+
+        /* set crtc when accessibility buffer destroy, or drmvlank is error */
+        if (!secCrtcApply (pCrtc))
+        {
+
+            XDBG_ERROR (MDISP, "Accessibility : Fail to set crtc\n");
+            secRenderBoUnref(pCrtcPriv->accessibility_front_bo);
+            pCrtcPriv->accessibility_front_bo = NULL;
+            pCrtcPriv->bAccessibility = FALSE;
+            return FALSE;
+        }
+
+    }
+    else
+    {
+        pCrtcPriv->bAccessibility = FALSE;
+
+        XDBG_INFO (MDISP, "accessibility_status(%d), scale(%d):[sx,sy,sw,sh]=[%d,%d,%d,%d]\n",
+                   pCrtcPriv->accessibility_status,
+                   pCrtcPriv->bScale, pCrtcPriv->sx, pCrtcPriv->sy, pCrtcPriv->sw, pCrtcPriv->sh);
+
+        if (!secCrtcApply (pCrtc))
+        {
+            XDBG_ERROR (MDISP, "Accessibility : Fail to set crtc\n");
+            pCrtcPriv->bAccessibility = TRUE;
+            return FALSE;
+        }
+
+        /* layer update */
+        pLayer = secLayerFind (output, LAYER_UPPER);
+        if (pLayer && secLayerIsVisible (pLayer))
+            secLayerUpdate (pLayer);
+    }
+
+    return TRUE;
+}
+
+Bool
+secCrtcEnableScreenRotate (xf86CrtcPtr pCrtc, Bool enable)
+{
+#ifdef _F_WEARABLE_FEATURE_
+    XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE);
+
+    ScrnInfoPtr pScrn = pCrtc->scrn;
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    int width = pCrtc->mode.HDisplay;
+    int height = pCrtc->mode.VDisplay;
+    int degree = pCrtcPriv->screen_rotate_degree;
+
+    /* accessibility and screen rotate can't be enable at the same time */
+    XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->bAccessibility == FALSE, FALSE);
+
+    if (enable)
+    {
+        struct drm_exynos_ipp_property property;
+        int prop_id;
+
+        if (!pCrtcPriv->accessibility_front_bo)
+        {
+            pCrtcPriv->accessibility_front_bo = secRenderBoCreate (pScrn, width, height);
+            XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->accessibility_front_bo != NULL, FALSE);
+
+            pCrtcPriv->accessibility_back_bo = secRenderBoCreate (pScrn, width, height);
+            XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->accessibility_back_bo != NULL, FALSE);
+        }
+
+        prop_id = pCrtcPriv->screen_rotate_prop_id;
+        if (prop_id != 0)
+        {
+            struct drm_exynos_ipp_cmd_ctrl ctrl = {0,};
+            ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id;
+            ctrl.ctrl = IPP_CTRL_PAUSE;
+            secDrmIppCmdCtrl (pScrn, &ctrl);
+            pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_PAUSE;
+            XDBG_INFO (MDISP, "screen rotate ipp(id:%d) pause\n",
+                       pCrtcPriv->screen_rotate_prop_id);
+        }
+        else
+            pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_STOP;
+
+        CLEAR (property);
+        property.config[0].ops_id = EXYNOS_DRM_OPS_SRC;
+        property.config[0].fmt = DRM_FORMAT_ARGB8888;
+        property.config[0].sz.hsize = (__u32)width;
+        property.config[0].sz.vsize = (__u32)height;
+        property.config[0].pos.x = 0;
+        property.config[0].pos.y = 0;
+        property.config[0].pos.w = (__u32)width;
+        property.config[0].pos.h = (__u32)height;
+        property.config[1].ops_id = EXYNOS_DRM_OPS_DST;
+        if (degree % 360 == 90)
+            property.config[1].degree = EXYNOS_DRM_DEGREE_90;
+        else if (degree % 360 == 180)
+            property.config[1].degree = EXYNOS_DRM_DEGREE_180;
+        else if (degree % 360 == 270)
+            property.config[1].degree = EXYNOS_DRM_DEGREE_270;
+        else
+            property.config[1].degree = EXYNOS_DRM_DEGREE_0;
+        property.config[1].fmt = DRM_FORMAT_ARGB8888;
+        property.config[1].sz.hsize = width;
+        property.config[1].sz.vsize = height;
+        property.config[1].pos.x = (__u32)0;
+        property.config[1].pos.y = (__u32)0;
+        property.config[1].pos.w = (__u32)width;
+        property.config[1].pos.h = (__u32)height;
+
+        property.cmd = IPP_CMD_M2M;
+        property.type = IPP_SYNC_WORK;
+        property.prop_id = prop_id;
+
+        prop_id = secDrmIppSetProperty (pScrn, &property);
+        XDBG_RETURN_VAL_IF_FAIL (prop_id != 0, FALSE);
+        pCrtcPriv->screen_rotate_prop_id = prop_id;
+
+        XDBG_INFO (MDISP, "screen rotate ipp(id:%d) start\n", prop_id);
+    }
+    else
+    {
+        if (pCrtcPriv->screen_rotate_prop_id > 0)
+        {
+            struct drm_exynos_ipp_cmd_ctrl ctrl = {0,};
+            ctrl.prop_id = pCrtcPriv->screen_rotate_prop_id;
+            ctrl.ctrl = IPP_CTRL_STOP;
+            secDrmIppCmdCtrl (pScrn, &ctrl);
+            pCrtcPriv->screen_rotate_prop_id = 0;
+            pCrtcPriv->screen_rotate_ipp_status = IPP_CTRL_STOP;
+            XDBG_INFO (MDISP, "screen rotate ipp(id:%d) stop\n",
+                       pCrtcPriv->screen_rotate_prop_id);
+        }
+    }
+#endif
+    return TRUE;
+}
+
+Bool
+secCrtcScreenRotate (xf86CrtcPtr pCrtc, int degree)
+{
+#ifdef _F_WEARABLE_FEATURE_
+    XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE);
+
+    ScrnInfoPtr pScrn = pCrtc->scrn;
+    SECPtr pSec = SECPTR(pCrtc->scrn);
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    CARD32 elapsed[3] = {0,};
+
+    if (pCrtcPriv->screen_rotate_degree == degree)
+        return TRUE;
+
+    /* accessibility and screen rotate can't be enable at the same time */
+    XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv->bAccessibility == FALSE, FALSE);
+
+    pCrtcPriv->screen_rotate_degree = degree;
+
+    if (pSec->isLcdOff)
+    {
+        XDBG_INFO (MDISP, "screen rotate(degree:%d)\n", degree);
+        secVideoScreenRotate (pScrn, degree);
+        return TRUE;
+    }
+
+    elapsed[0] = GetTimeInMillis ();
+
+    if (degree > 0)
+    {
+        secCrtcEnableScreenRotate (pCrtc, TRUE);
+
+        /* do accessibility */
+        if (!secCrtcExecAccessibility (pCrtc, pCrtcPriv->front_bo, pCrtcPriv->accessibility_back_bo))
+        {
+            secRenderBoUnref(pCrtcPriv->accessibility_front_bo);
+            pCrtcPriv->accessibility_front_bo = NULL;
+            secRenderBoUnref(pCrtcPriv->accessibility_back_bo);
+            pCrtcPriv->accessibility_back_bo = NULL;
+            return FALSE;
+        }
+    }
+    else
+        secCrtcEnableScreenRotate (pCrtc, FALSE);
+
+    elapsed[1] = GetTimeInMillis ();
+
+    secCrtcApply (pCrtc);
+
+    elapsed[2] = GetTimeInMillis ();
+
+    secVideoScreenRotate (pScrn, degree);
+
+    XDBG_INFO (MDISP, "screen rotate done(degree:%d, dur:%ld~%ld~%ld ms)\n",
+               degree, elapsed[1]-elapsed[0],elapsed[2]-elapsed[1],
+               GetTimeInMillis()-elapsed[2]);
+#endif
+    return TRUE;
+}
+
+Bool
+secCrtcTurn (xf86CrtcPtr pCrtc, Bool onoff, Bool always, Bool user)
+{
+    SECModePtr pSecMode = SECPTR (pCrtc->scrn)->pSecMode;
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    int crtc_id = secCrtcID(pCrtcPriv);
+    int mode;
+
+    mode = (onoff > 0) ? 0 : 1;
+
+    if (pCrtcPriv->onoff == onoff)
+    {
+        pCrtcPriv->onoff_always = always;
+        XDBG_ERROR (MDISP, "Crtc(%d) UI layer is '%s'%s\n",
+                crtc_id, (onoff)?"ON":"OFF", (always)?"(always).":".");
+        return TRUE;
+    }
+
+    if (pCrtcPriv->onoff_always)
+        if (!always)
+        {
+            XDBG_ERROR (MDISP, "Crtc(%d) UI layer can't be '%s'.\n", crtc_id, (onoff)?"ON":"OFF");
+            return FALSE;
+        }
+
+    /* 0 : normal, 1 : blank, 2 : defer */
+    if (!secUtilSetDrmProperty (pSecMode, crtc_id,
+                                DRM_MODE_OBJECT_CRTC, "mode", mode))
+    {
+        XDBG_ERROR (MDISP, "SetDrmProperty failed. crtc(%d) onoff(%d) \n", crtc_id, onoff);
+        return FALSE;
+    }
+
+    pCrtcPriv->onoff = onoff;
+    pCrtcPriv->onoff_always = always;
+
+    XDBG_INFO (MDISP, "%s >> crtc(%d) UI layer '%s'%s\n", (user)?"user":"Xorg",
+            crtc_id, (onoff)?"ON":"OFF", (always)?"(always).":".");
+
+    return TRUE;
+}
+
+Bool
+secCrtcCheckOn (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+    return pCrtcPriv->onoff;
+}
+
+/* return true if there is no flip pixmap available */
+Bool
+secCrtcFullFreeFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe)
+{
+    xf86CrtcPtr pCrtc = NULL;
+    SECCrtcPrivPtr pCrtcPriv = NULL;
+    int i;
+
+    pCrtc = _secCrtcGetFromPipe (pScrn, crtc_pipe);
+    XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE);
+
+    pCrtcPriv = pCrtc->driver_private;
+
+    /* there is a free flip pixmap, return false */
+    for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++)
+    {
+        if (pCrtcPriv->flip_backpixs.pix_free[i])
+        {
+            return FALSE;
+        }
+    }
+
+    XDBG_WARNING (MFLIP, "no free flip pixmap\n");
+
+    return TRUE;
+}
+
+#define GET_NEXT_IDX(idx, max) (((idx+1) % (max)))
+PixmapPtr
+secCrtcGetFreeFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe, DrawablePtr pDraw, unsigned int usage_hint)
+{
+    xf86CrtcPtr pCrtc = NULL;
+    SECCrtcPrivPtr pCrtcPriv = NULL;
+    PixmapPtr pPixmap = NULL;
+    ScreenPtr pScreen = pScrn->pScreen;
+    int i;
+    int check_release = 0;
+
+    pCrtc = _secCrtcGetFromPipe (pScrn, crtc_pipe);
+    XDBG_RETURN_VAL_IF_FAIL(pCrtc != NULL, FALSE);
+
+    pCrtcPriv = pCrtc->driver_private;
+
+    /* check if there is free flip pixmaps */
+    if (secCrtcFullFreeFlipPixmap(pScrn, crtc_pipe))
+    {
+        /* case : flip pixmap is never release
+           if flip_count is 0 where there is no uncompleted pageflipping,
+           release the flip_pixmap which occupied by a drawable. */
+        if (pCrtcPriv->flip_count == 0)
+        {
+            secCrtcRelAllFlipPixmap (pScrn, crtc_pipe);
+            check_release = 1;
+            XDBG_WARNING (MFLIP, "@@ release the drawable pre-occuiped the flip_pixmap\n");
+        }
+
+        /* return null, if there is no flip_backpixmap which can release */
+        if (!check_release)
+            return NULL;
+    }
+
+    /* return flip pixmap */
+    for (i = GET_NEXT_IDX(pCrtcPriv->flip_backpixs.lub, pCrtcPriv->flip_backpixs.num)
+            ; i < pCrtcPriv->flip_backpixs.num
+            ; i = GET_NEXT_IDX(i, pCrtcPriv->flip_backpixs.num))
+    {
+        if (pCrtcPriv->flip_backpixs.pix_free[i])
+        {
+            if (pCrtcPriv->flip_backpixs.flip_pixmaps[i])
+            {
+                pPixmap = pCrtcPriv->flip_backpixs.flip_pixmaps[i];
+                XDBG_DEBUG (MFLIP, "the index(%d, %d) of the flip pixmap in pipe(%d) is set\n",
+                            i, tbm_bo_export(secExaPixmapGetBo(pPixmap)), crtc_pipe);
+            }
+            else
+            {
+                pPixmap = (*pScreen->CreatePixmap) (pScreen,
+                                            pDraw->width,
+                                            pDraw->height,
+                                            pDraw->depth,
+                                            usage_hint);
+                XDBG_RETURN_VAL_IF_FAIL(pPixmap != NULL, NULL);
+                pCrtcPriv->flip_backpixs.flip_pixmaps[i] = pPixmap;
+
+                XDBG_DEBUG (MFLIP,
+                            "the index(%d, %d) of the flip pixmap in pipe(%d) is created\n",
+                            i, tbm_bo_export(secExaPixmapGetBo(pPixmap)), crtc_pipe);
+            }
+
+#if USE_XDBG
+            if (pCrtcPriv->flip_backpixs.flip_draws[i] &&
+                (pCrtcPriv->flip_backpixs.flip_draws[i] != pDraw))
+            {
+                xDbgLogPListDrawRemoveRefPixmap (pCrtcPriv->flip_backpixs.flip_draws[i],
+                                                   pCrtcPriv->flip_backpixs.flip_pixmaps[i]);
+            }
+#endif
+
+            pCrtcPriv->flip_backpixs.pix_free[i] = FALSE;
+            pCrtcPriv->flip_backpixs.flip_draws[i] = pDraw;
+            pCrtcPriv->flip_backpixs.lub = i;
+
+#if USE_XDBG
+            xDbgLogPListDrawAddRefPixmap (pDraw, pPixmap);
+#endif
+            break;
+        }
+    }
+
+    return pPixmap;
+}
+
+void
+secCrtcRelFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe, PixmapPtr pPixmap)
+{
+    xf86CrtcPtr pCrtc = NULL;
+    SECCrtcPrivPtr pCrtcPriv = NULL;
+    int i;
+
+    pCrtc = _secCrtcGetFromPipe (pScrn, crtc_pipe);
+    XDBG_RETURN_IF_FAIL(pCrtc != NULL);
+
+    pCrtcPriv = pCrtc->driver_private;
+
+    /* release flip pixmap */
+    for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++)
+    {
+        if (pPixmap == pCrtcPriv->flip_backpixs.flip_pixmaps[i])
+        {
+            pCrtcPriv->flip_backpixs.pix_free[i] = TRUE;
+            /*pCrtcPriv->flip_backpixs.flip_draws[i] = NULL;*/
+
+            XDBG_DEBUG (MFLIP, "the index(%d, %d) of the flip pixmap in pipe(%d) is unset\n",
+                        i, tbm_bo_export(secExaPixmapGetBo(pPixmap)), crtc_pipe);
+            break;
+        }
+    }
+}
+
+void
+secCrtcRelAllFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe)
+{
+    xf86CrtcPtr pCrtc = NULL;
+    SECCrtcPrivPtr pCrtcPriv = NULL;
+    int i;
+
+    pCrtc = _secCrtcGetFromPipe (pScrn, crtc_pipe);
+    XDBG_RETURN_IF_FAIL(pCrtc != NULL);
+
+    pCrtcPriv = pCrtc->driver_private;
+
+    /* release flip pixmap */
+    for (i = 0; i < pCrtcPriv->flip_backpixs.num; i++)
+    {
+        pCrtcPriv->flip_backpixs.pix_free[i] = TRUE;
+        /*pCrtcPriv->flip_backpixs.flip_draws[i] = NULL;*/
+
+        XDBG_DEBUG (MFLIP,
+                    "the index(%d) of the flip draw in pipe(%d) is unset\n",
+                    i, crtc_pipe);
+    }
+}
+
+void
+secCrtcRemoveFlipPixmap (xf86CrtcPtr pCrtc)
+{
+    _flipPixmapDeinit (pCrtc);
+}
+
+void
+secCrtcCountFps(xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = NULL;
+    int conn_type;
+
+    if (!pCrtc->enabled)
+        return;
+
+    pCrtcPriv = pCrtc->driver_private;
+    conn_type = secCrtcGetConnectType (pCrtc);
+
+    xDbgLogFpsDebugCount (pCrtcPriv->pFpsDebug, conn_type);
+}
diff --git a/src/crtcconfig/sec_crtc.h b/src/crtcconfig/sec_crtc.h
new file mode 100644 (file)
index 0000000..64d4a44
--- /dev/null
@@ -0,0 +1,170 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_CRTC_H__
+#define __SEC_CRTC_H__
+
+#include "sec_display.h"
+#include "sec_layer.h"
+#include "sec_util.h"
+
+typedef enum
+{
+    ACCESSIBILITY_MODE_NONE,
+    ACCESSIBILITY_MODE_NEGATIVE,
+}ACCESSIBILITY_STATUS;
+
+typedef struct _secCrtcPriv
+{
+    SECModePtr pSecMode;
+    drmModeModeInfo kmode;
+    drmModeCrtcPtr mode_crtc;
+    int pipe;
+
+    int idx;
+    tbm_bo front_bo;
+    tbm_bo back_bo;
+
+    /* for pageflip */
+    unsigned int fe_frame;
+    unsigned int fe_tv_sec;
+    unsigned int fe_tv_usec;
+    DRI2FrameEventPtr flip_info; /* pending flips : flipping must garauntee to do it sequentially */
+    struct xorg_list pending_flips;
+    Bool is_flipping;  /* check flipping */
+    Bool is_fb_blit_flipping;
+    int flip_count;    /* check flipping completed (check pairs of request_flip and complete_flip */
+    struct {
+        int num;        /* number of flip back pixmaps */
+        int lub;               /* Last used backbuffer */
+        Bool *pix_free;   /* flags for a flip pixmap to be free */
+        DrawablePtr *flip_draws;
+        PixmapPtr *flip_pixmaps; /* back flip pixmaps in a crtc */
+    } flip_backpixs;
+
+#if 1
+    /* for fps debug */
+    FpsDebugPtr pFpsDebug;
+#endif
+
+    /* overlay(cursor) */
+    Bool need_off;
+    Bool ref_overlay;
+    Bool move_layer;
+    Bool cursor_show;
+    Bool need_draw_cursor;
+    SECLayer  *ovl_layer;
+    SECVideoBuf *ovl_vbuf_cursor;
+    SECVideoBuf *ovl_vbuf_pixmap;
+    Bool need_cursor_update;
+    Bool registered_block_handler;
+    int user_rotate;
+    int cursor_old_offset;
+    int cursor_pos_x;
+    int cursor_pos_y;
+    int cursor_win_x;
+    int cursor_win_y;
+    BoxRec saved_box;
+    pixman_image_t *ovl_canvas;
+    pixman_image_t *saved_image;
+    pixman_image_t *cursor_image;
+    pixman_image_t *backup_image;
+
+    tbm_bo rotate_bo;
+    uint32_t rotate_pitch;
+    uint32_t rotate_fb_id;
+
+    /* crtc rotate by display conf */
+    Rotation rotate;
+
+    /* Accessibility */
+    tbm_bo accessibility_front_bo;
+    tbm_bo accessibility_back_bo;
+    Bool bAccessibility;
+    ACCESSIBILITY_STATUS accessibility_status;
+    Bool bScale;
+    int sx, sy, sw, sh;
+
+    /* screen rotate */
+    int    screen_rotate_degree;
+    int    screen_rotate_prop_id;
+    int    screen_rotate_ipp_status;
+
+    Bool onoff;
+    Bool onoff_always;
+
+    xf86CrtcPtr pCrtc;
+    struct xorg_list link;
+} SECCrtcPrivRec, *SECCrtcPrivPtr;
+
+void    secCrtcInit  (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num);
+Bool    secCrtcOn    (xf86CrtcPtr pCrtc);
+Bool    secCrtcApply (xf86CrtcPtr pCrtc);
+
+Bool    secCrtcOverlayNeedOff    (xf86CrtcPtr pCrtc, Bool need_off);
+Bool    secCrtcOverlayRef    (xf86CrtcPtr pCrtc, Bool refer);
+Bool    secCrtcCursorEnable  (ScrnInfoPtr pScrn, Bool enable);
+Bool    secCrtcCursorRotate  (xf86CrtcPtr pCrtc, int rotate);
+
+Bool    secCrtcScreenRotate (xf86CrtcPtr pCrtc, int degree);
+Bool    secCrtcEnableScreenRotate (xf86CrtcPtr pCrtc, Bool enable);
+
+xf86CrtcPtr secCrtcGetAtGeometry     (ScrnInfoPtr pScrn, int x, int y, int width, int height);
+int         secCrtcGetConnectType    (xf86CrtcPtr pCrtc);
+
+Bool secCrtcIsFlipping (xf86CrtcPtr pCrtc);
+void secCrtcAddPendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent);
+void secCrtcRemovePendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent);
+DRI2FrameEventPtr secCrtcGetPendingFlip (xf86CrtcPtr pCrtc, DRI2FrameEventPtr pEvent);
+DRI2FrameEventPtr secCrtcGetFirstPendingFlip (xf86CrtcPtr pCrtc);
+
+Bool    secCrtcEnableAccessibility (xf86CrtcPtr pCrtc);
+Bool    secCrtcExecAccessibility   (xf86CrtcPtr pCrtc, tbm_bo src_bo, tbm_bo dst_bo);
+
+Bool    secCrtcTurn (xf86CrtcPtr pCrtc, Bool onoff, Bool always, Bool user);
+Bool    secCrtcCheckOn (xf86CrtcPtr pCrtc);
+
+Bool      secCrtcFullFreeFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe);
+PixmapPtr secCrtcGetFreeFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe, DrawablePtr pDraw, unsigned int usage_hint);
+void      secCrtcRelFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe, PixmapPtr pPixmap);
+void      secCrtcRelAllFlipPixmap (ScrnInfoPtr pScrn, int crtc_pipe);
+void      secCrtcRemoveFlipPixmap (xf86CrtcPtr pCrtc);
+
+void    secCrtcCountFps(xf86CrtcPtr pCrtc);
+
+static inline int
+secCrtcID(SECCrtcPrivPtr pCrtcPriv)
+{
+    return pCrtcPriv->mode_crtc->crtc_id;
+}
+
+
+#endif /* __SEC_CRTC_H__ */
+
diff --git a/src/crtcconfig/sec_display.c b/src/crtcconfig/sec_display.c
new file mode 100644 (file)
index 0000000..ffda1a0
--- /dev/null
@@ -0,0 +1,1682 @@
+/*
+ * Copyright Â© 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Dave Airlie <airlied@redhat.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <poll.h>
+#include <dirent.h>
+
+#include <X11/extensions/dpmsconst.h>
+#include <xorgVersion.h>
+#include <X11/Xatom.h>
+#include <xf86Crtc.h>
+#include <xf86DDC.h>
+#include <xf86cmap.h>
+#include <sec.h>
+
+#include "sec_crtc.h"
+#include "sec_output.h"
+#include "sec_plane.h"
+#include "sec_display.h"
+#include "sec_video_fourcc.h"
+#include "sec_wb.h"
+#include "sec_converter.h"
+#include "sec_util.h"
+#include "sec_xberc.h"
+
+#include <exynos_drm.h>
+
+static Bool SECCrtcConfigResize(ScrnInfoPtr pScrn, int width, int height);
+static void SECModeVblankHandler(int fd, unsigned int frame, unsigned int tv_sec,
+                                 unsigned int tv_usec, void *event);
+static void SECModePageFlipHandler(int fd, unsigned int frame, unsigned int tv_sec,
+                                   unsigned int tv_usec, void *event_data);
+static void SECModeG2dHandler(int fd, unsigned int cmdlist_no, unsigned int tv_sec,
+                              unsigned int tv_usec, void *event_data);
+static void SECModeIppHandler(int fd, unsigned int prop_id, unsigned int *buf_idx, unsigned int tv_sec,
+                              unsigned int tv_usec, void *event_data);
+
+static const xf86CrtcConfigFuncsRec sec_xf86crtc_config_funcs =
+{
+    SECCrtcConfigResize
+};
+
+static void
+_secDisplaySetDrmEventCtx(SECModePtr pSecMode)
+{
+    pSecMode->event_context.vblank_handler = SECModeVblankHandler;
+    pSecMode->event_context.page_flip_handler = SECModePageFlipHandler;
+    pSecMode->event_context.g2d_handler = SECModeG2dHandler;
+    pSecMode->event_context.ipp_handler = SECModeIppHandler;
+}
+
+static int
+_secSetMainMode (ScrnInfoPtr pScrn, SECModePtr pSecMode)
+{
+    xf86CrtcConfigPtr pXf86CrtcConfig;
+    pXf86CrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
+    int i;
+
+    for (i = 0; i < pXf86CrtcConfig->num_output; i++)
+    {
+        xf86OutputPtr pOutput = pXf86CrtcConfig->output[i];
+        SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+        if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+            pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown)
+        {
+            memcpy (&pSecMode->main_lcd_mode, pOutputPriv->mode_output->modes, sizeof(drmModeModeInfo));
+            return 1;
+        }
+    }
+
+    return -1;
+}
+
+static void
+_secDisplayRemoveFlipPixmaps (ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
+    int c;
+
+    for (c = 0; c < pCrtcConfig->num_crtc; c++)
+    {
+        xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c];
+        int conn_type = secCrtcGetConnectType (pCrtc);
+        if (conn_type == DRM_MODE_CONNECTOR_Unknown)
+            secCrtcRemoveFlipPixmap (pCrtc);
+    }
+}
+
+static void
+_saveFrameBuffer (ScrnInfoPtr pScrn, tbm_bo bo, int w, int h)
+{
+    SECPtr pSec = SECPTR(pScrn);
+    char file[128];
+    SECFbBoDataPtr bo_data;
+
+    if (!pSec->dump_info)
+        return;
+
+    tbm_bo_get_user_data (bo, TBM_BO_DATA_FB, (void * *)&bo_data);
+    XDBG_RETURN_IF_FAIL(bo_data != NULL);
+
+    snprintf (file, sizeof(file), "%03d_fb_%d.bmp", pSec->flip_cnt, bo_data->fb_id);
+    secUtilDoDumpBmps (pSec->dump_info, bo, w, h, NULL, file);
+    pSec->flip_cnt++;
+}
+
+static int
+secHandleEvent (int fd, secDrmEventContextPtr evctx)
+{
+#define MAX_BUF_SIZE    1024
+
+    char buffer[MAX_BUF_SIZE];
+    unsigned int len, i;
+    struct drm_event *e;
+
+    /* The DRM read semantics guarantees that we always get only
+     * complete events. */
+    len = read (fd, buffer, sizeof buffer);
+    if (len == 0)
+    {
+        XDBG_WARNING (MDISP, "warning: the size of the drm_event is 0.\n");
+        return 0;
+    }
+    if (len < sizeof *e)
+    {
+        XDBG_WARNING (MDISP, "warning: the size of the drm_event is less than drm_event structure.\n");
+        return -1;
+    }
+    if (len > MAX_BUF_SIZE - sizeof (struct drm_exynos_ipp_event))
+    {
+        XDBG_WARNING (MDISP, "warning: the size of the drm_event can be over the maximum size.\n");
+        return -1;
+    }
+
+    i = 0;
+    while (i < len)
+    {
+        e = (struct drm_event *) &buffer[i];
+        switch (e->type)
+        {
+            case DRM_EVENT_VBLANK:
+                {
+                    struct drm_event_vblank *vblank;
+
+                    if (evctx->vblank_handler == NULL)
+                        break;
+
+                    vblank = (struct drm_event_vblank *) e;
+                    evctx->vblank_handler (fd,
+                            vblank->sequence,
+                            vblank->tv_sec,
+                            vblank->tv_usec,
+                            (void *)((unsigned long)vblank->user_data));
+                }
+                break;
+            case DRM_EVENT_FLIP_COMPLETE:
+                {
+                    struct drm_event_vblank *vblank;
+
+                    if (evctx->page_flip_handler == NULL)
+                        break;
+
+                    vblank = (struct drm_event_vblank *) e;
+                    evctx->page_flip_handler (fd,
+                            vblank->sequence,
+                            vblank->tv_sec,
+                            vblank->tv_usec,
+                            (void *)((unsigned long)vblank->user_data));
+                }
+                break;
+            case DRM_EXYNOS_G2D_EVENT:
+                {
+                    struct drm_exynos_g2d_event *g2d;
+
+                    if (evctx->g2d_handler == NULL)
+                        break;
+
+                    g2d = (struct drm_exynos_g2d_event *) e;
+                    evctx->g2d_handler (fd,
+                            g2d->cmdlist_no,
+                            g2d->tv_sec,
+                            g2d->tv_usec,
+                            (void *)((unsigned long)g2d->user_data));
+                }
+                break;
+            case DRM_EXYNOS_IPP_EVENT:
+                {
+                    struct drm_exynos_ipp_event *ipp;
+
+                    if (evctx->ipp_handler == NULL)
+                        break;
+
+                    ipp = (struct drm_exynos_ipp_event *) e;
+                    evctx->ipp_handler (fd,
+                            ipp->prop_id,
+                            ipp->buf_id,
+                            ipp->tv_sec,
+                            ipp->tv_usec,
+                            (void *)((unsigned long)ipp->user_data));
+                }
+                break;
+            default:
+                break;
+        }
+        i += e->length;
+    }
+
+    return 0;
+}
+
+static Bool
+SECCrtcConfigResize(ScrnInfoPtr pScrn, int width, int height)
+{
+    ScreenPtr pScreen = pScrn->pScreen;
+    SECPtr pSec = SECPTR (pScrn);
+
+    XDBG_DEBUG(MDISP, "Resize cur(%dx%d) new(%d,%d)\n",
+               pScrn->virtualX,
+               pScrn->virtualY,
+               width, height);
+
+    if (pScrn->virtualX == width &&
+        pScrn->virtualY == height)
+    {
+        return TRUE;
+    }
+
+    secFbResize(pSec->pFb, width, height);
+
+    /* set  the new size of pScrn */
+    pScrn->virtualX = width;
+    pScrn->virtualY = height;
+    secExaScreenSetScrnPixmap (pScreen);
+
+    secOutputDrmUpdate (pScrn);
+
+    _secDisplayRemoveFlipPixmaps (pScrn);
+
+    return TRUE;
+}
+
+static void
+SECModeVblankHandler(int fd, unsigned int frame, unsigned int tv_sec,
+                     unsigned int tv_usec, void *event)
+{
+    SECVBlankInfoPtr pVblankInfo = event;
+    SECVBlankInfoType vblank_type;
+    void *data;
+
+    XDBG_RETURN_IF_FAIL (pVblankInfo != NULL);
+
+    vblank_type = pVblankInfo->type;
+    data = pVblankInfo->data;
+
+#if DBG_DRM_EVENT
+    xDbgLogDrmEventRemoveVblank (pVblankInfo->xdbg_log_vblank);
+#endif
+
+    if (vblank_type == VBLANK_INFO_SWAP)
+    {
+        XDBG_TRACE (MDISP, "vblank handler (%p, %ld, %ld)\n",
+                    pVblankInfo, pVblankInfo->time, GetTimeInMillis () - pVblankInfo->time);
+        secDri2FrameEventHandler (frame, tv_sec, tv_usec, data);
+    }
+    else if (vblank_type == VBLANK_INFO_PLANE)
+        secLayerVBlankEventHandler (frame, tv_sec, tv_usec, data);
+    else
+        XDBG_ERROR (MDISP, "unknown the vblank type\n");
+
+    free (pVblankInfo);
+    pVblankInfo = NULL;
+}
+
+static void
+SECModePageFlipHandler(int fd, unsigned int frame, unsigned int tv_sec,
+                       unsigned int tv_usec, void *event_data)
+{
+    SECPageFlipPtr flip = event_data;
+    xf86CrtcPtr pCrtc;
+    SECCrtcPrivPtr pCrtcPriv;
+
+    if (!flip)
+    {
+        XDBG_ERROR (MDISP, "flip is null\n");
+        return;
+    }
+
+    XDBG_TRACE (MDISP, "pageflip handler (%p, %ld, %ld)\n",
+                flip, flip->time, GetTimeInMillis () - flip->time);
+
+   #if DBG_DRM_EVENT
+    if( flip->xdbg_log_pageflip != NULL )
+        xDbgLogDrmEventRemovePageflip (flip->xdbg_log_pageflip);
+   #endif
+
+    pCrtc = flip->pCrtc;
+    pCrtcPriv = pCrtc->driver_private;
+    pCrtcPriv->is_flipping = FALSE;
+    pCrtcPriv->is_fb_blit_flipping = FALSE;
+    pCrtcPriv->flip_count--; /* check flipping completed */
+
+    /* Is this the event whose info shall be delivered to higher level? */
+    /* Yes: Cache msc, ust for later delivery. */
+    pCrtcPriv->fe_frame = frame;
+    pCrtcPriv->fe_tv_sec = tv_sec;
+    pCrtcPriv->fe_tv_usec = tv_usec;
+
+    if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0)
+        if (pCrtcPriv->accessibility_front_bo && pCrtcPriv->accessibility_back_bo)
+        {
+            tbm_bo temp;
+            temp = pCrtcPriv->accessibility_front_bo;
+            pCrtcPriv->accessibility_front_bo = pCrtcPriv->accessibility_back_bo;
+            pCrtcPriv->accessibility_back_bo = temp;
+        }
+
+    /* accessibility */
+    if (flip->accessibility_back_bo)
+    {
+        secRenderBoUnref(flip->accessibility_back_bo);
+        flip->accessibility_back_bo = NULL;
+    }
+
+    /* if accessibility is diabled, remove the accessibility_bo
+       when the pageflip is occurred once after the accessibility is disabled */
+    if (!pCrtcPriv->bAccessibility && pCrtcPriv->screen_rotate_degree == 0)
+    {
+        if (pCrtcPriv->accessibility_front_bo)
+        {
+            secRenderBoUnref (pCrtcPriv->accessibility_front_bo);
+            pCrtcPriv->accessibility_front_bo = NULL;
+        }
+        if (pCrtcPriv->accessibility_back_bo)
+        {
+            secRenderBoUnref (pCrtcPriv->accessibility_back_bo);
+            pCrtcPriv->accessibility_back_bo = NULL;
+        }
+    }
+
+    /* Release back framebuffer */
+    if (flip->back_bo)
+    {
+        secRenderBoUnref(flip->back_bo);
+        flip->back_bo = NULL;
+    }
+
+    if (pCrtcPriv->flip_info == NULL)
+    {
+        /**
+        *  If pCrtcPriv->flip_info is failed and secCrtcGetFirstPendingFlip (pCrtc) has data,
+        *  ModePageFlipHandler is triggered by secDisplayUpdateRequest(). - Maybe FB_BLIT or FB is updated by CPU.
+        *  In this case we should call _secDri2ProcessPending().
+        */
+        DRI2FrameEventPtr pending_flip;
+        pending_flip = secCrtcGetFirstPendingFlip (pCrtc);
+        if( pending_flip != NULL )
+        {
+            XDBG_DEBUG (MDISP, "FB_BLIT or FB is updated by CPU. But there's secCrtcGetFirstPendingFlip(). So trigger it manually\n");
+            flip->dispatch_me = TRUE;
+            pCrtcPriv->flip_info = pending_flip;
+        }
+        else
+            goto fail;
+    }
+
+    XDBG_DEBUG(MDISP, "ModePageFlipHandler ctrc_id:%d dispatch_me:%d, frame:%d, flip_count=%d is_pending=%p\n",
+               secCrtcID(pCrtcPriv), flip->dispatch_me, frame, pCrtcPriv->flip_count, secCrtcGetFirstPendingFlip (pCrtc));
+
+    /* Last crtc completed flip? */
+    if (flip->dispatch_me)
+    {
+        secCrtcCountFps(pCrtc);
+
+        /* Deliver cached msc, ust from reference crtc to flip event handler */
+        secDri2FlipEventHandler (pCrtcPriv->fe_frame, pCrtcPriv->fe_tv_sec,
+                                 pCrtcPriv->fe_tv_usec, pCrtcPriv->flip_info, flip->flip_failed);
+    }
+
+    free (flip);
+    return;
+fail:
+    if (flip->accessibility_back_bo)
+    {
+        secRenderBoUnref(flip->accessibility_back_bo);
+        flip->accessibility_back_bo = NULL;
+    }
+
+    if (flip->back_bo)
+    {
+        secRenderBoUnref(flip->back_bo);
+        flip->back_bo = NULL;
+    }
+
+    free (flip);
+}
+
+static void
+SECModeG2dHandler(int fd, unsigned int cmdlist_no, unsigned int tv_sec,
+                  unsigned int tv_usec, void *event_data)
+{
+}
+
+static void
+SECModeIppHandler(int fd, unsigned int prop_id, unsigned int *buf_idx,
+                  unsigned int tv_sec, unsigned int tv_usec, void *event_data)
+{
+    XDBG_DEBUG (MDRM, "wb_prop_id(%d) prop_id(%d), buf_idx(%d, %d) \n",
+                secWbGetPropID(), prop_id, buf_idx[0], buf_idx[1]);
+
+    if (secWbGetPropID () == prop_id)
+        secWbHandleIppEvent (fd, buf_idx, event_data);
+    else
+        secCvtHandleIppEvent (fd, buf_idx, event_data, FALSE);
+}
+
+static void
+SECModeWakeupHanlder(pointer data, int err, pointer p)
+{
+    SECModePtr pSecMode;
+    fd_set *read_mask;
+
+    if (data == NULL || err < 0)
+        return;
+
+    pSecMode = data;
+    read_mask = p;
+    if (FD_ISSET (pSecMode->fd, read_mask))
+        secHandleEvent (pSecMode->fd, &pSecMode->event_context);
+}
+
+Bool
+secModePreInit (ScrnInfoPtr pScrn, int drm_fd)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode;
+    unsigned int i;
+    int cpp;
+
+//    secLogSetLevel(MDISP, 0);
+
+    pSecMode = calloc (1, sizeof *pSecMode);
+    if (!pSecMode)
+        return FALSE;
+
+    pSecMode->fd = drm_fd;
+    xorg_list_init (&pSecMode->crtcs);
+    xorg_list_init (&pSecMode->outputs);
+    xorg_list_init (&pSecMode->planes);
+
+    xf86CrtcConfigInit (pScrn, &sec_xf86crtc_config_funcs);
+
+    cpp = pScrn->bitsPerPixel /8;
+
+    pSecMode->cpp = cpp;
+    pSecMode->mode_res = drmModeGetResources (pSecMode->fd);
+    if (!pSecMode->mode_res)
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                    "failed to get resources: %s\n", strerror (errno));
+        free (pSecMode);
+        return FALSE;
+    }
+
+    pSecMode->plane_res = drmModeGetPlaneResources (pSecMode->fd);
+    if (!pSecMode->plane_res)
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                    "failed to get plane resources: %s\n", strerror (errno));
+        drmModeFreeResources (pSecMode->mode_res);
+        free (pSecMode);
+        return FALSE;
+    }
+
+    xf86CrtcSetSizeRange (pScrn, 320, 200, pSecMode->mode_res->max_width,
+                          pSecMode->mode_res->max_height);
+
+    for (i = 0; i < pSecMode->mode_res->count_crtcs; i++)
+        secCrtcInit (pScrn, pSecMode, i);
+
+    for (i = 0; i < pSecMode->mode_res->count_connectors; i++)
+        secOutputInit (pScrn, pSecMode, i);
+
+    for (i = 0; i < pSecMode->plane_res->count_planes; i++)
+        secPlaneInit (pScrn, pSecMode, i);
+
+    _secSetMainMode (pScrn, pSecMode);
+
+    xf86InitialConfiguration (pScrn, TRUE);
+
+    /* soolim::
+     * we assume that kernel always support the pageflipping
+     * and the drm vblank
+     */
+    /* set the drm event context */
+    _secDisplaySetDrmEventCtx(pSecMode);
+
+    pSec->pSecMode = pSecMode;
+
+    /* virtaul x and virtual y of the screen is ones from main lcd mode */
+    pScrn->virtualX = pSecMode->main_lcd_mode.hdisplay;
+    pScrn->virtualY = pSecMode->main_lcd_mode.vdisplay;
+
+#if DBG_DRM_EVENT
+    xDbgLogDrmEventInit();
+#endif
+
+    return TRUE;
+}
+
+void
+secModeInit (ScrnInfoPtr pScrn)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode = pSec->pSecMode;
+
+    /* We need to re-register the mode->fd for the synchronisation
+     * feedback on every server generation, so perform the
+     * registration within ScreenInit and not PreInit.
+     */
+    //pSecMode->flip_count = 0;
+    AddGeneralSocket(pSecMode->fd);
+    RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
+                                   SECModeWakeupHanlder, pSecMode);
+
+}
+
+void
+secModeDeinit (ScrnInfoPtr pScrn)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode = (SECModePtr) pSec->pSecMode;
+    xf86CrtcPtr pCrtc = NULL;
+    xf86OutputPtr pOutput = NULL;
+
+    secDisplayDeinitDispMode (pScrn);
+
+    SECCrtcPrivPtr crtc_ref=NULL, crtc_next=NULL;
+    xorg_list_for_each_entry_safe (crtc_ref, crtc_next, &pSecMode->crtcs, link)
+    {
+        pCrtc = crtc_ref->pCrtc;
+        xf86CrtcDestroy (pCrtc);
+    }
+
+    SECOutputPrivPtr output_ref, output_next;
+    xorg_list_for_each_entry_safe (output_ref, output_next, &pSecMode->outputs, link)
+    {
+        pOutput = output_ref->pOutput;
+        xf86OutputDestroy (pOutput);
+    }
+
+    SECPlanePrivPtr plane_ref, plane_next;
+    xorg_list_for_each_entry_safe (plane_ref, plane_next, &pSecMode->planes, link)
+    {
+        secPlaneDeinit (pScrn, plane_ref);
+    }
+
+    if (pSecMode->mode_res)
+        drmModeFreeResources (pSecMode->mode_res);
+
+    if (pSecMode->plane_res)
+        drmModeFreePlaneResources (pSecMode->plane_res);
+
+    /* mode->rotate_fb_id should have been destroyed already */
+
+    free (pSecMode);
+    pSec->pSecMode = NULL;
+}
+
+/*
+  * Return the crtc covering 'box'. If two crtcs cover a portion of
+  * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
+  * with greater coverage
+  */
+xf86CrtcPtr
+secModeCoveringCrtc (ScrnInfoPtr pScrn, BoxPtr pBox, xf86CrtcPtr pDesiredCrtc, BoxPtr pBoxCrtc)
+{
+    xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
+    xf86CrtcPtr pCrtc, pBestCrtc;
+    int coverage, best_coverage;
+    int c;
+    BoxRec crtc_box, cover_box;
+
+    XDBG_RETURN_VAL_IF_FAIL (pBox != NULL, NULL);
+
+    pBestCrtc = NULL;
+    best_coverage = 0;
+
+    if (pBoxCrtc)
+    {
+        pBoxCrtc->x1 = 0;
+        pBoxCrtc->y1 = 0;
+        pBoxCrtc->x2 = 0;
+        pBoxCrtc->y2 = 0;
+    }
+
+    for (c = 0; c < pCrtcConfig->num_crtc; c++)
+    {
+        pCrtc = pCrtcConfig->crtc[c];
+
+        /* If the CRTC is off, treat it as not covering */
+        if(!secCrtcOn(pCrtc))
+            continue;
+
+        crtc_box.x1 = pCrtc->x;
+        crtc_box.x2 = pCrtc->x + xf86ModeWidth (&pCrtc->mode, pCrtc->rotation);
+        crtc_box.y1 = pCrtc->y;
+        crtc_box.y2 = pCrtc->y + xf86ModeHeight (&pCrtc->mode, pCrtc->rotation);
+
+        secUtilBoxIntersect(&cover_box, &crtc_box, pBox);
+        coverage = secUtilBoxArea(&cover_box);
+
+        if (coverage && pCrtc == pDesiredCrtc)
+        {
+            if (pBoxCrtc)
+                *pBoxCrtc = crtc_box;
+            return pCrtc;
+        }
+
+        if (coverage > best_coverage)
+        {
+            if (pBoxCrtc)
+                *pBoxCrtc = crtc_box;
+            pBestCrtc = pCrtc;
+            best_coverage = coverage;
+        }
+    }
+
+    return pBestCrtc;
+}
+
+int secModeGetCrtcPipe (xf86CrtcPtr pCrtc)
+{
+    SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+    return pCrtcPriv->pipe;
+}
+
+Bool
+secModePageFlip (ScrnInfoPtr pScrn, xf86CrtcPtr pCrtc, void* flip_info, int pipe, tbm_bo back_bo)
+{
+    SECPageFlipPtr pPageFlip = NULL;
+    SECFbBoDataPtr bo_data;
+    SECCrtcPrivPtr pCrtcPriv;
+    SECModePtr pSecMode;
+    xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
+    xf86CrtcPtr pCurCrtc;
+    SECPtr pSec = SECPTR(pScrn);
+    int ret;
+    int fb_id = 0;
+    DRI2FrameEventPtr pEvent = (DRI2FrameEventPtr) flip_info;
+
+    BoxRec b1;
+    int retBox, found=0;
+    int i;
+
+    tbm_bo_get_user_data (back_bo, TBM_BO_DATA_FB, (void * *)&bo_data);
+    XDBG_RETURN_VAL_IF_FAIL(bo_data != NULL, FALSE);
+
+    for (i = 0; i < pCrtcConfig->num_crtc; i++)
+    {
+        pCurCrtc = pCrtcConfig->crtc[i];
+        if (!pCurCrtc->enabled)
+            continue;
+        pCrtcPriv =  pCurCrtc->driver_private;
+        pSecMode =  pCrtcPriv->pSecMode;
+
+        b1.x1 = pCurCrtc->x;
+        b1.y1 = pCurCrtc->y;
+        b1.x2 = pCurCrtc->x + pCurCrtc->mode.HDisplay;
+        b1.y2 = pCurCrtc->y + pCurCrtc->mode.VDisplay;
+
+        retBox = secUtilBoxInBox(&bo_data->pos, &b1);
+        if(retBox == rgnSAME || retBox == rgnIN)
+        {
+            pPageFlip = calloc (1, sizeof (SECPageFlipRec));
+            if (pPageFlip == NULL)
+            {
+                xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "Page flip alloc failed\n");
+                return FALSE;
+            }
+
+            /* Only the reference crtc will finally deliver its page flip
+             * completion event. All other crtc's events will be discarded.
+             */
+            pPageFlip->dispatch_me = 0;
+            pPageFlip->pCrtc = pCurCrtc;
+            pPageFlip->clone = TRUE;
+            pPageFlip->back_bo = secRenderBoRef (back_bo);
+            pPageFlip->data = flip_info;
+            pPageFlip->flip_failed = FALSE;
+
+            /* accessilitity */
+            if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0)
+            {
+                tbm_bo accessibility_bo = pCrtcPriv->accessibility_back_bo;
+                SECFbBoDataPtr accessibility_bo_data;
+
+                tbm_bo_get_user_data (accessibility_bo, TBM_BO_DATA_FB, (void * *)&accessibility_bo_data);
+                XDBG_GOTO_IF_FAIL (accessibility_bo_data != NULL, fail);
+
+                fb_id = accessibility_bo_data->fb_id;
+
+                /*Buffer is already changed by bo_swap*/
+                if (!secCrtcExecAccessibility (pCurCrtc, back_bo, accessibility_bo))
+                    goto fail;
+
+                pPageFlip->accessibility_back_bo = secRenderBoRef(accessibility_bo);
+            }
+            else
+            {
+                fb_id = bo_data->fb_id;
+
+                tbm_bo_map(pPageFlip->back_bo, TBM_DEVICE_2D, TBM_OPTION_READ);
+                tbm_bo_unmap(pPageFlip->back_bo);
+            }
+
+            pCrtcPriv->is_flipping = TRUE;
+
+            if (!pCrtcPriv->onoff && !pCrtcPriv->onoff_always)
+                secCrtcTurn (pCrtcPriv->pCrtc, TRUE, FALSE, FALSE);
+
+#if DBG_DRM_EVENT
+            pPageFlip->xdbg_log_pageflip = xDbgLogDrmEventAddPageflip (pipe, pEvent->client_idx, pEvent->drawable_id);
+#endif
+
+            XDBG_DEBUG (MSEC, "dump_mode(%x)\n", pSec->dump_mode);
+
+            if (pSec->dump_mode & XBERC_DUMP_MODE_FB)
+                _saveFrameBuffer (pScrn, back_bo,
+                                  bo_data->pos.x2 - bo_data->pos.x1,
+                                  bo_data->pos.y2 - bo_data->pos.y1);
+
+            pPageFlip->time = GetTimeInMillis ();
+
+            /*Set DirtyFB*/
+            if(pSec->use_partial_update && pEvent->pRegion)
+            {
+                int nBox;
+                BoxPtr pBox;
+                RegionRec new_region;
+                RegionPtr pRegion = pEvent->pRegion;
+
+                for (nBox = RegionNumRects(pRegion),
+                     pBox = RegionRects(pRegion); nBox--; pBox++)
+                {
+                    XDBG_DEBUG (MDISP, "dirtfb region(%d): (%d,%d %dx%d)\n", nBox,
+                                pBox->x1, pBox->y1, pBox->x2-pBox->x1, pBox->y2-pBox->y1);
+                }
+
+                if (pCrtcPriv->screen_rotate_degree > 0)
+                {
+                    RegionCopy (&new_region, pEvent->pRegion);
+                    secUtilRotateRegion (pCrtc->mode.HDisplay, pCrtc->mode.VDisplay,
+                                         &new_region, pCrtcPriv->screen_rotate_degree);
+                    pRegion = &new_region;
+
+                    for (nBox = RegionNumRects(pRegion),
+                         pBox = RegionRects(pRegion); nBox--; pBox++)
+                    {
+                        XDBG_DEBUG (MDISP, "(R)dirtfb region(%d): (%d,%d %dx%d)\n", nBox,
+                                    pBox->x1, pBox->y1, pBox->x2-pBox->x1, pBox->y2-pBox->y1);
+                    }
+                }
+
+                drmModeDirtyFB (pSec->drm_fd, fb_id,
+                                (drmModeClipPtr)RegionRects (pRegion),
+                                (uint32_t)RegionNumRects (pRegion));
+            }
+
+
+            /* DRM Page Flip */
+            ret  = drmModePageFlip (pSec->drm_fd, secCrtcID(pCrtcPriv), fb_id,
+                    DRM_MODE_PAGE_FLIP_EVENT, pPageFlip);
+            if (ret)
+            {
+                xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", strerror (errno));
+                goto fail;
+            }
+
+            XDBG_TRACE (MDISP, "pageflip do (%p, %ld)\n", pPageFlip, pPageFlip->time);
+
+            pCrtcPriv->flip_count++; /* check flipping completed */
+            pCrtcPriv->flip_info = (DRI2FrameEventPtr)flip_info;
+
+            found++;
+            XDBG_DEBUG(MDISP, "ModePageFlip crtc_id:%d, fb_id:%d, back_fb_id:%d, back_name:%d, accessibility:%d\n",
+                       secCrtcID(pCrtcPriv), fb_id, bo_data->fb_id,
+                       tbm_bo_export (back_bo), pCrtcPriv->bAccessibility);
+        }
+    }
+
+    if(found==0)
+    {
+        XDBG_WARNING(MDISP, "Cannot find CRTC in (%d,%d)-(%d,%d)\n",
+                     bo_data->pos.x1, bo_data->pos.y1, bo_data->pos.x2, bo_data->pos.y2);
+        return FALSE;
+    }
+
+    /* Set dispatch_me to last pageflip */
+    pPageFlip->dispatch_me = 1;
+
+    return TRUE;
+
+fail:
+    pCrtcPriv->flip_count++; /* check flipping completed */
+    pCrtcPriv->flip_info = (DRI2FrameEventPtr)flip_info;
+    pPageFlip->dispatch_me = 1;
+    pPageFlip->flip_failed = TRUE;
+
+    SECModePageFlipHandler(pSecMode->fd, 0, 0, 0, pPageFlip);
+
+    XDBG_ERROR(MDISP, "drmModePageFlip error(crtc:%d, fb_id:%d, back_fb_id:%d, back_name:%d, accessibility:%d)\n",
+               secCrtcID(pCrtcPriv), fb_id, bo_data->fb_id, tbm_bo_export (back_bo), pCrtcPriv->bAccessibility);
+
+    return FALSE;
+}
+
+/* load palette per a crtc */
+void
+secModeLoadPalette (ScrnInfoPtr pScrn, int numColors, int* indices,
+                    LOCO* colors, VisualPtr pVisual)
+{
+    xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
+    int i, j, index;
+    int p;
+    uint16_t lut_r[256], lut_g[256], lut_b[256];
+
+    for (p = 0; p < pCrtcConfig->num_crtc; p++)
+    {
+        xf86CrtcPtr pCrtc = pCrtcConfig->crtc[p];
+
+        switch (pScrn->depth)
+        {
+        case 16:
+            for (i = 0; i < numColors; i++)
+            {
+                index = indices[i];
+                if (index <= 31)
+                {
+                    for (j = 0; j < 8; j++)
+                    {
+                        lut_r[index * 8 + j] = colors[index].red << 8;
+                        lut_b[index * 8 + j] = colors[index].blue << 8;
+                    }
+                }
+                for (j = 0; j < 4; j++)
+                {
+                    lut_g[index * 4 + j] = colors[index].green << 8;
+                }
+            }
+            break;
+        default:
+            for (i = 0; i < numColors; i++)
+            {
+                index = indices[i];
+                lut_r[index] = colors[index].red << 8;
+                lut_g[index] = colors[index].green << 8;
+                lut_b[index] = colors[index].blue << 8;
+
+            }
+            break;
+        }
+
+        /* make the change through RandR */
+        RRCrtcGammaSet (pCrtc->randr_crtc, lut_r, lut_g, lut_b);
+    }
+}
+
+void
+secDisplaySwapModeFromKmode(ScrnInfoPtr pScrn,
+                            drmModeModeInfoPtr kmode,
+                            DisplayModePtr     pMode)
+{
+    char fake_name[32] = "fake_mode";
+
+    memset (pMode, 0, sizeof (DisplayModeRec));
+    pMode->status = MODE_OK;
+
+    pMode->Clock = kmode->clock;
+
+    pMode->HDisplay = kmode->vdisplay;
+    pMode->HSyncStart = kmode->vsync_start;
+    pMode->HSyncEnd = kmode->vsync_end;
+    pMode->HTotal = kmode->vtotal;
+    pMode->HSkew = kmode->vscan;
+
+    pMode->VDisplay = kmode->hdisplay;
+    pMode->VSyncStart = kmode->hsync_start;
+    pMode->VSyncEnd = kmode->hsync_end;
+    pMode->VTotal = kmode->htotal;
+    pMode->VScan = kmode->hskew;
+
+    pMode->Flags = kmode->flags; //& FLAG_BITS;
+    pMode->name = strdup (fake_name);
+
+    if (kmode->type & DRM_MODE_TYPE_DRIVER)
+        pMode->type = M_T_DRIVER;
+    if (kmode->type & DRM_MODE_TYPE_PREFERRED)
+        pMode->type |= M_T_PREFERRED;
+
+    xf86SetModeCrtc (pMode, pScrn->adjustFlags);
+}
+
+
+
+
+void
+secDisplayModeFromKmode(ScrnInfoPtr pScrn,
+                        drmModeModeInfoPtr kmode,
+                        DisplayModePtr pMode)
+{
+    memset (pMode, 0, sizeof (DisplayModeRec));
+    pMode->status = MODE_OK;
+
+    pMode->Clock = kmode->clock;
+
+    pMode->HDisplay = kmode->hdisplay;
+    pMode->HSyncStart = kmode->hsync_start;
+    pMode->HSyncEnd = kmode->hsync_end;
+    pMode->HTotal = kmode->htotal;
+    pMode->HSkew = kmode->hskew;
+
+    pMode->VDisplay = kmode->vdisplay;
+    pMode->VSyncStart = kmode->vsync_start;
+    pMode->VSyncEnd = kmode->vsync_end;
+    pMode->VTotal = kmode->vtotal;
+    pMode->VScan = kmode->vscan;
+
+    pMode->Flags = kmode->flags; //& FLAG_BITS;
+    pMode->name = strdup (kmode->name);
+    pMode->VRefresh = kmode->vrefresh;
+
+    if (kmode->type & DRM_MODE_TYPE_DRIVER)
+        pMode->type = M_T_DRIVER;
+    if (kmode->type & DRM_MODE_TYPE_PREFERRED)
+        pMode->type |= M_T_PREFERRED;
+
+    xf86SetModeCrtc (pMode, pScrn->adjustFlags);
+}
+
+
+void
+secDisplaySwapModeToKmode(ScrnInfoPtr pScrn,
+                          drmModeModeInfoPtr kmode,
+                          DisplayModePtr pMode)
+{
+    memset (kmode, 0, sizeof (*kmode));
+
+    kmode->clock = pMode->Clock;
+    kmode->hdisplay = pMode->VDisplay;
+    kmode->hsync_start = pMode->VSyncStart;
+    kmode->hsync_end = pMode->VSyncEnd;
+    kmode->htotal = pMode->VTotal;
+    kmode->hskew = pMode->VScan;
+
+    kmode->vdisplay = pMode->HDisplay;
+    kmode->vsync_start = pMode->HSyncStart;
+    kmode->vsync_end = pMode->HSyncEnd;
+    kmode->vtotal = pMode->HTotal;
+    kmode->vscan = pMode->HSkew;
+    kmode->vrefresh = xf86ModeVRefresh (pMode);
+
+    kmode->flags = pMode->Flags; //& FLAG_BITS;
+    if (pMode->name)
+        strncpy (kmode->name, pMode->name, DRM_DISPLAY_MODE_LEN);
+    kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+}
+
+
+void
+secDisplayModeToKmode(ScrnInfoPtr pScrn,
+                      drmModeModeInfoPtr kmode,
+                      DisplayModePtr pMode)
+{
+    memset (kmode, 0, sizeof (*kmode));
+
+    kmode->clock = pMode->Clock;
+    kmode->hdisplay = pMode->HDisplay;
+    kmode->hsync_start = pMode->HSyncStart;
+    kmode->hsync_end = pMode->HSyncEnd;
+    kmode->htotal = pMode->HTotal;
+    kmode->hskew = pMode->HSkew;
+
+    kmode->vdisplay = pMode->VDisplay;
+    kmode->vsync_start = pMode->VSyncStart;
+    kmode->vsync_end = pMode->VSyncEnd;
+    kmode->vtotal = pMode->VTotal;
+    kmode->vscan = pMode->VScan;
+    kmode->vrefresh = xf86ModeVRefresh (pMode);
+
+    kmode->flags = pMode->Flags; //& FLAG_BITS;
+    if (pMode->name)
+        strncpy (kmode->name, pMode->name, DRM_DISPLAY_MODE_LEN);
+
+    kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+}
+
+
+static uint32_t crtc_id;
+static tbm_bo hdmi_bo;
+
+static Bool connect_crtc;
+
+static int
+_secDisplayGetAvailableCrtcID (ScrnInfoPtr pScrn)
+{
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+    int i;
+    int crtc_id = 0;
+
+    for (i = 0; i < pSecMode->mode_res->count_crtcs; i++)
+    {
+        drmModeCrtcPtr kcrtc = NULL;
+        kcrtc = drmModeGetCrtc (pSecMode->fd, pSecMode->mode_res->crtcs[i]);
+        if (!kcrtc)
+        {
+            XDBG_ERROR (MSEC, "fail to get kcrtc. \n");
+            return 0;
+        }
+
+        if (kcrtc->buffer_id > 0)
+        {
+            drmModeFreeCrtc (kcrtc);
+            continue;
+        }
+
+        crtc_id = kcrtc->crtc_id;
+        drmModeFreeCrtc (kcrtc);
+
+        return crtc_id;
+    }
+
+    return 0;
+}
+
+static void
+_secDisplayWbCloseFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data)
+{
+    ScrnInfoPtr pScrn = (ScrnInfoPtr)user_data;
+    SECPtr pSec;
+
+    if (!pScrn)
+        return;
+
+    pSec = SECPTR (pScrn);
+
+    pSec->wb_clone = NULL;
+}
+
+Bool
+secDisplayInitDispMode (ScrnInfoPtr pScrn, SECDisplayConnMode conn_mode)
+{
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+    Bool ret = FALSE;
+    uint32_t *output_ids = NULL;
+    int output_cnt = 1;
+    uint32_t fb_id;
+    drmModeModeInfoPtr pKmode = NULL;
+    drmModeCrtcPtr kcrtc = NULL;
+    SECFbBoDataPtr bo_data = NULL;
+    SECOutputPrivPtr pOutputPriv=NULL, pNext=NULL;
+    int connector_type = -1;
+    int width, height;
+
+    if (connect_crtc)
+        return TRUE;
+
+    /* get output ids */
+    output_ids = calloc (output_cnt, sizeof (uint32_t));
+    XDBG_RETURN_VAL_IF_FAIL (output_ids != NULL, FALSE);
+
+    xorg_list_for_each_entry_safe (pOutputPriv, pNext, &pSecMode->outputs, link)
+    {
+        if (conn_mode == DISPLAY_CONN_MODE_HDMI)
+        {
+            if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+                pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB)
+            {
+                output_ids[0] = pOutputPriv->mode_output->connector_id;
+                pKmode = &pSecMode->ext_connector_mode;
+                connector_type = pOutputPriv->mode_output->connector_type;
+                break;
+            }
+        }
+        else if (conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+        {
+            if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)
+            {
+                output_ids[0] = pOutputPriv->mode_output->connector_id;
+                pKmode = &pSecMode->ext_connector_mode;
+                connector_type = pOutputPriv->mode_output->connector_type;
+                break;
+            }
+
+        }
+        else
+        {
+            XDBG_NEVER_GET_HERE (MTVO);
+            goto fail_to_init;
+        }
+    }
+    XDBG_GOTO_IF_FAIL (output_ids[0] > 0, fail_to_init);
+    XDBG_GOTO_IF_FAIL (pKmode != NULL, fail_to_init);
+
+    width = pKmode->hdisplay;
+    height = pKmode->vdisplay;
+
+    pOutputPriv = secOutputGetPrivateForConnType (pScrn, connector_type);
+    if (pOutputPriv && pOutputPriv->mode_encoder)
+        XDBG_GOTO_IF_FAIL (pOutputPriv->mode_encoder->crtc_id == 0, fail_to_init);
+
+    crtc_id = _secDisplayGetAvailableCrtcID (pScrn);
+    XDBG_GOTO_IF_FAIL (crtc_id > 0, fail_to_init);
+
+    /* get crtc_id */
+    kcrtc = drmModeGetCrtc (pSecMode->fd, crtc_id);
+    XDBG_GOTO_IF_FAIL (kcrtc != NULL, fail_to_init);
+
+    if (kcrtc->buffer_id > 0)
+    {
+        XDBG_ERROR (MTVO, "crtc(%d) already has buffer(%d) \n",
+                    crtc_id, kcrtc->buffer_id);
+        goto fail_to_init;
+    }
+
+    /* get fb_id */
+    hdmi_bo = secRenderBoCreate (pScrn, width, height);
+    XDBG_GOTO_IF_FAIL (hdmi_bo != NULL, fail_to_init);
+
+    tbm_bo_get_user_data(hdmi_bo, TBM_BO_DATA_FB, (void * *)&bo_data);
+    XDBG_GOTO_IF_FAIL (bo_data != NULL, fail_to_init);
+
+    fb_id = bo_data->fb_id;
+
+    /* set crtc */
+    if (drmModeSetCrtc (pSecMode->fd, crtc_id, fb_id, 0, 0, output_ids, output_cnt, pKmode))
+    {
+        XDBG_ERRNO (MTVO, "drmModeSetCrtc failed. \n");
+        goto fail_to_init;
+    }
+    else
+    {
+        ret = TRUE;
+    }
+
+    secUtilSetDrmProperty (pSecMode, crtc_id, DRM_MODE_OBJECT_CRTC, "mode", 1);
+
+    secOutputDrmUpdate (pScrn);
+
+    XDBG_INFO (MDISP, "** ModeSet : (%dx%d) %dHz !!\n", pKmode->hdisplay, pKmode->vdisplay, pKmode->vrefresh);
+
+    connect_crtc = TRUE;
+
+fail_to_init:
+    free (output_ids);
+    if (kcrtc)
+        drmModeFreeCrtc (kcrtc);
+
+    return ret;
+}
+
+void
+secDisplayDeinitDispMode (ScrnInfoPtr pScrn)
+{
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+
+    if (!connect_crtc)
+        return;
+
+    XDBG_INFO (MDISP, "** ModeUnset. !!\n");
+
+    secUtilSetDrmProperty (pSecMode, crtc_id, DRM_MODE_OBJECT_CRTC, "mode", 0);
+
+    if (hdmi_bo)
+    {
+        secRenderBoUnref (hdmi_bo);
+        hdmi_bo = NULL;
+    }
+
+    secOutputDrmUpdate (pScrn);
+
+    crtc_id = 0;
+    connect_crtc = FALSE;
+}
+
+Bool
+secDisplaySetDispSetMode  (ScrnInfoPtr pScrn, SECDisplaySetMode set_mode)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode = pSec->pSecMode;
+
+    if (pSecMode->set_mode == set_mode)
+    {
+        XDBG_INFO (MDISP, "set_mode(%d) is already set\n", set_mode);
+        return TRUE;
+    }
+
+    if (pSecMode->conn_mode == DISPLAY_CONN_MODE_NONE)
+    {
+        XDBG_WARNING (MDISP, "set_mode(%d) is failed : output is not connected yet\n", set_mode);
+        return FALSE;
+    }
+
+    switch (set_mode)
+    {
+    case DISPLAY_SET_MODE_OFF:
+        if (secWbIsOpened ())
+        {
+            SECWb *wb = secWbGet ();
+            secWbClose (wb);
+        }
+        secDisplayDeinitDispMode (pScrn);
+        break;
+    case DISPLAY_SET_MODE_CLONE:
+        /* In case of DISPLAY_CONN_MODE_VIRTUAL, we will open writeback
+         * on GetStill.
+         */
+        if (pSecMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL)
+        {
+            int wb_hz;
+
+            if (pSec->wb_clone)
+            {
+                XDBG_ERROR (MWB, "Fail : wb_clone(%p) already exists.\n", pSec->wb_clone);
+                break;
+            }
+
+            if (secWbIsOpened ())
+            {
+                XDBG_ERROR (MWB, "Fail : wb(%p) already opened.\n", secWbGet ());
+                break;
+            }
+
+            wb_hz = (pSec->wb_hz > 0)? pSec->wb_hz : pSecMode->ext_connector_mode.vrefresh;
+
+            XDBG_TRACE (MWB, "wb_hz(%d) vrefresh(%d)\n", pSec->wb_hz, pSecMode->ext_connector_mode.vrefresh);
+
+            pSec->wb_clone = secWbOpen (pScrn, FOURCC_SN12, 0, 0, (pSec->scanout)?TRUE:FALSE, wb_hz, TRUE);
+            if (pSec->wb_clone)
+            {
+                secWbAddNotifyFunc (pSec->wb_clone, WB_NOTI_CLOSED,
+                                    _secDisplayWbCloseFunc, pScrn);
+                secWbSetRotate (pSec->wb_clone, pSecMode->rotate);
+                secWbSetTvout (pSec->wb_clone, TRUE);
+                if (!secWbStart (pSec->wb_clone))
+                {
+                    secWbClose (pSec->wb_clone);
+                    return FALSE;
+                }
+            }
+       }
+       break;
+    case DISPLAY_SET_MODE_EXT:
+        if (secWbIsOpened ())
+        {
+            SECWb *wb = secWbGet ();
+            secWbClose (wb);
+        }
+        secDisplayDeinitDispMode (pScrn);
+       break;
+    default:
+       break;
+    }
+
+    pSecMode->set_mode = set_mode;
+
+    return TRUE;
+}
+
+SECDisplaySetMode
+secDisplayGetDispSetMode  (ScrnInfoPtr pScrn)
+{
+    SECDisplaySetMode set_mode;
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode = pSec->pSecMode;
+
+    set_mode = pSecMode->set_mode;
+
+    return set_mode;
+}
+
+Bool
+secDisplaySetDispRotate   (ScrnInfoPtr pScrn, int rotate)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode = pSec->pSecMode;
+
+    if (pSecMode->rotate == rotate)
+        return TRUE;
+
+    pSecMode->rotate = rotate;
+
+    if (pSec->wb_clone)
+        secWbSetRotate (pSec->wb_clone, rotate);
+
+    return TRUE;
+}
+
+int
+secDisplayGetDispRotate   (ScrnInfoPtr pScrn)
+{
+    int rotate;
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode = pSec->pSecMode;
+
+    rotate = pSecMode->rotate;
+
+    return rotate;
+}
+
+Bool
+secDisplaySetDispConnMode (ScrnInfoPtr pScrn, SECDisplayConnMode conn_mode)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode = pSec->pSecMode;
+
+    if (pSecMode->conn_mode == conn_mode)
+    {
+        XDBG_DEBUG (MDISP, "conn_mode(%d) is already set\n", conn_mode);
+        return TRUE;
+    }
+
+    switch (conn_mode)
+    {
+    case DISPLAY_CONN_MODE_NONE:
+       break;
+    case DISPLAY_CONN_MODE_HDMI:
+       break;
+    case DISPLAY_CONN_MODE_VIRTUAL:
+       break;
+    default:
+       break;
+    }
+
+    pSecMode->conn_mode = conn_mode;
+
+    return TRUE;
+}
+
+SECDisplayConnMode
+secDisplayGetDispConnMode (ScrnInfoPtr pScrn)
+{
+    SECDisplayConnMode conn_mode;
+
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode = pSec->pSecMode;
+
+    conn_mode = pSecMode->conn_mode;
+
+    return conn_mode;
+}
+
+Bool
+secDisplayGetCurMSC (ScrnInfoPtr pScrn, int pipe, CARD64 *ust, CARD64 *msc)
+{
+    drmVBlank vbl;
+    int ret;
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode = pSec->pSecMode;
+
+    /* if lcd is off, return true with msc = 0 */
+    if (pSec->isLcdOff)
+    {
+        *ust = 0;
+        *msc = 0;
+        return TRUE;
+    }
+
+
+    /* if pipe is -1, return the current msc of the main crtc */
+    if (pipe == -1)
+        pipe = 0;
+
+    vbl.request.type = DRM_VBLANK_RELATIVE;
+
+    if (pipe > 0)
+    {
+        if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+            vbl.request.type |= _DRM_VBLANK_EXYNOS_VIDI;
+        else
+            vbl.request.type |= DRM_VBLANK_SECONDARY;
+    }
+
+    vbl.request.sequence = 0;
+    ret = drmWaitVBlank (pSec->drm_fd, &vbl);
+    if (ret)
+    {
+        *ust = 0;
+        *msc = 0;
+        xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
+                    "first get vblank counter failed: %s\n",
+                    strerror (errno));
+        return FALSE;
+    }
+
+    *ust = ((CARD64) vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
+    *msc = vbl.reply.sequence;
+
+    return TRUE;
+}
+
+Bool
+secDisplayVBlank (ScrnInfoPtr pScrn, int pipe, CARD64 *target_msc, int flip,
+                        SECVBlankInfoType type, void *vblank_info)
+{
+    drmVBlank vbl;
+    int ret;
+    SECPtr pSec = SECPTR (pScrn);
+    SECVBlankInfoPtr pVblankInfo = NULL;
+    SECModePtr pSecMode = pSec->pSecMode;
+
+    pVblankInfo = calloc (1, sizeof (SECVBlankInfoRec));
+    if (pVblankInfo == NULL)
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "vblank_info alloc failed\n");
+        return FALSE;
+    }
+
+    pVblankInfo->type = type;
+    pVblankInfo->data = vblank_info;
+    pVblankInfo->time = GetTimeInMillis ();
+
+    vbl.request.type =  DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+
+    if (pipe > 0)
+    {
+        if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+            vbl.request.type |= _DRM_VBLANK_EXYNOS_VIDI;
+        else
+            vbl.request.type |= DRM_VBLANK_SECONDARY;
+    }
+
+    /* If non-pageflipping, but blitting/exchanging, we need to use
+     * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later
+     * on.
+     */
+    if (flip == 0)
+     {
+         if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL && pipe > 0)
+               ; /* do not set the DRM_VBLANK_NEXTMISS */
+         else
+             vbl.request.type |= DRM_VBLANK_NEXTONMISS;
+     }
+
+    vbl.request.sequence = *target_msc;
+    vbl.request.signal = (unsigned long) pVblankInfo;
+
+#if DBG_DRM_EVENT
+    DRI2FrameEventPtr pEvent = (DRI2FrameEventPtr) vblank_info;
+    if (type == VBLANK_INFO_SWAP)
+        pVblankInfo->xdbg_log_vblank = xDbgLogDrmEventAddVblank (pipe, pEvent->client_idx, pEvent->drawable_id, type);
+    else
+        pVblankInfo->xdbg_log_vblank = xDbgLogDrmEventAddVblank (pipe, 0, 0, type);
+#endif
+    ret = drmWaitVBlank (pSec->drm_fd, &vbl);
+    if (ret)
+    {
+#if DBG_DRM_EVENT
+        xDbgLogDrmEventRemoveVblank (pVblankInfo->xdbg_log_vblank);
+#endif
+        if (pVblankInfo)
+        {
+            free(pVblankInfo);
+            pVblankInfo = NULL;
+        }
+        xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
+                "divisor 0 get vblank counter failed: %s\n",
+                strerror (errno));
+        return FALSE;
+    }
+
+    XDBG_TRACE (MDISP, "vblank do (%p, %ld)\n", pVblankInfo, pVblankInfo->time);
+
+    /* Adjust returned value for 1 fame pageflip offset of flip > 0 */
+    *target_msc = vbl.reply.sequence + flip;
+
+    return TRUE;
+}
+
+int
+secDisplayDrawablePipe (DrawablePtr pDraw)
+{
+    ScreenPtr pScreen = pDraw->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    BoxRec box, crtc_box;
+    xf86CrtcPtr pCrtc;
+    int pipe = -1;
+
+    box.x1 = pDraw->x;
+    box.y1 = pDraw->y;
+    box.x2 = box.x1 + pDraw->width;
+    box.y2 = box.y1 + pDraw->height;
+
+    pCrtc = secModeCoveringCrtc (pScrn, &box, NULL, &crtc_box);
+
+    if (pCrtc != NULL && !pCrtc->rotatedData)
+        pipe = secModeGetCrtcPipe (pCrtc);
+
+    return pipe;
+}
+
+int
+secDisplayCrtcPipe (ScrnInfoPtr pScrn, int crtc_id)
+{
+    xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
+    int c;
+
+    for (c = 0; c < pCrtcConfig->num_crtc; c++)
+    {
+        xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c];
+        SECCrtcPrivPtr pCrtcPriv =  pCrtc->driver_private;
+        if (pCrtcPriv->mode_crtc->crtc_id == crtc_id)
+            return pCrtcPriv->pipe;
+    }
+
+    XDBG_ERROR (MDISP, "%s(%d): crtc(%d) not found.\n", __func__, __LINE__, crtc_id);
+
+    for (c = 0; c < pCrtcConfig->num_crtc; c++)
+    {
+        xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c];
+        SECCrtcPrivPtr pCrtcPriv =  pCrtc->driver_private;
+        XDBG_ERROR (MDISP, "%s(%d) : crtc(%d) != crtc(%d)\n", __func__, __LINE__,
+                    pCrtcPriv->mode_crtc->crtc_id, crtc_id);
+    }
+
+    return 0;
+}
+
+Bool secDisplayUpdateRequest(ScrnInfoPtr pScrn)
+{
+    XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, FALSE);
+
+    SECPtr pSec = SECPTR(pScrn);
+    xf86CrtcPtr pCrtc = xf86CompatCrtc (pScrn);
+    SECCrtcPrivPtr pCrtcPriv;
+    tbm_bo bo;
+    Bool ret = FALSE;
+    SECPageFlipPtr pPageFlip = NULL;
+
+    XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE);
+
+    pCrtcPriv =  pCrtc->driver_private;
+    XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv != NULL, FALSE);
+
+    bo = pCrtcPriv->front_bo;
+
+    if( pCrtcPriv->is_fb_blit_flipping || pCrtcPriv->is_flipping || secCrtcGetFirstPendingFlip (pCrtc) )
+    {
+        XDBG_DEBUG (MDISP, "drmModePageFlip is already requested!\n");
+    }
+    else
+    {
+        // Without buffer swap, we need to request drmModePageFlip().
+        if( bo != NULL )
+        {
+            SECFbBoDataPtr bo_data;
+            int fb_id = 0;
+
+            tbm_bo_get_user_data (bo, TBM_BO_DATA_FB, (void * *)&bo_data);
+            XDBG_RETURN_VAL_IF_FAIL(bo_data != NULL, FALSE);
+
+            fb_id = bo_data->fb_id;
+
+            pPageFlip = calloc (1, sizeof (SECPageFlipRec));
+            if (pPageFlip == NULL)
+            {
+                xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "Page flip alloc failed\n");
+                return FALSE;
+            }
+
+            /* Only the reference crtc will finally deliver its page flip
+             * completion event. All other crtc's events will be discarded.
+             */
+            pPageFlip->dispatch_me = 0;
+            pPageFlip->pCrtc = pCrtc;
+            pPageFlip->clone = TRUE;
+            pPageFlip->back_bo = secRenderBoRef (bo);
+            pPageFlip->data = NULL;
+            pPageFlip->flip_failed = FALSE;
+            pPageFlip->xdbg_log_pageflip = NULL;
+            pPageFlip->time = GetTimeInMillis ();
+
+            /* accessilitity */
+            if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0)
+            {
+                tbm_bo accessibility_bo = pCrtcPriv->accessibility_back_bo;
+                SECFbBoDataPtr accessibility_bo_data;
+
+                tbm_bo_get_user_data (accessibility_bo, TBM_BO_DATA_FB, (void * *)&accessibility_bo_data);
+                XDBG_GOTO_IF_FAIL (accessibility_bo_data != NULL, fail);
+
+                fb_id = accessibility_bo_data->fb_id;
+
+                /*Buffer is already changed by bo_swap*/
+                if (!secCrtcExecAccessibility (pCrtc, bo, accessibility_bo))
+                    goto fail;
+
+                pPageFlip->accessibility_back_bo = secRenderBoRef(accessibility_bo);
+            }
+
+            /*
+            * DRM Page Flip
+            * If pPageFlip->dispatch_me is NULL, then in SECModePageFlipHandler, nothing to happen.
+            * That means only LCD buffer is updated.
+            * Frame buffer is not swapped. Because these request is only for FB_BLIT case!
+            */
+            ret = drmModePageFlip (pSec->drm_fd, secCrtcID(pCrtcPriv), fb_id,
+                    DRM_MODE_PAGE_FLIP_EVENT, pPageFlip);
+            if (ret)
+            {
+                XDBG_ERRNO (MDISP, "Page flip failed: %s\n", strerror (errno));
+                goto fail;
+            }
+
+            pCrtcPriv->flip_info = NULL;
+            pCrtcPriv->flip_count++;
+            pCrtcPriv->is_fb_blit_flipping = TRUE;
+        }
+        else
+        {
+            XDBG_DEBUG (MDISP, "pCrtcPriv->front_bo is NULL!\n");
+        }
+    }
+
+    ret = TRUE;
+
+    return ret;
+
+fail :
+
+    if( pPageFlip != NULL )
+    {
+        if (pPageFlip->accessibility_back_bo)
+        {
+            secRenderBoUnref(pPageFlip->accessibility_back_bo);
+            pPageFlip->accessibility_back_bo = NULL;
+        }
+
+        if (pPageFlip->back_bo)
+        {
+            secRenderBoUnref(pPageFlip->back_bo);
+            pPageFlip->back_bo = NULL;
+        }
+
+        free(pPageFlip);
+    }
+
+    return ret;
+}
+
diff --git a/src/crtcconfig/sec_display.h b/src/crtcconfig/sec_display.h
new file mode 100644 (file)
index 0000000..e45cc05
--- /dev/null
@@ -0,0 +1,183 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_DISPLAY_H__
+#define __SEC_DISPLAY_H__
+
+#include <xf86drmMode.h>
+#include <xf86Crtc.h>
+#include <tbm_bufmgr.h>
+#include <list.h>
+
+#define DBG_DRM_EVENT 1
+
+typedef enum
+{
+    DISPLAY_SET_MODE_OFF,
+    DISPLAY_SET_MODE_CLONE,
+    DISPLAY_SET_MODE_EXT,
+} SECDisplaySetMode;
+
+typedef enum
+{
+    DISPLAY_CONN_MODE_NONE,
+    DISPLAY_CONN_MODE_HDMI,
+    DISPLAY_CONN_MODE_VIRTUAL,
+    DISPLAY_CONN_MODE_MAX,
+} SECDisplayConnMode;
+
+typedef enum
+{
+    VBLNAK_INFO_NONE,
+    VBLANK_INFO_SWAP,
+    VBLANK_INFO_PLANE,
+    VBLANK_INFO_MAX
+} SECVBlankInfoType;
+
+typedef struct _secDrmEventContext {
+    void (*vblank_handler) (int fd,
+                            unsigned int sequence,
+                            unsigned int tv_sec,
+                            unsigned int tv_usec,
+                            void *user_data);
+
+    void (*page_flip_handler) (int fd,
+                               unsigned int sequence,
+                               unsigned int tv_sec,
+                               unsigned int tv_usec,
+                               void *user_data);
+
+    void (*g2d_handler) (int fd,
+                         unsigned int cmdlist_no,
+                         unsigned int tv_sec,
+                         unsigned int tv_usec,
+                         void *user_data);
+
+    void (*ipp_handler) (int fd,
+                         unsigned int  prop_id,
+                         unsigned int *buf_idx,
+                         unsigned int  tv_sec,
+                         unsigned int  tv_usec,
+                         void *user_data);
+} secDrmEventContext, *secDrmEventContextPtr;
+
+typedef struct _secDrmMode
+{
+    int type;
+    int fd;
+    drmModeResPtr mode_res;
+    drmModePlaneResPtr plane_res;
+    int cpp;
+    drmModeModeInfo main_lcd_mode;
+    drmModeModeInfo ext_connector_mode;
+
+    secDrmEventContext event_context;
+
+    struct xorg_list outputs;
+    struct xorg_list crtcs;
+    struct xorg_list planes;
+
+    SECDisplaySetMode  set_mode;
+    SECDisplayConnMode conn_mode;
+    int                rotate;
+
+    int unset_connector_type;
+} SECModeRec, *SECModePtr;
+
+typedef struct _secPageFlip
+{
+    xf86CrtcPtr pCrtc;
+    Bool dispatch_me;
+    Bool clone;
+    Bool flip_failed;
+
+    tbm_bo back_bo;
+    tbm_bo accessibility_back_bo;
+
+    void *data;
+    CARD32 time;
+
+#if DBG_DRM_EVENT
+    void *xdbg_log_pageflip;
+#endif
+} SECPageFlipRec, *SECPageFlipPtr;
+
+typedef struct _secVBlankInfo
+{
+    SECVBlankInfoType type;
+    void *data; /* request data pointer */
+    CARD32 time;
+
+#if DBG_DRM_EVENT
+    void *xdbg_log_vblank;
+#endif
+} SECVBlankInfoRec, *SECVBlankInfoPtr;
+
+typedef struct _secProperty
+{
+    drmModePropertyPtr mode_prop;
+    uint64_t value;
+    int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */
+    Atom *atoms;
+} SECPropertyRec, *SECPropertyPtr;
+
+Bool        secModePreInit (ScrnInfoPtr pScrn, int drm_fd);
+void        secModeInit (ScrnInfoPtr pScrn);
+void        secModeDeinit (ScrnInfoPtr pScrn);
+xf86CrtcPtr secModeCoveringCrtc (ScrnInfoPtr pScrn, BoxPtr pBox, xf86CrtcPtr pDesiredCrtc, BoxPtr pBoxCrtc);
+int         secModeGetCrtcPipe (xf86CrtcPtr pCrtc);
+Bool        secModePageFlip (ScrnInfoPtr pScrn, xf86CrtcPtr pCrtc, void* flip_info, int pipe, tbm_bo back_bo);
+void        secModeLoadPalette (ScrnInfoPtr pScrn, int numColors, int* indices, LOCO* colors, VisualPtr pVisual);
+
+void        secDisplaySwapModeFromKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, DisplayModePtr    pMode);
+void        secDisplayModeFromKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, DisplayModePtr        pMode);
+void        secDisplaySwapModeToKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, DisplayModePtr pMode);
+void        secDisplayModeToKmode(ScrnInfoPtr pScrn, drmModeModeInfoPtr kmode, DisplayModePtr pMode);
+
+Bool               secDisplaySetDispSetMode  (ScrnInfoPtr pScrn, SECDisplaySetMode disp_mode);
+SECDisplaySetMode  secDisplayGetDispSetMode  (ScrnInfoPtr pScrn);
+Bool               secDisplaySetDispRotate   (ScrnInfoPtr pScrn, int disp_rotate);
+int                secDisplayGetDispRotate   (ScrnInfoPtr pScrn);
+Bool               secDisplaySetDispConnMode (ScrnInfoPtr pScrn, SECDisplayConnMode disp_conn);
+SECDisplayConnMode secDisplayGetDispConnMode (ScrnInfoPtr pScrn);
+
+Bool secDisplayInitDispMode (ScrnInfoPtr pScrn, SECDisplayConnMode conn_mode);
+void secDisplayDeinitDispMode (ScrnInfoPtr pScrn);
+
+Bool secDisplayGetCurMSC (ScrnInfoPtr pScrn, int pipe, CARD64 *ust, CARD64 *msc);
+Bool secDisplayVBlank (ScrnInfoPtr pScrn, int pipe, CARD64 *target_msc, int flip, SECVBlankInfoType type, void *vblank_info);
+int secDisplayDrawablePipe (DrawablePtr pDraw);
+
+int secDisplayCrtcPipe (ScrnInfoPtr pScrn, int crtc_id);
+
+Bool secDisplayUpdateRequest(ScrnInfoPtr pScrn);
+
+#endif /* __SEC_DISPLAY_H__ */
+
diff --git a/src/crtcconfig/sec_layer.c b/src/crtcconfig/sec_layer.c
new file mode 100644 (file)
index 0000000..05415f8
--- /dev/null
@@ -0,0 +1,1144 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "sec.h"
+#include "sec_util.h"
+#include "sec_crtc.h"
+#include "sec_output.h"
+#include "sec_plane.h"
+#include "sec_layer.h"
+#include "sec_video_fourcc.h"
+#include "sec_video_tvout.h"
+#include "sec_video_virtual.h"
+
+#include <exynos_drm.h>
+
+//#define DEBUG_REFCNT
+
+#ifdef DEBUG_REFCNT
+#define SEC_LAYER_PRINT_REFCNT(b) \
+            XDBG_TRACE(MLYR, "layer(%p) ref_cnt(%d) \n", b, b->ref_cnt)
+#else
+#define SEC_LAYER_PRINT_REFCNT(b)
+#endif
+
+typedef struct _NotifyFuncData
+{
+    NotifyFunc  func;
+    void       *user_data;
+
+    struct xorg_list link;
+} NotifyFuncData;
+
+struct _SECLayer
+{
+    ScrnInfoPtr    pScrn;
+
+    SECLayerOutput output;
+    SECLayerPos lpos;
+
+    int         plane_id;
+    int         crtc_id;
+
+    /* for buffer */
+    int         fb_id;
+
+    int         offset_x;
+    int         offset_y;
+
+    xRectangle *src;
+    xRectangle *dst;
+
+    SECVideoBuf *vbuf;
+    Bool         visible;
+
+    /* vblank */
+    Bool        enable_vblank;
+    Bool        wait_vblank;
+    SECVideoBuf *wait_vbuf;
+    SECVideoBuf *pending_vbuf;
+    SECVideoBuf *showing_vbuf;
+
+    struct xorg_list noti_data;
+    struct xorg_list link;
+
+    Bool onoff;
+    int ref_cnt;
+    Bool freeze_update;
+
+    /* count */
+    unsigned int put_counts;
+    OsTimerPtr timer;
+};
+
+static Bool crtc_layers_init;
+static struct xorg_list crtc_layers;
+static Bool wait_vblank[LAYER_OUTPUT_MAX];
+
+#define LAYER_VBLANK_FLAG 0xFFFF
+
+static CARD32
+_countPrint (OsTimerPtr timer, CARD32 now, pointer arg)
+{
+    SECLayer *layer = (SECLayer*)arg;
+
+    if (layer->timer)
+    {
+        TimerFree (layer->timer);
+        layer->timer = NULL;
+    }
+
+    XDBG_DEBUG (MEXA, "crtc(%d) pos(%d) : %d fps. \n",
+            layer->crtc_id, layer->lpos, layer->put_counts);
+
+    layer->put_counts = 0;
+
+    return 0;
+}
+
+static void
+_countFps (SECLayer *layer)
+{
+    layer->put_counts++;
+
+    if (layer->timer)
+        return;
+
+    layer->timer = TimerSet (NULL, 0, 1000, _countPrint, layer);
+}
+
+static void
+_secLayerInitList (void)
+{
+    if (!crtc_layers_init)
+    {
+        xorg_list_init (&crtc_layers);
+        crtc_layers_init = TRUE;
+    }
+}
+
+static void
+_secLayerNotify (SECLayer *layer, int type, void *type_data)
+{
+    NotifyFuncData *data = NULL, *data_next = NULL;
+
+    xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link)
+    {
+        if (data->func)
+            data->func (layer, type, type_data, data->user_data);
+    }
+}
+
+static int
+_GetCrtcIdForOutput (ScrnInfoPtr pScrn, SECLayerOutput output)
+{
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+    SECOutputPrivPtr pOutputPriv = NULL;
+    int crtc_id = 0;
+
+    switch (output)
+    {
+    case LAYER_OUTPUT_LCD:
+        pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_LVDS);
+        if (!pOutputPriv)
+            pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_Unknown);
+        if (pOutputPriv && pOutputPriv->mode_encoder)
+            crtc_id = pOutputPriv->mode_encoder->crtc_id;
+        break;
+    case LAYER_OUTPUT_EXT:
+        if (pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI)
+        {
+            pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_HDMIA);
+            if (!pOutputPriv)
+                pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_HDMIB);
+            if (pOutputPriv && pOutputPriv->mode_encoder)
+                crtc_id = pOutputPriv->mode_encoder->crtc_id;
+        }
+        else if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+        {
+            pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_VIRTUAL);
+            if (pOutputPriv && pOutputPriv->mode_encoder)
+                crtc_id = pOutputPriv->mode_encoder->crtc_id;
+        }
+        break;
+    default:
+        break;
+    }
+
+    XDBG_DEBUG (MLYR, "crtc(%d) for output(%d) \n", crtc_id, output);
+
+    if (crtc_id == 0)
+        XDBG_ERROR (MLYR, "no crtc for output(%d) \n", output);
+
+    return crtc_id;
+}
+
+static int
+_GetCrtcID (SECLayer *layer)
+{
+    if (layer->crtc_id > 0)
+        return layer->crtc_id;
+
+    layer->crtc_id = _GetCrtcIdForOutput (layer->pScrn, layer->output);
+
+    XDBG_RETURN_VAL_IF_FAIL (layer->crtc_id > 0, 0);
+
+    return layer->crtc_id;
+}
+
+static int
+_secLayerGetPlanePos (SECLayer *layer, SECLayerPos lpos)
+{
+    if (layer->output == LAYER_OUTPUT_LCD)
+    {
+        XDBG_DEBUG (MLYR, "lpos(%d) => ppos(%d) (1)\n", lpos, PLANE_POS_3 + lpos);
+        return PLANE_POS_3 + lpos;
+    }
+    else if (layer->output == LAYER_OUTPUT_EXT)
+    {
+        if (lpos == -1)
+        {
+            XDBG_DEBUG (MLYR, "lpos(%d) => ppos(%d) (2)\n", lpos, PLANE_POS_2);
+            return PLANE_POS_2;
+        }
+        else
+        {
+            XDBG_DEBUG (MLYR, "lpos(%d) => ppos(%d) (3)\n", lpos, PLANE_POS_0 + lpos);
+            return PLANE_POS_0 + lpos;
+        }
+    }
+    else
+    {
+        XDBG_NEVER_GET_HERE (MLYR);
+    }
+
+    return -1;
+}
+
+static void
+_secLayerDestroy (SECLayer *layer)
+{
+    NotifyFuncData *data = NULL, *data_next = NULL;
+
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+
+    xorg_list_del (&layer->link);
+
+    if (layer->src)
+        free (layer->src);
+    if (layer->dst)
+        free (layer->dst);
+
+    if (layer->wait_vbuf)
+        secUtilVideoBufferUnref (layer->wait_vbuf);
+    if (layer->pending_vbuf)
+        secUtilVideoBufferUnref (layer->pending_vbuf);
+    if (layer->showing_vbuf)
+        secUtilVideoBufferUnref (layer->showing_vbuf);
+    if (layer->vbuf)
+    {
+        secUtilVideoBufferUnref (layer->vbuf);
+        layer->vbuf = NULL;
+    }
+
+    XDBG_TRACE (MLYR, "layer(%p) destroyed. \n", layer);
+    SEC_LAYER_PRINT_REFCNT (layer);
+
+    _secLayerNotify (layer, LAYER_DESTROYED, NULL);
+
+    xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link)
+    {
+        xorg_list_del (&data->link);
+        free (data);
+    }
+
+    if (layer->plane_id > 0)
+        secPlaneFreeId (layer->plane_id);
+
+    free (layer);
+}
+
+static void
+_secLayerWatchVblank (SECLayer *layer)
+{
+    CARD64 ust, msc, target_msc;
+    int pipe, flip = 1;
+    SECPtr pSec = SECPTR (layer->pScrn);
+
+    /* if lcd is off, do not request vblank information */
+    if (pSec->isLcdOff)
+        return;
+
+    pipe = secDisplayCrtcPipe (layer->pScrn, _GetCrtcID (layer));
+
+    layer->wait_vblank = TRUE;
+
+    if (wait_vblank[pipe])
+        return;
+
+    wait_vblank[pipe] = TRUE;
+
+    if (!secDisplayGetCurMSC (layer->pScrn, pipe, &ust, &msc))
+        XDBG_WARNING (MLYR, "fail to get current_msc.\n");
+
+    target_msc = msc + 1;
+
+    XDBG_TRACE (MLYR, "layer(%p) wait vblank : cur(%lld) target(%lld). \n",
+                layer, msc, target_msc);
+
+    if (!secDisplayVBlank (layer->pScrn, pipe, &target_msc, flip, VBLANK_INFO_PLANE, (void*)pipe))
+        XDBG_WARNING (MLYR, "fail to Vblank.\n");
+}
+
+static Bool
+_secLayerShowInternal (SECLayer *layer, Bool need_update)
+{
+    int crtc_id, plane_pos;
+
+    XDBG_RETURN_VAL_IF_FAIL (layer->fb_id > 0, FALSE);
+
+    crtc_id = _GetCrtcID (layer);
+    plane_pos = _secLayerGetPlanePos (layer, layer->lpos);
+
+    if (!secPlaneShow (layer->plane_id, crtc_id,
+                       layer->src->x, layer->src->y,
+                       layer->src->width, layer->src->height,
+                       layer->offset_x + layer->dst->x,
+                       layer->offset_y + layer->dst->y,
+                       layer->dst->width, layer->dst->height,
+                       plane_pos, need_update))
+        return FALSE;
+
+    return TRUE;
+}
+
+static void
+_secLayerGetBufferID (SECLayer *layer, SECVideoBuf *vbuf)
+{
+    SECModePtr pSecMode;
+    unsigned int drmfmt;
+    unsigned int handles[4] = {0,};
+    unsigned int pitches[4] = {0,};
+    unsigned int offsets[4] = {0,};
+    int i;
+
+    if (vbuf->fb_id > 0)
+        return;
+
+    pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
+    drmfmt = secUtilGetDrmFormat (vbuf->id);
+
+    for (i = 0 ; i < PLANAR_CNT; i++)
+    {
+        handles[i] = (unsigned int)vbuf->handles[i];
+        pitches[i] = (unsigned int)vbuf->pitches[i];
+        offsets[i] = (unsigned int)vbuf->offsets[i];
+    }
+
+    if (drmModeAddFB2 (pSecMode->fd, vbuf->width, vbuf->height, drmfmt,
+                       handles, pitches, offsets, &vbuf->fb_id, 0))
+    {
+        XDBG_ERRNO (MLYR, "drmModeAddFB2 failed. handles(%d %d %d) pitches(%d %d %d) offsets(%d %d %d) '%c%c%c%c'\n",
+                    handles[0], handles[1], handles[2],
+                    pitches[0], pitches[1], pitches[2],
+                    offsets[0], offsets[1], offsets[2],
+                    FOURCC_STR (drmfmt));
+    }
+
+    XDBG_DEBUG (MVBUF, "layer(%p) vbuf(%ld) fb_id(%d) added. \n", layer, vbuf->stamp, vbuf->fb_id);
+}
+
+Bool
+secLayerSupport (ScrnInfoPtr pScrn, SECLayerOutput output, SECLayerPos lpos, unsigned int id)
+{
+    SECModePtr pSecMode;
+
+    XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (output < LAYER_OUTPUT_MAX, FALSE);
+
+    pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+
+    if (output == LAYER_OUTPUT_EXT && lpos == LAYER_LOWER1)
+    {
+        if (pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI)
+        {
+            if (id == FOURCC_SN12 || id == FOURCC_ST12)
+                return TRUE;
+            else
+                return FALSE;
+        }
+        else if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+        {
+            if (id == FOURCC_SN12 || id == FOURCC_RGB32)
+                return TRUE;
+            else
+                return FALSE;
+        }
+    }
+
+    return (id == FOURCC_RGB32 || id == FOURCC_SR32) ? TRUE : FALSE;
+}
+
+SECLayer*
+secLayerFind (SECLayerOutput output, SECLayerPos lpos)
+{
+    SECLayer *layer = NULL, *layer_next = NULL;
+
+    XDBG_RETURN_VAL_IF_FAIL (output < LAYER_OUTPUT_MAX, NULL);
+
+    _secLayerInitList ();
+
+    xorg_list_for_each_entry_safe (layer, layer_next, &crtc_layers, link)
+    {
+        if (layer->output == output && layer->lpos == lpos)
+            return layer;
+    }
+
+    return NULL;
+}
+
+void
+secLayerDestroyAll (void)
+{
+    SECLayer *layer = NULL, *layer_next = NULL;
+
+    _secLayerInitList ();
+
+    xorg_list_for_each_entry_safe (layer, layer_next, &crtc_layers, link)
+    {
+        _secLayerDestroy (layer);
+    }
+}
+
+void
+secLayerShowAll (ScrnInfoPtr pScrn, SECLayerOutput output)
+{
+    int crtc_id = _GetCrtcIdForOutput (pScrn, output);
+
+    secPlaneShowAll (crtc_id);
+}
+
+SECLayer*
+secLayerCreate (ScrnInfoPtr pScrn, SECLayerOutput output, SECLayerPos lpos)
+{
+    SECLayer* layer;
+
+    XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (output < LAYER_OUTPUT_MAX, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (lpos != LAYER_DEFAULT, NULL);
+
+    layer = secLayerFind (output, lpos);
+    if (layer)
+    {
+        XDBG_ERROR (MLYR, "layer(%p) already is at output(%d) lpos(%d). \n",
+                    layer, output, lpos);
+
+        return NULL;
+    }
+
+    layer = calloc (sizeof (SECLayer), 1);
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL);
+
+    layer->pScrn = pScrn;
+    layer->output = output;
+    layer->lpos = lpos;
+
+    layer->plane_id = secPlaneGetID ();
+    if (layer->plane_id < 0)
+    {
+        free (layer);
+        return NULL;
+    }
+
+    layer->ref_cnt = 1;
+
+    xorg_list_init (&layer->noti_data);
+
+    _secLayerInitList ();
+
+    xorg_list_add(&layer->link, &crtc_layers);
+
+    XDBG_TRACE (MLYR, "layer(%p) output(%d) lpos(%d) created. \n", layer, output, lpos);
+    SEC_LAYER_PRINT_REFCNT (layer);
+
+    return layer;
+}
+
+SECLayer*
+secLayerRef (SECLayer* layer)
+{
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL);
+
+    layer->ref_cnt++;
+
+    SEC_LAYER_PRINT_REFCNT (layer);
+
+    return layer;
+}
+
+void
+secLayerUnref (SECLayer* layer)
+{
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+
+    layer->ref_cnt--;
+
+    SEC_LAYER_PRINT_REFCNT (layer);
+
+    if (layer->ref_cnt == 0)
+    {
+        secLayerHide (layer);
+        _secLayerDestroy (layer);
+    }
+}
+
+void
+secLayerAddNotifyFunc (SECLayer* layer, NotifyFunc func, void *user_data)
+{
+    NotifyFuncData *data = NULL, *data_next = NULL;
+
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+    XDBG_RETURN_IF_FAIL (func != NULL);
+
+    xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link)
+    {
+        if (data->func == func && data->user_data == user_data)
+            return;
+    }
+
+    data = calloc (sizeof (NotifyFuncData), 1);
+    XDBG_RETURN_IF_FAIL (data != NULL);
+
+    data->func      = func;
+    data->user_data = user_data;
+
+    xorg_list_add (&data->link, &layer->noti_data);
+}
+
+void
+secLayerRemoveNotifyFunc (SECLayer* layer, NotifyFunc func)
+{
+    NotifyFuncData *data = NULL, *data_next = NULL;
+
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+    XDBG_RETURN_IF_FAIL (func != NULL);
+
+    xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link)
+    {
+        if (data->func == func)
+        {
+            xorg_list_del (&data->link);
+            free (data);
+        }
+    }
+}
+
+Bool
+secLayerIsVisible (SECLayer *layer)
+{
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
+
+    return layer->visible;
+}
+
+void
+secLayerShow (SECLayer *layer)
+{
+    SECModePtr pSecMode;
+
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+    XDBG_RETURN_IF_FAIL (layer->fb_id > 0);
+
+    pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
+
+    if (layer->visible)
+        return;
+
+    if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+    {
+        layer->visible = TRUE;
+        XDBG_TRACE (MLYR, "layer(%p) shown. \n", layer);
+        return;
+    }
+
+    if (!_secLayerShowInternal (layer, FALSE))
+        return;
+
+    if (layer->enable_vblank)
+        _secLayerWatchVblank (layer);
+
+    layer->visible = TRUE;
+
+    XDBG_TRACE (MLYR, "layer(%p) shown. \n", layer);
+
+    _secLayerNotify (layer, LAYER_SHOWN, (void*)layer->fb_id);
+}
+
+void
+secLayerHide (SECLayer *layer)
+{
+    SECModePtr pSecMode;
+
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+
+    pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
+
+    if (!layer->visible || layer->ref_cnt > 1)
+        return;
+
+    if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+    {
+        layer->visible = FALSE;
+        XDBG_TRACE (MLYR, "layer(%p) hidden. \n", layer);
+        return;
+    }
+
+    if (!secPlaneHide (layer->plane_id))
+        return;
+
+    if (layer->wait_vbuf && VBUF_IS_VALID (layer->wait_vbuf))
+    {
+        layer->wait_vbuf->showing = FALSE;
+        XDBG_DEBUG (MVBUF, "layer(%p) <-- %s (%ld,%d,%d) \n", layer,
+                    (layer->output==LAYER_OUTPUT_LCD)?"LCD":"TV",
+                    layer->wait_vbuf->stamp, VBUF_IS_CONVERTING (layer->wait_vbuf),
+                    layer->wait_vbuf->showing);
+        secUtilVideoBufferUnref (layer->wait_vbuf);
+    }
+
+    if (layer->pending_vbuf && VBUF_IS_VALID (layer->pending_vbuf))
+    {
+        layer->pending_vbuf->showing = FALSE;
+        secUtilVideoBufferUnref (layer->pending_vbuf);
+    }
+
+    if (layer->showing_vbuf && VBUF_IS_VALID (layer->showing_vbuf))
+    {
+        layer->showing_vbuf->showing = FALSE;
+        XDBG_DEBUG (MVBUF, "layer(%p) <-- %s (%ld,%d,%d) \n", layer,
+                    (layer->output==LAYER_OUTPUT_LCD)?"LCD":"TV",
+                    layer->showing_vbuf->stamp, VBUF_IS_CONVERTING (layer->showing_vbuf),
+                    layer->showing_vbuf->showing);
+        secUtilVideoBufferUnref (layer->showing_vbuf);
+    }
+
+    layer->showing_vbuf = NULL;
+    layer->pending_vbuf = NULL;
+    layer->wait_vbuf = NULL;
+    layer->wait_vblank = FALSE;
+    layer->visible = FALSE;
+    layer->crtc_id = 0;
+
+    XDBG_TRACE (MLYR, "layer(%p) hidden. \n", layer);
+
+    _secLayerNotify (layer, LAYER_HIDDEN, (void*)layer->fb_id);
+}
+
+void
+secLayerFreezeUpdate (SECLayer *layer, Bool enable)
+{
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+
+    layer->freeze_update = enable;
+
+    XDBG_TRACE (MLYR, "layer(%p) freeze %d. \n", layer, enable);
+
+    if (layer->plane_id > 0)
+        secPlaneFreezeUpdate (layer->plane_id, enable);
+}
+
+void
+secLayerUpdate (SECLayer *layer)
+{
+    SECModePtr pSecMode;
+
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+    XDBG_RETURN_IF_FAIL (layer->fb_id > 0);
+
+    pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
+
+    if (!layer->visible)
+        return;
+
+    xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (layer->pScrn);
+    SECCrtcPrivPtr pCrtcPriv = NULL;
+    int c;
+
+    for (c = 0; c < pCrtcConfig->num_crtc; c++)
+    {
+        xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c];
+        SECCrtcPrivPtr pTemp =  pCrtc->driver_private;
+        if (pTemp->mode_crtc && pTemp->mode_crtc->crtc_id == layer->crtc_id)
+        {
+            pCrtcPriv = pTemp;
+            break;
+        }
+    }
+
+    if (!pCrtcPriv || !pCrtcPriv->bAccessibility)
+        return;
+
+    if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+        return;
+
+    if (!_secLayerShowInternal (layer, TRUE))
+        return;
+}
+
+void
+secLayerTurn (SECLayer *layer, Bool onoff, Bool user)
+{
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+
+    secPlaneTrun (layer->plane_id, onoff, user);
+}
+
+Bool
+secLayerTurnStatus (SECLayer *layer)
+{
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
+
+    return secPlaneTrunStatus (layer->plane_id);
+}
+
+void
+secLayerEnableVBlank (SECLayer *layer, Bool enable)
+{
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+
+    layer->enable_vblank = (enable) ? TRUE : FALSE;
+}
+
+Bool
+secLayerSetOffset (SECLayer *layer, int x, int y)
+{
+    SECModePtr pSecMode;
+
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
+
+    pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
+
+    if (layer->offset_x == x && layer->offset_y == y)
+        return TRUE;
+
+    /* display controller restriction. x+width=2's mutiple */
+    XDBG_TRACE (MLYR, "layer(%p) offset(%d,%d => %d,%d).\n",
+                layer, x, y, x & (~0x1), y);
+    layer->offset_x = x & (~0x1);
+    layer->offset_y = y;
+
+    if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+        return TRUE;
+
+    if (secLayerIsVisible (layer) && !layer->freeze_update)
+    {
+        int crtc_id = _GetCrtcID (layer);
+        int plane_pos = _secLayerGetPlanePos (layer, layer->lpos);
+
+        if (!secPlaneShow (layer->plane_id, crtc_id,
+                           layer->src->x, layer->src->y,
+                           layer->src->width, layer->src->height,
+                           layer->offset_x + layer->dst->x,
+                           layer->offset_y + layer->dst->y,
+                           layer->dst->width, layer->dst->height,
+                           plane_pos, FALSE))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+void
+secLayerGetOffset (SECLayer *layer, int *x, int *y)
+{
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+
+    if (x)
+        *x = layer->offset_x;
+    if (y)
+        *y = layer->offset_y;
+}
+
+Bool
+secLayerSetPos (SECLayer *layer, SECLayerPos lpos)
+{
+    SECModePtr pSecMode;
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (lpos >= LAYER_NONE && lpos < LAYER_MAX, FALSE);
+
+    pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
+
+    if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+    {
+        layer->lpos = lpos;
+        return TRUE;
+    }
+
+
+    if (layer->lpos == lpos)
+        return TRUE;
+
+    if (secLayerFind (layer->output, lpos))
+        return FALSE;
+
+    if (secLayerIsVisible (layer) && !layer->freeze_update)
+    {
+        if (lpos == LAYER_NONE)
+        {
+            if (!secPlaneHide (layer->plane_id))
+                return FALSE;
+
+            layer->visible = FALSE;
+            layer->crtc_id = 0;
+        }
+        else
+        {
+            int crtc_id = _GetCrtcID (layer);
+            int plane_pos = _secLayerGetPlanePos (layer, lpos);
+
+            if (!secPlaneShow (layer->plane_id, crtc_id,
+                               layer->src->x, layer->src->y,
+                               layer->src->width, layer->src->height,
+                               layer->offset_x + layer->dst->x,
+                               layer->offset_y + layer->dst->y,
+                               layer->dst->width, layer->dst->height,
+                               plane_pos, FALSE))
+                return FALSE;
+        }
+    }
+
+    XDBG_TRACE (MLYR, "layer(%p) lpos(%d). \n", layer, lpos);
+
+    layer->lpos = lpos;
+
+    return TRUE;
+}
+
+Bool
+secLayerSwapPos (SECLayer *layer1, SECLayer *layer2)
+{
+    SECLayer *lower, *upper;
+    SECLayerPos upper_lpos, lower_lpos;
+
+    XDBG_RETURN_VAL_IF_FAIL (layer1 != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (layer2 != NULL, FALSE);
+
+    XDBG_TRACE (MLYR, "layer1(%p) layer2(%p). \n", layer1, layer2);
+
+    lower = (layer2->lpos < layer1->lpos) ? layer2 : layer1;
+    upper = (layer2->lpos < layer1->lpos) ? layer1 : layer2;
+
+    upper_lpos = upper->lpos;
+    lower_lpos = lower->lpos;
+
+    secLayerSetPos (upper, LAYER_NONE);
+    secLayerSetPos (lower, upper_lpos);
+    secLayerSetPos (upper, lower_lpos);
+
+    return TRUE;
+}
+
+SECLayerPos
+secLayerGetPos (SECLayer *layer)
+{
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, 0);
+
+    return layer->lpos;
+}
+
+Bool
+secLayerSetRect (SECLayer *layer, xRectangle *src, xRectangle *dst)
+{
+    SECModePtr pSecMode;
+
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (src != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (dst != NULL, FALSE);
+
+    pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
+
+    if (!layer->src)
+        layer->src = calloc (sizeof (xRectangle), 1);
+
+    XDBG_RETURN_VAL_IF_FAIL (layer->src != NULL, FALSE);
+
+    if (!layer->dst)
+        layer->dst = calloc (sizeof (xRectangle), 1);
+
+    XDBG_RETURN_VAL_IF_FAIL (layer->dst != NULL, FALSE);
+
+    if (!memcmp (layer->src, src, sizeof (xRectangle)) &&
+        !memcmp (layer->dst, dst, sizeof (xRectangle)))
+        return TRUE;
+
+    *layer->src = *src;
+    *layer->dst = *dst;
+
+    XDBG_TRACE (MLYR, "layer(%p) src(%d,%d %dx%d) dst(%d,%d %dx%d). \n",
+                layer, src->x, src->y, src->width, src->height,
+                dst->x, dst->y, dst->width, dst->height);
+    if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+        return TRUE;
+
+    if (layer->pending_vbuf && VBUF_IS_VALID (layer->pending_vbuf))
+    {
+        layer->pending_vbuf->showing = FALSE;
+        secUtilVideoBufferUnref (layer->pending_vbuf);
+        layer->pending_vbuf = NULL;
+    }
+
+    if (secLayerIsVisible (layer) && !layer->freeze_update)
+    {
+        int plane_pos = _secLayerGetPlanePos (layer, layer->lpos);
+
+        if (!secPlaneShow (layer->plane_id, _GetCrtcID (layer),
+                           src->x, src->y, src->width, src->height,
+                           layer->offset_x + dst->x,
+                           layer->offset_y + dst->y,
+                           dst->width, dst->height,
+                           plane_pos, FALSE))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+void
+secLayerGetRect (SECLayer *layer, xRectangle *src, xRectangle *dst)
+{
+    XDBG_RETURN_IF_FAIL (layer != NULL);
+
+    if (src && layer->src)
+        *src = *layer->src;
+
+    if (dst && layer->dst)
+        *dst = *layer->dst;
+}
+
+int
+secLayerSetBuffer (SECLayer *layer, SECVideoBuf *vbuf)
+{
+    SECModePtr pSecMode;
+    unsigned int fb_id;
+
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, 0);
+    XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), 0);
+
+    if (!secLayerSupport (layer->pScrn, layer->output, layer->lpos, vbuf->id))
+    {
+        XDBG_ERROR (MLYR, "fail : layer(%p) output(%d) lpos(%d) vbuf(%c%c%c%c)\n",
+                    layer, layer->output, layer->lpos, FOURCC_STR (vbuf->id));
+        return 0;
+    }
+
+    pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
+
+    if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+    {
+        XDBG_RETURN_VAL_IF_FAIL (layer->enable_vblank == FALSE, 0);
+
+        XDBG_TRACE (MLYR, "layer(%p) vbuf('%c%c%c%c', %dx%d, %d,%d %dx%d)\n",
+                    layer, FOURCC_STR(vbuf->id), vbuf->width, vbuf->height,
+                    vbuf->crop.x, vbuf->crop.y, vbuf->crop.width, vbuf->crop.height);
+
+        if (layer->vbuf)
+            secUtilVideoBufferUnref (layer->vbuf);
+
+        layer->vbuf = secUtilVideoBufferRef (vbuf);
+        layer->fb_id = 1;
+
+        _secLayerNotify (layer, LAYER_BUF_CHANGED, vbuf);
+
+        return layer->fb_id;
+    }
+
+    if (layer->wait_vbuf && layer->pending_vbuf)
+    {
+        XDBG_TRACE (MLYR, "pending_vbuf(%ld) exists.\n", layer->pending_vbuf->stamp);
+        return 0;
+    }
+
+    _secLayerGetBufferID (layer, vbuf);
+    XDBG_RETURN_VAL_IF_FAIL (vbuf->fb_id > 0, 0);
+
+    if (layer->wait_vbuf && !layer->pending_vbuf)
+    {
+        layer->pending_vbuf = secUtilVideoBufferRef (vbuf);
+        layer->pending_vbuf->showing = TRUE;
+        XDBG_TRACE (MLYR, "pending vbuf(%ld).\n", layer->pending_vbuf->stamp);
+        return vbuf->fb_id;
+    }
+
+    fb_id = secPlaneGetBuffer (layer->plane_id, NULL, vbuf);
+    if (fb_id == 0)
+    {
+        fb_id = secPlaneAddBuffer (layer->plane_id, vbuf);
+        XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, 0);
+
+        layer->fb_id = vbuf->fb_id;
+    }
+
+    if (vbuf->fb_id != fb_id)
+        XDBG_WARNING (MLYR, "fb_id (%d != %d) \n", vbuf->fb_id, fb_id);
+
+    layer->fb_id = fb_id;
+    if (!secPlaneAttach (layer->plane_id, fb_id))
+        return 0;
+
+    if (secLayerIsVisible (layer) && !layer->freeze_update)
+        if (!_secLayerShowInternal (layer, TRUE))
+            return 0;
+
+    if (layer->enable_vblank)
+    {
+        XDBG_RETURN_VAL_IF_FAIL (layer->wait_vbuf == NULL, 0);
+
+        layer->wait_vbuf = secUtilVideoBufferRef (vbuf);
+        layer->wait_vbuf->showing = TRUE;
+        XDBG_DEBUG (MVBUF, "layer(%p) --> %s (%ld,%d,%d) \n", layer,
+                    (layer->output==LAYER_OUTPUT_LCD)?"LCD":"TV",
+                    layer->wait_vbuf->stamp,
+                    VBUF_IS_CONVERTING (layer->wait_vbuf),
+                    layer->wait_vbuf->showing);
+
+        if (secLayerIsVisible (layer))
+        {
+            XDBG_TRACE (MLYR, "layer(%p) fb_id(%d) attached. \n", layer, fb_id);
+            _secLayerWatchVblank (layer);
+        }
+    }
+
+    if (layer->vbuf)
+        secUtilVideoBufferUnref (layer->vbuf);
+    layer->vbuf = secUtilVideoBufferRef (vbuf);
+
+    _secLayerNotify (layer, LAYER_BUF_CHANGED, vbuf);
+
+    return fb_id;
+}
+
+SECVideoBuf*
+secLayerGetBuffer (SECLayer *layer)
+{
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL);
+
+    if (layer->showing_vbuf && layer->dst && layer->visible)
+        return layer->showing_vbuf;
+    else if (layer->vbuf)
+        return layer->vbuf;
+
+    return NULL;
+}
+
+void
+secLayerVBlankEventHandler (unsigned int frame, unsigned int tv_sec,
+                            unsigned int tv_usec, void *event_data)
+{
+    SECLayer *layer = NULL, *layer_next = NULL;
+    int pipe = (int)event_data;
+
+    XDBG_RETURN_IF_FAIL (pipe < LAYER_OUTPUT_MAX);
+
+    _secLayerInitList ();
+
+    wait_vblank[pipe] = FALSE;
+
+    XDBG_DEBUG (MLYR, "frame(%d), tv_sec(%d), tv_usec(%d) \n", frame, tv_sec, tv_usec);
+
+    xorg_list_for_each_entry_safe (layer, layer_next, &crtc_layers, link)
+    {
+        int crtc_pipe = secDisplayCrtcPipe (layer->pScrn, _GetCrtcID (layer));
+
+        if (!layer->enable_vblank || !layer->wait_vblank)
+            continue;
+
+        if (crtc_pipe != pipe)
+            continue;
+
+        layer->wait_vblank = FALSE;
+
+        if (VBUF_IS_VALID (layer->wait_vbuf))
+        {
+            if (layer->showing_vbuf && VBUF_IS_VALID (layer->showing_vbuf))
+            {
+                layer->showing_vbuf->showing = FALSE;
+                secUtilVideoBufferUnref (layer->showing_vbuf);
+            }
+
+            layer->showing_vbuf = layer->wait_vbuf;
+            layer->wait_vbuf = NULL;
+
+            if (layer->pending_vbuf && VBUF_IS_VALID (layer->pending_vbuf))
+            {
+                int fb_id;
+
+                layer->wait_vbuf = layer->pending_vbuf;
+                layer->pending_vbuf = NULL;
+
+                fb_id = secPlaneGetBuffer (layer->plane_id, NULL, layer->wait_vbuf);
+                if (fb_id == 0)
+                {
+                    fb_id = secPlaneAddBuffer (layer->plane_id, layer->wait_vbuf);
+                    XDBG_RETURN_IF_FAIL (fb_id > 0);
+
+                    layer->fb_id = layer->wait_vbuf->fb_id;
+                }
+
+                if (!secPlaneAttach (layer->plane_id, layer->wait_vbuf->fb_id))
+                    continue;
+
+                if (secLayerIsVisible (layer) && !layer->freeze_update)
+                    _secLayerShowInternal (layer, TRUE);
+
+                _secLayerWatchVblank (layer);
+            }
+
+            SECPtr pSec = SECPTR (layer->pScrn);
+            if (pSec->pVideoPriv->video_fps)
+                _countFps (layer);
+
+            XDBG_TRACE (MLYR, "layer(%p) fb_id(%d) now showing frame(%d) (%ld,%ld,%ld) => crtc(%d) pos(%d). \n",
+                        layer, layer->fb_id, frame,
+                        VSTMAP(layer->pending_vbuf), VSTMAP(layer->wait_vbuf), VSTMAP(layer->showing_vbuf),
+                        _GetCrtcID (layer), layer->lpos);
+
+            _secLayerNotify (layer, LAYER_VBLANK, (void*)layer->showing_vbuf);
+        }
+    }
+}
diff --git a/src/crtcconfig/sec_layer.h b/src/crtcconfig/sec_layer.h
new file mode 100644 (file)
index 0000000..e3f0685
--- /dev/null
@@ -0,0 +1,105 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_LAYER_H__
+#define __SEC_LAYER_H__
+
+#include "sec_video_types.h"
+#include "sec_video_fourcc.h"
+
+typedef enum
+{
+    LAYER_OUTPUT_LCD,
+    LAYER_OUTPUT_EXT,
+    LAYER_OUTPUT_MAX
+} SECLayerOutput;
+
+typedef enum
+{
+    LAYER_NONE      = -3,
+    LAYER_LOWER2    = -2,
+    LAYER_LOWER1    = -1,
+    LAYER_DEFAULT   =  0,
+    LAYER_UPPER     = +1,
+    LAYER_MAX       = +2,
+} SECLayerPos;
+
+#define LAYER_DESTROYED         1
+#define LAYER_SHOWN             2
+#define LAYER_HIDDEN            3
+/* To manage buffer */
+#define LAYER_BUF_CHANGED       4  /* type_data: SECLayerBufInfo */
+#define LAYER_VBLANK            5  /* type_data: SECLayerBufInfo */
+
+typedef struct _SECLayer SECLayer;
+
+typedef void (*NotifyFunc) (SECLayer *layer, int type, void *type_data, void *user_data);
+
+Bool        secLayerSupport     (ScrnInfoPtr pScrn, SECLayerOutput output,
+                                 SECLayerPos lpos, unsigned int id);
+
+SECLayer*   secLayerFind        (SECLayerOutput output, SECLayerPos lpos);
+void        secLayerDestroyAll  (void);
+void        secLayerShowAll     (ScrnInfoPtr pScrn, SECLayerOutput output);
+
+void        secLayerAddNotifyFunc    (SECLayer *layer, NotifyFunc func, void *user_data);
+void        secLayerRemoveNotifyFunc (SECLayer *layer, NotifyFunc func);
+
+SECLayer*   secLayerCreate    (ScrnInfoPtr pScrn, SECLayerOutput output, SECLayerPos lpos);
+SECLayer*   secLayerRef       (SECLayer *layer);
+void        secLayerUnref     (SECLayer *layer);
+
+Bool        secLayerIsVisible (SECLayer *layer);
+void        secLayerShow      (SECLayer *layer);
+void        secLayerHide      (SECLayer *layer);
+void        secLayerFreezeUpdate (SECLayer *layer, Bool enable);
+void        secLayerUpdate    (SECLayer *layer);
+void        secLayerTurn      (SECLayer *layer, Bool onoff, Bool user);
+Bool        secLayerTurnStatus (SECLayer *layer);
+
+void        secLayerEnableVBlank (SECLayer *layer, Bool enable);
+
+Bool        secLayerSetOffset (SECLayer *layer, int x, int y);
+void        secLayerGetOffset (SECLayer *layer, int *x, int *y);
+
+Bool        secLayerSetPos    (SECLayer *layer, SECLayerPos lpos);
+SECLayerPos secLayerGetPos    (SECLayer *layer);
+Bool        secLayerSwapPos   (SECLayer *layer1, SECLayer *layer2);
+
+Bool        secLayerSetRect   (SECLayer *layer, xRectangle *src, xRectangle *dst);
+void        secLayerGetRect   (SECLayer *layer, xRectangle *src, xRectangle *dst);
+
+int          secLayerSetBuffer (SECLayer *layer, SECVideoBuf *vbuf);
+SECVideoBuf* secLayerGetBuffer (SECLayer *layer);
+
+void        secLayerVBlankEventHandler (unsigned int frame, unsigned int tv_sec,
+                                        unsigned int tv_usec, void *event_data);
+
+#endif /* __SEC_LAYER_H__ */
diff --git a/src/crtcconfig/sec_output.c b/src/crtcconfig/sec_output.c
new file mode 100644 (file)
index 0000000..b0e5e41
--- /dev/null
@@ -0,0 +1,878 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <poll.h>
+
+#include <xorgVersion.h>
+#include <tbm_bufmgr.h>
+#include <xf86Crtc.h>
+#include <xf86DDC.h>
+#include <xf86cmap.h>
+#include <list.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/dpmsconst.h>
+#include <sec.h>
+
+#include "sec_util.h"
+#include "sec_crtc.h"
+#include "sec_output.h"
+#include "sec_prop.h"
+#include "sec_xberc.h"
+#include "sec_layer.h"
+#include "sec_wb.h"
+#include "sec_video_virtual.h"
+
+static const int subpixel_conv_table[7] =
+{
+    0,
+    SubPixelUnknown,
+    SubPixelHorizontalRGB,
+    SubPixelHorizontalBGR,
+    SubPixelVerticalRGB,
+    SubPixelVerticalBGR,
+    SubPixelNone
+};
+
+static const char *output_names[] =
+{
+    "None",
+    "VGA",
+    "DVI",
+    "DVI",
+    "DVI",
+    "Composite",
+    "TV",
+    "LVDS",
+    "CTV",
+    "DIN",
+    "DP",
+    "HDMI",
+    "HDMI",
+    "TV",
+    "eDP",
+    "Virtual",
+};
+
+static CARD32
+_secOutputResumeWbTimeout (OsTimerPtr timer, CARD32 now, pointer arg)
+{
+    XDBG_RETURN_VAL_IF_FAIL(arg, 0);
+
+    xf86OutputPtr pOutput = (xf86OutputPtr)arg;
+    SECPtr pSec = SECPTR (pOutput->scrn);
+
+    pSec = SECPTR (pOutput->scrn);
+
+    if (pSec->resume_timer)
+    {
+        TimerFree (pSec->resume_timer);
+        pSec->resume_timer = NULL;
+    }
+
+    secDisplaySetDispSetMode (pOutput->scrn, pSec->set_mode);
+    pSec->set_mode = DISPLAY_SET_MODE_OFF;
+
+    return 0;
+}
+
+static void
+_secOutputAttachEdid(xf86OutputPtr pOutput)
+{
+    SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+    drmModeConnectorPtr koutput = pOutputPriv->mode_output;
+    SECModePtr pSecMode = pOutputPriv->pSecMode;
+    drmModePropertyBlobPtr edid_blob = NULL;
+    xf86MonPtr mon = NULL;
+    int i;
+
+    /* look for an EDID property */
+    for (i = 0; i < koutput->count_props; i++)
+    {
+        drmModePropertyPtr props;
+
+        props = drmModeGetProperty (pSecMode->fd, koutput->props[i]);
+        if (!props)
+            continue;
+
+        if (!(props->flags & DRM_MODE_PROP_BLOB))
+        {
+            drmModeFreeProperty (props);
+            continue;
+        }
+
+        if (!strcmp (props->name, "EDID"))
+        {
+            drmModeFreePropertyBlob (edid_blob);
+            edid_blob =
+                drmModeGetPropertyBlob (pSecMode->fd,
+                                        koutput->prop_values[i]);
+        }
+        drmModeFreeProperty (props);
+    }
+
+    if (edid_blob)
+    {
+        mon = xf86InterpretEDID (pOutput->scrn->scrnIndex,
+                                 edid_blob->data);
+
+        if (mon && edid_blob->length > 128)
+            mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
+    }
+
+    xf86OutputSetEDID (pOutput, mon);
+
+    if (edid_blob)
+        drmModeFreePropertyBlob (edid_blob);
+}
+
+static Bool
+_secOutputPropertyIgnore(drmModePropertyPtr prop)
+{
+    if (!prop)
+        return TRUE;
+
+    /* ignore blob prop */
+    if (prop->flags & DRM_MODE_PROP_BLOB)
+        return TRUE;
+
+    /* ignore standard property */
+    if (!strcmp (prop->name, "EDID") ||
+        !strcmp (prop->name, "DPMS"))
+        return TRUE;
+
+    return FALSE;
+}
+
+static xf86OutputStatus
+SECOutputDetect(xf86OutputPtr output)
+{
+    /* go to the hw and retrieve a new output struct */
+    SECOutputPrivPtr pOutputPriv = output->driver_private;
+    SECModePtr pSecMode = pOutputPriv->pSecMode;
+    xf86OutputStatus status;
+//    char *conn_str[] = {"connected", "disconnected", "unknow"};
+
+    /* update output */
+    drmModeFreeConnector (pOutputPriv->mode_output);
+    pOutputPriv->mode_output =
+        drmModeGetConnector (pSecMode->fd, pOutputPriv->output_id);
+    XDBG_RETURN_VAL_IF_FAIL (pOutputPriv->mode_output != NULL, XF86OutputStatusUnknown);
+
+    /* update encoder */
+    drmModeFreeEncoder (pOutputPriv->mode_encoder);
+    pOutputPriv->mode_encoder =
+        drmModeGetEncoder (pSecMode->fd, pOutputPriv->mode_output->encoders[0]);
+    XDBG_RETURN_VAL_IF_FAIL (pOutputPriv->mode_encoder != NULL, XF86OutputStatusUnknown);
+
+    if (pSecMode->unset_connector_type == pOutputPriv->mode_output->connector_type)
+    {
+        return XF86OutputStatusDisconnected;
+    }
+#if 0
+    XDBG_INFO (MSEC, "detect : connect(%d, type:%d, status:%s) encoder(%d) crtc(%d).\n",
+               pOutputPriv->output_id, pOutputPriv->mode_output->connector_type,
+               conn_str[pOutputPriv->mode_output->connection-1],
+               pOutputPriv->mode_encoder->encoder_id, pOutputPriv->mode_encoder->crtc_id);
+#endif
+    switch (pOutputPriv->mode_output->connection)
+    {
+    case DRM_MODE_CONNECTED:
+        status = XF86OutputStatusConnected;
+        break;
+    case DRM_MODE_DISCONNECTED:
+        status = XF86OutputStatusDisconnected;
+        /* unset write-back clone */
+        secPropUnSetDisplayMode (output);
+        break;
+    default:
+    case DRM_MODE_UNKNOWNCONNECTION:
+        status = XF86OutputStatusUnknown;
+        break;
+    }
+    return status;
+}
+
+static Bool
+SECOutputModeValid(xf86OutputPtr pOutput, DisplayModePtr pModes)
+{
+    SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+    drmModeConnectorPtr koutput = pOutputPriv->mode_output;
+    int i;
+
+    /* driver want to remain available modes which is same as mode
+       supported from drmmode */
+    if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS)
+    {
+        for (i = 0; i < koutput->count_modes; i++)
+        {
+            if (pModes->HDisplay == koutput->modes[i].hdisplay &&
+                pModes->VDisplay == koutput->modes[i].vdisplay)
+                return MODE_OK;
+        }
+        return MODE_ERROR;
+    }
+
+    return MODE_OK;
+}
+
+static DisplayModePtr
+SECOutputGetModes(xf86OutputPtr pOutput)
+{
+    SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+    drmModeConnectorPtr koutput = pOutputPriv->mode_output;
+    DisplayModePtr Modes = NULL;
+    int i;
+    SECPtr pSec = SECPTR (pOutput->scrn);
+    DisplayModePtr Mode;
+
+    /* LVDS1 (main LCD) does not provide edid data */
+    if (pOutputPriv->mode_output->connector_type != DRM_MODE_CONNECTOR_LVDS)
+        _secOutputAttachEdid(pOutput);
+
+    /* modes should already be available */
+    for (i = 0; i < koutput->count_modes; i++)
+    {
+        Mode = calloc (1, sizeof (DisplayModeRec));
+        if (Mode)
+        {
+            /* generate the fake modes when screen rotation is set */
+            if(pSec->fake_root)
+                secDisplaySwapModeFromKmode(pOutput->scrn, &koutput->modes[i], Mode);
+            else
+                secDisplayModeFromKmode(pOutput->scrn, &koutput->modes[i], Mode);
+            Modes = xf86ModesAdd(Modes, Mode);
+        }
+    }
+
+    return Modes;
+}
+
+static void
+SECOutputDestory(xf86OutputPtr pOutput)
+{
+    SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+    SECPtr pSec = SECPTR (pOutput->scrn);
+    int i;
+
+    if (pSec->resume_timer)
+    {
+        TimerFree (pSec->resume_timer);
+        pSec->resume_timer = NULL;
+    }
+    pSec->set_mode = DISPLAY_SET_MODE_OFF;
+
+    for (i = 0; i < pOutputPriv->num_props; i++)
+    {
+        drmModeFreeProperty (pOutputPriv->props[i].mode_prop);
+        free (pOutputPriv->props[i].atoms);
+    }
+    free (pOutputPriv->props);
+
+    drmModeFreeEncoder (pOutputPriv->mode_encoder);
+    drmModeFreeConnector (pOutputPriv->mode_output);
+    xorg_list_del (&pOutputPriv->link);
+    free (pOutputPriv);
+
+    pOutput->driver_private = NULL;
+}
+
+static void
+SECOutputDpms(xf86OutputPtr pOutput, int dpms)
+{
+    SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+    drmModeConnectorPtr koutput = pOutputPriv->mode_output;
+    SECModePtr pSecMode = pOutputPriv->pSecMode;
+    SECPtr pSec = SECPTR (pOutput->scrn);
+    int old_dpms = pOutputPriv->dpms_mode;
+    int i;
+
+    if (!strcmp(pOutput->name, "HDMI1") ||
+        !strcmp(pOutput->name, "Virtual1"))
+            return;
+
+    if (dpms == DPMSModeSuspend)
+        return;
+
+    for (i = 0; i < koutput->count_props; i++)
+    {
+        drmModePropertyPtr props;
+
+        props = drmModeGetProperty (pSecMode->fd, koutput->props[i]);
+        if (!props)
+            continue;
+
+        if ((old_dpms == DPMSModeStandby && dpms == DPMSModeOn) ||
+            (old_dpms == DPMSModeOn && dpms == DPMSModeStandby))
+        {
+            if (!strcmp (props->name, "panel"))
+            {
+                int value = (dpms == DPMSModeStandby)? 1 : 0;
+                drmModeConnectorSetProperty(pSecMode->fd,
+                                            pOutputPriv->output_id,
+                                            props->prop_id,
+                                            value);
+                pOutputPriv->dpms_mode = dpms;
+                drmModeFreeProperty (props);
+                XDBG_INFO (MDPMS, "panel '%s'\n", (value)?"OFF":"ON");
+                return;
+            }
+        }
+        else if (!strcmp (props->name, "DPMS"))
+        {
+            int _tmp_dpms = dpms;
+            switch (dpms)
+            {
+            case DPMSModeStandby:
+            case DPMSModeOn:
+                if (pOutputPriv->isLcdOff == FALSE)
+                {
+                    drmModeFreeProperty (props);
+                    return;
+                }
+                /* lcd on */
+                XDBG_INFO (MDPMS, "\t Reqeust DPMS ON (%s)\n", pOutput->name);
+                _tmp_dpms = DPMSModeOn;
+                pOutputPriv->isLcdOff = FALSE;
+
+                if (!strcmp(pOutput->name, "LVDS1"))
+                {
+                    pSec->isLcdOff = FALSE;
+
+                    /* if wb need to be started, start wb after timeout. */
+                    if (pSec->set_mode == DISPLAY_SET_MODE_CLONE)
+                    {
+                        pSec->resume_timer = TimerSet (pSec->resume_timer,
+                                                       0, 30,
+                                                       _secOutputResumeWbTimeout,
+                                                       pOutput);
+                    }
+
+                    secVideoDpms (pOutput->scrn, TRUE);
+                    secVirtualVideoDpms (pOutput->scrn, TRUE);
+                }
+
+                /* accessibility */
+                SECCrtcPrivPtr pCrtcPriv = pOutput->crtc->driver_private;
+                if (pCrtcPriv->screen_rotate_degree > 0)
+                    secCrtcEnableScreenRotate (pOutput->crtc, TRUE);
+                else
+                    secCrtcEnableScreenRotate (pOutput->crtc, FALSE);
+                if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0)
+                {
+                    tbm_bo src_bo = pCrtcPriv->front_bo;
+                    tbm_bo dst_bo = pCrtcPriv->accessibility_back_bo;
+                    if (!secCrtcExecAccessibility (pOutput->crtc, src_bo, dst_bo))
+                    {
+                        XDBG_ERROR(MDPMS, "Fail execute accessibility(output name, %s)\n",
+                                   pOutput->name);
+                    }
+                }
+
+                /* set current fb to crtc */
+                if(!secCrtcApply(pOutput->crtc))
+                {
+                    XDBG_ERROR(MDPMS, "Fail crtc apply(output name, %s)\n",
+                               pOutput->name);
+                }
+                break;
+            case DPMSModeOff:
+                if (pOutputPriv->isLcdOff == TRUE)
+                {
+                    drmModeFreeProperty (props);
+                    return;
+                }
+                /* lcd off */
+                XDBG_INFO (MDPMS, "\t Reqeust DPMS OFF (%s)\n", pOutput->name);
+                _tmp_dpms = DPMSModeOff;
+                pOutputPriv->isLcdOff = TRUE;
+
+                secCrtcEnableScreenRotate (pOutput->crtc, FALSE);
+
+                if (!strcmp(pOutput->name, "LVDS1"))
+                {
+                    secVideoDpms (pOutput->scrn, FALSE);
+                    secVirtualVideoDpms (pOutput->scrn, FALSE);
+
+                    pSec->isLcdOff = TRUE;
+
+                    if (pSec->resume_timer)
+                    {
+                        TimerFree (pSec->resume_timer);
+                        drmModeFreeProperty (props);
+                        pSec->resume_timer = NULL;
+                        return;
+                    }
+
+                    /* keep previous pSecMode's set_mode. */
+                    pSec->set_mode = secDisplayGetDispSetMode (pOutput->scrn);
+
+                    if (pSec->set_mode == DISPLAY_SET_MODE_CLONE)
+                    {
+                        /* stop wb if wb is working. */
+                        secDisplaySetDispSetMode (pOutput->scrn, DISPLAY_SET_MODE_OFF);
+                    }
+                }
+                break;
+            default:
+                 drmModeFreeProperty (props);
+                return;
+            }
+
+            drmModeConnectorSetProperty(pSecMode->fd,
+                                        pOutputPriv->output_id,
+                                        props->prop_id,
+                                        _tmp_dpms);
+
+            XDBG_INFO (MDPMS, "\t Success DPMS request (%s)\n", pOutput->name);
+
+            pOutputPriv->dpms_mode = _tmp_dpms;
+            drmModeFreeProperty (props);
+            return;
+        }
+
+        drmModeFreeProperty (props);
+    }
+}
+
+static void
+SECOutputCreateReaources(xf86OutputPtr pOutput)
+{
+    SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+    drmModeConnectorPtr mode_output = pOutputPriv->mode_output;
+    SECModePtr pSecMode = pOutputPriv->pSecMode;
+    int i, j, err;
+
+    pOutputPriv->props = calloc (mode_output->count_props, sizeof (SECPropertyRec));
+    if (!pOutputPriv->props)
+        return;
+
+    pOutputPriv->num_props = 0;
+    for (i = j = 0; i < mode_output->count_props; i++)
+    {
+        drmModePropertyPtr drmmode_prop;
+
+        drmmode_prop = drmModeGetProperty(pSecMode->fd,
+                                          mode_output->props[i]);
+        if (_secOutputPropertyIgnore(drmmode_prop))
+        {
+            drmModeFreeProperty (drmmode_prop);
+            continue;
+        }
+
+        pOutputPriv->props[j].mode_prop = drmmode_prop;
+        pOutputPriv->props[j].value = mode_output->prop_values[i];
+        j++;
+    }
+    pOutputPriv->num_props = j;
+
+    for (i = 0; i < pOutputPriv->num_props; i++)
+    {
+        SECPropertyPtr p = &pOutputPriv->props[i];
+        drmModePropertyPtr drmmode_prop = p->mode_prop;
+
+        if (drmmode_prop->flags & DRM_MODE_PROP_RANGE)
+        {
+            INT32 range[2];
+
+            p->num_atoms = 1;
+            p->atoms = calloc (p->num_atoms, sizeof (Atom));
+            if (!p->atoms)
+                continue;
+
+            p->atoms[0] = MakeAtom (drmmode_prop->name, strlen (drmmode_prop->name), TRUE);
+            range[0] = drmmode_prop->values[0];
+            range[1] = drmmode_prop->values[1];
+            err = RRConfigureOutputProperty (pOutput->randr_output, p->atoms[0],
+                                             FALSE, TRUE,
+                                             drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+                                             2, range);
+            if (err != 0)
+            {
+                xf86DrvMsg (pOutput->scrn->scrnIndex, X_ERROR,
+                            "RRConfigureOutputProperty error, %d\n", err);
+            }
+            err = RRChangeOutputProperty (pOutput->randr_output, p->atoms[0],
+                                          XA_INTEGER, 32, PropModeReplace, 1, &p->value, FALSE, TRUE);
+            if (err != 0)
+            {
+                xf86DrvMsg (pOutput->scrn->scrnIndex, X_ERROR,
+                            "RRChangeOutputProperty error, %d\n", err);
+            }
+        }
+        else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM)
+        {
+            p->num_atoms = drmmode_prop->count_enums + 1;
+            p->atoms = calloc (p->num_atoms, sizeof (Atom));
+            if (!p->atoms)
+                continue;
+
+            p->atoms[0] = MakeAtom (drmmode_prop->name, strlen (drmmode_prop->name), TRUE);
+            for (j = 1; j <= drmmode_prop->count_enums; j++)
+            {
+                struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
+                p->atoms[j] = MakeAtom (e->name, strlen (e->name), TRUE);
+            }
+
+            err = RRConfigureOutputProperty (pOutput->randr_output, p->atoms[0],
+                                             FALSE, FALSE,
+                                             drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+                                             p->num_atoms - 1, (INT32*)&p->atoms[1]);
+            if (err != 0)
+            {
+                xf86DrvMsg (pOutput->scrn->scrnIndex, X_ERROR,
+                            "RRConfigureOutputProperty error, %d\n", err);
+            }
+
+            for (j = 0; j < drmmode_prop->count_enums; j++)
+                if (drmmode_prop->enums[j].value == p->value)
+                    break;
+            /* there's always a matching value */
+            err = RRChangeOutputProperty (pOutput->randr_output, p->atoms[0],
+                                          XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE);
+            if (err != 0)
+            {
+                xf86DrvMsg (pOutput->scrn->scrnIndex, X_ERROR,
+                            "RRChangeOutputProperty error, %d\n", err);
+            }
+        }
+    }
+}
+
+static Bool
+SECOutputSetProperty(xf86OutputPtr output, Atom property,
+                     RRPropertyValuePtr value)
+{
+    SECOutputPrivPtr pOutputPriv = output->driver_private;
+    SECModePtr pSecMode = pOutputPriv->pSecMode;
+    int i;
+
+    //SECOutputDpms(output, DPMSModeStandby);
+
+    for (i = 0; i < pOutputPriv->num_props; i++)
+    {
+        SECPropertyPtr p = &pOutputPriv->props[i];
+
+        if (p->atoms[0] != property)
+            continue;
+
+        if (p->mode_prop->flags & DRM_MODE_PROP_RANGE)
+        {
+            uint32_t val;
+
+            if (value->type != XA_INTEGER || value->format != 32 ||
+                    value->size != 1)
+                return FALSE;
+            val = *(uint32_t*)value->data;
+
+            drmModeConnectorSetProperty (pSecMode->fd, pOutputPriv->output_id,
+                                         p->mode_prop->prop_id, (uint64_t) val);
+            return TRUE;
+        }
+        else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM)
+        {
+            Atom       atom;
+            const char *name;
+            int                j;
+
+            if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
+                return FALSE;
+            memcpy (&atom, value->data, 4);
+            name = NameForAtom (atom);
+
+            /* search for matching name string, then set its value down */
+            for (j = 0; j < p->mode_prop->count_enums; j++)
+            {
+                if (!strcmp (p->mode_prop->enums[j].name, name))
+                {
+                    drmModeConnectorSetProperty (pSecMode->fd, pOutputPriv->output_id,
+                                                 p->mode_prop->prop_id, p->mode_prop->enums[j].value);
+                    return TRUE;
+                }
+            }
+            return FALSE;
+        }
+    }
+
+    /* We didn't recognise this property, just report success in order
+     * to allow the set to continue, otherwise we break setting of
+     * common properties like EDID.
+     */
+    /* set the hidden properties : features for sec debugging*/
+    /* TODO : xberc can works on only LVDS????? */
+    if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS)
+    {
+        if (secPropSetLvdsFunc (output, property, value))
+            return TRUE;
+
+        if (secPropSetFbVisible (output, property, value))
+            return TRUE;
+
+        if (secPropSetVideoOffset (output, property, value))
+            return TRUE;
+
+        if (secPropSetScreenRotate (output, property, value))
+            return TRUE;
+
+        if (secXbercSetProperty (output, property, value))
+            return TRUE;
+    }
+    /* set the hidden properties : features for driver specific funtions */
+    if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+        pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB ||
+        pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)
+    {
+        /* set the property for the display mode */
+        if (secPropSetDisplayMode(output, property, value))
+            return TRUE;
+    }
+
+    return TRUE;
+}
+
+static Bool
+SECOutputGetProperty(xf86OutputPtr pOutput, Atom property)
+{
+    return FALSE;
+}
+
+static const xf86OutputFuncsRec sec_output_funcs =
+{
+    .create_resources = SECOutputCreateReaources,
+#ifdef RANDR_12_INTERFACE
+    .set_property = SECOutputSetProperty,
+    .get_property = SECOutputGetProperty,
+#endif
+    .dpms = SECOutputDpms,
+#if 0
+    .save = drmmode_crt_save,
+    .restore = drmmode_crt_restore,
+    .mode_fixup = drmmode_crt_mode_fixup,
+    .prepare = sec_output_prepare,
+    .mode_set = drmmode_crt_mode_set,
+    .commit = sec_output_commit,
+#endif
+    .detect = SECOutputDetect,
+    .mode_valid = SECOutputModeValid,
+
+    .get_modes = SECOutputGetModes,
+    .destroy = SECOutputDestory
+};
+
+Bool
+secOutputDrmUpdate (ScrnInfoPtr pScrn)
+{
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+    Bool ret = TRUE;
+    int i;
+
+    for (i = 0; i < pSecMode->mode_res->count_connectors; i++)
+    {
+        SECOutputPrivPtr pOutputPriv = NULL;
+        SECOutputPrivPtr pCur, pNext;
+        drmModeConnectorPtr koutput;
+        drmModeEncoderPtr kencoder;
+        char *conn_str[] = {"connected", "disconnected", "unknow"};
+
+        xorg_list_for_each_entry_safe (pCur, pNext, &pSecMode->outputs, link)
+        {
+            if (pCur->output_id == pSecMode->mode_res->connectors[i])
+            {
+                pOutputPriv = pCur;
+                break;
+            }
+        }
+
+        if (!pOutputPriv)
+        {
+            ret = FALSE;
+            break;
+        }
+
+        koutput = drmModeGetConnector (pSecMode->fd,
+                                       pSecMode->mode_res->connectors[i]);
+        if (!koutput)
+        {
+            ret = FALSE;
+            break;
+        }
+
+        kencoder = drmModeGetEncoder (pSecMode->fd, koutput->encoders[0]);
+        if (!kencoder)
+        {
+            drmModeFreeConnector (koutput);
+            ret = FALSE;
+            break;
+        }
+
+        if (pOutputPriv->mode_output)
+        {
+            drmModeFreeConnector (pOutputPriv->mode_output);
+            pOutputPriv->mode_output = NULL;
+        }
+        pOutputPriv->mode_output = koutput;
+
+        if (pOutputPriv->mode_encoder)
+        {
+            drmModeFreeEncoder (pOutputPriv->mode_encoder);
+            pOutputPriv->mode_encoder = NULL;
+        }
+        pOutputPriv->mode_encoder = kencoder;
+
+        XDBG_INFO (MSEC, "drm update : connect(%d, type:%d, status:%s) encoder(%d) crtc(%d).\n",
+                   pSecMode->mode_res->connectors[i], koutput->connector_type,
+                   conn_str[pOutputPriv->mode_output->connection-1],
+                   kencoder->encoder_id, kencoder->crtc_id);
+#if 0
+        /* Does these need to update? */
+        pOutput->mm_width = koutput->mmWidth;
+        pOutput->mm_height = koutput->mmHeight;
+
+        pOutput->possible_crtcs = kencoder->possible_crtcs;
+        pOutput->possible_clones = kencoder->possible_clones;
+#endif
+    }
+
+    if (!ret)
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "drm(output) update error. (%s)\n", strerror (errno));
+
+    return ret;
+}
+
+void
+secOutputInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num)
+{
+    xf86OutputPtr pOutput;
+    drmModeConnectorPtr koutput;
+    drmModeEncoderPtr kencoder;
+    SECOutputPrivPtr pOutputPriv;
+    const char *output_name;
+    char name[32];
+
+    koutput = drmModeGetConnector (pSecMode->fd,
+                                   pSecMode->mode_res->connectors[num]);
+    if (!koutput)
+        return;
+
+    kencoder = drmModeGetEncoder (pSecMode->fd, koutput->encoders[0]);
+    if (!kencoder)
+    {
+        drmModeFreeConnector (koutput);
+        return;
+    }
+
+    if (koutput->connector_type < ARRAY_SIZE (output_names))
+        output_name = output_names[koutput->connector_type];
+    else
+        output_name = "UNKNOWN";
+    snprintf (name, 32, "%s%d", output_name, koutput->connector_type_id);
+
+    pOutput = xf86OutputCreate (pScrn, &sec_output_funcs, name);
+    if (!pOutput)
+    {
+        drmModeFreeEncoder (kencoder);
+        drmModeFreeConnector (koutput);
+        return;
+    }
+
+    pOutputPriv = calloc (sizeof (SECOutputPrivRec), 1);
+    if (!pOutputPriv)
+    {
+        xf86OutputDestroy (pOutput);
+        drmModeFreeConnector (koutput);
+        drmModeFreeEncoder (kencoder);
+        return;
+    }
+
+    pOutputPriv->output_id = pSecMode->mode_res->connectors[num];
+    pOutputPriv->mode_output = koutput;
+    pOutputPriv->mode_encoder = kencoder;
+    pOutputPriv->pSecMode = pSecMode;
+
+    pOutput->mm_width = koutput->mmWidth;
+    pOutput->mm_height = koutput->mmHeight;
+
+    pOutput->subpixel_order = subpixel_conv_table[koutput->subpixel];
+    pOutput->driver_private = pOutputPriv;
+
+    pOutput->possible_crtcs = kencoder->possible_crtcs;
+    pOutput->possible_clones = kencoder->possible_clones;
+    pOutput->interlaceAllowed = TRUE;
+
+    pOutputPriv->pOutput = pOutput;
+    /* TODO : soolim : management crtc privates */
+    xorg_list_add(&pOutputPriv->link, &pSecMode->outputs);
+}
+
+int
+secOutputDpmsStatus(xf86OutputPtr pOutput)
+{
+    SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+    return pOutputPriv->dpms_mode;
+}
+
+void
+secOutputDpmsSet(xf86OutputPtr pOutput, int mode)
+{
+    SECOutputDpms(pOutput, mode);
+}
+
+SECOutputPrivPtr
+secOutputGetPrivateForConnType (ScrnInfoPtr pScrn, int connect_type)
+{
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+    int i;
+
+    for (i = 0; i < pSecMode->mode_res->count_connectors; i++)
+    {
+        SECOutputPrivPtr pCur, pNext;
+
+        xorg_list_for_each_entry_safe (pCur, pNext, &pSecMode->outputs, link)
+        {
+            drmModeConnectorPtr koutput = pCur->mode_output;
+
+            if (koutput && koutput->connector_type == connect_type)
+                return pCur;
+        }
+    }
+
+    XDBG_ERROR (MSEC, "no output for connect_type(%d) \n", connect_type);
+
+    return NULL;
+}
diff --git a/src/crtcconfig/sec_output.h b/src/crtcconfig/sec_output.h
new file mode 100644 (file)
index 0000000..7b9b107
--- /dev/null
@@ -0,0 +1,65 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_OUTPUT_H__
+#define __SEC_OUTPUT_H__
+
+#include "sec_display.h"
+
+typedef struct _secOutputPriv
+{
+    SECModePtr pSecMode;
+    int output_id;
+    drmModeConnectorPtr mode_output;
+    drmModeEncoderPtr mode_encoder;
+    int num_props;
+    SECPropertyPtr props;
+    void *private_data;
+
+    Bool isLcdOff;
+    int dpms_mode;
+
+    int disp_mode;
+
+    xf86OutputPtr pOutput;
+    struct xorg_list link;
+} SECOutputPrivRec, *SECOutputPrivPtr;
+
+
+void    secOutputInit       (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num);
+int     secOutputDpmsStatus (xf86OutputPtr pOutput);
+void    secOutputDpmsSet    (xf86OutputPtr pOutput, int mode);
+
+Bool    secOutputDrmUpdate  (ScrnInfoPtr pScrn);
+
+SECOutputPrivPtr secOutputGetPrivateForConnType (ScrnInfoPtr pScrn, int connect_type);
+
+#endif /* __SEC_OUTPUT_H__ */
+
diff --git a/src/crtcconfig/sec_plane.c b/src/crtcconfig/sec_plane.c
new file mode 100644 (file)
index 0000000..41384a6
--- /dev/null
@@ -0,0 +1,1334 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/ioctl.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <poll.h>
+
+#include <xorgVersion.h>
+#include <tbm_bufmgr.h>
+#include <xf86Crtc.h>
+#include <xf86DDC.h>
+#include <xf86cmap.h>
+#include <list.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/dpmsconst.h>
+#include <sec.h>
+#include <exynos_drm.h>
+
+#include "sec_crtc.h"
+#include "sec_output.h"
+#include "sec_util.h"
+#include "sec_video_fourcc.h"
+#include "sec_plane.h"
+#include "fimg2d.h"
+
+/* HW restriction */
+#define MIN_WIDTH   32
+
+enum
+{
+    PLANE_FB_TYPE_NONE,
+    PLANE_FB_TYPE_DEFAULT,
+    PLANE_FB_TYPE_BO,
+    PLANE_FB_TYPE_MAX
+};
+
+typedef struct _SECPlaneAccess
+{
+    unsigned int fb_id;
+
+    tbm_bo bo;
+
+    int width;
+    int height;
+
+    xRectangle src;
+    xRectangle dst;
+} SECPlaneAccess;
+
+/* This is structure to manage a added buffer. */
+typedef struct _SECPlaneFb
+{
+    unsigned int id;
+
+    int type;
+    union
+    {
+        /* for framebuffer */
+        tbm_bo       bo;
+        SECVideoBuf *vbuf;
+    } buffer;
+
+    int width;
+    int height;
+
+    Bool buffer_gone;
+
+    struct xorg_list link;
+} SECPlaneFb;
+
+typedef struct _SECPlaneTable
+{
+    SECPlanePrivPtr pPlanePriv;
+    int plane_id;
+
+    /* buffers which this plane has */
+    struct xorg_list  fbs;
+    SECPlaneFb  *cur_fb;
+
+    /* visibilitiy information */
+    Bool visible;
+    int  crtc_id;
+    int  zpos;
+    xRectangle src;
+    xRectangle dst;
+    int  conn_type;
+
+    Bool onoff;
+    Bool in_use;
+    Bool freeze_update;
+
+    /* accessibility */
+    SECPlaneAccess *access;
+} SECPlaneTable;
+
+/* table of planes which system has entirely */
+static SECPlaneTable *plane_table;
+static int plane_table_size;
+
+static SECPlaneTable* _secPlaneTableFind (int plane_id);
+static SECPlaneFb* _secPlaneTableFindBuffer (SECPlaneTable *table, int fb_id,
+                                             tbm_bo bo, SECVideoBuf *vbuf);
+static Bool _secPlaneHideInternal (SECPlaneTable *table);
+
+static void
+_secPlaneFreeVbuf (SECVideoBuf *vbuf, void *data)
+{
+    int plane_id = (int)data;
+    SECPlaneTable *table;
+    SECPlaneFb *fb;
+
+    table = _secPlaneTableFind (plane_id);
+    XDBG_RETURN_IF_FAIL (table != NULL);
+
+    fb = _secPlaneTableFindBuffer (table, vbuf->fb_id, NULL, NULL);
+    XDBG_RETURN_IF_FAIL (fb != NULL);
+
+    fb->buffer_gone = TRUE;
+    secPlaneRemoveBuffer (plane_id, vbuf->fb_id);
+}
+
+static SECPlaneTable*
+_secPlaneTableFindPos (int crtc_id, int zpos)
+{
+    int i;
+
+    XDBG_RETURN_VAL_IF_FAIL (crtc_id > 0, NULL);
+
+    for (i = 0; i < plane_table_size; i++)
+        if (plane_table[i].crtc_id == crtc_id && plane_table[i].zpos == zpos)
+            return &plane_table[i];
+
+    return NULL;
+}
+
+static SECPlaneTable*
+_secPlaneTableFind (int plane_id)
+{
+    int i;
+
+    XDBG_RETURN_VAL_IF_FAIL (plane_id > 0, NULL);
+
+    for (i = 0; i < plane_table_size; i++)
+        if (plane_table[i].plane_id == plane_id)
+            return &plane_table[i];
+
+    XDBG_TRACE (MPLN, "plane(%d) not found. \n", plane_id);
+
+    return NULL;
+}
+
+static SECPlaneTable*
+_secPlaneTableFindEmpty (void)
+{
+    int i;
+
+    for (i = 0; i < plane_table_size; i++)
+        if (!plane_table[i].in_use)
+            return &plane_table[i];
+
+    return NULL;
+}
+
+static SECPlaneFb*
+_secPlaneTableFindBuffer (SECPlaneTable *table,
+                          int fb_id,
+                          tbm_bo bo,
+                          SECVideoBuf *vbuf)
+{
+    SECPlaneFb *fb = NULL, *fb_next = NULL;
+
+    xorg_list_for_each_entry_safe (fb, fb_next, &table->fbs, link)
+    {
+        if (fb_id > 0)
+        {
+            if (fb->id == fb_id)
+                return fb;
+        }
+        else if (bo)
+        {
+            if (fb->type == PLANE_FB_TYPE_BO && fb->buffer.bo == bo)
+                return fb;
+        }
+        else if (vbuf)
+        {
+            XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), NULL);
+
+            if (fb->type == PLANE_FB_TYPE_DEFAULT)
+                if (fb->buffer.vbuf == vbuf && fb->buffer.vbuf->stamp == vbuf->stamp)
+                    return fb;
+        }
+    }
+
+    return NULL;
+}
+
+static void
+_secPlaneTableFreeBuffer (SECPlaneTable *table, SECPlaneFb *fb)
+{
+    if (table->cur_fb == fb)
+        return;
+
+    if (fb->type == PLANE_FB_TYPE_BO)
+    {
+        if (fb->buffer.bo)
+            tbm_bo_unref (fb->buffer.bo);
+    }
+    else
+    {
+        if (!fb->buffer_gone && fb->buffer.vbuf)
+            secUtilRemoveFreeVideoBufferFunc (fb->buffer.vbuf, _secPlaneFreeVbuf,
+                                              (void*)table->plane_id);
+    }
+
+    xorg_list_del (&fb->link);
+
+    free (fb);
+}
+
+static Bool
+_secPlaneTableEnsure (ScrnInfoPtr pScrn, int count_planes)
+{
+    int i;
+
+    XDBG_RETURN_VAL_IF_FAIL (count_planes > 0, FALSE);
+
+    if (plane_table)
+    {
+        if (plane_table_size != count_planes)
+            XDBG_WARNING (MPLN, "%d != %d, need to re-create! \n",
+                          plane_table_size, count_planes);
+        return TRUE;
+    }
+
+    plane_table = calloc (sizeof (SECPlaneTable), count_planes);
+    XDBG_RETURN_VAL_IF_FAIL (plane_table != NULL, FALSE);
+
+    plane_table_size = count_planes;
+
+    for (i = 0; i < plane_table_size; i++)
+    {
+        SECPlaneTable *table = &plane_table[i];
+        table->plane_id = -1;
+        table->onoff = TRUE;
+    }
+
+    return TRUE;
+}
+
+static void
+_secPlaneExecAccessibility (tbm_bo src_bo, int sw, int sh, xRectangle *sr,
+                            tbm_bo dst_bo, int dw, int dh, xRectangle *dr,
+                            Bool bNegative)
+{
+    G2dImage *srcImg = NULL, *dstImg = NULL;
+    tbm_bo_handle src_bo_handle = {0,};
+    tbm_bo_handle dst_bo_handle = {0,};
+    G2dColorKeyMode mode;
+
+    mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+    src_bo_handle = tbm_bo_map (src_bo, TBM_DEVICE_2D, TBM_OPTION_READ);
+    XDBG_GOTO_IF_FAIL (src_bo_handle.s32 > 0, access_done);
+
+    dst_bo_handle = tbm_bo_map (dst_bo, TBM_DEVICE_2D, TBM_OPTION_WRITE);
+    XDBG_GOTO_IF_FAIL (dst_bo_handle.s32 > 0, access_done);
+
+    srcImg = g2d_image_create_bo (mode, sw, sh, src_bo_handle.s32, sw * 4);
+    XDBG_GOTO_IF_FAIL (srcImg != NULL, access_done);
+
+    dstImg = g2d_image_create_bo (mode, dw, dh, dst_bo_handle.s32, dw * 4);
+    XDBG_GOTO_IF_FAIL (dstImg != NULL, access_done);
+
+    util_g2d_copy_with_scale (srcImg, dstImg,
+                              (int)sr->x, (int)sr->y, sr->width, sr->height,
+                              (int)dr->x, (int)dr->y, dr->width, dr->height,
+                              (int)bNegative);
+    g2d_exec ();
+
+access_done:
+    if (src_bo_handle.s32)
+        tbm_bo_unmap (src_bo);
+    if (dst_bo_handle.s32)
+        tbm_bo_unmap (dst_bo);
+    if (srcImg)
+        g2d_image_free (srcImg);
+    if (dstImg)
+        g2d_image_free (dstImg);
+}
+
+static Bool
+_check_hw_restriction (ScrnInfoPtr pScrn, int crtc_id, int buf_w,
+                       int src_x, int src_w, int dst_x, int dst_w,
+                       int *new_src_x, int *new_src_w,
+                       int *new_dst_x, int *new_dst_w)
+{
+    SECOutputPrivPtr pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_LVDS);
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+    int max = pSecMode->main_lcd_mode.hdisplay;
+    int start, end, diff;
+    Bool virtual_screen;
+
+    XDBG_RETURN_VAL_IF_FAIL (pOutputPriv != NULL, FALSE);
+
+    if (pOutputPriv->mode_encoder->crtc_id != crtc_id)
+        return TRUE;
+
+    if (buf_w < MIN_WIDTH || buf_w % 2)
+    {
+        XDBG_TRACE (MPLN, "hide: buf_w(%d) not 2's multiple or less than %d\n",
+                    buf_w, MIN_WIDTH);
+        return FALSE;
+    }
+
+    if (src_x > dst_x || ((dst_x - src_x) + buf_w) > max)
+        virtual_screen = TRUE;
+    else
+        virtual_screen = FALSE;
+
+    start = (dst_x < 0) ? 0 : dst_x;
+    end = ((dst_x + dst_w) > max) ? max : (dst_x + dst_w);
+
+    /* check window minimun width */
+    if ((end - start) < MIN_WIDTH)
+    {
+        XDBG_TRACE (MPLN, "hide: %d than min size: buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)\n",
+                    end-start, buf_w, src_x, src_w, dst_x, dst_w,
+                    virtual_screen, start, end);
+        return FALSE;
+    }
+
+    XDBG_DEBUG (MPLN, "buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)\n",
+                buf_w, src_x, src_w, dst_x, dst_w, virtual_screen, start, end);
+
+    if (!virtual_screen)
+    {
+        /* Pagewidth of window (= 8 byte align / bytes-per-pixel ) */
+        if ((end - start) % 2)
+            end--;
+    }
+    else
+    {
+        /* You should align the sum of PAGEWIDTH_F and OFFSIZE_F double-word (8 byte) boundary. */
+        if (end % 2)
+            end--;
+    }
+
+    *new_dst_x = start;
+    *new_dst_w = end - start;
+    *new_src_w = *new_dst_w;
+    diff = start - dst_x;
+    *new_src_x += diff;
+
+    XDBG_RETURN_VAL_IF_FAIL (*new_src_w > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (*new_dst_w > 0, FALSE);
+
+    if (src_x != *new_src_x || src_w != *new_src_w ||
+        dst_x != *new_dst_x || dst_w != *new_dst_w)
+        XDBG_TRACE (MPLN, " => buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)\n",
+                    buf_w, *new_src_x, *new_src_w, *new_dst_x, *new_dst_w, virtual_screen, start, end);
+
+    return TRUE;
+}
+
+static Bool
+_secPlaneShowInternal (SECPlaneTable *table,
+                       SECPlaneFb *old_fb, SECPlaneFb *new_fb,
+                       xRectangle *new_src, xRectangle *new_dst, int new_zpos,
+                       Bool need_set_plane)
+{
+    SECPtr pSec;
+    SECModePtr pSecMode;
+    xRectangle old_src = table->src;
+    xRectangle old_dst = table->dst;
+    int old_zpos = table->zpos;
+    Bool change_zpos = FALSE;
+    tbm_bo_handle bo_handle;
+
+    pSec = SECPTR (table->pPlanePriv->pScrn);
+    pSecMode = table->pPlanePriv->pSecMode;
+
+    if (pSec->isLcdOff)
+    {
+        XDBG_TRACE (MPLN, "lcd off, can't show : plane(%d) crtc(%d) pos(%d). \n",
+                    table->plane_id, table->crtc_id, new_zpos);
+        return FALSE;
+    }
+
+    if (!table->onoff)
+    {
+        XDBG_TRACE (MPLN, "plane off, can't show : plane(%d) crtc(%d) pos(%d). \n",
+                    table->plane_id, table->crtc_id, new_zpos);
+        return FALSE;
+    }
+
+    /* should set zpos before doing drmModeSetPlane */
+    if (new_zpos != old_zpos)
+    {
+        if (!secUtilSetDrmProperty (pSecMode, table->plane_id, DRM_MODE_OBJECT_PLANE,
+                                    "zpos", new_zpos))
+            return FALSE;
+
+        table->zpos = new_zpos;
+        change_zpos = TRUE;
+
+        XDBG_TRACE (MPLN, "plane(%d) => crtc(%d) zpos(%d)\n",
+                    table->plane_id, table->crtc_id, table->zpos);
+    }
+
+    if (!table->visible || need_set_plane ||
+        change_zpos ||
+        (!old_fb || (old_fb != new_fb)) ||
+        (memcmp (&old_src, new_src, sizeof (xRectangle))) ||
+        (memcmp (&old_dst, new_dst, sizeof (xRectangle))))
+    {
+        xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (table->pPlanePriv->pScrn);
+        SECCrtcPrivPtr pCrtcPriv = NULL;
+        int c;
+
+        for (c = 0; c < pCrtcConfig->num_crtc; c++)
+        {
+            xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c];
+            SECCrtcPrivPtr pTemp =  pCrtc->driver_private;
+            if (pTemp->mode_crtc && pTemp->mode_crtc->crtc_id == table->crtc_id)
+            {
+                pCrtcPriv = pTemp;
+                break;
+            }
+        }
+
+        XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv != NULL, FALSE);
+
+        XDBG_TRACE (MPLN, "plane(%d) => crtc(%d) fb(%d) (%d,%d %dx%d) => (%d,%d %dx%d) [%d,%d,%c%c%c%c]\n",
+                    table->plane_id, table->crtc_id, new_fb->id,
+                    new_src->x, new_src->y, new_src->width, new_src->height,
+                    new_dst->x, new_dst->y, new_dst->width, new_dst->height,
+                    pCrtcPriv->bAccessibility, new_fb->type,
+                    FOURCC_STR (new_fb->buffer.vbuf->id));
+
+        if (!pCrtcPriv->bAccessibility ||
+            (new_fb->type == PLANE_FB_TYPE_DEFAULT && new_fb->buffer.vbuf->id != FOURCC_RGB32))
+        {
+            int aligned_src_x = new_src->x;
+            int aligned_src_w = new_src->width;
+            int aligned_dst_x = new_dst->x;
+            int aligned_dst_w = new_dst->width;
+
+            if (!_check_hw_restriction (table->pPlanePriv->pScrn, table->crtc_id,
+                                        table->cur_fb->width,
+                                        new_src->x, new_src->width,
+                                        new_dst->x, new_dst->width,
+                                        &aligned_src_x, &aligned_src_w,
+                                        &aligned_dst_x, &aligned_dst_w))
+            {
+                XDBG_TRACE (MPLN, "out of range: plane(%d) crtc(%d) pos(%d) crtc(%d,%d %dx%d). \n",
+                            table->plane_id, table->crtc_id, new_zpos,
+                            aligned_dst_x, new_dst->y, aligned_dst_w, new_dst->height);
+
+                _secPlaneHideInternal (table);
+
+                return TRUE;
+            }
+
+            /* Source values are 16.16 fixed point */
+            uint32_t fixed_x = ((unsigned int)aligned_src_x) << 16;
+            uint32_t fixed_y = ((unsigned int)new_src->y) << 16;
+            uint32_t fixed_w = ((unsigned int)aligned_src_w) << 16;
+            uint32_t fixed_h = ((unsigned int)new_src->height) << 16;
+
+            if (drmModeSetPlane (pSecMode->fd, table->plane_id, table->crtc_id,
+                                 new_fb->id, 0,
+                                 aligned_dst_x, new_dst->y,
+                                 aligned_dst_w, new_dst->height,
+                                 fixed_x, fixed_y,
+                                 fixed_w, fixed_h))
+            {
+                XDBG_ERRNO (MPLN, "drmModeSetPlane failed. plane(%d) crtc(%d) pos(%d) on: fb(%d,%c%c%c%c,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
+                            table->plane_id, table->crtc_id, table->zpos,
+                            new_fb->id, FOURCC_STR (new_fb->buffer.vbuf->id),
+                            new_fb->buffer.vbuf->width, new_fb->buffer.vbuf->height,
+                            aligned_src_x, new_src->y, aligned_src_w, new_src->height,
+                            aligned_dst_x, new_dst->y, aligned_dst_w, new_dst->height);
+
+                return FALSE;
+            }
+
+            if (!table->visible)
+            {
+                XDBG_SECURE (MPLN, "plane(%d) crtc(%d) pos(%d) on: fb(%d,%c%c%c%c,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
+                             table->plane_id, table->crtc_id, table->zpos,
+                             new_fb->id, FOURCC_STR (new_fb->buffer.vbuf->id),
+                             new_fb->buffer.vbuf->width, new_fb->buffer.vbuf->height,
+                             aligned_src_x, new_src->y, aligned_src_w, new_src->height,
+                             aligned_dst_x, new_dst->y, aligned_dst_w, new_dst->height);
+                table->visible = TRUE;
+            }
+        }
+        else
+        {
+            SECPlaneAccess *access;
+            xRectangle fb_src = {0,};
+            tbm_bo src_bo;
+            int old_w = 0, old_h = 0;
+
+            if (!table->access)
+            {
+                table->access = calloc (1, sizeof (SECPlaneAccess));
+                XDBG_RETURN_VAL_IF_FAIL (table->access != NULL, FALSE);
+            }
+            else
+            {
+                old_w = table->access->width;
+                old_h = table->access->height;
+            }
+
+            access = table->access;
+
+            if (pCrtcPriv->bScale)
+            {
+                float h_ratio = 0.0, v_ratio = 0.0;
+                xRectangle crop;
+
+                h_ratio = (float)pCrtcPriv->kmode.hdisplay / pCrtcPriv->sw;
+                v_ratio = (float)pCrtcPriv->kmode.vdisplay / pCrtcPriv->sh;
+
+                fb_src.x = new_src->x;
+                fb_src.y = new_src->y;
+                fb_src.width = new_src->width;
+                fb_src.height = new_src->height;
+
+                CLEAR (crop);
+                crop.x = pCrtcPriv->sx;
+                crop.y = pCrtcPriv->sy;
+                crop.width = pCrtcPriv->sw;
+                crop.height = pCrtcPriv->sh;
+
+                crop.x -= new_dst->x;
+                crop.y -= new_dst->y;
+                crop.x += new_src->x;
+                crop.y += new_src->y;
+                secUtilRectIntersect (&fb_src, &fb_src, &crop);
+
+                access->dst = *new_dst;
+
+                access->dst.x = new_dst->x;
+                access->dst.y = new_dst->y;
+                access->dst.width = new_dst->width;
+                access->dst.height = new_dst->height;
+
+                CLEAR (crop);
+                crop.x = pCrtcPriv->sx;
+                crop.y = pCrtcPriv->sy;
+                crop.width = pCrtcPriv->sw;
+                crop.height = pCrtcPriv->sh;
+                secUtilRectIntersect (&access->dst, &access->dst, &crop);
+
+                access->dst.x -= pCrtcPriv->sx;
+                access->dst.y -= pCrtcPriv->sy;
+
+                access->dst.x *= h_ratio;
+                access->dst.y *= v_ratio;
+                access->dst.width *= h_ratio;
+                access->dst.height *= v_ratio;
+
+                access->width = pCrtcPriv->kmode.hdisplay;
+                access->height = pCrtcPriv->kmode.vdisplay;
+
+                access->src.x = 0;
+                access->src.y = 0;
+                access->src.width = access->dst.width;
+                access->src.height = access->dst.height;
+            }
+            else
+            {
+                fb_src.x = new_src->x;
+                fb_src.y = new_src->y;
+                fb_src.width = new_src->width;
+                fb_src.height = new_src->height;
+
+                /* hw restriction: 8 bytes */
+                new_dst->width &= ~1;
+
+                access->dst.x = new_dst->x;
+                access->dst.y = new_dst->y;
+                access->dst.width = new_dst->width;
+                access->dst.height = new_dst->height;
+
+                access->width = access->dst.width;
+                access->height = access->dst.height;
+
+                access->src.x = 0;
+                access->src.y = 0;
+                access->src.width = access->dst.width;
+                access->src.height = access->dst.height;
+            }
+
+            XDBG_DEBUG (MPLN, "access : accessibility_status(%d) scale(%d) bo(%p) fb(%d) (%d,%d %dx%d) (%dx%d) (%d,%d %dx%d) (%d,%d %dx%d).\n",
+                        pCrtcPriv->accessibility_status, pCrtcPriv->bScale,
+                        access->bo, access->fb_id,
+                        fb_src.x, fb_src.y, fb_src.width, fb_src.height,
+                        access->width, access->height,
+                        access->src.x, access->src.y, access->src.width, access->src.height,
+                        access->dst.x, access->dst.y, access->dst.width, access->dst.height);
+
+            if (!fb_src.width || !fb_src.height ||
+                !access->width || !access->height ||
+                !access->dst.width || !access->dst.height)
+            {
+                _secPlaneHideInternal (table);
+
+                return TRUE;
+            }
+
+            if (access->bo)
+            {
+                if (old_w != access->width || old_h != access->height)
+                {
+                    if (table->access->fb_id)
+                    {
+                        drmModeRmFB (pSecMode->fd, table->access->fb_id);
+                        table->access->fb_id = 0;
+                    }
+
+                    tbm_bo_unref (table->access->bo);
+                    table->access->bo = NULL;
+                }
+            }
+
+            if (!access->bo)
+            {
+                access->bo = tbm_bo_alloc (pSec->tbm_bufmgr,
+                                               access->width * access->height * 4,
+                                               TBM_BO_NONCACHABLE);
+                XDBG_RETURN_VAL_IF_FAIL (access->bo != NULL, FALSE);
+
+                bo_handle = tbm_bo_get_handle (access->bo, TBM_DEVICE_DEFAULT);
+                if (drmModeAddFB (pSecMode->fd, access->width, access->height,
+                                  table->pPlanePriv->pScrn->depth,
+                                  table->pPlanePriv->pScrn->bitsPerPixel,
+                                  access->width * 4,
+                                  bo_handle.u32,
+                                  &access->fb_id))
+                {
+                    XDBG_ERRNO (MPLN, "drmModeAddFB failed. plane(%d)\n", table->plane_id);
+                    return FALSE;
+                }
+
+                XDBG_RETURN_VAL_IF_FAIL (access->fb_id > 0, FALSE);
+            }
+
+            if (new_fb->type == PLANE_FB_TYPE_DEFAULT)
+                src_bo = new_fb->buffer.vbuf->bo[0];
+            else
+                src_bo = new_fb->buffer.bo;
+            XDBG_RETURN_VAL_IF_FAIL (src_bo != NULL, FALSE);
+
+            _secPlaneExecAccessibility (src_bo, new_fb->width, new_fb->height, &fb_src,
+                                        access->bo, access->width, access->height, &access->src,
+                                        pCrtcPriv->accessibility_status);
+
+            int aligned_src_x = access->src.x;
+            int aligned_src_w = access->src.width;
+            int aligned_dst_x = access->dst.x;
+            int aligned_dst_w = access->dst.width;
+
+            if (!_check_hw_restriction (table->pPlanePriv->pScrn, table->crtc_id,
+                                        access->width,
+                                        access->src.x, access->src.width,
+                                        access->dst.x, access->dst.width,
+                                        &aligned_src_x, &aligned_src_w,
+                                        &aligned_dst_x, &aligned_dst_w))
+            {
+                XDBG_TRACE (MPLN, "out of range: plane(%d) crtc(%d) pos(%d) crtc(%d,%d %dx%d). \n",
+                            table->plane_id, table->crtc_id, new_zpos,
+                            aligned_dst_x, new_dst->y, aligned_dst_w, new_dst->height);
+
+                _secPlaneHideInternal (table);
+
+                return TRUE;
+            }
+
+            /* Source values are 16.16 fixed point */
+            uint32_t fixed_x = ((unsigned int)aligned_src_x) << 16;
+            uint32_t fixed_y = ((unsigned int)access->src.y) << 16;
+            uint32_t fixed_w = ((unsigned int)aligned_src_w) << 16;
+            uint32_t fixed_h = ((unsigned int)access->src.height) << 16;
+
+            if (drmModeSetPlane (pSecMode->fd, table->plane_id, table->crtc_id,
+                                 access->fb_id, 0,
+                                 aligned_dst_x, access->dst.y,
+                                 aligned_dst_w, access->dst.height,
+                                 fixed_x, fixed_y,
+                                 fixed_w, fixed_h))
+            {
+                XDBG_ERRNO (MPLN, "drmModeSetPlane failed. \n");
+
+                return FALSE;
+            }
+
+            if (!table->visible)
+            {
+                XDBG_SECURE (MPLN, "plane(%d) crtc(%d) pos(%d) on: access_fb(%d,%dx%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
+                             table->plane_id, table->crtc_id, table->zpos,
+                             access->fb_id, access->width, access->height,
+                             aligned_src_x, access->src.y, aligned_src_w, access->src.height,
+                             aligned_dst_x, access->dst.y, aligned_dst_w, access->dst.height);
+
+                table->visible = TRUE;
+            }
+        }
+
+        memcpy (&table->src, new_src, sizeof (xRectangle));
+        memcpy (&table->dst, new_dst, sizeof (xRectangle));
+    }
+
+    return TRUE;
+}
+
+static Bool
+_secPlaneHideInternal (SECPlaneTable *table)
+{
+    SECPtr pSec;
+    SECModePtr pSecMode;
+
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
+
+    if (!table->visible)
+        return TRUE;
+
+    XDBG_RETURN_VAL_IF_FAIL (table->crtc_id > 0, FALSE);
+
+    pSec = SECPTR (table->pPlanePriv->pScrn);
+    pSecMode = table->pPlanePriv->pSecMode;
+
+    if (!pSec->isLcdOff && table->onoff)
+    {
+        if (drmModeSetPlane (pSecMode->fd,
+                             table->plane_id,
+                             table->crtc_id,
+                             0, 0,
+                             0, 0, 0, 0, 0, 0, 0, 0))
+        {
+            XDBG_ERRNO (MPLN, "drmModeSetPlane failed. plane(%d) crtc(%d) zpos(%d) fb(%d)\n",
+                        table->plane_id, table->crtc_id, table->zpos, table->cur_fb->id);
+
+            return FALSE;
+        }
+    }
+
+    if (table->visible)
+    {
+        XDBG_SECURE (MPLN, "plane(%d) crtc(%d) zpos(%d) off. lcd(%s) onoff(%d)\n",
+                     table->plane_id, table->crtc_id, table->zpos,
+                     (pSec->isLcdOff)?"off":"on", table->onoff);
+        table->visible = FALSE;
+    }
+
+    XDBG_TRACE (MPLN, "plane(%d) fb(%d) removed from crtc(%d) zpos(%d). LCD(%s) ONOFF(%s).\n",
+                table->plane_id, table->cur_fb->id, table->crtc_id, table->zpos,
+                (pSec->isLcdOff)?"OFF":"ON", (table->onoff)?"ON":"OFF");
+
+    return TRUE;
+
+}
+
+void
+secPlaneInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num)
+{
+    SECPlanePrivPtr pPlanePriv;
+
+    XDBG_RETURN_IF_FAIL (pScrn != NULL);
+    XDBG_RETURN_IF_FAIL (pSecMode != NULL);
+    XDBG_RETURN_IF_FAIL (pSecMode->plane_res != NULL);
+    XDBG_RETURN_IF_FAIL (pSecMode->plane_res->count_planes > 0);
+
+    if (!_secPlaneTableEnsure (pScrn, pSecMode->plane_res->count_planes))
+        return;
+
+    pPlanePriv = calloc (sizeof (SECPlanePrivRec), 1);
+    XDBG_RETURN_IF_FAIL (pPlanePriv != NULL);
+
+    pPlanePriv->mode_plane = drmModeGetPlane (pSecMode->fd,
+                             pSecMode->plane_res->planes[num]);
+    if (!pPlanePriv->mode_plane)
+    {
+        XDBG_ERRNO (MPLN, "drmModeGetPlane failed. plane(%d)\n",
+                    pSecMode->plane_res->planes[num]);
+
+        free (pPlanePriv);
+        return;
+    }
+
+    pPlanePriv->pScrn = pScrn;
+    pPlanePriv->pSecMode = pSecMode;
+    pPlanePriv->plane_id = pPlanePriv->mode_plane->plane_id;
+
+    plane_table[num].plane_id = pPlanePriv->plane_id;
+    plane_table[num].pPlanePriv = pPlanePriv;
+    xorg_list_init (&plane_table[num].fbs);
+
+    xorg_list_add(&pPlanePriv->link, &pSecMode->planes);
+}
+
+void
+secPlaneDeinit (ScrnInfoPtr pScrn, SECPlanePrivPtr pPlanePriv)
+{
+    int i;
+
+    XDBG_RETURN_IF_FAIL (pScrn != NULL);
+    XDBG_RETURN_IF_FAIL (pPlanePriv != NULL);
+
+    secPlaneFreeId (pPlanePriv->plane_id);
+    drmModeFreePlane (pPlanePriv->mode_plane);
+    xorg_list_del (&pPlanePriv->link);
+
+    for (i = 0; i < plane_table_size; i++)
+        if (plane_table[i].plane_id == pPlanePriv->plane_id)
+        {
+            plane_table[i].plane_id = -1;
+            break;
+        }
+
+    free (pPlanePriv);
+
+    if (plane_table)
+    {
+        for (i = 0; i < plane_table_size; i++)
+            if (plane_table[i].plane_id != -1)
+                return;
+
+        free (plane_table);
+        plane_table = NULL;
+        plane_table_size = 0;
+        XDBG_TRACE (MPLN, "plane_table destroyed. %d\n", plane_table_size);
+    }
+}
+
+void
+secPlaneShowAll (int crtc_id)
+{
+    int i;
+
+    XDBG_TRACE (MPLN, "crtc(%d) \n", crtc_id);
+
+    for (i = 0; i < plane_table_size; i++)
+    {
+        SECPlaneTable *table = &plane_table[i];
+
+        if (!table || !table->in_use || !table->visible || !table->onoff)
+            continue;
+
+        if (table->crtc_id != crtc_id)
+            continue;
+
+        if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
+                                    &table->src, &table->dst, table->zpos, TRUE))
+
+        {
+            XDBG_WARNING (MPLN, "_secPlaneShowInternal failed. \n");
+        }
+
+        XDBG_TRACE (MPLN, "plane(%d) crtc(%d) zpos(%d) on.\n",
+                    table->plane_id, table->crtc_id, table->zpos);
+    }
+}
+
+int
+secPlaneGetID (void)
+{
+    SECPlaneTable *table = _secPlaneTableFindEmpty ();
+
+    if (!table)
+    {
+        XDBG_ERROR (MPLN, "No avaliable plane ID. %d\n", -1);
+        return -1;
+    }
+
+    table->in_use = TRUE;
+    table->onoff = TRUE;
+
+    XDBG_TRACE (MPLN, "plane(%d). \n", table->plane_id);
+
+    return table->plane_id;
+}
+
+void
+secPlaneFreeId (int plane_id)
+{
+    SECPlaneTable *table = _secPlaneTableFind (plane_id);
+    SECPlaneFb *fb = NULL, *fb_next = NULL;
+
+    XDBG_RETURN_IF_FAIL (table != NULL);
+
+    secPlaneHide (table->plane_id);
+
+    table->visible = FALSE;
+    table->crtc_id = 0;
+
+    table->zpos = 0;
+    memset (&table->src, 0x00, sizeof (xRectangle));
+    memset (&table->dst, 0x00, sizeof (xRectangle));
+
+    table->cur_fb = NULL;
+    xorg_list_for_each_entry_safe (fb, fb_next, &table->fbs, link)
+    {
+        _secPlaneTableFreeBuffer (table, fb);
+    }
+
+    if (table->access)
+    {
+        if (table->access->fb_id)
+        {
+            SECModePtr pSecMode = table->pPlanePriv->pSecMode;
+            if (pSecMode)
+                drmModeRmFB (pSecMode->fd, table->access->fb_id);
+        }
+
+        if (table->access->bo)
+            tbm_bo_unref (table->access->bo);
+
+        free (table->access);
+        table->access = NULL;
+    }
+
+    table->in_use = FALSE;
+    table->onoff = TRUE;
+
+    XDBG_TRACE (MPLN, "plane(%d).\n", table->plane_id);
+}
+
+Bool
+secPlaneTrun (int plane_id, Bool onoff, Bool user)
+{
+    SECPlaneTable *table = _secPlaneTableFind (plane_id);
+    SECPtr pSec;
+
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
+
+    pSec = SECPTR (table->pPlanePriv->pScrn);
+
+    if (pSec->isLcdOff)
+        return TRUE;
+
+    onoff = (onoff > 0) ? TRUE : FALSE;
+
+    if (table->onoff == onoff)
+        return TRUE;
+
+    if (onoff)
+    {
+        table->onoff = onoff;
+
+        if (!table->visible)
+        {
+            if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
+                                        &table->src, &table->dst, table->zpos, TRUE))
+
+            {
+                XDBG_WARNING (MPLN, "_secPlaneShowInternal failed. \n");
+            }
+
+            XDBG_DEBUG (MPLN, "%s >> plane(%d,%d,%d) '%s'. \n", (user)?"user":"Xorg",
+                        plane_id, table->crtc_id, table->zpos, (onoff)?"ON":"OFF");
+        }
+    }
+    else
+    {
+        if (table->visible)
+        {
+            if (!_secPlaneHideInternal (table))
+
+            {
+                XDBG_WARNING (MPLN, "_secPlaneHideInternal failed. \n");
+            }
+
+            XDBG_DEBUG (MPLN, "%s >> plane(%d,%d,%d) '%s'. \n", (user)?"user":"Xorg",
+                        plane_id, table->crtc_id, table->zpos, (onoff)?"ON":"OFF");
+        }
+
+        table->onoff = onoff;
+    }
+
+    return TRUE;
+}
+
+Bool
+secPlaneTrunStatus (int plane_id)
+{
+    SECPlaneTable *table = _secPlaneTableFind (plane_id);
+
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
+
+    return table->onoff;
+}
+
+void
+secPlaneFreezeUpdate (int plane_id, Bool enable)
+{
+    SECPlaneTable *table = _secPlaneTableFind (plane_id);
+
+    XDBG_RETURN_IF_FAIL (table != NULL);
+
+    table->freeze_update = enable;
+}
+
+Bool
+secPlaneRemoveBuffer (int plane_id, int fb_id)
+{
+    SECPlaneTable *table;
+    SECPlaneFb *fb;
+
+    XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, FALSE);
+
+    table = _secPlaneTableFind (plane_id);
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
+
+    fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (fb != NULL, FALSE);
+
+    _secPlaneTableFreeBuffer (table, fb);
+
+    XDBG_TRACE (MPLN, "plane(%d) fb(%d). \n", plane_id, fb_id);
+
+    return TRUE;
+}
+
+int
+secPlaneAddBo (int plane_id, tbm_bo bo)
+{
+    SECPlaneTable *table;
+    SECPlaneFb *fb;
+    int fb_id = 0;
+    SECFbBoDataPtr bo_data = NULL;
+    int width, height;
+
+    XDBG_RETURN_VAL_IF_FAIL (bo != NULL, 0);
+
+    table = _secPlaneTableFind (plane_id);
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0);
+
+    fb = _secPlaneTableFindBuffer (table, 0, bo, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (fb == NULL, 0);
+
+    tbm_bo_get_user_data (bo, TBM_BO_DATA_FB, (void**)&bo_data);
+    XDBG_RETURN_VAL_IF_FAIL (bo_data != NULL, 0);
+
+    fb_id = bo_data->fb_id;
+    width = bo_data->pos.x2 - bo_data->pos.x1;
+    height = bo_data->pos.y2 - bo_data->pos.y1;
+
+    XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, 0);
+    XDBG_RETURN_VAL_IF_FAIL (width > 0, 0);
+    XDBG_RETURN_VAL_IF_FAIL (height > 0, 0);
+
+    fb = calloc (1, sizeof (SECPlaneFb));
+    XDBG_RETURN_VAL_IF_FAIL (fb != NULL, 0);
+
+    xorg_list_add(&fb->link, &table->fbs);
+
+    fb->type = PLANE_FB_TYPE_BO;
+    fb->id = fb_id;
+    fb->width = width;
+    fb->height = height;
+
+    fb->buffer.bo = tbm_bo_ref (bo);
+
+    XDBG_TRACE (MPLN, "plane(%d) bo(%d,%dx%d)\n", plane_id,
+                fb_id, fb->width, fb->height);
+
+    return fb->id;
+}
+
+int
+secPlaneAddBuffer (int plane_id, SECVideoBuf *vbuf)
+{
+    SECPlaneTable *table;
+    SECPlaneFb *fb;
+
+    XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), 0);
+    XDBG_RETURN_VAL_IF_FAIL (vbuf->fb_id > 0, 0);
+    XDBG_RETURN_VAL_IF_FAIL (vbuf->width > 0, 0);
+    XDBG_RETURN_VAL_IF_FAIL (vbuf->height > 0, 0);
+
+    table = _secPlaneTableFind (plane_id);
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0);
+
+    fb = _secPlaneTableFindBuffer (table, 0, NULL, vbuf);
+    XDBG_RETURN_VAL_IF_FAIL (fb == NULL, 0);
+
+    fb = calloc (1, sizeof (SECPlaneFb));
+    XDBG_RETURN_VAL_IF_FAIL (fb != NULL, 0);
+
+    xorg_list_add(&fb->link, &table->fbs);
+
+    fb->type = PLANE_FB_TYPE_DEFAULT;
+    fb->id = vbuf->fb_id;
+    fb->width = vbuf->width;
+    fb->height = vbuf->height;
+
+    fb->buffer.vbuf = vbuf;
+
+    secUtilAddFreeVideoBufferFunc (vbuf, _secPlaneFreeVbuf, (void*)plane_id);
+
+    XDBG_TRACE (MPLN, "plane(%d) vbuf(%ld,%d,%dx%d)\n", plane_id,
+                vbuf->stamp, vbuf->fb_id, vbuf->width, vbuf->height);
+
+    return fb->id;
+}
+
+int
+secPlaneGetBuffer (int plane_id, tbm_bo bo, SECVideoBuf *vbuf)
+{
+    SECPlaneTable *table;
+    SECPlaneFb *fb;
+
+    table = _secPlaneTableFind (plane_id);
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, 0);
+
+    fb = _secPlaneTableFindBuffer (table, 0, bo, vbuf);
+    if (!fb)
+        return 0;
+
+    return fb->id;
+}
+
+void
+secPlaneGetBufferSize (int plane_id, int fb_id, int *width, int *height)
+{
+    SECPlaneTable *table;
+    SECPlaneFb *fb;
+
+    table = _secPlaneTableFind (plane_id);
+    XDBG_RETURN_IF_FAIL (table != NULL);
+
+    fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL);
+    XDBG_RETURN_IF_FAIL (fb != NULL);
+
+    if (width)
+        *width = fb->width;
+
+    if (height)
+        *height = fb->height;
+}
+
+Bool
+secPlaneAttach (int plane_id, int fb_id)
+{
+    SECPlaneTable *table = _secPlaneTableFind (plane_id);
+    SECPlaneFb *fb;
+
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, FALSE);
+
+    fb = _secPlaneTableFindBuffer (table, fb_id, NULL, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (fb != NULL, FALSE);
+
+    table->cur_fb = fb;
+
+    XDBG_DEBUG (MPLN, "plane(%d) fb(%d)\n", plane_id, fb_id);
+
+    return TRUE;
+}
+
+Bool
+secPlaneIsVisible (int plane_id)
+{
+    SECPlaneTable *table = _secPlaneTableFind (plane_id);
+
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
+
+    return table->visible;
+}
+
+Bool
+secPlaneShow (int plane_id, int crtc_id,
+              int src_x, int src_y, int src_w, int src_h,
+              int dst_x, int dst_y, int dst_w, int dst_h,
+              int zpos, Bool need_update)
+{
+    SECPlaneTable *table = _secPlaneTableFind (plane_id);
+    SECPlaneTable *temp;
+    xRectangle src = {src_x, src_y, src_w, src_h};
+    xRectangle dst = {dst_x, dst_y, dst_w, dst_h};
+
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (table->cur_fb != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (crtc_id > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (zpos >= 0, FALSE);
+
+    temp = _secPlaneTableFindPos (crtc_id, zpos);
+
+    if (temp && temp->plane_id != plane_id)
+    {
+        XDBG_ERROR (MPLN, "can't change zpos. plane(%d) is at zpos(%d) crtc(%d) \n",
+                    temp->plane_id, temp->zpos, crtc_id);
+        return FALSE;
+    }
+
+    if (!table->visible)
+        table->crtc_id = crtc_id;
+    else if (table->crtc_id != crtc_id)
+    {
+        XDBG_ERROR (MPLN, "can't change crtc. plane(%d) is on crtc(%d) \n",
+                    table->plane_id, table->zpos);
+        return FALSE;
+    }
+
+    if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
+                                &src, &dst, zpos, need_update))
+    {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+Bool
+secPlaneHide (int plane_id)
+{
+    SECPlaneTable *table = _secPlaneTableFind (plane_id);
+
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
+
+    if (!table->visible)
+        return TRUE;
+
+    XDBG_TRACE (MPLN, "plane(%d) crtc(%d)\n", table->plane_id, table->crtc_id);
+
+    _secPlaneHideInternal (table);
+
+    return TRUE;
+}
+
+Bool
+secPlaneMove (int plane_id, int x, int y)
+{
+    SECPlaneTable *table = _secPlaneTableFind (plane_id);
+    xRectangle dst;
+
+    XDBG_RETURN_VAL_IF_FAIL (table != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (table->cur_fb != NULL, FALSE);
+
+    dst.x = x;
+    dst.y = y;
+    dst.width = table->dst.width;
+    dst.height = table->dst.height;
+
+    if (table->visible && !table->freeze_update)
+        if (!_secPlaneShowInternal (table, table->cur_fb, table->cur_fb,
+                                    &table->src, &dst, table->zpos, FALSE))
+        {
+            return FALSE;
+        }
+
+    XDBG_TRACE (MPLN, "plane(%d) moved to (%d,%d)\n", table->plane_id, x, y);
+
+    return TRUE;
+}
+
+char*
+secPlaneDump (char *reply, int *len)
+{
+    Bool in_use = FALSE;
+    int i;
+
+    for (i = 0; i < plane_table_size; i++)
+        if (plane_table[i].in_use)
+        {
+            in_use = TRUE;
+            break;
+        }
+
+    if (!in_use)
+        return reply;
+
+    XDBG_REPLY ("=================================================\n");
+    XDBG_REPLY ("plane\tcrtc\tpos\tvisible\tonoff\tfb(w,h)\tsrc\t\tdst\n");
+
+    for (i = 0; i < plane_table_size; i++)
+    {
+        if (plane_table[i].in_use)
+            XDBG_REPLY ("%d\t%d\t%d\t%d\t%d\t%d(%dx%d)\t%d,%d %dx%d\t%d,%d %dx%d\n",
+                        plane_table[i].plane_id,
+                        plane_table[i].crtc_id, plane_table[i].zpos,
+                        plane_table[i].visible,
+                        plane_table[i].onoff,
+                        (plane_table[i].cur_fb)?plane_table[i].cur_fb->id:0,
+                        (plane_table[i].cur_fb)?plane_table[i].cur_fb->width:0,
+                        (plane_table[i].cur_fb)?plane_table[i].cur_fb->height:0,
+                        plane_table[i].src.x, plane_table[i].src.y,
+                        plane_table[i].src.width, plane_table[i].src.height,
+                        plane_table[i].dst.x, plane_table[i].dst.y,
+                        plane_table[i].dst.width, plane_table[i].dst.height);
+    }
+
+    XDBG_REPLY ("=================================================\n");
+
+    return reply;
+}
diff --git a/src/crtcconfig/sec_plane.h b/src/crtcconfig/sec_plane.h
new file mode 100644 (file)
index 0000000..5ce2fd1
--- /dev/null
@@ -0,0 +1,84 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_PLANE_H__
+#define __SEC_PLANE_H__
+
+#include "sec_display.h"
+
+#define PLANE_POS_0            0
+#define PLANE_POS_1            1
+#define PLANE_POS_2            2
+#define PLANE_POS_3            3
+#define PLANE_POS_4            4
+
+typedef struct _SECPlanePriv
+{
+    ScrnInfoPtr pScrn;
+    SECModePtr pSecMode;
+    drmModePlanePtr mode_plane;
+
+    int plane_id;
+
+    struct xorg_list link;
+} SECPlanePrivRec, *SECPlanePrivPtr;
+
+void   secPlaneInit (ScrnInfoPtr pScrn, SECModePtr pSecMode, int num);
+void   secPlaneDeinit (ScrnInfoPtr pScrn, SECPlanePrivPtr pPlanePriv);
+
+void   secPlaneShowAll (int crtc_id);
+int    secPlaneGetID   (void);
+void   secPlaneFreeId  (int plane_id);
+Bool   secPlaneTrun    (int plane_id, Bool onoff, Bool user);
+Bool   secPlaneTrunStatus (int plane_id);
+void   secPlaneFreezeUpdate (int plane_id, Bool enable);
+
+Bool   secPlaneRemoveBuffer (int plane_id, int fb_id);
+int    secPlaneAddBo        (int plane_id, tbm_bo bo);
+int    secPlaneAddBuffer    (int plane_id, SECVideoBuf *vbuf);
+
+int    secPlaneGetBuffer     (int plane_id, tbm_bo bo, SECVideoBuf *vbuf);
+void   secPlaneGetBufferSize (int plane_id, int fb_id, int *width, int *height);
+
+Bool   secPlaneAttach     (int plane_id, int fb_id);
+
+Bool   secPlaneIsVisible (int plane_id);
+Bool   secPlaneHide (int plane_id);
+Bool   secPlaneShow (int plane_id, int crtc_id,
+                     int src_x, int src_y, int src_w, int src_h,
+                     int dst_x, int dst_y, int dst_w, int dst_h,
+                     int zpos, Bool need_update);
+
+Bool   secPlaneMove (int plane_id, int x, int y);
+
+/* for debug */
+char*  secPlaneDump (char *reply, int *len);
+
+#endif /* __SEC_PLANE_H__ */
diff --git a/src/crtcconfig/sec_prop.c b/src/crtcconfig/sec_prop.c
new file mode 100644 (file)
index 0000000..5c32753
--- /dev/null
@@ -0,0 +1,712 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <string.h>
+
+#include "sec.h"
+#include "sec_display.h"
+#include "sec_output.h"
+#include "sec_crtc.h"
+#include "sec_prop.h"
+#include "sec_util.h"
+#include <exynos_drm.h>
+#include <sys/ioctl.h>
+
+#define STR_XRR_DISPLAY_MODE_PROPERTY "XRR_PROPERTY_DISPLAY_MODE"
+#define STR_XRR_LVDS_FUNCTION "XRR_PROPERTY_LVDS_FUNCTION"
+#define STR_XRR_FB_VISIBLE_PROPERTY "XRR_PROPERTY_FB_VISIBLE"
+#define STR_XRR_VIDEO_OFFSET_PROPERTY "XRR_PROPERTY_VIDEO_OFFSET"
+#define STR_XRR_PROPERTY_SCREEN_ROTATE "XRR_PROPERTY_SCREEN_ROTATE"
+
+#define PROP_VERIFY_RR_MODE(id, ptr, a)\
+    {\
+       int rc = dixLookupResourceByType((pointer *)&(ptr), id,\
+                                        RRModeType, serverClient, a);\
+       if (rc != Success) {\
+           serverClient->errorValue = id;\
+           return 0;\
+       }\
+    }
+
+
+#define FLAG_BITS (RR_HSyncPositive | \
+                  RR_HSyncNegative | \
+                  RR_VSyncPositive | \
+                  RR_VSyncNegative | \
+                  RR_Interlace | \
+                  RR_DoubleScan | \
+                  RR_CSync | \
+                  RR_CSyncPositive | \
+                  RR_CSyncNegative | \
+                  RR_HSkewPresent | \
+                  RR_BCast | \
+                  RR_PixelMultiplex | \
+                  RR_DoubleClock | \
+                  RR_ClockDivideBy2)
+
+static Bool g_display_mode_prop_init = FALSE;
+static Bool g_lvds_func_prop_init = FALSE;
+static Bool g_fb_visible_prop_init = FALSE;
+static Bool g_video_offset_prop_init = FALSE;
+static Bool g_screen_rotate_prop_init = FALSE;
+
+static Atom xrr_property_display_mode_atom;
+static Atom xrr_property_lvds_func_atom;
+static Atom xrr_property_fb_visible_atom;
+static Atom xrr_property_video_offset_atom;
+static Atom xrr_property_screen_rotate_atom;
+
+typedef enum
+{
+    XRR_OUTPUT_DISPLAY_MODE_NULL,
+       XRR_OUTPUT_DISPLAY_MODE_WB_CLONE,
+       XRR_OUTPUT_DISPLAY_MODE_VIDEO_ONLY,
+} XRROutputPropDisplayMode;
+
+typedef enum
+{
+    XRR_OUTPUT_LVDS_FUNC_NULL,
+       XRR_OUTPUT_LVDS_FUNC_INIT_VIRTUAL,
+       XRR_OUTPUT_LVDS_FUNC_HIBERNATION,
+       XRR_OUTPUT_LVDS_FUNC_ACCESSIBILITY,
+} XRROutputPropLvdsFunc;
+
+/*
+ * Convert a RandR mode to a DisplayMode
+ */
+static void
+_RRModeConvertToDisplayMode (ScrnInfoPtr       scrn,
+                     RRModePtr         randr_mode,
+                     DisplayModePtr    mode)
+{
+    memset(mode, 0, sizeof(DisplayModeRec));
+    mode->status = MODE_OK;
+
+    mode->Clock = randr_mode->mode.dotClock / 1000;
+
+    mode->HDisplay = randr_mode->mode.width;
+    mode->HSyncStart = randr_mode->mode.hSyncStart;
+    mode->HSyncEnd = randr_mode->mode.hSyncEnd;
+    mode->HTotal = randr_mode->mode.hTotal;
+    mode->HSkew = randr_mode->mode.hSkew;
+
+    mode->VDisplay = randr_mode->mode.height;
+    mode->VSyncStart = randr_mode->mode.vSyncStart;
+    mode->VSyncEnd = randr_mode->mode.vSyncEnd;
+    mode->VTotal = randr_mode->mode.vTotal;
+    mode->VScan = 0;
+
+    mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS;
+
+    xf86SetModeCrtc (mode, scrn->adjustFlags);
+}
+
+
+static int
+_secPropUnsetCrtc (xf86OutputPtr pOutput)
+{
+    if (!pOutput->crtc)
+        return 1;
+
+    ScrnInfoPtr pScrn = pOutput->scrn;
+    SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+    SECModePtr pSecMode =  pOutputPriv->pSecMode;
+
+    pSecMode->unset_connector_type = pOutputPriv->mode_output->connector_type;
+    RRGetInfo (pScrn->pScreen, TRUE);
+    pSecMode->unset_connector_type = 0;
+    RRGetInfo (pScrn->pScreen, TRUE);
+
+    return 1;
+}
+
+static int
+_secPropSetWbClone (xf86OutputPtr pOutput, int mode_xid)
+{
+    SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+    SECModePtr pSecMode =  pOutputPriv->pSecMode;
+    RRModePtr pRRMode;
+    DisplayModeRec mode;
+
+    /* find kmode and set the external default mode */
+    PROP_VERIFY_RR_MODE (mode_xid, pRRMode, DixSetAttrAccess);
+    _RRModeConvertToDisplayMode (pOutput->scrn, pRRMode, &mode);
+    secDisplayModeToKmode (pOutput->scrn, &pSecMode->ext_connector_mode, &mode);
+
+    if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+        pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB)
+    {
+        secDisplaySetDispConnMode (pOutput->scrn, DISPLAY_CONN_MODE_HDMI);
+        _secPropUnsetCrtc (pOutput);
+    }
+    else if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)
+    {
+        secDisplaySetDispConnMode (pOutput->scrn, DISPLAY_CONN_MODE_VIRTUAL);
+        _secPropUnsetCrtc (pOutput);
+    }
+    else
+    {
+        XDBG_WARNING (MDISP, "(WB_CLONE) Not suuport for this connecotor type\n");
+        return 0;
+    }
+
+    if(!secDisplaySetDispSetMode (pOutput->scrn, DISPLAY_SET_MODE_CLONE))
+    {
+        return 0;
+    }
+
+    return 1;
+}
+
+static void
+_secPropUnSetWbClone (xf86OutputPtr pOutput)
+{
+    secDisplaySetDispSetMode (pOutput->scrn, DISPLAY_SET_MODE_OFF);
+    secDisplaySetDispConnMode (pOutput->scrn, DISPLAY_CONN_MODE_NONE);
+}
+
+Bool
+secPropSetDisplayMode (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value)
+{
+    XDBG_RETURN_VAL_IF_FAIL(value, FALSE);
+    XDBG_TRACE (MPROP, "%s\n", __FUNCTION__);
+
+    XRROutputPropDisplayMode disp_mode = XRR_OUTPUT_DISPLAY_MODE_NULL;
+    SECOutputPrivPtr pOutputPriv;
+
+    if (g_display_mode_prop_init == FALSE)
+    {
+        xrr_property_display_mode_atom = MakeAtom (STR_XRR_DISPLAY_MODE_PROPERTY, strlen (STR_XRR_DISPLAY_MODE_PROPERTY), TRUE);
+        g_display_mode_prop_init = TRUE;
+    }
+
+    if (xrr_property_display_mode_atom != property)
+    {
+        //ErrorF ("[Display_mode]: Unrecognized property name.\n");
+        return FALSE;
+    }
+
+    if (!value->data || value->size == 0)
+    {
+        //ErrorF ("[Display_mode]: Unrecognized property value.\n");
+        return TRUE;
+    }
+
+    XDBG_DEBUG (MDISP, "output_name=%s, data=%d size=%ld\n", pOutput->name, *(int *)value->data, value->size);
+
+    disp_mode = *(int *)value->data;
+
+    if (disp_mode == XRR_OUTPUT_DISPLAY_MODE_NULL)
+        return TRUE;
+
+    XDBG_DEBUG (MDISP, "output_name=%s, disp_mode=%d\n", pOutput->name, disp_mode);
+
+    pOutputPriv = pOutput->driver_private;
+
+    int mode_xid;
+    switch (disp_mode)
+    {
+        case XRR_OUTPUT_DISPLAY_MODE_WB_CLONE:
+            mode_xid = *((int *)value->data+1);
+            XDBG_INFO (MDISP, "[DISPLAY_MODE]: Set WriteBack Clone\n");
+            _secPropSetWbClone (pOutput, mode_xid);
+            pOutputPriv->disp_mode = disp_mode;
+            break;
+        default:
+            break;
+    }
+
+    return TRUE;
+}
+
+void
+secPropUnSetDisplayMode (xf86OutputPtr pOutput)
+{
+    XRROutputPropDisplayMode disp_mode;
+    SECOutputPrivPtr pOutputPriv;
+
+    pOutputPriv = pOutput->driver_private;
+    disp_mode = pOutputPriv->disp_mode;
+
+    if (disp_mode == XRR_OUTPUT_DISPLAY_MODE_NULL)
+        return;
+
+    /* check the private and unset the diplaymode */
+    switch (disp_mode)
+    {
+        case XRR_OUTPUT_DISPLAY_MODE_WB_CLONE:
+            XDBG_INFO (MDISP, "[DISPLAY_MODE]: UnSet WriteBack Clone\n");
+            _secPropUnSetWbClone (pOutput);
+            break;
+        default:
+            break;
+    }
+
+    pOutputPriv->disp_mode = XRR_OUTPUT_DISPLAY_MODE_NULL;
+}
+
+static const char fake_edid_info[] = {
+    /* fill the edid information */
+};
+
+static void
+_secPropSetVirtual (xf86OutputPtr pOutput, int sc_conn)
+{
+    SECPtr pSec = SECPTR (pOutput->scrn);
+    int fd = pSec->drm_fd;
+
+    struct drm_exynos_vidi_connection vidi;
+
+    if (sc_conn == 1)
+    {
+        vidi.connection = 1;
+        vidi.extensions = 1;
+        vidi.edid = (uint64_t *)fake_edid_info;
+    }
+    else if (sc_conn == 2)
+    {
+        vidi.connection = 0;
+    }
+    else
+    {
+        XDBG_WARNING (MDISP, "Warning : wrong virtual connection command\n");
+        return;
+    }
+
+    ioctl (fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &vidi);
+}
+
+Bool
+secPropSetLvdsFunc (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value)
+{
+    XDBG_TRACE (MPROP, "%s\n", __FUNCTION__);
+    XDBG_RETURN_VAL_IF_FAIL(value, FALSE);
+
+    XRROutputPropLvdsFunc lvds_func = XRR_OUTPUT_LVDS_FUNC_NULL;
+
+    if (g_lvds_func_prop_init == FALSE)
+    {
+        xrr_property_lvds_func_atom = MakeAtom (STR_XRR_LVDS_FUNCTION, strlen (STR_XRR_LVDS_FUNCTION), TRUE);
+        g_lvds_func_prop_init = TRUE;
+    }
+
+    if (xrr_property_lvds_func_atom != property)
+    {
+        return FALSE;
+    }
+
+    if (!value->data || value->size == 0)
+    {
+        //ErrorF ("[Display_mode]: Unrecognized property value.\n");
+        return TRUE;
+    }
+
+    XDBG_DEBUG (MDISP, "output_name=%s, data=%d size=%ld\n", pOutput->name, *(int *)value->data, value->size);
+
+    lvds_func = *(int *)value->data;
+
+    if (lvds_func == XRR_OUTPUT_LVDS_FUNC_NULL)
+        return TRUE;
+
+    XDBG_DEBUG (MDISP, "output_name=%s, lvds_func=%d\n", pOutput->name, lvds_func);
+
+    int sc_conn;
+    switch (lvds_func)
+    {
+        case XRR_OUTPUT_LVDS_FUNC_INIT_VIRTUAL:
+            sc_conn = *((int *)value->data+1);
+            XDBG_INFO (MDISP, "[LVDS_FUNC]: set virtual output (%d)\n", sc_conn);
+            _secPropSetVirtual (pOutput, sc_conn);
+            break;
+        case XRR_OUTPUT_LVDS_FUNC_HIBERNATION:
+            XDBG_INFO (MDISP, "[LVDS_FUNC]: set hibernationn\n");
+            break;
+        case XRR_OUTPUT_LVDS_FUNC_ACCESSIBILITY:
+            XDBG_INFO (MDISP, "[LVDS_FUNC]: set accessibility\n");
+            break;
+        default:
+            break;
+    }
+
+    return TRUE;
+}
+
+void
+secPropUnSetLvdsFunc (xf86OutputPtr pOutput)
+{
+
+}
+
+static void
+_secPropReturnProperty (RRPropertyValuePtr value, const char * f, ...)
+{
+    int len;
+    va_list args;
+    char buf[1024];
+
+    if (value->data)
+    {
+        free (value->data);
+        value->data = NULL;
+    }
+    va_start (args, f);
+    len = vsnprintf (buf, sizeof(buf), f, args) + 1;
+    va_end (args);
+
+    value->data = calloc (1, len);
+    value->format = 8;
+    value->size = len;
+
+    if (value->data)
+        strncpy (value->data, buf, len-1);
+}
+
+Bool secPropFbVisible (char *cmd, Bool always, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    int output = 0;
+    int pos = 0;
+    Bool onoff = FALSE;
+    char str[128];
+    char *p;
+    SECLayer *layer;
+    SECLayerPos lpos;
+
+    XDBG_RETURN_VAL_IF_FAIL (cmd != NULL, FALSE);
+
+    snprintf (str, sizeof(str), "%s", cmd);
+
+    p = strtok (str, ":");
+    XDBG_RETURN_VAL_IF_FAIL (p != NULL, FALSE);
+    output = atoi (p);
+
+    p = strtok (NULL, ":");
+    XDBG_RETURN_VAL_IF_FAIL (p != NULL, FALSE);
+    pos = atoi (p);
+
+    if (output == LAYER_OUTPUT_LCD)
+        lpos = pos - 3;
+    else
+        lpos = pos - 1;
+
+    p = strtok (NULL, ":");
+    if (!p)
+    {
+        _secPropReturnProperty (value, "%d", 0);
+
+        if (lpos != 0)
+        {
+            layer = secLayerFind ((SECLayerOutput)output, lpos);
+            if (layer)
+                _secPropReturnProperty (value, "%d", secLayerTurnStatus (layer));
+        }
+        else
+        {
+            xf86CrtcConfigPtr pCrtcConfig;
+            int i;
+
+            pCrtcConfig = XF86_CRTC_CONFIG_PTR (scrn);
+            if (!pCrtcConfig)
+                return FALSE;
+
+            for (i = 0; i < pCrtcConfig->num_output; i++)
+            {
+                xf86OutputPtr pOutput = pCrtcConfig->output[i];
+                SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+
+                if ((output == LAYER_OUTPUT_LCD &&
+                    (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+                     pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown)) ||
+                    (output == LAYER_OUTPUT_EXT &&
+                    (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+                     pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB ||
+                     pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)))
+                {
+                    if (pOutput->crtc)
+                    {
+                        SECCrtcPrivPtr pCrtcPriv = pOutput->crtc->driver_private;
+                        _secPropReturnProperty (value, "%d", pCrtcPriv->onoff);
+                    }
+                    break;
+                }
+            }
+        }
+
+        return TRUE;
+    }
+    onoff = atoi (p);
+
+    if (lpos != 0)
+    {
+        if (!always)
+            if (output == LAYER_OUTPUT_LCD && lpos == LAYER_UPPER)
+            {
+                xf86CrtcPtr pCrtc = xf86CompatCrtc (scrn);
+                SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
+
+                secCrtcOverlayNeedOff (pCrtc, !onoff);
+
+                if (pCrtcPriv->cursor_show && !onoff)
+                {
+                    XDBG_TRACE (MCRS, "can't turn upper off.\n");
+                    return FALSE;
+                }
+            }
+
+        layer = secLayerFind ((SECLayerOutput)output, lpos);
+        if (!layer)
+            return FALSE;
+
+        if (onoff)
+            secLayerTurn (layer, TRUE, TRUE);
+        else
+            secLayerTurn (layer, FALSE, TRUE);
+    }
+    else
+    {
+        xf86CrtcConfigPtr pCrtcConfig;
+        int i;
+
+        pCrtcConfig = XF86_CRTC_CONFIG_PTR (scrn);
+        if (!pCrtcConfig)
+            return FALSE;
+
+        for (i = 0; i < pCrtcConfig->num_output; i++)
+        {
+            xf86OutputPtr pOutput = pCrtcConfig->output[i];
+            SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+
+            if ((output == LAYER_OUTPUT_LCD &&
+                (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+                 pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown)) ||
+                (output == LAYER_OUTPUT_EXT &&
+                (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+                 pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB ||
+                 pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)))
+            {
+                SECCrtcPrivPtr pCrtcPriv;
+
+                if (!pOutput->crtc)
+                    break;
+
+                pCrtcPriv = pOutput->crtc->driver_private;
+                if (pCrtcPriv->bAccessibility)
+                {
+                    _secPropReturnProperty (value, "[Xorg] crtc(%d) accessibility ON. \n",
+                                            secCrtcID(pCrtcPriv));
+                    return TRUE;
+                }
+
+                if (pOutput->crtc && !secCrtcTurn (pOutput->crtc, onoff, always, TRUE))
+                {
+                    _secPropReturnProperty (value, "[Xorg] crtc(%d) now %s%s\n",
+                                                secCrtcID(pCrtcPriv),
+                                                (pCrtcPriv->onoff)?"ON":"OFF",
+                                                (pCrtcPriv->onoff_always)?"(always).":".");
+                    return TRUE;
+                }
+                break;
+            }
+        }
+    }
+
+    _secPropReturnProperty (value, "[Xorg] output(%d), zpos(%d) layer %s%s\n",
+                                output, pos, (onoff)?"ON":"OFF", (always)?"(always).":".");
+
+    return TRUE;
+}
+
+Bool secPropVideoOffset (char *cmd, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+    int x, y;
+    char str[128];
+    char *p;
+    SECLayer *layer;
+
+    snprintf (str, sizeof(str), "%s", cmd);
+
+    p = strtok (str, ",");
+    XDBG_RETURN_VAL_IF_FAIL (p != NULL, FALSE);
+    x = atoi (p);
+
+    p = strtok (NULL, ",");
+    XDBG_RETURN_VAL_IF_FAIL (p != NULL, FALSE);
+    y = atoi (p);
+
+#if 0
+    PropertyPtr rotate_prop;
+    int rotate = 0;
+    rotate_prop = secUtilGetWindowProperty (scrn->pScreen->root, "_E_ILLUME_ROTATE_ROOT_ANGLE");
+    if (rotate_prop)
+        rotate = *(int*)rotate_prop->data;
+#endif
+
+    pSec->pVideoPriv->video_offset_x = x;
+    pSec->pVideoPriv->video_offset_y = y;
+
+    layer = secLayerFind (LAYER_OUTPUT_LCD, LAYER_LOWER1);
+    if (layer)
+        secLayerSetOffset (layer, x, y);
+
+    layer = secLayerFind (LAYER_OUTPUT_LCD, LAYER_LOWER2);
+    if (layer)
+        secLayerSetOffset (layer, x, y);
+
+    _secPropReturnProperty (value, "[Xorg] video_offset : %d,%d.\n",
+                            pSec->pVideoPriv->video_offset_x,
+                            pSec->pVideoPriv->video_offset_y);
+
+    return TRUE;
+}
+
+Bool
+secPropSetFbVisible (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value)
+{
+    if (g_fb_visible_prop_init == FALSE)
+    {
+        xrr_property_fb_visible_atom = MakeAtom (STR_XRR_FB_VISIBLE_PROPERTY,
+                                                 strlen (STR_XRR_FB_VISIBLE_PROPERTY), TRUE);
+        g_fb_visible_prop_init = TRUE;
+    }
+
+    if (xrr_property_fb_visible_atom != property)
+        return FALSE;
+
+    if (!value || !value->data || value->size == 0)
+        return TRUE;
+
+    if (value->format != 8)
+        return TRUE;
+
+    XDBG_TRACE (MPROP, "%s \n", value->data);
+
+    secPropFbVisible (value->data, FALSE, value, pOutput->scrn);
+
+    return TRUE;
+}
+
+Bool
+secPropSetVideoOffset (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value)
+{
+    if (g_video_offset_prop_init == FALSE)
+    {
+        xrr_property_video_offset_atom = MakeAtom (STR_XRR_VIDEO_OFFSET_PROPERTY,
+                                                 strlen (STR_XRR_VIDEO_OFFSET_PROPERTY), TRUE);
+        g_video_offset_prop_init = TRUE;
+    }
+
+    if (xrr_property_video_offset_atom != property)
+        return FALSE;
+
+    if (!value || !value->data || value->size == 0)
+        return TRUE;
+
+    if (value->format != 8)
+        return TRUE;
+
+    XDBG_TRACE (MPROP, "%s \n", value->data);
+
+    secPropVideoOffset (value->data, value, pOutput->scrn);
+
+    return TRUE;
+}
+
+Bool secPropScreenRotate (char *cmd, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    xf86CrtcPtr crtc = xf86CompatCrtc (scrn);
+    int degree;
+
+    if (!crtc)
+        return TRUE;
+
+    if (!strcmp (cmd, "normal"))
+        degree = 0;
+    else if (!strcmp (cmd, "right"))
+        degree = 90;
+    else if (!strcmp (cmd, "inverted"))
+        degree = 180;
+    else if (!strcmp (cmd, "left"))
+        degree = 270;
+    else if (!strcmp (cmd, "0"))
+        degree = 0;
+    else if (!strcmp (cmd, "1"))
+        degree = 270;
+    else if (!strcmp (cmd, "2"))
+        degree = 180;
+    else if (!strcmp (cmd, "3"))
+        degree = 90;
+    else
+    {
+        _secPropReturnProperty (value, "[Xorg] unknown value: %s\n", cmd);
+        return TRUE;
+    }
+
+    if (secCrtcScreenRotate (crtc, degree))
+        _secPropReturnProperty (value, "[Xorg] screen rotated %d.\n", degree);
+    else
+    {
+        _secPropReturnProperty (value, "[Xorg] Fail screen rotate %d.\n", degree);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+Bool
+secPropSetScreenRotate (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value)
+{
+    if (g_screen_rotate_prop_init == FALSE)
+    {
+        xrr_property_screen_rotate_atom = MakeAtom (STR_XRR_PROPERTY_SCREEN_ROTATE,
+                                                 strlen (STR_XRR_PROPERTY_SCREEN_ROTATE), TRUE);
+        g_screen_rotate_prop_init = TRUE;
+    }
+
+    if (xrr_property_screen_rotate_atom != property)
+        return FALSE;
+
+    if (!value || !value->data || value->size == 0)
+        return TRUE;
+
+    if (value->format != 8)
+        return TRUE;
+
+    XDBG_TRACE (MPROP, "%s \n", value->data);
+
+    secPropScreenRotate (value->data, value, pOutput->scrn);
+
+    return TRUE;
+}
+
diff --git a/src/crtcconfig/sec_prop.h b/src/crtcconfig/sec_prop.h
new file mode 100644 (file)
index 0000000..79a2135
--- /dev/null
@@ -0,0 +1,50 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_PROP_H__
+#define __SEC_PROP_H__
+
+Bool secPropSetLvdsFunc (xf86OutputPtr output, Atom property, RRPropertyValuePtr value);
+void secPropUnSetLvdsFunc (xf86OutputPtr pOutput);
+
+Bool secPropSetDisplayMode (xf86OutputPtr output, Atom property, RRPropertyValuePtr value);
+void secPropUnSetDisplayMode (xf86OutputPtr pOutput);
+
+Bool secPropSetFbVisible    (xf86OutputPtr output, Atom property, RRPropertyValuePtr value);
+Bool secPropSetVideoOffset  (xf86OutputPtr output, Atom property, RRPropertyValuePtr value);
+Bool secPropSetScreenRotate (xf86OutputPtr pOutput, Atom property, RRPropertyValuePtr value);
+
+Bool secPropFbVisible       (char *cmd, Bool always, RRPropertyValuePtr value, ScrnInfoPtr scrn);
+Bool secPropVideoOffset     (char *cmd, RRPropertyValuePtr value, ScrnInfoPtr scrn);
+Bool secPropScreenRotate    (char *cmd, RRPropertyValuePtr value, ScrnInfoPtr scrn);
+
+
+#endif /* __SEC_PROP_H__ */
+
diff --git a/src/crtcconfig/sec_xberc.c b/src/crtcconfig/sec_xberc.c
new file mode 100644 (file)
index 0000000..9af272c
--- /dev/null
@@ -0,0 +1,1264 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <poll.h>
+#include <dirent.h>
+
+#include <xorgVersion.h>
+#include <tbm_bufmgr.h>
+#include <xf86Crtc.h>
+#include <xf86DDC.h>
+#include <xf86cmap.h>
+#include <xf86Priv.h>
+#include <list.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/dpmsconst.h>
+
+#include "sec.h"
+#include "sec_util.h"
+#include "sec_xberc.h"
+#include "sec_output.h"
+#include "sec_crtc.h"
+#include "sec_layer.h"
+#include "sec_wb.h"
+#include "sec_plane.h"
+#include "sec_prop.h"
+#include "sec_drmmode_dump.h"
+
+#define XRRPROPERTY_ATOM       "X_RR_PROPERTY_REMOTE_CONTROLLER"
+#define XBERC_BUF_SIZE  8192
+
+static Atom rr_property_atom;
+
+static void _secXbercSetReturnProperty (RRPropertyValuePtr value, const char * f, ...);
+
+static Bool SECXbercSetTvoutMode (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+    SECModePtr pSecMode = pSec->pSecMode;
+    const char * mode_string[] = {"Off", "Clone", "UiClone", "Extension"};
+    SECDisplaySetMode mode;
+
+    XDBG_DEBUG (MSEC, "%s value : %d\n", __FUNCTION__, *(unsigned int*)value->data);
+
+    if (argc < 2)
+    {
+        _secXbercSetReturnProperty (value, "Error : too few arguments\n");
+        return TRUE;
+    }
+
+    if (argc == 2)
+    {
+        _secXbercSetReturnProperty (value, "Current Tv Out mode is %d (%s)\n",
+                                    pSecMode->set_mode, mode_string[pSecMode->set_mode]);
+        return TRUE;
+    }
+
+    mode = (SECDisplaySetMode)atoi (argv[2]);
+
+    if (mode < DISPLAY_SET_MODE_OFF)
+    {
+        _secXbercSetReturnProperty (value, "Error : value(%d) is out of range.\n", mode);
+        return TRUE;
+    }
+
+    if (mode == pSecMode->set_mode)
+    {
+        _secXbercSetReturnProperty (value, "[Xorg] already tvout : %s.\n", mode_string[mode]);
+        return TRUE;
+    }
+
+    if (pSecMode->conn_mode != DISPLAY_CONN_MODE_HDMI && pSecMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL)
+    {
+        _secXbercSetReturnProperty (value, "Error : not connected.\n");
+        return TRUE;
+    }
+
+    secDisplaySetDispSetMode (scrn, mode);
+
+    _secXbercSetReturnProperty (value, "[Xorg] tvout : %s.\n", mode_string[mode]);
+
+    return TRUE;
+}
+
+static Bool SECXbercSetConnectMode (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+    SECModePtr pSecMode = pSec->pSecMode;
+    const char * mode_string[] = {"Off", "HDMI", "Virtual"};
+    SECDisplayConnMode mode;
+
+    XDBG_DEBUG (MSEC, "%s value : %d\n", __FUNCTION__, *(unsigned int*)value->data);
+
+    if (argc < 2)
+    {
+        _secXbercSetReturnProperty (value, "Error : too few arguments\n");
+        return TRUE;
+    }
+
+    if (argc == 2)
+    {
+        _secXbercSetReturnProperty (value, "Current connect mode is %d (%s)\n",
+                                    pSecMode->conn_mode, mode_string[pSecMode->conn_mode]);
+        return TRUE;
+    }
+
+    mode = (SECDisplayConnMode)atoi (argv[2]);
+
+    if (mode < DISPLAY_CONN_MODE_NONE || mode >= DISPLAY_CONN_MODE_MAX)
+    {
+        _secXbercSetReturnProperty (value, "Error : value(%d) is out of range.\n", mode);
+        return TRUE;
+    }
+
+    if (mode == pSecMode->conn_mode)
+    {
+        _secXbercSetReturnProperty (value, "[Xorg] already connect : %s.\n", mode_string[mode]);
+        return TRUE;
+    }
+
+    secDisplaySetDispConnMode (scrn, mode);
+
+    _secXbercSetReturnProperty (value, "[Xorg] connect : %s.\n", mode_string[mode]);
+
+    return TRUE;
+}
+
+static Bool SECXbercAsyncSwap (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    ScreenPtr pScreen = scrn->pScreen;
+    int bEnable;
+    int status = -1;
+
+    if (argc !=3 )
+    {
+        status = secExaScreenAsyncSwap (pScreen, -1);
+        if (status < 0)
+        {
+            _secXbercSetReturnProperty (value, "%s", "faili to set async swap\n");
+            return TRUE;
+        }
+
+        _secXbercSetReturnProperty (value, "Async swap : %d\n", status);
+        return TRUE;
+    }
+
+    bEnable = atoi (argv[2]);
+
+    status = secExaScreenAsyncSwap (pScreen, bEnable);
+    if (status < 0)
+    {
+        _secXbercSetReturnProperty (value, "%s", "faili to set async swap\n");
+        return TRUE;
+    }
+
+    if (status)
+        _secXbercSetReturnProperty (value, "%s", "Set async swap.\n");
+    else
+        _secXbercSetReturnProperty (value, "%s", "Unset async swap.\n");
+
+    return TRUE;
+}
+
+static long
+_parse_long (char *s)
+{
+    char *fmt = "%lu";
+    long retval = 0L;
+    int thesign = 1;
+
+    if (s && s[0])
+    {
+        char temp[12];
+        snprintf (temp, sizeof (temp), "%s", s);
+        s = temp;
+
+        if (s[0] == '-')
+            s++, thesign = -1;
+        if (s[0] == '0')
+            s++, fmt = "%lo";
+        if (s[0] == 'x' || s[0] == 'X')
+            s++, fmt = "%lx";
+        (void) sscanf (s, fmt, &retval);
+    }
+    return (thesign * retval);
+}
+
+static Bool SECXbercDump (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+    int dump_mode;
+    Bool flush = TRUE;
+    char *c;
+    int buf_cnt = 30;
+
+    if (argc < 3)
+        goto print_dump;
+
+    pSec->dump_xid = 0;
+    dump_mode = 0;
+
+    if (pSec->dump_str)
+        free (pSec->dump_str);
+    pSec->dump_str = strdup (argv[2]);
+
+    c = strtok (argv[2], ",");
+    do
+    {
+        if (!strcmp (c, "off"))
+        {
+            dump_mode = 0;
+            break;
+        }
+        else if (!strcmp (c, "clear"))
+        {
+            dump_mode = 0;
+            flush = FALSE;
+            break;
+        }
+        else if (!strcmp (c, "drawable"))
+        {
+            dump_mode = XBERC_DUMP_MODE_DRAWABLE;
+            pSec->dump_xid = _parse_long (argv[3]);
+        }
+        else if (!strcmp (c, "fb"))
+            dump_mode |= XBERC_DUMP_MODE_FB;
+        else if (!strcmp (c, "all"))
+            dump_mode |= (XBERC_DUMP_MODE_DRAWABLE|XBERC_DUMP_MODE_FB);
+        else if (!strcmp (c, "ia"))
+            dump_mode |= XBERC_DUMP_MODE_IA;
+        else if (!strcmp (c, "ca"))
+            dump_mode |= XBERC_DUMP_MODE_CA;
+        else if (!strcmp (c, "ea"))
+            dump_mode |= XBERC_DUMP_MODE_EA;
+        else
+        {
+            _secXbercSetReturnProperty (value, "[Xorg] fail: unknown option('%s')\n", c);
+            return TRUE;
+        }
+    } while ((c = strtok (NULL, ",")));
+
+    snprintf (pSec->dump_type, sizeof (pSec->dump_type), "bmp");
+    if (argc > 3)
+    {
+        int i;
+        for (i = 3; i < argc; i++)
+        {
+            c = argv[i];
+            if (!strcmp (c, "-count"))
+                buf_cnt = MIN((argv[i+1])?atoi(argv[i+1]):30,100);
+            else if (!strcmp (c, "-type"))
+            {
+                if (!strcmp (argv[i+1], "bmp") || !strcmp (argv[i+1], "raw"))
+                    snprintf (pSec->dump_type, sizeof (pSec->dump_type), "%s", argv[i+1]);
+            }
+        }
+    }
+
+    if (dump_mode != 0)
+    {
+        char *dir = DUMP_DIR;
+        DIR *dp;
+        int ret = -1;
+
+        if (!(dp = opendir (dir)))
+        {
+            ret = mkdir (dir, 0755);
+            if (ret < 0)
+            {
+                _secXbercSetReturnProperty (value, "[Xorg] fail: mkdir '%s'\n", dir);
+                return FALSE;
+            }
+        }
+        else
+            closedir (dp);
+    }
+
+    if (dump_mode != pSec->dump_mode)
+    {
+        pSec->dump_mode = dump_mode;
+
+        if (dump_mode == 0)
+        {
+            if (flush)
+                secUtilFlushDump (pSec->dump_info);
+            secUtilFinishDump (pSec->dump_info);
+            pSec->dump_info = NULL;
+            pSec->flip_cnt = 0;
+            goto print_dump;
+        }
+        else
+        {
+            if (pSec->dump_info)
+            {
+                secUtilFlushDump (pSec->dump_info);
+                secUtilFinishDump (pSec->dump_info);
+                pSec->dump_info = NULL;
+                pSec->flip_cnt = 0;
+            }
+
+            pSec->dump_info = secUtilPrepareDump (scrn,
+                                                  pSec->pSecMode->main_lcd_mode.hdisplay * pSec->pSecMode->main_lcd_mode.vdisplay * 4,
+                                                  buf_cnt);
+            if (pSec->dump_info)
+            {
+                if (pSec->dump_mode & ~XBERC_DUMP_MODE_DRAWABLE)
+                    _secXbercSetReturnProperty (value, "[Xorg] Dump buffer: %s(cnt:%d)\n",
+                                                pSec->dump_str, buf_cnt);
+                else
+                    _secXbercSetReturnProperty (value, "[Xorg] Dump buffer: %s(xid:0x%x,cnt:%d)\n",
+                                                pSec->dump_str, pSec->dump_xid, buf_cnt);
+            }
+            else
+                _secXbercSetReturnProperty (value, "[Xorg] Dump buffer: %s(fail)\n", pSec->dump_str);
+        }
+    }
+    else
+        goto print_dump;
+
+    return TRUE;
+print_dump:
+    if (pSec->dump_mode & XBERC_DUMP_MODE_DRAWABLE)
+        _secXbercSetReturnProperty (value, "[Xorg] Dump buffer: %s(0x%x)\n", pSec->dump_str, pSec->dump_xid);
+    else
+        _secXbercSetReturnProperty (value, "[Xorg] Dump buffer: %s\n", pSec->dump_str);
+
+    return TRUE;
+}
+
+static Bool SECXbercCursorEnable (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+
+    Bool bEnable;
+
+    if (argc != 3)
+    {
+        _secXbercSetReturnProperty (value, "Enable cursor : %d\n", pSec->enableCursor);
+        return TRUE;
+    }
+
+    bEnable = atoi (argv[2]);
+
+    if (bEnable!=pSec->enableCursor)
+    {
+        pSec->enableCursor = bEnable;
+        if (secCrtcCursorEnable (scrn, bEnable))
+        {
+            _secXbercSetReturnProperty (value, "[Xorg] cursor %s.\n", bEnable?"enable":"disable");
+        }
+        else
+        {
+            _secXbercSetReturnProperty (value, "[Xorg] Fail cursor %s.\n", bEnable?"enable":"disable");
+        }
+    }
+    else
+    {
+        _secXbercSetReturnProperty (value, "[Xorg] already cursor %s.\n", bEnable?"enabled":"disabled");
+    }
+
+    return TRUE;
+}
+
+static Bool SECXbercCursorRotate (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    xf86CrtcPtr crtc = xf86CompatCrtc (scrn);
+    SECCrtcPrivPtr fimd_crtc;
+    int rotate, RR_rotate;
+
+    if (!crtc)
+        return TRUE;
+
+    fimd_crtc = crtc->driver_private;
+
+    if (argc != 3)
+    {
+        rotate = secUtilRotateToDegree (fimd_crtc->user_rotate);
+        _secXbercSetReturnProperty (value, "Current cursor rotate value : %d\n", rotate);
+        return TRUE;
+    }
+
+    rotate = atoi (argv[2]);
+    RR_rotate = secUtilDegreeToRotate (rotate);
+    if (!RR_rotate)
+    {
+        _secXbercSetReturnProperty (value, "[Xorg] Not support rotate(0, 90, 180, 270 only)\n");
+        return TRUE;
+    }
+
+    if (secCrtcCursorRotate (crtc, RR_rotate))
+    {
+        _secXbercSetReturnProperty (value, "[Xorg] cursor rotated %d.\n", rotate);
+    }
+    else
+    {
+        _secXbercSetReturnProperty (value, "[Xorg] Fail cursor rotate %d.\n", rotate);
+    }
+
+    return TRUE;
+}
+
+static Bool SECXbercVideoPunch (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+
+    Bool video_punch;
+
+    if (argc != 3)
+    {
+        _secXbercSetReturnProperty (value, "video_punch : %d\n", pSec->pVideoPriv->video_punch);
+        return TRUE;
+    }
+
+    video_punch = atoi (argv[2]);
+
+    if (pSec->pVideoPriv->video_punch != video_punch)
+    {
+        pSec->pVideoPriv->video_punch = video_punch;
+        _secXbercSetReturnProperty (value, "[Xorg] video_punch %s.\n", video_punch?"enabled":"disabled");
+    }
+    else
+        _secXbercSetReturnProperty (value, "[Xorg] already punch %s.\n", video_punch?"enabled":"disabled");
+
+    return TRUE;
+}
+
+static Bool SECXbercVideoOffset (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+
+    if (argc != 3)
+    {
+        _secXbercSetReturnProperty (value, "video_offset : %d,%d.\n",
+                                    pSec->pVideoPriv->video_offset_x,
+                                    pSec->pVideoPriv->video_offset_y);
+        return TRUE;
+    }
+
+    if (!secPropVideoOffset (argv[2], value, scrn))
+    {
+        _secXbercSetReturnProperty (value, "ex) xberc video_offset 0,100.\n");
+        return TRUE;
+    }
+
+    return TRUE;
+}
+
+static Bool SECXbercVideoFps (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+
+    Bool video_fps;
+
+    if (argc != 3)
+    {
+        _secXbercSetReturnProperty (value, "video_fps : %d\n", pSec->pVideoPriv->video_fps);
+        return TRUE;
+    }
+
+    video_fps = atoi (argv[2]);
+
+    if (pSec->pVideoPriv->video_fps != video_fps)
+    {
+        pSec->pVideoPriv->video_fps = video_fps;
+        _secXbercSetReturnProperty (value, "[Xorg] video_fps %s.\n", video_fps?"enabled":"disabled");
+    }
+    else
+        _secXbercSetReturnProperty (value, "[Xorg] already video_fps %s.\n", video_fps?"enabled":"disabled");
+
+    return TRUE;
+}
+
+static Bool SECXbercVideoSync (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+
+    Bool video_sync;
+
+    if (argc != 3)
+    {
+        _secXbercSetReturnProperty (value, "video_sync : %d\n", pSec->pVideoPriv->video_sync);
+        return TRUE;
+    }
+
+    video_sync = atoi (argv[2]);
+
+    if (pSec->pVideoPriv->video_sync != video_sync)
+    {
+        pSec->pVideoPriv->video_sync = video_sync;
+        _secXbercSetReturnProperty (value, "[Xorg] video_sync %s.\n", video_sync?"enabled":"disabled");
+    }
+    else
+        _secXbercSetReturnProperty (value, "[Xorg] already video_sync %s.\n", video_sync?"enabled":"disabled");
+
+    return TRUE;
+}
+
+static Bool SECXbercVideoNoRetbuf (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+
+    if (argc != 3)
+    {
+        _secXbercSetReturnProperty (value, "[Xorg] %s wait retbuf\n", (pSec->pVideoPriv->no_retbuf)?"No":"");
+        return TRUE;
+    }
+
+    pSec->pVideoPriv->no_retbuf = atoi (argv[2]);
+
+    _secXbercSetReturnProperty (value, "[Xorg] %s wait retbuf\n", (pSec->pVideoPriv->no_retbuf)?"No":"");
+
+    return TRUE;
+}
+
+static Bool SECXbercVideoOutput (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+    const char * output_string[] = {"None", "default", "video", "ext_only"};
+    int video_output;
+
+    if (argc != 3)
+    {
+        _secXbercSetReturnProperty (value, "video_output : %d\n", output_string[pSec->pVideoPriv->video_output]);
+        return TRUE;
+    }
+
+    video_output = atoi (argv[2]);
+
+    if (video_output < OUTPUT_MODE_DEFAULT || video_output > OUTPUT_MODE_EXT_ONLY)
+    {
+        _secXbercSetReturnProperty (value, "Error : value(%d) is out of range.\n", video_output);
+        return TRUE;
+    }
+
+    video_output += 1;
+
+    if (pSec->pVideoPriv->video_output != video_output)
+    {
+        pSec->pVideoPriv->video_output = video_output;
+        _secXbercSetReturnProperty (value, "[Xorg] video_output : %s.\n", output_string[video_output]);
+    }
+    else
+        _secXbercSetReturnProperty (value, "[Xorg] already video_output : %s.\n", output_string[video_output]);
+
+    return TRUE;
+}
+
+static Bool SECXbercWbFps (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+
+    Bool wb_fps;
+
+    if (argc != 3)
+    {
+        _secXbercSetReturnProperty (value, "wb_fps : %d\n", pSec->wb_fps);
+        return TRUE;
+    }
+
+    wb_fps = atoi (argv[2]);
+
+    if (pSec->wb_fps != wb_fps)
+    {
+        pSec->wb_fps = wb_fps;
+        _secXbercSetReturnProperty (value, "[Xorg] wb_fps %s.\n", wb_fps?"enabled":"disabled");
+    }
+    else
+        _secXbercSetReturnProperty (value, "[Xorg] already wb_fps %s.\n", wb_fps?"enabled":"disabled");
+
+    return TRUE;
+}
+
+static Bool SECXbercWbHz (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+
+    Bool wb_hz;
+
+    if (argc != 3)
+    {
+        _secXbercSetReturnProperty (value, "wb_hz : %d\n", pSec->wb_hz);
+        return TRUE;
+    }
+
+    wb_hz = atoi (argv[2]);
+
+    if (pSec->wb_hz != wb_hz)
+    {
+        pSec->wb_hz = wb_hz;
+        _secXbercSetReturnProperty (value, "[Xorg] wb_hz %d.\n", wb_hz);
+    }
+    else
+        _secXbercSetReturnProperty (value, "[Xorg] already wb_hz %d.\n", wb_hz);
+
+    return TRUE;
+}
+
+static Bool SECXbercXvPerf (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+    char *c;
+
+    if (argc < 3)
+    {
+        _secXbercSetReturnProperty (value, "[Xorg] xvperf: %s\n",
+                                    (pSec->xvperf)?pSec->xvperf:"off");
+        return TRUE;
+    }
+
+    if (pSec->xvperf)
+        free (pSec->xvperf);
+    pSec->xvperf = strdup (argv[2]);
+
+    c = strtok (argv[2], ",");
+    do
+    {
+        if (!strcmp (c, "off"))
+            pSec->xvperf_mode = 0;
+        else if (!strcmp (c, "ia"))
+            pSec->xvperf_mode |= XBERC_XVPERF_MODE_IA;
+        else if (!strcmp (c, "ca"))
+            pSec->xvperf_mode |= XBERC_XVPERF_MODE_CA;
+        else if (!strcmp (c, "cvt"))
+            pSec->xvperf_mode |= XBERC_XVPERF_MODE_CVT;
+        else if (!strcmp (c, "wb"))
+            pSec->xvperf_mode |= XBERC_XVPERF_MODE_WB;
+        else if (!strcmp (c, "access"))
+            pSec->xvperf_mode |= XBERC_XVPERF_MODE_ACCESS;
+        else
+        {
+            _secXbercSetReturnProperty (value, "[Xorg] fail: unknown option('%s')\n", c);
+            return TRUE;
+        }
+    } while ((c = strtok (NULL, ",")));
+
+    _secXbercSetReturnProperty (value, "[Xorg] xvperf: %s\n",
+                                (pSec->xvperf)?pSec->xvperf:"off");
+
+    return TRUE;
+}
+
+static Bool SECXbercSwap (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    if (argc != 2)
+    {
+        _secXbercSetReturnProperty (value, "Error : too few arguments\n");
+        return TRUE;
+    }
+
+    secVideoSwapLayers (scrn->pScreen);
+
+    _secXbercSetReturnProperty (value, "%s", "Video layers swapped.\n");
+
+    return TRUE;
+}
+
+static Bool SECXbercDrmmodeDump (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    SECPtr pSec = SECPTR (scrn);
+    char reply[XBERC_BUF_SIZE] = {0,};
+    int len = sizeof (reply);
+
+    if (argc != 2)
+    {
+        _secXbercSetReturnProperty (value, "Error : too few arguments\n");
+        return TRUE;
+    }
+
+    sec_drmmode_dump (pSec->drm_fd, reply, &len);
+    _secXbercSetReturnProperty (value, "%s", reply);
+
+    return TRUE;
+}
+
+static Bool SECXbercAccessibility (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    Bool found = FALSE;
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR (scrn);
+    xf86OutputPtr pOutput = NULL;
+    xf86CrtcPtr pCrtc = NULL;
+    SECCrtcPrivPtr pCrtcPriv = NULL;
+    int output_w = 0, output_h = 0;
+
+    char *opt;
+    char *mode;
+    int i;
+
+    int accessibility_status;
+    int bScale;
+    _X_UNUSED Bool bChange = FALSE;
+
+    char seps[]="x+-";
+    char *tr;
+    int geo[10], g=0;
+
+    for (i = 0; i < xf86_config->num_output; i++)
+    {
+        pOutput = xf86_config->output[i];
+        if (!pOutput->crtc->enabled)
+            continue;
+
+        /* modify the physical size of monitor */
+        if (!strcmp(pOutput->name, "LVDS1"))
+        {
+            found = TRUE;
+            break;
+        }
+    }
+
+    if (!found)
+    {
+        _secXbercSetReturnProperty (value, "Error : cannot found LVDS1\n");
+        return TRUE;
+    }
+
+    pCrtc = pOutput->crtc;
+    pCrtcPriv = pCrtc->driver_private;
+
+    output_w = pCrtc->mode.HDisplay;
+    output_h = pCrtc->mode.VDisplay;
+
+    for(i=0; i<argc; i++)
+    {
+        opt = argv[i];
+        if(*opt != '-') continue;
+
+        if(!strcmp(opt, "-n") )
+        {
+                       accessibility_status = atoi(argv[++i]);
+                       if(pCrtcPriv->accessibility_status != accessibility_status)
+                       {
+                               pCrtcPriv->accessibility_status = accessibility_status;
+                               bChange = TRUE;
+                       }
+        }
+        else if(!strcmp(opt, "-scale"))
+        {
+                       bScale = atoi(argv[++i]);
+
+                   pCrtcPriv->bScale = bScale;
+                       bChange = TRUE;
+                       //ErrorF("[XORG] Set Scale = %d\n", bScale);
+
+                       if(bScale)
+                       {
+                               int x,y,w,h;
+
+                               mode = argv[++i];
+                               tr = strtok(mode, seps);
+                               while(tr != NULL)
+                               {
+                                       geo[g++] = atoi(tr);
+                                       tr=strtok(NULL, seps);
+                               }
+
+                               if(g < 4)
+                               {
+                    _secXbercSetReturnProperty (value, "[Xberc] Invalid geometry(%s)\n", mode);
+                                       continue;
+                               }
+
+                               w = geo[0];
+                               h = geo[1];
+                               x = geo[2];
+                               y = geo[3];
+
+                               /*Check invalidate region */
+                               if(x<0) x=0;
+                               if(y<0) y=0;
+                               if(x+w > output_w) w = output_w-x;
+                               if(y+h > output_h) h = output_h-y;
+
+                               if(pCrtcPriv->rotate == RR_Rotate_90)
+                               {
+                                       pCrtcPriv->sx = y;
+                                       pCrtcPriv->sy = output_w - (x+w);
+                                       pCrtcPriv->sw = h;
+                                       pCrtcPriv->sh = w;
+                               }
+                               else if(pCrtcPriv->rotate == RR_Rotate_270)
+                               {
+                                       pCrtcPriv->sx = output_h - (y+h);
+                                       pCrtcPriv->sy = x;
+                                       pCrtcPriv->sw = h;
+                                       pCrtcPriv->sh = w;
+                               }
+                               else if(pCrtcPriv->rotate == RR_Rotate_180)
+                               {
+                                       pCrtcPriv->sx = output_w - (x+w);
+                                       pCrtcPriv->sy = output_h - (y+h);
+                                       pCrtcPriv->sw = w;
+                                       pCrtcPriv->sh = h;
+                               }
+                               else
+                               {
+                                       pCrtcPriv->sx = x;
+                                       pCrtcPriv->sy = y;
+                                       pCrtcPriv->sw = w;
+                                       pCrtcPriv->sh = h;
+                               }
+                       }
+        }
+    }
+
+    secCrtcEnableAccessibility (pCrtc);
+
+    return TRUE;
+}
+
+static Bool SECXbercEnableFb (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    Bool always = FALSE;
+
+    if (argc == 2)
+    {
+        char ret_buf[XBERC_BUF_SIZE] = {0,};
+        char temp[1024] = {0,};
+        xf86CrtcConfigPtr pCrtcConfig;
+        int i, len, remain = XBERC_BUF_SIZE;
+        char *buf = ret_buf;
+
+        pCrtcConfig = XF86_CRTC_CONFIG_PTR (scrn);
+        if (!pCrtcConfig)
+            goto fail_enable_fb;
+
+        for (i = 0; i < pCrtcConfig->num_output; i++)
+        {
+            xf86OutputPtr pOutput = pCrtcConfig->output[i];
+            if (pOutput->crtc)
+            {
+                SECCrtcPrivPtr pCrtcPriv = pOutput->crtc->driver_private;
+                snprintf (temp, sizeof (temp), "crtc(%d)   : %s%s\n",
+                          pCrtcPriv->mode_crtc->crtc_id,
+                          (pCrtcPriv->onoff)?"ON":"OFF",
+                          (pCrtcPriv->onoff_always)?"(always).":".");
+                len = MIN (remain, strlen (temp));
+                strncpy (buf, temp, len);
+                buf += len;
+                remain -= len;
+            }
+        }
+
+        secPlaneDump (buf, &remain);
+
+        _secXbercSetReturnProperty (value, "%s", ret_buf);
+
+        return TRUE;
+    }
+
+    if (argc > 4)
+        goto fail_enable_fb;
+
+    if (!strcmp ("always", argv[3]))
+        always = TRUE;
+
+    if (!secPropFbVisible (argv[2], always, value, scrn))
+        goto fail_enable_fb;
+
+    return TRUE;
+
+fail_enable_fb:
+    _secXbercSetReturnProperty (value, "ex) xberc fb [output]:[zpos]:[onoff] {always}.\n");
+
+    return TRUE;
+}
+
+static Bool SECXbercScreenRotate (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn)
+{
+    xf86CrtcPtr crtc = xf86CompatCrtc (scrn);
+    SECCrtcPrivPtr fimd_crtc;
+
+    if (!crtc)
+        return TRUE;
+
+    fimd_crtc = crtc->driver_private;
+
+    if (argc != 3)
+    {
+        _secXbercSetReturnProperty (value, "Current screen rotate value : %d\n", fimd_crtc->screen_rotate_degree);
+        return TRUE;
+    }
+
+    secPropScreenRotate (argv[2], value, scrn);
+
+    return TRUE;
+}
+
+static struct
+{
+    const char * Cmd;
+    const char * Description;
+    const char * Options;
+
+    const char *(*DynamicUsage) (int);
+    const char * DetailedUsage;
+
+    Bool (*set_property) (int argc, char ** argv, RRPropertyValuePtr value, ScrnInfoPtr scrn);
+    Bool (*get_property) (RRPropertyValuePtr value);
+} xberc_property_proc[] =
+{
+    {
+        "tvout", "to set Tv Out Mode", "[0-4]",
+        NULL, "[Off:0 / Clone:1 / UiClone:2 / Extension:3]",
+        SECXbercSetTvoutMode, NULL,
+    },
+
+    {
+        "connect", "to set connect mode", "[0-2]",
+        NULL, "[Off:0 / HDMI:1 / Virtual:2]",
+        SECXbercSetConnectMode, NULL,
+    },
+
+    {
+        "async_swap", "not block by vsync", "[0 or 1]",
+        NULL, "[0/1]",
+        SECXbercAsyncSwap, NULL
+    },
+
+    {
+        "dump", "to dump buffers", "[off,clear,drawable,fb,all]",
+        NULL, "[off,clear,drawable,fb,all] -count [n] -type [raw|bmp]",
+        SECXbercDump, NULL
+    },
+
+    {
+        "cursor_enable", "to enable/disable cursor", "[0 or 1]",
+        NULL, "[Enable:1 / Disable:0]",
+        SECXbercCursorEnable, NULL
+    },
+
+    {
+        "cursor_rotate", "to set cursor rotate degree", "[0,90,180,270]",
+        NULL, "[0,90,180,270]",
+        SECXbercCursorRotate, NULL
+    },
+
+    {
+        "video_punch", "to punch screen when XV put image on screen", "[0 or 1]",
+        NULL, "[0/1]",
+        SECXbercVideoPunch, NULL
+    },
+
+    {
+        "video_offset", "to add x,y to the position video", "[x,y]",
+        NULL, "[x,y]",
+        SECXbercVideoOffset, NULL
+    },
+
+    {
+        "video_fps", "to print fps of video", "[0 or 1]",
+        NULL, "[0/1]",
+        SECXbercVideoFps, NULL
+    },
+
+    {
+        "video_sync", "to sync video", "[0 or 1]",
+        NULL, "[0/1]",
+        SECXbercVideoSync, NULL
+    },
+
+    {
+        "video_output", "to set output", "[0,1,2]",
+        NULL, "[default:0 / video:1 / ext_only:2]",
+        SECXbercVideoOutput, NULL
+    },
+
+    {
+        "video_no_retbuf", "no wait until buffer returned", "[0,1]",
+        NULL, "[disable:0 / enable:1]",
+        SECXbercVideoNoRetbuf, NULL
+    },
+
+    {
+        "wb_fps", "to print fps of writeback", "[0 or 1]",
+        NULL, "[0/1]",
+        SECXbercWbFps, NULL
+    },
+
+    {
+        "wb_hz", "to set hz of writeback", "[0, 12, 15, 20, 30, 60]",
+        NULL, "[0, 12, 15, 20, 30, 60]",
+        SECXbercWbHz, NULL
+    },
+
+    {
+        "xv_perf", "to print xv elapsed time", "[off,ia,ca,cvt,wb]",
+        NULL, "[off,ia,ca,cvt,wb]",
+        SECXbercXvPerf, NULL
+    },
+
+    {
+        "swap", "to swap video layers", "",
+        NULL, "",
+        SECXbercSwap, NULL
+    },
+
+    {
+        "drmmode_dump", "to print drmmode resources", "",
+        NULL, "",
+        SECXbercDrmmodeDump, NULL
+    },
+
+    {
+        "accessibility", "to set accessibility", "-n [0 or 1] -scale [0 or 1] [{width}x{height}+{x}+{y}]",
+        NULL, "-n [0 or 1] -scale [0 or 1] [{width}x{height}+{x}+{y}]",
+        SECXbercAccessibility, NULL
+    },
+
+    {
+        "fb", "to turn framebuffer on/off", "[0~1]:[0~4]:[0~1] {always}",
+        NULL, "[output : 0(lcd)~1(ext)]:[zpos : 0 ~ 4]:[onoff : 0(on)~1(off)] {always}",
+        SECXbercEnableFb, NULL
+    },
+
+    {
+        "screen_rotate", "to set screen orientation", "[normal,inverted,left,right,0,1,2,3]",
+        NULL, "[normal,inverted,left,right,0,1,2,3]",
+        SECXbercScreenRotate, NULL
+    },
+};
+
+static int _secXbercPrintUsage (char *buf, int size, const char * exec)
+{
+    char * begin = buf;
+    char temp[1024];
+    int i, len, remain = size;
+
+    int option_cnt = sizeof (xberc_property_proc) / sizeof (xberc_property_proc[0]);
+
+    snprintf (temp, sizeof (temp), "Usage : %s [cmd] [options]\n", exec);
+    len = MIN (remain, strlen (temp));
+    strncpy (buf, temp, len);
+    buf += len;
+    remain -= len;
+
+    if (remain <= 0)
+        return (buf - begin);
+
+    snprintf (temp, sizeof (temp), "     ex)\n");
+    len = MIN (remain, strlen (temp));
+    strncpy (buf, temp, len);
+    buf += len;
+    remain -= len;
+
+    if (remain <= 0)
+        return (buf - begin);
+
+    for (i=0; i<option_cnt; i++)
+    {
+        snprintf (temp, sizeof (temp), "       %s %s %s\n", exec, xberc_property_proc[i].Cmd, xberc_property_proc[i].Options);
+        len = MIN (remain, strlen (temp));
+        strncpy (buf, temp, len);
+        buf += len;
+        remain -= len;
+
+        if (remain <= 0)
+            return (buf - begin);
+    }
+
+    snprintf (temp, sizeof (temp), " options :\n");
+    len = MIN (remain, strlen (temp));
+    strncpy (buf, temp, len);
+    buf += len;
+    remain -= len;
+
+    if (remain <= 0)
+        return (buf - begin);
+
+    for (i=0; i<option_cnt; i++)
+    {
+        if (xberc_property_proc[i].Cmd && xberc_property_proc[i].Description)
+            snprintf (temp, sizeof (temp), "  %s (%s)\n", xberc_property_proc[i].Cmd, xberc_property_proc[i].Description);
+        else
+            snprintf (temp, sizeof (temp), "  Cmd(%p) or Descriptiont(%p).\n", xberc_property_proc[i].Cmd, xberc_property_proc[i].Description);
+        len = MIN (remain, strlen (temp));
+        strncpy (buf, temp, len);
+        buf += len;
+        remain -= len;
+
+        if (remain <= 0)
+            return (buf - begin);
+
+        if (xberc_property_proc[i].DynamicUsage)
+        {
+            snprintf (temp, sizeof (temp), "     [MODULE:%s]\n", xberc_property_proc[i].DynamicUsage (MODE_NAME_ONLY));
+            len = MIN (remain, strlen (temp));
+            strncpy (buf, temp, len);
+            buf += len;
+            remain -= len;
+
+            if (remain <= 0)
+                return (buf - begin);
+        }
+
+        if (xberc_property_proc[i].DetailedUsage)
+            snprintf (temp, sizeof (temp), "     %s\n", xberc_property_proc[i].DetailedUsage);
+        else
+            snprintf (temp, sizeof (temp), "  DetailedUsage(%p).\n", xberc_property_proc[i].DetailedUsage);
+        len = MIN (remain, strlen (temp));
+        strncpy (buf, temp, len);
+        buf += len;
+        remain -= len;
+
+        if (remain <= 0)
+            return (buf - begin);
+    }
+
+    return (buf - begin);
+}
+
+static unsigned int _secXbercInit()
+{
+    XDBG_DEBUG (MSEC, "%s()\n", __FUNCTION__);
+
+    static Bool g_property_init = FALSE;
+    static unsigned int nProperty = sizeof (xberc_property_proc) / sizeof (xberc_property_proc[0]);
+
+    if (g_property_init == FALSE)
+    {
+        rr_property_atom = MakeAtom (XRRPROPERTY_ATOM, strlen (XRRPROPERTY_ATOM), TRUE);
+        g_property_init = TRUE;
+    }
+
+    return nProperty;
+}
+
+static int _secXbercParseArg (int * argc, char ** argv, RRPropertyValuePtr value)
+{
+    int i;
+    char * data;
+
+    if (argc == NULL || value == NULL || argv == NULL || value->data == NULL)
+        return FALSE;
+
+    data = value->data;
+
+    if (value->format != 8)
+        return FALSE;
+
+    if (value->size < 3 || data[value->size - 2] != '\0' || data[value->size - 1] != '\0')
+        return FALSE;
+
+    for (i=0; *data; i++)
+    {
+        argv[i] = data;
+        data += strlen (data) + 1;
+        if (data - (char*)value->data > value->size)
+            return FALSE;
+    }
+    argv[i] = data;
+    *argc = i;
+
+    return TRUE;
+}
+
+static void _secXbercSetReturnProperty (RRPropertyValuePtr value, const char * f, ...)
+{
+    int len;
+    va_list args;
+    char buf[XBERC_BUF_SIZE];
+
+    if (value->data)
+    {
+        free (value->data);
+        value->data = NULL;
+    }
+    va_start (args, f);
+    len = vsnprintf (buf, sizeof(buf), f, args) + 1;
+    va_end (args);
+
+    value->data = calloc (1, len);
+    value->format = 8;
+    value->size = len;
+
+    if (value->data)
+        strncpy (value->data, buf, len-1);
+}
+
+int
+secXbercSetProperty (xf86OutputPtr output, Atom property, RRPropertyValuePtr value)
+{
+    XDBG_TRACE (MXBRC, "%s\n", __FUNCTION__);
+
+    unsigned int nProperty = _secXbercInit();
+    unsigned int p;
+
+    int argc;
+    char * argv[1024];
+    char buf[XBERC_BUF_SIZE] = {0,};
+
+    if (rr_property_atom != property)
+    {
+        _secXbercSetReturnProperty (value, "[Xberc]: Unrecognized property name.\n");
+        return TRUE;
+    }
+
+    if (_secXbercParseArg (&argc, argv, value) == FALSE || argc < 1)
+    {
+        _secXbercSetReturnProperty (value, "[Xberc]: Parse error.\n");
+        return TRUE;
+    }
+
+    if (argc < 2)
+    {
+        _secXbercPrintUsage (buf, sizeof (buf), argv[0]);
+        _secXbercSetReturnProperty (value, buf);
+
+        return TRUE;
+    }
+
+    for (p=0; p<nProperty; p++)
+    {
+        if (!strcmp (argv[1], xberc_property_proc[p].Cmd) ||
+                (argv[1][0] == '-' && !strcmp (1 + argv[1], xberc_property_proc[p].Cmd)))
+        {
+            xberc_property_proc[p].set_property (argc, argv, value, output->scrn);
+            return TRUE;
+        }
+    }
+
+    _secXbercPrintUsage (buf, sizeof (buf), argv[0]);
+    _secXbercSetReturnProperty (value, buf);
+
+    return TRUE;
+}
diff --git a/src/crtcconfig/sec_xberc.h b/src/crtcconfig/sec_xberc.h
new file mode 100644 (file)
index 0000000..bf9beaa
--- /dev/null
@@ -0,0 +1,51 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_XBERC_H__
+#define __SEC_XBERC_H__
+
+#define XBERC
+
+#define XBERC_DUMP_MODE_DRAWABLE    0x1
+#define XBERC_DUMP_MODE_FB          0x2
+#define XBERC_DUMP_MODE_IA          0x10
+#define XBERC_DUMP_MODE_CA          0x20
+#define XBERC_DUMP_MODE_EA          0x40
+
+#define XBERC_XVPERF_MODE_IA        0x1
+#define XBERC_XVPERF_MODE_CA        0x2
+#define XBERC_XVPERF_MODE_CVT       0x10
+#define XBERC_XVPERF_MODE_WB        0x20
+#define XBERC_XVPERF_MODE_ACCESS    0x40
+
+int    secXbercSetProperty (xf86OutputPtr output, Atom property, RRPropertyValuePtr value);
+
+#endif /* __SEC_XBERC_H__ */
+
diff --git a/src/debug/sec_drmmode_dump.c b/src/debug/sec_drmmode_dump.c
new file mode 100644 (file)
index 0000000..f53ebd8
--- /dev/null
@@ -0,0 +1,422 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <time.h>
+#include <signal.h>
+
+#include "libdrm/drm.h"
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+#include "exynos_drm.h"
+#include "sec_display.h"
+#include "sec_util.h"
+
+typedef struct _DRMModeTest
+{
+    int tc_num;
+    int drm_fd;
+
+    drmModeRes *resources;
+    drmModePlaneRes *plane_resources;
+    drmModeEncoder *encoders[3];
+    drmModeConnector *connectors[3];
+    drmModeCrtc *crtcs[3];
+    drmModeFB *fbs[10];
+    drmModePlane *planes[10];
+
+} DRMModeTest;
+
+struct type_name
+{
+    int type;
+    char *name;
+};
+
+#define dump_resource(res, reply, len) if (res) reply = dump_##res(reply, len)
+
+static DRMModeTest test;
+
+struct type_name encoder_type_names[] =
+{
+    { DRM_MODE_ENCODER_NONE, "none" },
+    { DRM_MODE_ENCODER_DAC, "DAC" },
+    { DRM_MODE_ENCODER_TMDS, "TMDS" },
+    { DRM_MODE_ENCODER_LVDS, "LVDS" },
+    { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
+};
+
+struct type_name connector_status_names[] =
+{
+    { DRM_MODE_CONNECTED, "connected" },
+    { DRM_MODE_DISCONNECTED, "disconnected" },
+    { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
+};
+
+struct type_name connector_type_names[] =
+{
+    { DRM_MODE_CONNECTOR_Unknown, "unknown" },
+    { DRM_MODE_CONNECTOR_VGA, "VGA" },
+    { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
+    { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
+    { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
+    { DRM_MODE_CONNECTOR_Composite, "composite" },
+    { DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
+    { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
+    { DRM_MODE_CONNECTOR_Component, "component" },
+    { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
+    { DRM_MODE_CONNECTOR_DisplayPort, "displayport" },
+    { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
+    { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
+    { DRM_MODE_CONNECTOR_TV, "TV" },
+    { DRM_MODE_CONNECTOR_eDP, "embedded displayport" },
+};
+
+extern char* secPlaneDump (char *reply, int *len);
+extern char* secUtilDumpVideoBuffer (char *reply, int *len);
+
+static char * encoder_type_str (int type)
+{
+    int i;
+    for (i = 0; i < ARRAY_SIZE(encoder_type_names); i++)
+    {
+        if (encoder_type_names[i].type == type)
+            return encoder_type_names[i].name;
+    }
+    return "(invalid)";
+}
+
+
+static char * connector_status_str (int type)
+{
+    int i;
+    for (i = 0; i < ARRAY_SIZE(connector_status_names); i++)
+    {
+        if (connector_status_names[i].type == type)
+            return connector_status_names[i].name;
+    }
+    return "(invalid)";
+}
+
+static char * connector_type_str (int type)
+{
+    int i;
+    for (i = 0; i < ARRAY_SIZE(connector_type_names); i++)
+    {
+        if (connector_type_names[i].type == type)
+            return connector_type_names[i].name;
+    }
+    return "(invalid)";
+}
+
+static char* dump_encoders(char *reply, int *len)
+{
+    drmModeEncoder *encoder;
+    drmModeRes *resources = test.resources;
+    int i;
+
+    XDBG_REPLY ("Encoders:\n");
+    XDBG_REPLY ("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
+    for (i = 0; i < resources->count_encoders; i++)
+    {
+        encoder = test.encoders[i];;
+
+        if (!encoder)
+        {
+            XDBG_REPLY ("could not get encoder %i\n", i);
+            continue;
+        }
+        XDBG_REPLY ("%d\t%d\t%s\t0x%08x\t0x%08x\n",
+                    encoder->encoder_id,
+                    encoder->crtc_id,
+                    encoder_type_str(encoder->encoder_type),
+                    encoder->possible_crtcs,
+                    encoder->possible_clones);
+    }
+
+    XDBG_REPLY ("\n");
+
+    return reply;
+}
+
+static char* dump_mode(drmModeModeInfo *mode, char *reply, int *len)
+{
+    XDBG_REPLY ("  %s %d %d %d %d %d %d %d %d %d\n",
+                mode->name,
+                mode->vrefresh,
+                mode->hdisplay,
+                mode->hsync_start,
+                mode->hsync_end,
+                mode->htotal,
+                mode->vdisplay,
+                mode->vsync_start,
+                mode->vsync_end,
+                mode->vtotal);
+
+    return reply;
+}
+
+static char*
+dump_props(drmModeConnector *connector, char *reply, int *len)
+{
+    drmModePropertyPtr props;
+    int i;
+
+    for (i = 0; i < connector->count_props; i++)
+    {
+        props = drmModeGetProperty(test.drm_fd, connector->props[i]);
+        if (props == NULL)
+            continue;
+        XDBG_REPLY ("\t%s, flags %d\n", props->name, props->flags);
+        drmModeFreeProperty(props);
+    }
+
+    return reply;
+}
+
+static char* dump_connectors(char *reply, int *len)
+{
+    drmModeConnector *connector;
+    drmModeRes *resources = test.resources;
+    int i, j;
+
+    XDBG_REPLY ("Connectors:\n");
+    XDBG_REPLY ("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\tencoders\n");
+    for (i = 0; i < resources->count_connectors; i++)
+    {
+        connector = test.connectors[i];
+
+        if (!connector)
+        {
+            XDBG_REPLY ("could not get connector %i\n", i);
+            continue;
+        }
+
+        XDBG_REPLY ("%d\t%d\t%s\t%s\t%dx%d\t\t%d\t",
+                    connector->connector_id,
+                    connector->encoder_id,
+                    connector_status_str(connector->connection),
+                    connector_type_str(connector->connector_type),
+                    connector->mmWidth, connector->mmHeight,
+                    connector->count_modes);
+
+        for (j = 0; j < connector->count_encoders; j++)
+            XDBG_REPLY ("%s%d", j > 0 ? ", " : "", connector->encoders[j]);
+        XDBG_REPLY ("\n");
+
+        if (!connector->count_modes)
+            continue;
+
+        XDBG_REPLY ("  modes:\n");
+        XDBG_REPLY ("  name refresh (Hz) hdisp hss hse htot vdisp "
+                    "vss vse vtot)\n");
+        for (j = 0; j < connector->count_modes; j++)
+            reply = dump_mode(&connector->modes[j], reply, len);
+
+        XDBG_REPLY ("  props:\n");
+        reply = dump_props(connector, reply, len);
+    }
+    XDBG_REPLY ("\n");
+
+    return reply;
+}
+
+static char* dump_crtcs(char *reply, int *len)
+{
+    drmModeCrtc *crtc;
+    drmModeRes *resources = test.resources;
+    int i;
+
+    XDBG_REPLY ("CRTCs:\n");
+    XDBG_REPLY ("id\tfb\tpos\tsize\n");
+    for (i = 0; i < resources->count_crtcs; i++)
+    {
+        crtc = test.crtcs[i];
+
+        if (!crtc)
+        {
+            XDBG_REPLY ("could not get crtc %i\n", i);
+            continue;
+        }
+        XDBG_REPLY ("%d\t%d\t(%d,%d)\t(%dx%d)\n",
+                    crtc->crtc_id,
+                    crtc->buffer_id,
+                    crtc->x, crtc->y,
+                    crtc->width, crtc->height);
+        reply = dump_mode(&crtc->mode, reply, len);
+    }
+    XDBG_REPLY ("\n");
+
+    return reply;
+}
+
+static char* dump_framebuffers(char *reply, int *len)
+{
+    drmModeFB *fb;
+    drmModeRes *resources = test.resources;
+    int i;
+
+    XDBG_REPLY ("Frame buffers:\n");
+    XDBG_REPLY ("id\tsize\tpitch\n");
+    for (i = 0; i < resources->count_fbs; i++)
+    {
+        fb = test.fbs[i];
+
+        if (!fb)
+        {
+            XDBG_REPLY ("could not get fb %i\n", i);
+            continue;
+        }
+        XDBG_REPLY ("%u\t(%ux%u)\t%u\n",
+                    fb->fb_id,
+                    fb->width, fb->height,
+                    fb->pitch);
+    }
+    XDBG_REPLY ("\n");
+
+    return reply;
+}
+
+static char* get_resources_all (char *reply, int *len)
+{
+    int i;
+
+    /* get drm mode resources */
+    test.resources = drmModeGetResources (test.drm_fd);
+    if (!test.resources)
+    {
+        XDBG_REPLY ("drmModeGetResources failed: %s\n", strerror(errno));
+        return reply;
+    }
+
+    /* get drm mode encoder */
+    for (i = 0; i < test.resources->count_encoders; i++)
+    {
+        test.encoders[i] = drmModeGetEncoder (test.drm_fd, test.resources->encoders[i]);
+        if (!test.encoders[i])
+        {
+            XDBG_REPLY ("fail to get encoder %i; %s\n",
+                        test.resources->encoders[i], strerror(errno));
+            continue;
+        }
+    }
+
+    /* get drm mode connector */
+    for (i = 0; i < test.resources->count_connectors; i++)
+    {
+        test.connectors[i] = drmModeGetConnector (test.drm_fd, test.resources->connectors[i]);
+        if (!test.connectors[i])
+        {
+            XDBG_REPLY ("fail to get connector %i; %s\n",
+                        test.resources->connectors[i], strerror(errno));
+            continue;
+        }
+    }
+
+    /* get drm mode crtc */
+    for (i = 0; i < test.resources->count_crtcs; i++)
+    {
+        test.crtcs[i] = drmModeGetCrtc (test.drm_fd, test.resources->crtcs[i]);
+        if (!test.crtcs[i])
+        {
+            XDBG_REPLY ("fail to get crtc %i; %s\n",
+                        test.resources->crtcs[i], strerror(errno));
+            continue;
+        }
+    }
+
+    /* drm mode fb */
+    for (i = 0; i < test.resources->count_fbs; i++)
+    {
+        test.fbs[i] = drmModeGetFB (test.drm_fd, test.resources->fbs[i]);
+        if (!test.fbs[i])
+        {
+            XDBG_REPLY ("fail to get fb %i; %s\n",
+                        test.resources->fbs[i], strerror(errno));
+            continue;
+        }
+    }
+
+    return reply;
+}
+
+static void free_resources_all ()
+{
+    int i;
+
+    if (test.resources)
+    {
+        /* free drm mode fbs */
+        for (i = 0; i < test.resources->count_fbs; i++)
+            if (test.fbs[i])
+            {
+                drmModeFreeFB (test.fbs[i]);
+                test.fbs[i] = NULL;
+            }
+
+        /* free drm mode crtcs */
+        for (i = 0; i < test.resources->count_crtcs; i++)
+            if (test.crtcs[i])
+            {
+                drmModeFreeCrtc (test.crtcs[i]);
+                test.crtcs[i] = NULL;
+            }
+
+        /* free drm mode connectors */
+        for (i = 0; i < test.resources->count_connectors; i++)
+            if (test.connectors[i])
+            {
+                drmModeFreeConnector (test.connectors[i]);
+                test.connectors[i] = NULL;
+            }
+
+        /* free drm mode encoders */
+        for (i = 0; i < test.resources->count_encoders; i++)
+            if (test.encoders[i])
+            {
+                drmModeFreeEncoder (test.encoders[i]);
+                test.encoders[i] = NULL;
+            }
+
+        /* free drm mode resources */
+        drmModeFreeResources (test.resources);
+        test.resources = NULL;
+    }
+}
+
+void sec_drmmode_dump (int drm_fd, char *reply, int *len)
+{
+    int encoders, connectors, crtcs, modes, framebuffers;
+
+    encoders = connectors = crtcs = modes = framebuffers = 1;
+
+    test.drm_fd = drm_fd;
+
+    get_resources_all (reply, len);
+    dump_resource(encoders, reply, len);
+    dump_resource(connectors, reply, len);
+    dump_resource(crtcs, reply, len);
+    dump_resource(framebuffers, reply, len);
+
+    reply = secPlaneDump (reply, len);
+    reply = secUtilDumpVideoBuffer (reply, len);
+
+    free_resources_all ();
+
+}
diff --git a/src/debug/sec_drmmode_dump.h b/src/debug/sec_drmmode_dump.h
new file mode 100644 (file)
index 0000000..b1493a9
--- /dev/null
@@ -0,0 +1,36 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_DRMMODE_DUMP_H_
+#define __SEC_DRMMODE_DUMP_H_
+
+void sec_drmmode_dump (int drm_fd, char *reply, int *len);
+
+#endif
diff --git a/src/g2d/fimg2d.c b/src/g2d/fimg2d.c
new file mode 100644 (file)
index 0000000..a68347b
--- /dev/null
@@ -0,0 +1,670 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+#include "exynos_drm.h"
+#include "fimg2d.h"
+#include "sec_util.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 1
+#endif
+
+#define G2D_MAX_CMD 64
+#define G2D_MAX_GEM_CMD 64
+#define G2D_MAX_CMD_LIST    64
+
+typedef struct _G2D_CONTEXT {
+    unsigned int major;
+    unsigned int minor;
+    int drm_fd;
+
+    struct drm_exynos_g2d_cmd cmd[G2D_MAX_CMD];
+    struct drm_exynos_g2d_cmd cmd_gem[G2D_MAX_GEM_CMD];
+
+    unsigned int cmd_nr;
+    unsigned int cmd_gem_nr;
+
+    unsigned int cmdlist_nr;
+}G2dContext;
+
+G2dContext* gCtx=NULL;
+
+static void
+_g2d_clear(void)
+{
+    gCtx->cmd_nr = 0;
+    gCtx->cmd_gem_nr = 0;
+}
+
+int
+g2d_init (int fd)
+{
+    int ret;
+    struct drm_exynos_g2d_get_ver ver;
+
+    if(gCtx) return FALSE;
+
+   gCtx = calloc(1, sizeof(*gCtx));
+   gCtx->drm_fd = fd;
+
+    ret = ioctl(fd, DRM_IOCTL_EXYNOS_G2D_GET_VER, &ver);
+    if (ret < 0) {
+        XDBG_ERROR (MG2D, "failed to get version: %s\n", strerror(-ret));
+        free(gCtx);
+        gCtx = NULL;
+
+        return FALSE;
+    }
+
+    gCtx->major = ver.major;
+    gCtx->minor = ver.minor;
+
+    XDBG_INFO (MG2D, "[G2D] version(%d.%d) init....OK\n", gCtx->major, gCtx->minor);
+
+    return TRUE;
+}
+
+void
+g2d_fini (void)
+{
+    free(gCtx);
+    gCtx = NULL;
+}
+
+int
+g2d_add_cmd (unsigned int cmd, unsigned int value)
+{
+    switch(cmd) /* Check GEM Command */
+    {
+    case SRC_BASE_ADDR_REG:
+    case SRC_PLANE2_BASE_ADDR_REG:
+    case DST_BASE_ADDR_REG:
+    case DST_PLANE2_BASE_ADDR_REG:
+    case PAT_BASE_ADDR_REG:
+    case MASK_BASE_ADDR_REG:
+        if(gCtx->cmd_gem_nr >= G2D_MAX_GEM_CMD)
+        {
+            XDBG_ERROR (MG2D, "Overflow cmd_gem size:%d\n", gCtx->cmd_gem_nr);
+            return FALSE;
+        }
+
+        gCtx->cmd_gem[gCtx->cmd_gem_nr].offset = cmd;
+        gCtx->cmd_gem[gCtx->cmd_gem_nr].data = value;
+        gCtx->cmd_gem_nr++;
+        break;
+    default:
+        if(gCtx->cmd_nr >= G2D_MAX_CMD)
+        {
+            XDBG_ERROR (MG2D, "Overflow cmd size:%d\n", gCtx->cmd_nr);
+            return FALSE;
+        }
+
+        gCtx->cmd[gCtx->cmd_nr].offset = cmd;
+        gCtx->cmd[gCtx->cmd_nr].data = value;
+        gCtx->cmd_nr++;
+        break;
+    }
+
+    return TRUE;
+}
+
+void
+g2d_reset (unsigned int clear_reg)
+{
+    gCtx->cmd_nr = 0;
+    gCtx->cmd_gem_nr = 0;
+
+    if(clear_reg)
+    {
+        g2d_add_cmd(SOFT_RESET_REG, 0x01);
+    }
+}
+
+int
+g2d_exec (void)
+{
+    struct drm_exynos_g2d_exec exec;
+    int ret;
+
+    if(gCtx->cmdlist_nr == 0)
+        return TRUE;
+
+    exec.async = 0;
+    ret = ioctl(gCtx->drm_fd, DRM_IOCTL_EXYNOS_G2D_EXEC, &exec);
+    if (ret < 0) {
+        XDBG_ERROR (MG2D, "failed to execute(%d): %s\n", ret, strerror(-ret));
+        return FALSE;
+    }
+
+    gCtx->cmdlist_nr = 0;
+    return TRUE;
+}
+
+int
+g2d_flush (void)
+{
+    int ret;
+    struct drm_exynos_g2d_set_cmdlist cmdlist;
+
+    if (gCtx->cmd_nr == 0 && gCtx->cmd_gem_nr == 0)
+        return TRUE;
+
+    if(gCtx->cmdlist_nr >= G2D_MAX_CMD_LIST)
+    {
+        XDBG_WARNING (MG2D, "Overflow cmdlist:%d\n", gCtx->cmdlist_nr);
+        g2d_exec();
+    }
+
+    memset(&cmdlist, 0, sizeof(struct drm_exynos_g2d_set_cmdlist));
+
+    cmdlist.cmd = (unsigned long)&gCtx->cmd[0];
+    cmdlist.cmd_gem = (unsigned long)&gCtx->cmd_gem[0];
+    cmdlist.cmd_nr = gCtx->cmd_nr;
+    cmdlist.cmd_gem_nr = gCtx->cmd_gem_nr;
+    cmdlist.event_type = G2D_EVENT_NOT;
+    cmdlist.user_data = 0;
+
+    gCtx->cmd_nr = 0;
+    gCtx->cmd_gem_nr = 0;
+    ret = ioctl(gCtx->drm_fd, DRM_IOCTL_EXYNOS_G2D_SET_CMDLIST, &cmdlist);
+    if (ret < 0) {
+
+        XDBG_ERROR (MG2D, "numFlush:%d, failed to set cmdlist(%d): %s\n", gCtx->cmdlist_nr, ret, strerror(-ret));
+        return FALSE;
+    }
+
+    gCtx->cmdlist_nr++;
+    return TRUE;
+}
+
+G2dImage*
+g2d_image_new(void)
+{
+    G2dImage* img;
+
+    img = calloc(1, sizeof(G2dImage));
+    if(img == NULL)
+    {
+        XDBG_ERROR (MG2D, "Cannot create solid image\n");
+        return NULL;
+    }
+
+    img->repeat_mode = G2D_REPEAT_MODE_NONE;
+    img->scale_mode = G2D_SCALE_MODE_NONE;
+    img->xscale = G2D_FIXED_1;
+    img->yscale = G2D_FIXED_1;
+
+    return img;
+}
+
+G2dImage*
+g2d_image_create_solid (unsigned int color)
+{
+    G2dImage* img;
+
+    img = g2d_image_new();
+    if(img == NULL)
+    {
+        XDBG_ERROR (MG2D, "Cannot create solid image\n");
+        return NULL;
+    }
+
+    img->select_mode = G2D_SELECT_MODE_FGCOLOR;
+    img->color_mode = G2D_COLOR_FMT_ARGB8888|G2D_ORDER_AXRGB;
+    img->data.color = color;
+    img->width = -1;
+    img->height = -1;
+
+    return img;
+}
+
+G2dImage*
+g2d_image_create_bo (G2dColorMode format, unsigned int width, unsigned int height,
+                                            unsigned int bo, unsigned int stride)
+{
+    G2dImage* img;
+
+    img = g2d_image_new();
+    if(img == NULL)
+    {
+        XDBG_ERROR (MG2D, "Cannot alloc bo\n");
+        return NULL;
+    }
+
+    img->select_mode = G2D_SELECT_MODE_NORMAL;
+    img->color_mode = format;
+    img->width = width;
+    img->height = height;
+
+    if(bo)
+    {
+        img->data.bo[0] = bo;
+        img->stride = stride;
+    }
+    else
+    {
+        unsigned int stride;
+        struct drm_exynos_gem_create arg;
+
+        switch(format&G2D_COLOR_FMT_MASK)
+        {
+        case G2D_COLOR_FMT_XRGB8888:
+        case G2D_COLOR_FMT_ARGB8888:
+            stride = width*4;
+            break;
+        case G2D_COLOR_FMT_A1:
+            stride = (width+7) / 8;
+            break;
+        case G2D_COLOR_FMT_A4:
+            stride = (width*4+7) /8;
+            break;
+        case G2D_COLOR_FMT_A8:
+        case G2D_COLOR_FMT_L8:
+            stride = width;
+            break;
+        default:
+            XDBG_ERROR (MG2D, "Unsurpported format(%d)\n", format);
+            free(img);
+            return NULL;
+        }
+
+        /* Allocation gem buffer */
+        arg.flags = EXYNOS_BO_CACHABLE;
+        arg.size = stride*height;
+        if(drmCommandWriteRead(gCtx->drm_fd, DRM_EXYNOS_GEM_CREATE, &arg, sizeof(arg)))
+        {
+            XDBG_ERROR (MG2D, "Cannot create bo image(flag:%x, size:%d)\n", arg.flags, (unsigned int)arg.size);
+            free(img);
+            return NULL;
+        }
+
+        /* Map gembuffer */
+        {
+            struct drm_exynos_gem_mmap arg_map;
+
+            memset(&arg_map, 0, sizeof(arg_map));
+            arg_map.handle = arg.handle;
+            arg_map.size = arg.size;
+            if(drmCommandWriteRead(gCtx->drm_fd, DRM_EXYNOS_GEM_MMAP, &arg_map, sizeof(arg_map)))
+            {
+                XDBG_ERROR (MG2D, "Cannot map offset bo image\n");
+                free(img);
+                return NULL;
+            }
+
+            img->mapped_ptr[0] = (void*)(unsigned long)arg_map.mapped;
+        }
+
+        img->stride = stride;
+        img->data.bo[0] = arg.handle;
+        img->need_free = 1;
+    }
+
+    return img;
+}
+
+G2dImage*
+g2d_image_create_bo2 (G2dColorMode format,
+                      unsigned int width, unsigned int height,
+                      unsigned int bo1, unsigned int bo2, unsigned int stride)
+{
+    G2dImage* img;
+
+    if (bo1 == 0)
+    {
+        XDBG_ERROR (MG2D, "[G2D] first bo is NULL. \n");
+        return NULL;
+    }
+
+    if (format & G2D_YCbCr_2PLANE)
+        if (bo2 == 0)
+        {
+            XDBG_ERROR (MG2D, "[G2D] second bo is NULL. \n");
+            return NULL;
+        }
+
+    img = g2d_image_new();
+
+    if(img == NULL)
+    {
+        XDBG_ERROR (MG2D, "Cannot alloc bo\n");
+        return NULL;
+    }
+
+    img->select_mode = G2D_SELECT_MODE_NORMAL;
+    img->color_mode = format;
+    img->width = width;
+    img->height = height;
+
+    img->data.bo[0] = bo1;
+    img->data.bo[1] = bo2;
+    img->stride = stride;
+
+    return img;
+}
+
+G2dImage*
+g2d_image_create_data (G2dColorMode format, unsigned int width, unsigned int height,
+                                            void* data, unsigned int stride)
+{
+    G2dImage* img;
+
+    img = g2d_image_new();
+    if(img == NULL)
+    {
+        XDBG_ERROR (MG2D, "Cannot alloc bo\n");
+        return NULL;
+    }
+
+    img->select_mode = G2D_SELECT_MODE_NORMAL;
+    img->color_mode = format;
+    img->width = width;
+    img->height = height;
+
+    if(data)
+    {
+        struct drm_exynos_gem_userptr userptr;
+
+        memset(&userptr, 0, sizeof(struct drm_exynos_gem_userptr));
+        userptr.userptr = (uint64_t)((uint32_t)data);
+        userptr.size = stride*height;
+
+        img->mapped_ptr[0] = data;
+        img->stride = stride;
+        if(drmCommandWriteRead(gCtx->drm_fd,
+                                        DRM_EXYNOS_GEM_USERPTR,
+                                        &userptr, sizeof(userptr)))
+        {
+            XDBG_ERROR (MG2D, "Cannot create userptr(ptr:%p, size:%d)\n", (void*)((uint32_t)userptr.userptr), (uint32_t)userptr.size);
+            free(img);
+            return NULL;
+        }
+        img->data.bo[0] = userptr.handle;
+        img->need_free = 1;
+    }
+    else
+    {
+        unsigned int stride;
+        struct drm_exynos_gem_create arg;
+
+        switch(format&G2D_COLOR_FMT_MASK)
+        {
+        case G2D_COLOR_FMT_XRGB8888:
+        case G2D_COLOR_FMT_ARGB8888:
+            stride = width*4;
+            break;
+        case G2D_COLOR_FMT_A1:
+            stride = (width+7) / 8;
+            break;
+        case G2D_COLOR_FMT_A4:
+            stride = (width*4+7) /8;
+            break;
+        case G2D_COLOR_FMT_A8:
+        case G2D_COLOR_FMT_L8:
+            stride = width;
+            break;
+        default:
+            XDBG_ERROR (MG2D, "Unsurpported format(%d)\n", format);
+            free(img);
+            return NULL;
+        }
+
+        /* Allocation gem buffer */
+        arg.flags = EXYNOS_BO_NONCONTIG|EXYNOS_BO_CACHABLE;
+        arg.size = stride*height;
+        if(drmCommandWriteRead(gCtx->drm_fd,
+                                        DRM_EXYNOS_GEM_CREATE,
+                                        &arg, sizeof(arg)))
+        {
+            XDBG_ERROR (MG2D, "Cannot create bo image(flag:%x, size:%d)\n", arg.flags, (unsigned int)arg.size);
+            free(img);
+            return NULL;
+        }
+
+        /* Map gembuffer */
+        {
+            struct drm_exynos_gem_mmap arg_map;
+
+            memset(&arg_map, 0, sizeof(arg_map));
+            arg_map.handle = arg.handle;
+            arg_map.size = arg.size;
+            if(drmCommandWriteRead(gCtx->drm_fd,
+                                                    DRM_EXYNOS_GEM_MMAP,
+                                                    &arg_map, sizeof(arg_map)))
+            {
+                XDBG_ERROR (MG2D, "Cannot map offset bo image\n");
+                free(img);
+                return NULL;
+            }
+
+            img->mapped_ptr[0] = (void*)(unsigned long)arg_map.mapped;
+        }
+
+        img->stride = stride;
+        img->data.bo[0] = arg.handle;
+        img->need_free = 1;
+    }
+
+    return img;
+}
+
+void
+g2d_image_free (G2dImage* img)
+{
+    if(img->need_free)
+    {
+        struct drm_gem_close arg;
+
+        /* Free gem buffer */
+        memset(&arg, 0, sizeof(arg));
+        arg.handle = img->data.bo[0];
+        if(drmIoctl(gCtx->drm_fd, DRM_IOCTL_GEM_CLOSE, &arg))
+        {
+            XDBG_ERROR (MG2D, "[G2D] %s:%d error: %d\n",__FUNCTION__, __LINE__, errno);
+        }
+    }
+
+    free(img);
+}
+
+int
+g2d_set_src(G2dImage* img)
+{
+    if(img == NULL) return FALSE;
+
+    g2d_add_cmd(SRC_SELECT_REG, img->select_mode);
+    g2d_add_cmd(SRC_COLOR_MODE_REG, img->color_mode);
+
+    switch(img->select_mode)
+    {
+    case G2D_SELECT_MODE_NORMAL:
+        g2d_add_cmd(SRC_BASE_ADDR_REG, img->data.bo[0]);
+        if (img->color_mode & G2D_YCbCr_2PLANE)
+        {
+            if (img->data.bo[1] > 0)
+                g2d_add_cmd(SRC_PLANE2_BASE_ADDR_REG, img->data.bo[1]);
+            else
+                XDBG_ERROR (MG2D, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__);
+        }
+        g2d_add_cmd(SRC_STRIDE_REG, img->stride);
+        break;
+    case G2D_SELECT_MODE_FGCOLOR:
+        g2d_add_cmd(FG_COLOR_REG, img->data.color);
+        break;
+    case G2D_SELECT_MODE_BGCOLOR:
+        g2d_add_cmd(BG_COLOR_REG, img->data.color);
+        break;
+    default:
+        XDBG_ERROR (MG2D, "Error: set src\n");
+        _g2d_clear();
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+int
+g2d_set_mask(G2dImage* img)
+{
+    G2dMaskModeVal mode;
+
+    if(img == NULL) return FALSE;
+    if(img->select_mode != G2D_SELECT_MODE_NORMAL) return FALSE;
+
+    g2d_add_cmd(MASK_BASE_ADDR_REG, img->data.bo[0]);
+    g2d_add_cmd(MASK_STRIDE_REG, img->stride);
+
+    mode.val = 0;
+    switch(img->color_mode & G2D_COLOR_FMT_MASK)
+    {
+    case G2D_COLOR_FMT_A1:
+        mode.data.maskMode = G2D_MASK_MODE_1BPP;
+        break;
+    case G2D_COLOR_FMT_A4:
+        mode.data.maskMode = G2D_MASK_MODE_4BPP;
+        break;
+    case G2D_COLOR_FMT_A8:
+        mode.data.maskMode = G2D_MASK_MODE_8BPP;
+        break;
+    case G2D_COLOR_FMT_ARGB8888:
+        mode.data.maskMode = G2D_MASK_MODE_32BPP;
+        mode.data.maskOrder = (img->color_mode&G2D_ORDER_MASK)>>4;
+        break;
+    case G2D_COLOR_FMT_RGB565:
+        mode.data.maskMode = G2D_MASK_MODE_16BPP_565;
+        mode.data.maskOrder = (img->color_mode&G2D_ORDER_MASK)>>4;
+        break;
+    case G2D_COLOR_FMT_ARGB1555:
+        mode.data.maskMode = G2D_MASK_MODE_16BPP_1555;
+        mode.data.maskOrder = (img->color_mode&G2D_ORDER_MASK)>>4;
+        break;
+    case G2D_COLOR_FMT_ARGB4444:
+        mode.data.maskMode = G2D_MASK_MODE_16BPP_4444;
+        mode.data.maskOrder = (img->color_mode&G2D_ORDER_MASK)>>4;
+        break;
+    default:
+        break;
+    }
+    g2d_add_cmd(MASK_MODE_REG, mode.val);
+
+    return TRUE;
+}
+
+int
+g2d_set_dst(G2dImage* img)
+{
+    if(img == NULL) return FALSE;
+
+    g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_FGCOLOR);
+    g2d_add_cmd(DST_COLOR_MODE_REG, img->color_mode);
+
+    switch(img->select_mode)
+    {
+    case G2D_SELECT_MODE_NORMAL:
+        g2d_add_cmd(DST_BASE_ADDR_REG, img->data.bo[0]);
+        g2d_add_cmd(DST_STRIDE_REG, img->stride);
+        break;
+    case G2D_SELECT_MODE_FGCOLOR:
+        g2d_add_cmd(FG_COLOR_REG, img->data.color);
+        break;
+    case G2D_SELECT_MODE_BGCOLOR:
+        g2d_add_cmd(BG_COLOR_REG, img->data.color);
+        break;
+    default:
+        XDBG_ERROR (MG2D, "Error: set src\n");
+        _g2d_clear();
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+unsigned int
+g2d_get_blend_op(G2dOp op)
+{
+    G2dBlendFunctionVal val;
+#define     set_bf(sc, si, scsa, scda, dc, di, dcsa, dcda)    \
+                        val.data.srcCoeff = sc;        \
+                        val.data.invSrcColorCoeff = si;    \
+                        val.data.srcCoeffSrcA = scsa;        \
+                        val.data.srcCoeffDstA = scda;        \
+                        val.data.dstCoeff = dc;        \
+                        val.data.invDstColorCoeff = di;    \
+                        val.data.dstCoeffSrcA = dcsa;        \
+                        val.data.dstCoeffDstA = dcda
+
+    val.val = 0;
+    switch (op)
+    {
+    case G2D_OP_CLEAR:
+    case G2D_OP_DISJOINT_CLEAR:
+    case G2D_OP_CONJOINT_CLEAR:
+        set_bf (G2D_COEFF_MODE_ZERO, 0,0,0,
+                    G2D_COEFF_MODE_ZERO, 0,0,0);
+        break;
+    case G2D_OP_SRC:
+    case G2D_OP_DISJOINT_SRC:
+    case G2D_OP_CONJOINT_SRC:
+        set_bf (G2D_COEFF_MODE_ONE, 0,0,0,
+                    G2D_COEFF_MODE_ZERO, 0,0,0);
+        break;
+    case G2D_OP_DST:
+    case G2D_OP_DISJOINT_DST:
+    case G2D_OP_CONJOINT_DST:
+        set_bf (G2D_COEFF_MODE_ZERO, 0,0,0,
+                    G2D_COEFF_MODE_ONE, 0,0,0);
+        break;
+    case G2D_OP_OVER:
+        set_bf (G2D_COEFF_MODE_ONE, 0,0,0,
+                    G2D_COEFF_MODE_SRC_ALPHA, 1,0,0);
+        break;
+    case G2D_OP_OVER_REVERSE:
+    case G2D_OP_IN:
+    case G2D_OP_IN_REVERSE:
+    case G2D_OP_OUT:
+    case G2D_OP_OUT_REVERSE:
+    case G2D_OP_ATOP:
+    case G2D_OP_ATOP_REVERSE:
+    case G2D_OP_XOR:
+    case G2D_OP_ADD:
+    case G2D_OP_NONE:
+    default:
+        XDBG_ERROR (MG2D, "[FIMG2D] Not support op:%d\n", op);
+        set_bf (G2D_COEFF_MODE_ONE, 0,0,0,
+                    G2D_COEFF_MODE_ZERO, 0,0,0);
+        break;
+    }
+#undef set_bf
+
+    return val.val;
+}
+
+void
+g2d_dump(void)
+{
+    int i;
+    XDBG_DEBUG (MG2D, "==================\n");
+    XDBG_DEBUG (MG2D, "         G2D REG DUMP         \n");
+    XDBG_DEBUG (MG2D, "==================\n");
+
+    for(i=0; i<gCtx->cmd_gem_nr; i++)
+    {
+        XDBG_DEBUG (MG2D, "[GEM] 0x%08x   0x%08x\n",
+                gCtx->cmd_gem[i].offset, gCtx->cmd_gem[i].data);
+    }
+
+    for(i=0; i<gCtx->cmd_nr; i++)
+    {
+        XDBG_DEBUG (MG2D, "[CMD] 0x%08x   0x%08x\n",
+                gCtx->cmd[i].offset, gCtx->cmd[i].data);
+    }
+}
diff --git a/src/g2d/fimg2d.h b/src/g2d/fimg2d.h
new file mode 100644 (file)
index 0000000..ada1c2f
--- /dev/null
@@ -0,0 +1,670 @@
+#ifndef _FIMG2D_H_
+#define _FIMG2D_H_
+
+#include "fimg2d_reg.h"
+
+typedef unsigned int G2dFixed;
+
+typedef enum {
+       G2D_INT_MODE_LEVEL,
+       G2D_INT_MODE_EDGE,
+
+       G2D_INT_MODE_MAX = G2D_INT_MODE_EDGE
+} G2dIntMode;
+
+typedef enum {
+       G2D_TRANSPARENT_MODE_OPAQUE,
+       G2D_TRANSPARENT_MODE_TRANSPARENT,
+       G2D_TRANSPARENT_MODE_BLUESCREEN,
+       G2D_TRANSPARENT_MODE_MAX
+} G2dTransparentMode;
+
+typedef enum {
+       G2D_COLORKEY_MODE_DISABLE = 0,
+       G2D_COLORKEY_MODE_SRC_RGBA = (1<<0),
+       G2D_COLORKEY_MODE_DST_RGBA = (1<<1),
+       G2D_COLORKEY_MODE_SRC_YCbCr = (1<<2),                   /* VER4.1 */
+       G2D_COLORKEY_MODE_DST_YCbCr = (1<<3),                   /* VER4.1 */
+       
+       G2D_COLORKEY_MODE_MASK = 15, 
+} G2dColorKeyMode;
+
+typedef enum {
+       G2D_ALPHA_BLEND_MODE_DISABLE,
+       G2D_ALPHA_BLEND_MODE_ENABLE,
+       G2D_ALPHA_BLEND_MODE_FADING,                    /* VER3.0 */
+       G2D_ALPHA_BLEND_MODE_MAX
+} G2dAlphaBlendMode;
+
+typedef enum {
+       G2D_SRC_NONPREBLAND_MODE_DISABLE,               /* VER3.0 */
+       G2D_SRC_NONPREBLAND_MODE_CONSTANT,      /* VER3.0 */
+       G2D_SRC_NONPREBLAND_MODE_PERPIXEL,              /* VER3.0 */
+       G2D_SRC_NONPREBLAND_MODE_MAX,                   /* VER3.0 */
+} G2dSrcNonPreBlendMode;
+
+typedef enum {
+       G2D_SELECT_SRC_FOR_ALPHA_BLEND, /* VER4.1 */
+       G2D_SELECT_ROP_FOR_ALPHA_BLEND, /* VER4.1 */
+} G2dSelectAlphaSource;
+
+
+typedef enum {                                                         /* VER4.1 */
+       G2D_COEFF_MODE_ONE,
+       G2D_COEFF_MODE_ZERO,
+       G2D_COEFF_MODE_SRC_ALPHA,
+       G2D_COEFF_MODE_SRC_COLOR,
+       G2D_COEFF_MODE_DST_ALPHA,
+       G2D_COEFF_MODE_DST_COLOR,
+       G2D_COEFF_MODE_GB_ALPHA,        /* Global Alpha : Set by ALPHA_REG(0x618) */
+       G2D_COEFF_MODE_GB_COLOR,        /* Global Alpha : Set by ALPHA_REG(0x618) */
+       G2D_COEFF_MODE_DISJOINT_S, /* (1-SRC alpha)/DST Alpha */
+       G2D_COEFF_MODE_DISJOINT_D, /* (1-DST alpha)/SRC Alpha */
+       G2D_COEFF_MODE_CONJOINT_S, /* SRC alpha/DST alpha */
+       G2D_COEFF_MODE_CONJOINT_D, /* DST alpha/SRC alpha */
+       G2D_COEFF_MODE_MASK
+}G2dCoeffMode;
+
+typedef enum {
+    G2D_ACOEFF_MODE_A,          /*alpha*/
+    G2D_ACOEFF_MODE_APGA,   /*alpha + global alpha*/
+    G2D_ACOEFF_MODE_AMGA,   /*alpha * global alpha*/
+    G2D_ACOEFF_MODE_MASK
+}G2dACoeffMode;
+
+typedef enum {
+       G2D_SELECT_MODE_NORMAL = (0 << 0),
+       G2D_SELECT_MODE_FGCOLOR = (1 << 0),
+       G2D_SELECT_MODE_BGCOLOR = (2 << 0),
+       G2D_SELECT_MODE_MAX = (3 << 0),
+} G2dSelectMode;
+
+typedef enum {
+       /* COLOR FORMAT */
+       G2D_COLOR_FMT_XRGB8888,
+       G2D_COLOR_FMT_ARGB8888,
+       G2D_COLOR_FMT_RGB565,
+       G2D_COLOR_FMT_XRGB1555,
+       G2D_COLOR_FMT_ARGB1555,
+       G2D_COLOR_FMT_XRGB4444,
+       G2D_COLOR_FMT_ARGB4444,
+       G2D_COLOR_FMT_PRGB888,
+       G2D_COLOR_FMT_YCbCr444,
+       G2D_COLOR_FMT_YCbCr422,
+       G2D_COLOR_FMT_YCbCr420=10,     
+       G2D_COLOR_FMT_A8,                       /* alpha 8bit */
+       G2D_COLOR_FMT_L8,                       /* Luminance 8bit: gray color */
+       G2D_COLOR_FMT_A1,                       /* alpha 1bit */
+       G2D_COLOR_FMT_A4,                       /* alpha 4bit */
+       G2D_COLOR_FMT_MASK = (15 << 0),         /* VER4.1 */
+
+       /* COLOR ORDER */
+       G2D_ORDER_AXRGB = (0 << 4),                     /* VER4.1 */
+       G2D_ORDER_RGBAX = (1 << 4),                     /* VER4.1 */
+       G2D_ORDER_AXBGR = (2 << 4),                     /* VER4.1 */
+       G2D_ORDER_BGRAX = (3 << 4),                     /* VER4.1 */
+       G2D_ORDER_MASK = (3 << 4),                              /* VER4.1 */
+
+       /* Number of YCbCr plane */
+       G2D_YCbCr_1PLANE = (0 << 8),                    /* VER4.1 */
+       G2D_YCbCr_2PLANE = (1 << 8),                    /* VER4.1 */
+       G2D_YCbCr_PLANE_MASK = (3 << 8),                /* VER4.1 */
+       
+       /* Order in YCbCr */
+       G2D_YCbCr_ORDER_CrY1CbY0 = (0 << 12),   /* VER4.1 */
+       G2D_YCbCr_ORDER_CbY1CrY0 = (1 << 12),   /* VER4.1 */
+       G2D_YCbCr_ORDER_Y1CrY0Cb = (2 << 12),   /* VER4.1 */
+       G2D_YCbCr_ORDER_Y1CbY0Cr = (3 << 12),   /* VER4.1 */
+       G2D_YCbCr_ORDER_CrCb = G2D_YCbCr_ORDER_CrY1CbY0,        /* VER4.1, for 2 plane */
+       G2D_YCbCr_ORDER_CbCr = G2D_YCbCr_ORDER_CbY1CrY0,        /* VER4.1, for 2 plane */
+       G2D_YCbCr_ORDER_MASK = (3 < 12),                /* VER4.1 */
+       
+       /* CSC */
+       G2D_CSC_601 = (0 << 16),                                /* VER4.1 */
+       G2D_CSC_709 = (1 << 16),                                /* VER4.1 */
+       G2D_CSC_MASK = (1 << 16),                               /* VER4.1 */
+       
+       /* Valid value range of YCbCr */
+       G2D_YCbCr_RANGE_NARROW = (0 << 17),     /* VER4.1 */
+       G2D_YCbCr_RANGE_WIDE = (1 << 17),               /* VER4.1 */
+       G2D_YCbCr_RANGE_MASK= (1 << 17),                /* VER4.1 */
+
+       G2D_COLOR_MODE_MASK = 0xFFFFFFFF
+}G2dColorMode;
+
+typedef enum {
+       G2D_SCALE_MODE_NONE = 0,
+       G2D_SCALE_MODE_NEAREST,
+       G2D_SCALE_MODE_BILINEAR,
+
+       G2D_SCALE_MODE_MAX
+} G2dScaleMode;
+
+typedef enum {
+    G2D_REPEAT_MODE_REPEAT,
+    G2D_REPEAT_MODE_PAD,
+    G2D_REPEAT_MODE_REFLECT,
+    G2D_REPEAT_MODE_CLAMP,
+    G2D_REPEAT_MODE_NONE,
+} G2dRepeatMode;
+
+typedef enum {
+    G2D_MASK_OP_ALPHA_ONLY,
+    G2D_MASK_OP_CMPONENT,
+    G2D_MASK_OP_CHANNEL,
+
+    G2D_MASK_OP_MAX
+} G2dMaskOpType;
+
+typedef enum {
+    G2D_MASK_ORDER_AXRGB,
+    G2D_MASK_ORDER_RGBAX,
+    G2D_MASK_ORDER_AXBGR,
+    G2D_MASK_ORDER_BGRAX,
+    
+    G2D_MASK_ORDER_MAX
+} G2dMaskOrder;
+
+typedef enum {
+       G2D_MASK_MODE_1BPP = 0,
+       G2D_MASK_MODE_4BPP,
+       G2D_MASK_MODE_8BPP,
+       G2D_MASK_MODE_16BPP_565,
+       G2D_MASK_MODE_16BPP_1555,
+       G2D_MASK_MODE_16BPP_4444,
+       G2D_MASK_MODE_32BPP,
+       G2D_MASK_MODE_4BPP_FOR_WINCE, /* ([31:24]bit field of 32bit is used as mask) */
+       
+       G2D_MASK_MODE_MAX
+} G2dMaskMode;
+
+/*
+Here are some examples on how to use the ROP3 value to perform the operations:
+1)     Final Data = Source. Only the Source data matter, so ROP Value = "0xCC".
+2)     Final Data = Destination. Only the Destination data matter, so ROP Value = "0xAA".
+3)     Final Data = Pattern. Only the Pattern data matter, so ROP Value = "0xF0".
+4)     Final Data = Source AND Destination.  ROP Value = "0xCC" & "0xAA" = "0x88"
+5)     Final Data = Source OR Pattern. ROP Value = "0xCC" | "0xF0" = "0xFC".
+*/
+typedef enum G2D_ROP3_TYPE {
+       G2D_ROP3_DST = 0xAA,
+       G2D_ROP3_SRC = 0xCC,
+       G2D_ROP3_3RD = 0xF0,
+
+       G2D_ROP3_MASK = 0xFF
+} G2dROP3Type;
+
+typedef enum G2D_ALU {
+    /*Common alu for x base*/    
+    G2Dclear = 0x0,            /* 0 */
+    G2Dand     =               0x1,            /* src AND dst */
+    G2DandReverse =            0x2,            /* src AND NOT dst */
+    G2Dcopy =                  0x3,            /* src */
+    G2DandInverted =           0x4,            /* NOT src AND dst */
+    G2Dnoop =                  0x5,            /* dst */
+    G2Dxor =                   0x6,            /* src XOR dst */
+    G2Dor =                    0x7,            /* src OR dst */
+    G2Dnor =                   0x8,            /* NOT src AND NOT dst */
+    G2Dequiv =                 0x9,            /* NOT src XOR dst */
+    G2Dinvert =                0xa,            /* NOT dst */
+    G2DorReverse =             0xb,            /* src OR NOT dst */
+    G2DcopyInverted =          0xc,            /* NOT src */
+    G2DorInverted =            0xd,            /* NOT src OR dst */
+    G2Dnand =                  0xe,            /* NOT src OR NOT dst */
+    G2Dset =                   0xf,            /* 1 */
+
+    /*Special alu*/
+    G2Dnegative =       0x20,       /*NOT src XOR 0x00FFFFFF*/
+}G2dAlu;
+
+typedef union _G2D_BITBLT_CMD_VAL {
+       unsigned int val;
+       struct {
+               /* [0:3] */
+               unsigned int maskROP4En:1;
+               unsigned int maskingEn:1;
+               G2dSelectAlphaSource ROP4AlphaEn:1;
+               unsigned int ditherEn:1;
+               /* [4:7] */
+               unsigned int resolved1:4;
+               /* [8:11] */
+               unsigned int cwEn:4;
+               /* [12:15] */
+               G2dTransparentMode transparentMode:4;
+               /* [16:19] */
+               G2dColorKeyMode colorKeyMode:4;
+               /* [20:23] */
+               G2dAlphaBlendMode alphaBlendMode:4;
+               /* [24:27] */
+               unsigned int srcPreMultiply:1;
+               unsigned int patPreMultiply:1;
+               unsigned int dstPreMultiply:1;
+               unsigned int dstDepreMultiply:1;
+               /* [28:31] */
+               unsigned int fastSolidColorFillEn:1;
+               unsigned int reserved:3;
+       }data;
+} G2dBitBltCmdVal;
+
+typedef union _G2D_BLEND_FUNCTION_VAL {
+       unsigned int val;
+       struct {
+               /* [0:15] */
+               G2dCoeffMode srcCoeff:4;
+               G2dACoeffMode srcCoeffSrcA:2;
+               G2dACoeffMode srcCoeffDstA:2;
+               G2dCoeffMode dstCoeff:4;
+               G2dACoeffMode dstCoeffSrcA:2;
+               G2dACoeffMode dstCoeffDstA:2;
+               /* [16:19] */
+               unsigned int invSrcColorCoeff:1;
+               unsigned int resoled1:1;
+               unsigned int invDstColorCoeff:1;
+               unsigned int resoled2:1;
+               /* [20:23] */
+               unsigned int lightenEn:1;
+               unsigned int darkenEn:1;
+               unsigned int winCESrcOverEn:2;
+               /* [24:31] */
+               unsigned int reserved:8;
+       }data;
+} G2dBlendFunctionVal;
+
+typedef union _G2D_ROUND_MODE_VAL {
+       unsigned int val;
+       struct {
+               /*
+                       Round Mode in Blending
+                       2'b00 : 
+                       Result = ((A + 1) * B) >>8;
+                       2'b01 :
+                       Result = ((A+ (A>>7)) * B) >>8;
+                       2'b10 :
+                       Result_tmp =  A * B + 0x80;
+                       Result = (Result_tmp + (Result_tmp>>8))>>8;
+                       2'b11 :
+                          Result_A = A * B; (16 bpp)
+                       Result_B = C * D; (16 bpp)
+                          Result_tmp = Result_A + Result_B + 0x80;
+                       Result = (Result_tmp + (Result_tmp>>8))>>8;
+               */
+               unsigned int blend:4;
+               /*
+                       Round Mode in Alpha Premultiply
+                       2'b00 : 
+                       Result = (A * B) >>8;
+                       2'b01 :
+                       Result = ((A + 1) * B) >>8;
+                       2'b10 :
+                       Result = ((A+ (A>>7)) * B) >>8;
+                       2'b11 : 
+                       Result_tmp =  A * B + 0x80;
+                       Result = (Result_tmp + (Result_tmp>>8))>>8;
+               */
+               unsigned int alphaPremultiply:4;
+               /*
+                       Round Mode in Alpha Depremultiply
+                       2'b00 : 
+                       Result = ((A + 1) * B) >>8;
+                       2'b01 :
+                       Result = ((A+ (A>>7)) * B) >>8;
+                       2'b10 :
+                       Result_tmp =  A * B + 0x80;
+                       Result = (Result_tmp + (Result_tmp>>8))>>8;
+                       2'b11 : Reserved
+               */
+               unsigned int alphaDepremultiply:4;
+
+               unsigned int reserved:20;
+       }data;
+} G2dRoundModeVal;
+
+typedef union _G2D_ROTATE_VAL {
+       unsigned int val;
+       struct {
+               /*
+                       0 : No rotation
+                       1 : 90 degree rotation
+               */
+               unsigned int srcRotate:4;
+               unsigned int patRotate:4;
+               unsigned int maskRotate:4;
+
+               unsigned int reserved:20;
+       }data;
+} G2dRotateVal;
+
+typedef union _G2D_SRC_MASK_DIR_VAL {
+       unsigned int val;
+       struct {
+               unsigned int dirSrcX:1;
+               unsigned int dirSrcY:1;
+               unsigned int reserved1:2;
+
+               unsigned int dirMaskX:1;
+               unsigned int dirMaskY:1;
+               unsigned int reserved2:2;
+               
+               unsigned int reserved:24;
+       }data;
+} G2dSrcMaskDirVal;
+
+typedef union _G2D_DST_PAT_DIR_VAL {
+       unsigned int val;
+       struct {
+               unsigned int dirDstX:1;
+               unsigned int dirDstY:1;
+               unsigned int reserved1:2;
+
+               unsigned int dirPatX:1;
+               unsigned int dirPatY:1;
+               unsigned int reserved2:2;
+
+               unsigned int reserved:24;
+       }data;
+} G2dDstPatDirVal;
+
+typedef union G2D_POINT_VAL {
+       unsigned int val;
+       struct {
+               /*
+                       X Coordinate of Source Image
+                       Range: 0 ~ 8000 (Requirement: SrcLeftX < SrcRightX)
+                       In YCbCr 422 and YCbCr 420 format, this value should be even number.
+               */
+               unsigned int x:16;
+               /*
+                       Y Coordinate of Source Image
+                       Range: 0 ~ 8000 (Requirement: SrcTopY < SrcBottomY)
+                       In YCbCr 420 format, this value should be even number.
+               */
+               unsigned int y:16;
+       }data;
+} G2dPointVal;
+
+typedef union G2D_BOX_SIZE_VAL {
+       unsigned int val;
+       struct {
+               /*
+                       Width of box. Range: 1 ~ 8000.
+               */
+               unsigned int width:16;
+               /*
+                       Height of box. Range: 1 ~ 8000.
+               */
+               unsigned int height:16;
+       }data;
+} G2dBoxSizeVal;
+
+typedef union _G2D_SELECT_3RD_VAL {
+       unsigned int val;
+       struct{
+               G2dSelectMode unmasked:4;
+               G2dSelectMode masked:4;
+
+               unsigned int reserved:24;
+       }data;
+} G2dSelect3rdVal;
+
+typedef union _G2D_ROP4_VAL {
+       unsigned int val;
+       struct{
+               G2dROP3Type unmaskedROP3:8;
+               G2dROP3Type maskedROP3:8;
+
+               unsigned int reserved:16;
+       }data;
+} G2dROP4Val;
+
+typedef union _G2D_MASK_MODE_VAL {
+    unsigned int val;
+    struct{
+        /* [0:7] */
+        G2dMaskMode maskMode:4;
+        G2dMaskOrder maskOrder:4;
+        /* [8:11] */
+        G2dMaskOpType maskOp:4;
+        /* [12:31] */
+        unsigned int reserved:20;
+    }data;
+} G2dMaskModeVal;
+
+typedef union _G2D_GLOBAL_ARGB_VAL {
+       unsigned int val;
+       struct{
+               unsigned int alpha:8;
+               unsigned int color:24;
+       }data;
+} G2dGlovalARGBVal;
+
+typedef union _G2D_COLORKEY_CTL_VAL {
+       unsigned int val;
+       struct{
+               /*
+                       0: Stencil Test Off for each RGBA value
+                       1: Stencil Test On for each RGBA value
+               */
+               unsigned int stencilOnB:4;
+               unsigned int stencilOnG:4;
+               unsigned int stencilOnR:4;
+               unsigned int stencilOnA:4;
+               unsigned int stencilInv:4;
+
+               unsigned int reserved:12;
+       }data;
+} G2dColorkeyCtlVal;
+
+typedef union _G2D_COLORKEY_DR_MIN_VAL {
+       unsigned int val;
+       struct{
+               /*
+               The color format of source colorkey decision reference register is generally the same as the source color format. 
+               If the color format of source is YCbCr format, the color format of this register is ARGB_8888 format.
+               But if the source color is selected as the foreground color or the background color, 
+               the source colorkey operation is not activated because the colorkeying for the foreground color 
+               and the background color set by user is meaningless.
+               */
+               unsigned int drMinB:8;
+               unsigned int drMinG:8;
+               unsigned int drMinR:8;
+               unsigned int drMinA:8;
+       }data;
+} G2dColorkeyDrMinVal;
+
+typedef union _G2D_COLORKEY_DR_MAX_VAL {
+       unsigned int val;
+       struct{
+               /*
+               The color format of source colorkey decision reference register is generally the same as the source color format. 
+               If the color format of source is YCbCr format, the color format of this register is ARGB_8888 format.
+               But if the source color is selected as the foreground color or the background color, 
+               the source colorkey operation is not activated because the colorkeying for the foreground color and 
+               the background color set by user is meaningless.
+               */
+               unsigned int drMaxB:8;
+               unsigned int drMaxG:8;
+               unsigned int drMaxR:8;
+               unsigned int drMaxA:8;
+       }data;
+} G2dColorkeyDrMaxVal;
+
+typedef union _G2D_COLORKEY_YCBCR_CTL_VAL {
+       unsigned int val;
+       struct{
+               unsigned int stencilOnCr:4;
+               unsigned int stencilOnCb:4;
+               unsigned int stencilOnY:4;
+               unsigned int stencilInv:4;
+
+               unsigned int reserved:16;
+       }data;
+} G2dColorkeyYCbCrCtlVal;
+
+typedef union _G2D_COLORKEY_YCBCR_DR_MIN_VAL {
+       unsigned int val;
+       struct{
+               unsigned int drMinCr:8;
+               unsigned int drMinCb:8;
+               unsigned int drMinY:8;
+
+               unsigned int reserved:8;
+       }data;          
+} G2dColorkeyYCbCrDrMinVal;
+
+typedef union _G2D_COLORKEY_YCBCR_DR_MAX_VAL {
+       unsigned int val;
+       struct{
+               unsigned int drMaxCr:8;
+               unsigned int drMaxCb:8;
+               unsigned int drMaxY:8;
+
+               unsigned int reserved:8;
+       }data;
+} G2dColorkeyYCbCrDrMaxVal;
+
+typedef enum {
+       G2D_OP_CLEAR                                    = 0x00,
+       G2D_OP_SRC                                              = 0x01,
+       G2D_OP_DST                                      = 0x02,
+       G2D_OP_OVER                                     = 0x03,
+       G2D_OP_OVER_REVERSE                     = 0x04,
+       G2D_OP_IN                                               = 0x05,
+       G2D_OP_IN_REVERSE                               = 0x06,
+       G2D_OP_OUT                                      = 0x07,
+       G2D_OP_OUT_REVERSE                      = 0x08,
+       G2D_OP_ATOP                                     = 0x09,
+       G2D_OP_ATOP_REVERSE                     = 0x0a,
+       G2D_OP_XOR                                      = 0x0b,
+       G2D_OP_ADD                                      = 0x0c,
+       G2D_OP_SATURATE                         = 0x0d,
+
+       G2D_OP_DISJOINT_CLEAR           = 0x10,
+       G2D_OP_DISJOINT_SRC                     = 0x11,
+       G2D_OP_DISJOINT_DST                     = 0x12,
+       G2D_OP_DISJOINT_OVER                    = 0x13,
+       G2D_OP_DISJOINT_OVER_REVERSE    = 0x14,
+       G2D_OP_DISJOINT_IN                              = 0x15,
+       G2D_OP_DISJOINT_IN_REVERSE              = 0x16,
+       G2D_OP_DISJOINT_OUT                             = 0x17,
+       G2D_OP_DISJOINT_OUT_REVERSE             = 0x18,
+       G2D_OP_DISJOINT_ATOP                            = 0x19,
+       G2D_OP_DISJOINT_ATOP_REVERSE    = 0x1a,
+       G2D_OP_DISJOINT_XOR             = 0x1b,
+
+       G2D_OP_CONJOINT_CLEAR   = 0x20,
+       G2D_OP_CONJOINT_SRC             = 0x21,
+       G2D_OP_CONJOINT_DST             = 0x22,
+       G2D_OP_CONJOINT_OVER            = 0x23,
+       G2D_OP_CONJOINT_OVER_REVERSE    = 0x24,
+       G2D_OP_CONJOINT_IN                              = 0x25,
+       G2D_OP_CONJOINT_IN_REVERSE              = 0x26,
+       G2D_OP_CONJOINT_OUT                             = 0x27,
+       G2D_OP_CONJOINT_OUT_REVERSE             = 0x28,
+       G2D_OP_CONJOINT_ATOP                            = 0x29,
+       G2D_OP_CONJOINT_ATOP_REVERSE    = 0x2a,
+       G2D_OP_CONJOINT_XOR                             = 0x2b,
+       
+       G2D_N_OPERATORS,
+       G2D_OP_NONE = G2D_N_OPERATORS
+}G2dOp;
+#define G2D_OP_DEFAULT G2D_OP_NONE
+
+#define G2D_PLANE_MAX 2
+
+typedef struct _G2D_IMAGE      G2dImage;
+struct _G2D_IMAGE {
+    G2dSelectMode select_mode;
+    G2dColorMode color_mode;
+    G2dRepeatMode repeat_mode;
+
+    G2dFixed xscale;
+    G2dFixed yscale;
+    G2dScaleMode scale_mode;
+
+    unsigned char rotate_90;
+    unsigned char xDir;
+    unsigned char yDir;
+    unsigned char componentAlpha;
+    
+    unsigned int width;
+    unsigned int height;
+    unsigned int stride;
+
+    unsigned int need_free;
+    union{
+        unsigned int   color;
+        unsigned int   bo[G2D_PLANE_MAX];
+    }data;
+
+    void *mapped_ptr[G2D_PLANE_MAX];
+};
+
+#define G2D_PT(_x, _y) ( (unsigned int)(_y<<16|_x<<0))
+
+#define G2D_FIXED_1 (1<<16)
+#define G2D_DOUBLE_TO_FIXED(_d) ((G2dFixed)((_d) * 65536.0))
+#define G2D_INT_TO_FIXED(_i)    ((G2dFixed)((_i) << 16))
+#define G2D_FIXED_TO_DOUBLE(_f) (double) ((_f) / (double) G2D_FIXED_1)
+#define G2D_FIXED_TO_INT(_f)    ((int) ((_f) >> 16))
+
+int g2d_init(int fd);
+void g2d_fini(void);
+int g2d_add_cmd(unsigned int cmd, unsigned int value);
+void g2d_reset (unsigned int clear_reg);
+int g2d_exec(void);
+int g2d_flush(void);
+void g2d_dump(void);
+
+G2dImage* g2d_image_create_solid(unsigned int color);
+G2dImage* g2d_image_create_bo(G2dColorMode format, 
+                                                        unsigned int width, unsigned int height, 
+                                                        unsigned int bo, unsigned int stride);
+G2dImage* g2d_image_create_bo2 (G2dColorMode format,
+                                unsigned int width, unsigned int height,
+                                unsigned int bo1, unsigned int bo2, unsigned int stride);
+G2dImage* g2d_image_create_data (G2dColorMode format, 
+                                                        unsigned int width, unsigned int height, 
+                                                        void* data, unsigned int stride);
+
+void g2d_image_free (G2dImage* img);
+
+int g2d_set_src(G2dImage* img);
+int g2d_set_dst(G2dImage* img);
+int g2d_set_mask(G2dImage* img);
+unsigned int g2d_get_blend_op(G2dOp op);
+
+/* UTIL Functions */
+void util_g2d_fill(G2dImage* img,
+                            int x, int y, unsigned int w, unsigned int h,
+                            unsigned int color);
+void util_g2d_fill_alu(G2dImage* img,
+            int x, int y, unsigned int w, unsigned int h,
+            unsigned int color, G2dAlu alu);
+void util_g2d_copy(G2dImage* src, G2dImage* dst, 
+                            int src_x, int src_y, 
+                            int dst_x, int dst_y,
+                            unsigned int width, unsigned int height);
+void util_g2d_copy_alu(G2dImage* src, G2dImage* dst, 
+            int src_x, int src_y, 
+            int dst_x, int dst_y,
+            unsigned int width, unsigned int height,
+            G2dAlu alu);                            
+void util_g2d_copy_with_scale(G2dImage* src, G2dImage* dst, 
+                            int src_x, int src_y, unsigned int src_w, unsigned int src_h,
+                            int dst_x, int dst_y, unsigned int dst_w, unsigned int dst_h, 
+                            int negative);
+void util_g2d_blend(G2dOp op, G2dImage* src, G2dImage* dst, 
+                            int src_x, int src_y, 
+                            int dst_x, int dst_y,
+                            unsigned int width, unsigned int height);
+void util_g2d_blend_with_scale(G2dOp op, G2dImage* src, G2dImage* dst,
+                            int src_x, int src_y, unsigned int src_w, unsigned int src_h,
+                            int dst_x, int dst_y, unsigned int dst_w, unsigned int dst_h,
+                            int negative);
+void util_g2d_composite(G2dOp op, G2dImage* src, G2dImage* mask, G2dImage* dst, 
+            int src_x, int src_y, 
+            int mask_x, int mask_y, 
+            int dst_x, int dst_y,
+            unsigned int width, unsigned int height);
+
+#endif /* _FIMG2D3X_H_ */
diff --git a/src/g2d/fimg2d_reg.h b/src/g2d/fimg2d_reg.h
new file mode 100644 (file)
index 0000000..97813c8
--- /dev/null
@@ -0,0 +1,120 @@
+#ifndef _FIMG2D_HW_H_
+#define _FIMG2D_HW_H_
+
+/* Registers */
+/*
+*       GEBERAL REGISTER
+*/
+#define SOFT_RESET_REG                 (0x0000)
+#define INTEN_REG                              (0x0004)
+#define INTC_PEND_REG                  (0x000c)
+#define FIFO_STAT_REG                  (0x0010)
+#define AXI_MODE_REG                   (0x001C)
+#define DMA_SFR_BASE_ADDR_REG  (0x0080)
+#define DMA_COMMAND_REG                        (0x0084)
+#define DMA_EXE_LIST_NUM_REG           (0x0088)
+#define DMA_STATUS_REG                         (0x008C)
+#define DMA_HOLD_CMD_REG                       (0x0090)
+
+/*
+*       COMMAND REGISTER
+*/
+#define BITBLT_START_REG               (0x0100)
+#define BITBLT_COMMAND_REG     (0x0104)
+#define BLEND_FUNCTION_REG     (0x0108)        /* VER4.1 */
+#define ROUND_MODE_REG         (0x010C)        /* VER4.1 */
+
+/*
+*       PARAMETER SETTING REGISTER
+*/
+
+/*     ROTATE and DIRECTION*/
+#define ROTATE_REG                             (0x0200)
+#define SRC_MASK_DIRECT_REG    (0x0204)
+#define DST_PAT_DIRECT_REG             (0x0208)
+
+/*     SOURCE  */
+#define SRC_SELECT_REG                 (0x0300)
+#define SRC_BASE_ADDR_REG              (0x0304)
+#define SRC_STRIDE_REG                 (0x0308)
+#define SRC_COLOR_MODE_REG     (0x030c)
+#define SRC_LEFT_TOP_REG               (0x0310)
+#define SRC_RIGHT_BOTTOM_REG   (0x0314)
+#define SRC_PLANE2_BASE_ADDR_REG       (0x0318)        /* VER4.1 */
+#define SRC_REPEAT_MODE_REG            (0x031C)        
+#define SRC_PAD_VALUE_REG                      (0x0320)
+#define SRC_A8_RGB_EXT_REG                     (0x0324)
+#define SRC_SCALE_CTRL_REG                     (0x0328)
+#define SRC_XSCALE_REG                         (0x032C)
+#define SRC_YSCALE_REG                         (0x0330)
+
+/*     DESTINATION     */
+#define DST_SELECT_REG                 (0x0400)
+#define DST_BASE_ADDR_REG              (0x0404)
+#define DST_STRIDE_REG                 (0x0408)
+#define DST_COLOR_MODE_REG     (0x040C)
+#define DST_LEFT_TOP_REG               (0x0410)
+#define DST_RIGHT_BOTTOM_REG   (0x0414)
+#define DST_PLANE2_BASE_ADDR_REG       (0x0418)        /* VER4.1 */
+#define DST_A8_RGB_EXT_REG             (0x041C)
+
+/*     PATTERN */
+#define PAT_BASE_ADDR_REG              (0x0500)
+#define PAT_SIZE_REG                   (0x0504)
+#define PAT_COLOR_MODE_REG     (0x0508)
+#define PAT_OFFSET_REG                 (0x050C)
+#define PAT_STRIDE_REG                 (0x0510)
+
+/*     MASK    */
+#define MASK_BASE_ADDR_REG             (0x0520)
+#define MASK_STRIDE_REG                (0x0524)
+#define MASK_LEFT_TOP_REG              (0x0528)                /* VER4.1 */
+#define MASK_RIGHT_BOTTOM_REG  (0x052C)        /* VER4.1 */
+#define MASK_MODE_REG                          (0x0530)        /* VER4.1 */
+#define MASK_REPEAT_MODE_REG           (0x0534)
+#define MASK_PAD_VALUE_REG             (0x0538)
+#define MASK_SCALE_CTRL_REG            (0x053C)
+#define MASK_XSCALE_REG                        (0x0540)
+#define MASK_YSCALE_REG                        (0x0544)
+
+/*
+*       CLIPPING WINDOW
+*/
+#define CW_LT_REG                              (0x0600)
+#define CW_RB_REG                              (0x0604)
+
+/*
+*       ROP & ALPHA SETTING
+*/
+#define THIRD_OPERAND_REG              (0x0610)
+#define ROP4_REG                               (0x0614)
+#define ALPHA_REG                              (0x0618)
+
+/*
+*       COLOR SETTING
+*/
+#define FG_COLOR_REG                   (0x0700)
+#define BG_COLOR_REG                   (0x0704)
+#define BS_COLOR_REG                   (0x0708)
+#define SF_COLOR_REG                   (0x070C)        /* VER4.1 */
+
+/*
+*       COLOR KEY
+*/
+#define SRC_COLORKEY_CTRL_REG          (0x0710)
+#define SRC_COLORKEY_DR_MIN_REG        (0x0714)
+#define SRC_COLORKEY_DR_MAX_REG        (0x0718)
+#define DST_COLORKEY_CTRL_REG          (0x071C)
+#define DST_COLORKEY_DR_MIN_REG        (0x0720)
+#define DST_COLORKEY_DR_MAX_REG        (0x0724)
+/*     YCbCr src Color Key     */
+#define YCbCr_SRC_COLORKEY_CTRL_REG            (0x0728)        /* VER4.1 */
+#define YCbCr_SRC_COLORKEY_DR_MIN_REG  (0x072C)        /* VER4.1 */
+#define YCbCr_SRC_COLORKEY_DR_MAX_REG  (0x0730)        /* VER4.1 */
+/*     YCbCr dst Color Key     */
+#define YCbCr_DST_COLORKEY_CTRL_REG            (0x0734)        /* VER4.1 */
+#define YCbCr_DST_COLORKEY_DR_MIN_REG  (0x0738)        /* VER4.1 */
+#define YCbCr_DST_COLORKEY_DR_MAX_REG  (0x073C)        /* VER4.1 */
+
+#endif
+
diff --git a/src/g2d/util_g2d.c b/src/g2d/util_g2d.c
new file mode 100644 (file)
index 0000000..7c5f2d7
--- /dev/null
@@ -0,0 +1,889 @@
+#include <stdio.h>
+#include "xf86.h"
+#include "fimg2d.h"
+#include "sec_util.h"
+
+static int
+_util_get_clip(G2dImage* img, int x, int y, int width, int height, G2dPointVal *lt, G2dPointVal *rb)
+{
+    if(img->select_mode != G2D_SELECT_MODE_NORMAL)
+    {
+        lt->data.x = 0;
+        lt->data.y = 0;
+        rb->data.x = 1;
+        rb->data.y = 1;
+        return 1;
+    }
+
+    if(x<0)
+    {
+        width += x;
+        x=0;
+    }
+
+    if(y<0)
+    {
+        height += y;
+        y=0;
+    }
+
+    if(x+width > img->width)
+    {
+        width = img->width - x;
+    }
+
+    if(y+height > img->height)
+    {
+        height = img->height - y;
+    }
+
+    if(width <= 0 || height <= 0)
+    {
+        if(img->repeat_mode != G2D_REPEAT_MODE_NONE)
+        {
+            x=0;
+            y=0;
+            width = img->width;
+            height = img->height;
+            return 1;
+        }
+
+        return 0;
+    }
+
+    lt->data.x = x;
+    lt->data.y = y;
+    rb->data.x = x+width;
+    rb->data.y = y+height;
+
+    return 1;
+}
+
+void
+util_g2d_fill(G2dImage* img,
+            int x, int y, unsigned int w, unsigned int h,
+            unsigned int color)
+{
+    G2dBitBltCmdVal bitblt={0,};
+    G2dPointVal lt, rb;
+
+    g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_FGCOLOR);
+    g2d_add_cmd(DST_COLOR_MODE_REG, img->color_mode);
+    g2d_add_cmd(DST_BASE_ADDR_REG, img->data.bo[0]);
+    g2d_add_cmd(DST_STRIDE_REG, img->stride);
+
+    /*Set Geometry*/
+    if(!_util_get_clip(img, x, y, w, h, &lt, &rb))
+    {
+        XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__);
+        g2d_reset(0);
+        return;
+    }
+    g2d_add_cmd(DST_LEFT_TOP_REG, lt.val);
+    g2d_add_cmd(DST_RIGHT_BOTTOM_REG, rb.val);
+
+    /*set Src Image*/
+    g2d_add_cmd(SF_COLOR_REG, color);
+
+    /*Set G2D Command*/
+    bitblt.val = 0;
+    bitblt.data.fastSolidColorFillEn = 1;
+    g2d_add_cmd(BITBLT_COMMAND_REG, bitblt.val);
+
+    /* Flush and start */
+    g2d_flush();
+}
+
+void
+util_g2d_fill_alu(G2dImage* img,
+            int x, int y, unsigned int w, unsigned int h,
+            unsigned int color, G2dAlu alu)
+{
+    G2dBitBltCmdVal bitblt={0,};
+    G2dROP4Val rop4;
+    G2dPointVal lt, rb;
+    _X_UNUSED unsigned int bg_color;
+    unsigned int dst_mode = G2D_SELECT_MODE_BGCOLOR;
+    G2dROP3Type rop3 = 0;
+
+    switch(alu)
+    {
+    case G2Dclear: /* 0 */
+        color = 0x00000000;
+        break;
+    case G2Dand: /* src AND dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_SRC & G2D_ROP3_DST;
+        break;
+    case G2DandReverse: /* src AND NOT dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_SRC & (~G2D_ROP3_DST);
+        break;
+    case G2Dcopy: /* src */
+        break;
+    case G2DandInverted: /* NOT src AND dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = (~G2D_ROP3_SRC) & G2D_ROP3_DST;
+        break;
+    case G2Dnoop: /* dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_DST;
+        break;
+    case G2Dxor: /* src XOR dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_SRC ^ G2D_ROP3_DST;
+        break;
+    case G2Dor: /* src OR dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_SRC | G2D_ROP3_DST;
+        break;
+    case G2Dnor: /* NOT src AND NOT dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = (~G2D_ROP3_SRC) & (~G2D_ROP3_DST);
+        break;
+    case G2Dequiv: /* NOT src XOR dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = (~G2D_ROP3_SRC) ^ G2D_ROP3_DST;
+        break;
+    case G2Dinvert: /* NOT dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = ~G2D_ROP3_DST;
+        break;
+    case G2DorReverse: /* src OR NOT dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_SRC |( ~G2D_ROP3_DST);
+        break;
+    case G2DcopyInverted: /* NOT src */
+        rop3 = ~G2D_ROP3_SRC;
+        break;
+    case G2DorInverted: /* NOT src OR dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = (~G2D_ROP3_SRC) | G2D_ROP3_DST;
+        break;
+    case G2Dnand: /* NOT src OR NOT dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = (~G2D_ROP3_SRC) | (~G2D_ROP3_DST);
+        break;
+    case G2Dset: /* 1 */
+        color = 0xFFFFFFFF;
+        break;
+    case G2Dnegative:
+        bg_color = 0x00FFFFFF;
+        rop3 = G2D_ROP3_SRC ^ G2D_ROP3_DST;
+        break;
+    default:
+        break;
+    }
+
+    /*set Dst Image*/
+    g2d_add_cmd(DST_SELECT_REG, dst_mode);
+    g2d_add_cmd(DST_COLOR_MODE_REG, img->color_mode);
+    g2d_add_cmd(DST_BASE_ADDR_REG, img->data.bo[0]);
+    g2d_add_cmd(DST_STRIDE_REG, img->stride);
+
+    /*Set Geometry*/
+    if(!_util_get_clip(img, x, y, w, h, &lt, &rb))
+    {
+        XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__);
+        g2d_reset(0);
+        return;
+    }
+    g2d_add_cmd(DST_LEFT_TOP_REG, lt.val);
+    g2d_add_cmd(DST_RIGHT_BOTTOM_REG, rb.val);
+
+    /*set ROP4 val*/
+    if(rop3 != 0)
+    {
+        /*set Src Image*/
+        g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_FGCOLOR);
+        g2d_add_cmd(SRC_COLOR_MODE_REG, G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB);
+        g2d_add_cmd(FG_COLOR_REG, color);
+
+        rop4.val = 0;
+        rop4.data.unmaskedROP3 = rop3;
+        g2d_add_cmd(ROP4_REG, rop4.val);
+    }
+    else
+    {
+        g2d_add_cmd(SF_COLOR_REG, color);
+
+        /*Set G2D Command*/
+        bitblt.val = 0;
+        bitblt.data.fastSolidColorFillEn = 1;
+        g2d_add_cmd(BITBLT_COMMAND_REG, bitblt.val);
+    }
+
+    /* Flush and start */
+    g2d_flush();
+}
+
+void
+util_g2d_copy(G2dImage* src, G2dImage* dst,
+            int src_x, int src_y,
+            int dst_x, int dst_y,
+            unsigned int width, unsigned int height)
+{
+    G2dROP4Val rop4;
+    G2dPointVal lt, rb;
+
+    /*Set dst*/
+    g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR);
+    g2d_add_cmd(DST_COLOR_MODE_REG, dst->color_mode);
+    g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]);
+    if (dst->color_mode & G2D_YCbCr_2PLANE)
+    {
+        if (dst->data.bo[1] > 0)
+            g2d_add_cmd(DST_PLANE2_BASE_ADDR_REG, dst->data.bo[1]);
+        else
+            XDBG_ERROR (MG2D, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__);
+    }
+    g2d_add_cmd(DST_STRIDE_REG, dst->stride);
+
+    /*Set src*/
+    g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL);
+    g2d_add_cmd(SRC_COLOR_MODE_REG, src->color_mode);
+    g2d_add_cmd(SRC_BASE_ADDR_REG, src->data.bo[0]);
+    if (src->color_mode & G2D_YCbCr_2PLANE)
+    {
+        if (src->data.bo[1] > 0)
+            g2d_add_cmd(DST_PLANE2_BASE_ADDR_REG, src->data.bo[1]);
+        else
+            XDBG_ERROR (MG2D, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__);
+    }
+    g2d_add_cmd(SRC_STRIDE_REG, src->stride);
+    if(src->repeat_mode)
+        g2d_add_cmd(SRC_REPEAT_MODE_REG, src->repeat_mode);
+
+    /*Set cmd*/
+    if(!_util_get_clip(src, src_x, src_y, width, height, &lt, &rb))
+    {
+        XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__);
+        g2d_reset(0);
+        return;
+    }
+    g2d_add_cmd(SRC_LEFT_TOP_REG, lt.val);
+    g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, rb.val);
+
+    if(!_util_get_clip(dst, dst_x, dst_y, width, height, &lt, &rb))
+    {
+        XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__);
+        g2d_reset(0);
+        return;
+    }
+    g2d_add_cmd(DST_LEFT_TOP_REG, lt.val);
+    g2d_add_cmd(DST_RIGHT_BOTTOM_REG, rb.val);
+
+    rop4.val = 0;
+    rop4.data.unmaskedROP3 = G2D_ROP3_SRC;
+    g2d_add_cmd(ROP4_REG, rop4.val);
+
+    g2d_flush();
+}
+
+void
+util_g2d_copy_alu(G2dImage* src, G2dImage* dst,
+            int src_x, int src_y,
+            int dst_x, int dst_y,
+            unsigned int width, unsigned int height,
+            G2dAlu alu)
+{
+    G2dROP4Val rop4;
+    G2dPointVal lt, rb;
+    unsigned int dst_mode = G2D_SELECT_MODE_BGCOLOR;
+    unsigned int src_mode = G2D_SELECT_MODE_NORMAL;
+    G2dROP3Type rop3=0;
+    unsigned int fg_color = 0, bg_color = 0;
+
+    /*Select alu*/
+    switch(alu)
+    {
+    case G2Dclear: /* 0 */
+        src_mode = G2D_SELECT_MODE_FGCOLOR;
+        fg_color = 0x00000000;
+        break;
+    case G2Dand: /* src AND dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_SRC & G2D_ROP3_DST;
+        break;
+    case G2DandReverse: /* src AND NOT dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_SRC & (~G2D_ROP3_DST);
+        break;
+    case G2Dcopy: /* src */
+        rop3 = G2D_ROP3_SRC;
+        break;
+    case G2DandInverted: /* NOT src AND dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = (~G2D_ROP3_SRC) & G2D_ROP3_DST;
+        break;
+    case G2Dnoop: /* dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_DST;
+        break;
+    case G2Dxor: /* src XOR dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_SRC ^ G2D_ROP3_DST;
+        break;
+    case G2Dor: /* src OR dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_SRC | G2D_ROP3_DST;
+        break;
+    case G2Dnor: /* NOT src AND NOT dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = (~G2D_ROP3_SRC) & (~G2D_ROP3_DST);
+        break;
+    case G2Dequiv: /* NOT src XOR dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = (~G2D_ROP3_SRC) ^ G2D_ROP3_DST;
+        break;
+    case G2Dinvert: /* NOT dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = ~G2D_ROP3_DST;
+        break;
+    case G2DorReverse: /* src OR NOT dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = G2D_ROP3_SRC |( ~G2D_ROP3_DST);
+        break;
+    case G2DcopyInverted: /* NOT src */
+        rop3 = ~G2D_ROP3_SRC;
+        break;
+    case G2DorInverted: /* NOT src OR dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = (~G2D_ROP3_SRC) | G2D_ROP3_DST;
+        break;
+    case G2Dnand: /* NOT src OR NOT dst */
+        dst_mode = G2D_SELECT_MODE_NORMAL;
+        rop3 = (~G2D_ROP3_SRC) | (~G2D_ROP3_DST);
+        break;
+    case G2Dset: /* 1 */
+        src_mode = G2D_SELECT_MODE_FGCOLOR;
+        fg_color = 0xFFFFFFFF;
+        rop3 = G2D_ROP3_DST;
+        break;
+    case G2Dnegative:
+        bg_color = 0x00FFFFFF;
+        rop3 = G2D_ROP3_SRC ^ G2D_ROP3_DST;
+        break;
+    default:
+        break;
+    }
+
+    /*Set dst*/
+    if(dst_mode != G2D_SELECT_MODE_NORMAL)
+    {
+        g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR);
+        g2d_add_cmd(DST_COLOR_MODE_REG, G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB);
+        g2d_add_cmd(BG_COLOR_REG, bg_color);
+    }
+    else
+    {
+        g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_NORMAL);
+        g2d_add_cmd(DST_COLOR_MODE_REG, dst->color_mode);
+    }
+    g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]);
+    g2d_add_cmd(DST_STRIDE_REG, dst->stride);
+
+    /*Set src*/
+    if(src_mode != G2D_SELECT_MODE_NORMAL)
+    {
+        g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_FGCOLOR);
+        g2d_add_cmd(SRC_COLOR_MODE_REG, G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB);
+        g2d_add_cmd(FG_COLOR_REG, fg_color);
+    }
+    else
+    {
+        g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL);
+        g2d_add_cmd(SRC_COLOR_MODE_REG, src->color_mode);
+        g2d_add_cmd(SRC_BASE_ADDR_REG, src->data.bo[0]);
+        g2d_add_cmd(SRC_STRIDE_REG, src->stride);
+        if(src->repeat_mode)
+            g2d_add_cmd(SRC_REPEAT_MODE_REG, src->repeat_mode);
+    }
+
+    /*Set cmd*/
+    if(!_util_get_clip(src, src_x, src_y, width, height, &lt, &rb))
+    {
+        XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__);
+        g2d_reset(0);
+        return;
+    }
+    g2d_add_cmd(SRC_LEFT_TOP_REG, lt.val);
+    g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, rb.val);
+
+    if(!_util_get_clip(dst, dst_x, dst_y, width, height, &lt, &rb))
+    {
+        XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__);
+        g2d_reset(0);
+        return;
+    }
+    g2d_add_cmd(DST_LEFT_TOP_REG, lt.val);
+    g2d_add_cmd(DST_RIGHT_BOTTOM_REG, rb.val);
+
+    rop4.val = 0;
+    rop4.data.unmaskedROP3 = rop3;
+    g2d_add_cmd(ROP4_REG, rop4.val);
+
+    g2d_flush();
+}
+
+void
+util_g2d_copy_with_scale(G2dImage* src, G2dImage* dst,
+            int src_x, int src_y, unsigned int src_w, unsigned int src_h,
+            int dst_x, int dst_y, unsigned int dst_w, unsigned int dst_h,
+            int negative)
+{
+    G2dROP4Val rop4;
+    G2dPointVal pt;
+    int bScale;
+    double scalex=1.0, scaley=1.0;
+
+    /*Set dst*/
+    g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR);
+    g2d_add_cmd(DST_COLOR_MODE_REG, dst->color_mode);
+    g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]);
+    g2d_add_cmd(DST_STRIDE_REG, dst->stride);
+
+    /*Set src*/
+    g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL);
+    g2d_add_cmd(SRC_COLOR_MODE_REG, src->color_mode);
+    g2d_add_cmd(SRC_BASE_ADDR_REG, src->data.bo[0]);
+    g2d_add_cmd(SRC_STRIDE_REG, src->stride);
+
+    /*Set cmd*/
+    if(src_w == dst_w && src_h == dst_h)
+        bScale = 0;
+    else
+    {
+        bScale = 1;
+        scalex = (double)src_w/(double)dst_w;
+        scaley = (double)src_h/(double)dst_h;
+    }
+
+    if(src_x < 0)
+    {
+        src_w += src_x;
+        src_x = 0;
+    }
+
+    if(src_y < 0)
+    {
+        src_h += src_y;
+        src_y = 0;
+    }
+    if(src_x+src_w > src->width) src_w = src->width - src_x;
+    if(src_y+src_h > src->height) src_h = src->height - src_y;
+
+    if(dst_x < 0)
+    {
+        dst_w += dst_x;
+        dst_x = 0;
+    }
+
+    if(dst_y < 0)
+    {
+        dst_h += dst_y;
+        dst_y = 0;
+    }
+    if(dst_x+dst_w > dst->width) dst_w = dst->width - dst_x;
+    if(dst_y+dst_h > dst->height) dst_h = dst->height - dst_y;
+
+    if(src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0)
+    {
+        XDBG_ERROR (MG2D, "[G2D] error: invalid geometry\n");
+        g2d_reset(0);
+        return;
+    }
+
+    if(negative)
+    {
+        g2d_add_cmd(BG_COLOR_REG, 0x00FFFFFF);
+        rop4.val = 0;
+        rop4.data.unmaskedROP3 = G2D_ROP3_SRC^G2D_ROP3_DST;
+        g2d_add_cmd(ROP4_REG, rop4.val);
+    }
+    else
+    {
+        rop4.val = 0;
+        rop4.data.unmaskedROP3 = G2D_ROP3_SRC;
+        g2d_add_cmd(ROP4_REG, rop4.val);
+    }
+
+    if(bScale)
+    {
+        g2d_add_cmd(SRC_SCALE_CTRL_REG, G2D_SCALE_MODE_BILINEAR);
+        g2d_add_cmd(SRC_XSCALE_REG, G2D_DOUBLE_TO_FIXED(scalex));
+        g2d_add_cmd(SRC_YSCALE_REG, G2D_DOUBLE_TO_FIXED(scaley));
+    }
+
+    pt.data.x = src_x;
+    pt.data.y = src_y;
+    pt.val = (pt.data.y << 16) | pt.data.x ;
+    g2d_add_cmd(SRC_LEFT_TOP_REG, pt.val);
+    pt.data.x = src_x + src_w;
+    pt.data.y = src_y + src_h;
+    pt.val = (pt.data.y << 16) | pt.data.x ;
+    g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, pt.val);
+
+
+    pt.data.x = dst_x;
+    pt.data.y = dst_y;
+    pt.val = (pt.data.y << 16) | pt.data.x ;
+    g2d_add_cmd(DST_LEFT_TOP_REG, pt.val);
+    pt.data.x = dst_x + dst_w;
+    pt.data.y = dst_y + dst_h;
+    pt.val = (pt.data.y << 16) | pt.data.x ;
+    g2d_add_cmd(DST_RIGHT_BOTTOM_REG, pt.val);
+
+    g2d_flush();
+}
+
+void
+util_g2d_blend(G2dOp op, G2dImage* src, G2dImage* dst,
+            int src_x, int src_y,
+            int dst_x, int dst_y,
+            unsigned int width, unsigned int height)
+{
+    G2dBitBltCmdVal bitblt;
+    G2dBlendFunctionVal blend;
+    G2dPointVal pt;
+
+    bitblt.val = 0;
+    blend.val = 0;
+
+    /*Set dst*/
+    if(op == G2D_OP_SRC || op == G2D_OP_CLEAR)
+        g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR);
+    else
+        g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_NORMAL);
+    g2d_add_cmd(DST_COLOR_MODE_REG, dst->color_mode);
+    g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]);
+    g2d_add_cmd(DST_STRIDE_REG, dst->stride);
+
+    /*Set src*/
+    g2d_set_src(src);
+
+    /*Set cmd*/
+    if(src_x < 0) src_x = 0;
+    if(src_y < 0) src_y = 0;
+    if(src_x+width > src->width) width = src->width - src_x;
+    if(src_y+height > src->height) height = src->height - src_y;
+
+    if(dst_x < 0) dst_x = 0;
+    if(dst_y < 0) dst_y = 0;
+    if(dst_x+width > dst->width) width = dst->width - dst_x;
+    if(dst_y+height > dst->height) height = dst->height - dst_y;
+
+    if(width <= 0 || height <= 0)
+    {
+        XDBG_ERROR (MG2D, "[G2D] error: invalid geometry\n");
+        g2d_reset(0);
+        return;
+    }
+
+    bitblt.data.alphaBlendMode = G2D_ALPHA_BLEND_MODE_ENABLE;
+    blend.val = g2d_get_blend_op(op);
+    g2d_add_cmd(BITBLT_COMMAND_REG, bitblt.val);
+    g2d_add_cmd(BLEND_FUNCTION_REG, blend.val);
+
+    pt.data.x = src_x;
+    pt.data.y = src_y;
+    g2d_add_cmd(SRC_LEFT_TOP_REG, pt.val);
+    pt.data.x = src_x + width;
+    pt.data.y = src_y + height;
+    g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, pt.val);
+
+
+    pt.data.x = dst_x;
+    pt.data.y = dst_y;
+    g2d_add_cmd(DST_LEFT_TOP_REG, pt.val);
+    pt.data.x = dst_x + width;
+    pt.data.y = dst_y + height;
+    g2d_add_cmd(DST_RIGHT_BOTTOM_REG, pt.val);
+
+    g2d_flush();
+}
+
+void
+util_g2d_blend_with_scale(G2dOp op, G2dImage* src, G2dImage* dst,
+            int src_x, int src_y, unsigned int src_w, unsigned int src_h,
+            int dst_x, int dst_y, unsigned int dst_w, unsigned int dst_h,
+            int negative)
+{
+    G2dROP4Val rop4;
+    G2dPointVal pt;
+    int bScale;
+    double scalex=1.0, scaley=1.0;
+    G2dRotateVal rotate;
+    G2dSrcMaskDirVal dir;
+    int rotate_w, rotate_h;
+    G2dBitBltCmdVal bitblt;
+    G2dBlendFunctionVal blend;
+
+    bitblt.val = 0;
+    blend.val = 0;
+    rotate.val = 0;
+    dir.val = 0;
+
+    if(src_x < 0)
+    {
+        src_w += src_x;
+        src_x = 0;
+    }
+
+    if(src_y < 0)
+    {
+        src_h += src_y;
+        src_y = 0;
+    }
+    if(src_x+src_w > src->width)
+        src_w = src->width - src_x;
+    if(src_y+src_h > src->height)
+        src_h = src->height - src_y;
+
+    if(dst_x < 0)
+    {
+        dst_w += dst_x;
+        dst_x = 0;
+    }
+    if(dst_y < 0)
+    {
+        dst_h += dst_y;
+        dst_y = 0;
+    }
+    if(dst_x+dst_w > dst->width)
+        dst_w = dst->width - dst_x;
+    if(dst_y+dst_h > dst->height)
+        dst_h = dst->height - dst_y;
+
+    if(src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0)
+    {
+        XDBG_ERROR (MG2D, "[G2D] error: invalid geometry\n");
+        g2d_reset(0);
+        return;
+    }
+
+    /*Set dst*/
+    if(op == G2D_OP_SRC || op == G2D_OP_CLEAR)
+        g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR);
+    else
+        g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_NORMAL);
+    g2d_add_cmd(DST_COLOR_MODE_REG, dst->color_mode);
+    g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]);
+    if (dst->color_mode & G2D_YCbCr_2PLANE)
+    {
+        if (dst->data.bo[1] > 0)
+            g2d_add_cmd(DST_PLANE2_BASE_ADDR_REG, dst->data.bo[1]);
+        else
+            fprintf(stderr, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__);
+    }
+    g2d_add_cmd(DST_STRIDE_REG, dst->stride);
+
+    /*Set src*/
+    g2d_add_cmd(SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL);
+    g2d_add_cmd(SRC_COLOR_MODE_REG, src->color_mode);
+    g2d_add_cmd(SRC_BASE_ADDR_REG, src->data.bo[0]);
+    if (src->color_mode & G2D_YCbCr_2PLANE)
+    {
+        if (src->data.bo[1] > 0)
+            g2d_add_cmd(SRC_PLANE2_BASE_ADDR_REG, src->data.bo[1]);
+        else
+            fprintf(stderr, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__);
+    }
+    g2d_add_cmd(SRC_STRIDE_REG, src->stride);
+
+    /*Set cmd*/
+    rotate_w = (src->rotate_90)?dst_h:dst_w;
+    rotate_h = (src->rotate_90)?dst_w:dst_h;
+
+    if(src_w == rotate_w && src_h == rotate_h)
+        bScale = 0;
+    else
+    {
+        bScale = 1;
+        scalex = (double)src_w/(double)rotate_w;
+        scaley = (double)src_h/(double)rotate_h;
+    }
+
+    if(negative)
+    {
+        g2d_add_cmd(BG_COLOR_REG, 0x00FFFFFF);
+        rop4.val = 0;
+        rop4.data.unmaskedROP3 = G2D_ROP3_SRC^G2D_ROP3_DST;
+        g2d_add_cmd(ROP4_REG, rop4.val);
+    }
+    else
+    {
+        rop4.val = 0;
+        rop4.data.unmaskedROP3 = G2D_ROP3_SRC;
+        g2d_add_cmd(ROP4_REG, rop4.val);
+    }
+
+    if(bScale)
+    {
+        g2d_add_cmd(SRC_SCALE_CTRL_REG, G2D_SCALE_MODE_BILINEAR);
+        g2d_add_cmd(SRC_XSCALE_REG, G2D_DOUBLE_TO_FIXED(scalex));
+        g2d_add_cmd(SRC_YSCALE_REG, G2D_DOUBLE_TO_FIXED(scaley));
+    }
+
+    if(src->rotate_90 || src->xDir || src->yDir)
+    {
+        rotate.data.srcRotate = src->rotate_90;
+        dir.data.dirSrcX = src->xDir;
+        dir.data.dirSrcY = src->yDir;
+    }
+
+    pt.data.x = src_x;
+    pt.data.y = src_y;
+    pt.val = (pt.data.y << 16) | pt.data.x ;
+    g2d_add_cmd(SRC_LEFT_TOP_REG, pt.val);
+    pt.data.x = src_x + src_w;
+    pt.data.y = src_y + src_h;
+    pt.val = (pt.data.y << 16) | pt.data.x ;
+    g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, pt.val);
+
+    pt.data.x = dst_x;
+    pt.data.y = dst_y;
+    pt.val = (pt.data.y << 16) | pt.data.x ;
+    g2d_add_cmd(DST_LEFT_TOP_REG, pt.val);
+    pt.data.x = dst_x + dst_w;
+    pt.data.y = dst_y + dst_h;
+    pt.val = (pt.data.y << 16) | pt.data.x ;
+    g2d_add_cmd(DST_RIGHT_BOTTOM_REG, pt.val);
+
+    if(op != G2D_OP_SRC || op != G2D_OP_CLEAR)
+    {
+        bitblt.data.alphaBlendMode = G2D_ALPHA_BLEND_MODE_ENABLE;
+        blend.val = g2d_get_blend_op(op);
+        g2d_add_cmd(BITBLT_COMMAND_REG, bitblt.val);
+        g2d_add_cmd(BLEND_FUNCTION_REG, blend.val);
+    }
+
+    g2d_add_cmd(ROTATE_REG, rotate.val);
+    g2d_add_cmd(SRC_MASK_DIRECT_REG, dir.val);
+
+    g2d_flush();
+}
+
+void
+util_g2d_composite(G2dOp op, G2dImage* src, G2dImage* mask, G2dImage* dst,
+            int src_x, int src_y,
+            int mask_x, int mask_y,
+            int dst_x, int dst_y,
+            unsigned int width, unsigned int height)
+{
+    G2dBitBltCmdVal bitblt;
+    G2dBlendFunctionVal blend;
+    G2dRotateVal rotate;
+    G2dSrcMaskDirVal dir;
+    G2dPointVal lt, rb;
+
+    bitblt.val = 0;
+    blend.val = 0;
+    rotate.val = 0;
+    dir.val = 0;
+
+    /*Set dst*/
+    if(op == G2D_OP_SRC || op == G2D_OP_CLEAR)
+        g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR);
+    else
+        g2d_add_cmd(DST_SELECT_REG, G2D_SELECT_MODE_NORMAL);
+    g2d_add_cmd(DST_COLOR_MODE_REG, dst->color_mode);
+    g2d_add_cmd(DST_BASE_ADDR_REG, dst->data.bo[0]);
+
+    if (dst->color_mode & G2D_YCbCr_2PLANE)
+    {
+        if (dst->data.bo[1] > 0)
+            g2d_add_cmd(DST_PLANE2_BASE_ADDR_REG, dst->data.bo[1]);
+        else
+            XDBG_ERROR (MG2D, "[G2D] %s:%d error: second bo is null.\n",__FUNCTION__, __LINE__);
+    }
+
+    g2d_add_cmd(DST_STRIDE_REG, dst->stride);
+
+    /*Set src*/
+    g2d_set_src(src);
+    if(src->repeat_mode)
+    {
+        g2d_add_cmd(SRC_REPEAT_MODE_REG, src->repeat_mode);
+    }
+
+    if(src->scale_mode)
+    {
+        g2d_add_cmd(SRC_XSCALE_REG, src->xscale);
+        g2d_add_cmd(SRC_YSCALE_REG, src->yscale);
+        g2d_add_cmd(SRC_SCALE_CTRL_REG, src->scale_mode);
+    }
+
+    if(src->rotate_90 || src->xDir || src->yDir)
+    {
+        rotate.data.srcRotate = src->rotate_90;
+        dir.data.dirSrcX = src->xDir;
+        dir.data.dirSrcY = src->yDir;
+    }
+
+    /*Set Mask*/
+    if(mask)
+    {
+        bitblt.data.maskingEn = 1;
+        g2d_set_mask(mask);
+
+        if(mask->repeat_mode)
+        {
+            g2d_add_cmd(MASK_REPEAT_MODE_REG, mask->repeat_mode);
+        }
+
+        if(mask->scale_mode)
+        {
+            g2d_add_cmd(MASK_XSCALE_REG, mask->xscale);
+            g2d_add_cmd(MASK_YSCALE_REG, mask->yscale);
+            g2d_add_cmd(MASK_SCALE_CTRL_REG, mask->scale_mode);
+        }
+
+        if(mask->rotate_90 || mask->xDir || mask->yDir)
+        {
+            rotate.data.maskRotate = mask->rotate_90;
+            dir.data.dirMaskX = mask->xDir;
+            dir.data.dirMaskY = mask->yDir;
+        }
+    }
+
+    /*Set Geometry*/
+    if(!_util_get_clip(src, src_x, src_y, width, height, &lt, &rb))
+    {
+        XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__);
+        g2d_reset(0);
+        return;
+    }
+    g2d_add_cmd(SRC_LEFT_TOP_REG, lt.val);
+    g2d_add_cmd(SRC_RIGHT_BOTTOM_REG, rb.val);
+
+    if(mask)
+    {
+        if(!_util_get_clip(mask, mask_x, mask_y, width, height, &lt, &rb))
+        {
+            XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__);
+            g2d_reset(0);
+            return;
+        }
+        g2d_add_cmd(MASK_LEFT_TOP_REG, lt.val);
+        g2d_add_cmd(MASK_RIGHT_BOTTOM_REG, rb.val);
+    }
+
+    if(!_util_get_clip(dst, dst_x, dst_y, width, height, &lt, &rb))
+    {
+        XDBG_ERROR (MG2D, "[G2D] %s:%d error: invalid geometry\n",__FUNCTION__, __LINE__);
+        g2d_reset(0);
+        return;
+    }
+    g2d_add_cmd(DST_LEFT_TOP_REG, lt.val);
+    g2d_add_cmd(DST_RIGHT_BOTTOM_REG, rb.val);
+
+    bitblt.data.alphaBlendMode = G2D_ALPHA_BLEND_MODE_ENABLE;
+    blend.val = g2d_get_blend_op(op);
+    g2d_add_cmd(BITBLT_COMMAND_REG, bitblt.val);
+    g2d_add_cmd(BLEND_FUNCTION_REG, blend.val);
+    g2d_add_cmd(ROTATE_REG, rotate.val);
+    g2d_add_cmd(SRC_MASK_DIRECT_REG, dir.val);
+
+    g2d_flush();
+}
diff --git a/src/ipp/sec_converter.c b/src/ipp/sec_converter.c
new file mode 100644 (file)
index 0000000..f4aa92a
--- /dev/null
@@ -0,0 +1,1020 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include <sys/ioctl.h>
+
+#include "sec.h"
+#include "sec_util.h"
+#include "sec_video_types.h"
+#include "sec_video_fourcc.h"
+#include "sec_drm_ipp.h"
+#include "sec_converter.h"
+
+#include <drm_fourcc.h>
+
+//#define INCREASE_NUM 1
+#define DEQUEUE_FORCE 1
+
+#if INCREASE_NUM
+#define CVT_BUF_MAX    6
+#endif
+
+typedef struct _SECCvtFuncData
+{
+    CvtFunc  func;
+    void    *data;
+    struct xorg_list   link;
+} SECCvtFuncData;
+
+typedef struct _SECCvtBuf
+{
+    SECCvtType    type;
+    int           index;
+    unsigned int  handles[EXYNOS_DRM_PLANAR_MAX];
+    CARD32        begin;
+
+    SECVideoBuf  *vbuf;
+
+    struct xorg_list   link;
+} SECCvtBuf;
+
+struct _SECCvt
+{
+    CARD32        stamp;
+
+    int  prop_id;
+
+    ScrnInfoPtr   pScrn;
+    SECCvtOp      op;
+    SECCvtProp    props[CVT_TYPE_MAX];
+
+    struct xorg_list   func_datas;
+    struct xorg_list   src_bufs;
+    struct xorg_list   dst_bufs;
+
+#if INCREASE_NUM
+    int           src_index;
+    int           dst_index;
+#endif
+
+    Bool          started;
+    Bool          first_event;
+
+    struct xorg_list   link;
+};
+
+static unsigned int formats[] =
+{
+    FOURCC_RGB565,
+    FOURCC_SR16,
+    FOURCC_RGB32,
+    FOURCC_SR32,
+    FOURCC_YV12,
+    FOURCC_I420,
+    FOURCC_S420,
+    FOURCC_ST12,
+    FOURCC_SN12,
+    FOURCC_NV12,
+    FOURCC_SN21,
+    FOURCC_NV21,
+    FOURCC_YUY2,
+    FOURCC_SUYV,
+    FOURCC_UYVY,
+    FOURCC_SYVY,
+    FOURCC_ITLV,
+};
+
+static struct xorg_list cvt_list;
+
+static void
+_initList (void)
+{
+    static Bool inited = FALSE;
+
+    if (inited)
+        return;
+
+    xorg_list_init (&cvt_list);
+
+    inited = TRUE;
+}
+
+static SECCvt*
+_findCvt (CARD32 stamp)
+{
+    SECCvt *cur = NULL, *next = NULL;
+
+    _initList ();
+
+    if (cvt_list.next != NULL)
+    {
+        xorg_list_for_each_entry_safe (cur, next, &cvt_list, link)
+        {
+            if (cur->stamp == stamp)
+                return cur;
+        }
+    }
+
+    return NULL;
+}
+
+static enum drm_exynos_ipp_cmd
+_drmCommand (SECCvtOp op)
+{
+    switch (op)
+    {
+    case CVT_OP_OUTPUT:
+        return IPP_CMD_OUTPUT;
+    default:
+        return IPP_CMD_M2M;
+    }
+}
+
+static enum drm_exynos_degree
+_drmDegree (int degree)
+{
+    switch (degree % 360)
+    {
+    case 90:
+        return EXYNOS_DRM_DEGREE_90;
+    case 180:
+        return EXYNOS_DRM_DEGREE_180;
+    case 270:
+        return EXYNOS_DRM_DEGREE_270;
+    default:
+        return EXYNOS_DRM_DEGREE_0;
+    }
+}
+
+static void
+_FillConfig (SECCvtType type, SECCvtProp *prop, struct drm_exynos_ipp_config *config)
+{
+    config->ops_id = (type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST;
+
+    if (prop->hflip)
+        config->flip |= EXYNOS_DRM_FLIP_HORIZONTAL;
+    if (prop->vflip)
+        config->flip |= EXYNOS_DRM_FLIP_VERTICAL;
+
+    config->degree = _drmDegree (prop->degree);
+    config->fmt = secUtilGetDrmFormat (prop->id);
+    config->sz.hsize = (__u32)prop->width;
+    config->sz.vsize = (__u32)prop->height;
+    config->pos.x = (__u32)prop->crop.x;
+    config->pos.y = (__u32)prop->crop.y;
+    config->pos.w = (__u32)prop->crop.width;
+    config->pos.h = (__u32)prop->crop.height;
+}
+
+static void
+_fillProperty (SECCvt *cvt, SECCvtType type, SECVideoBuf *vbuf, SECCvtProp *prop)
+{
+    prop->id = vbuf->id;
+    prop->width = vbuf->width;
+    prop->height = vbuf->height;
+    prop->crop = vbuf->crop;
+
+    prop->degree = cvt->props[type].degree;
+    prop->vflip = cvt->props[type].vflip;
+    prop->hflip = cvt->props[type].hflip;
+    prop->secure = cvt->props[type].secure;
+    prop->csc_range = cvt->props[type].csc_range;
+}
+
+static Bool
+_SetVbufConverting (SECVideoBuf *vbuf, SECCvt *cvt, Bool converting)
+{
+    if (!converting)
+    {
+        ConvertInfo *cur = NULL, *next = NULL;
+
+        xorg_list_for_each_entry_safe (cur, next, &vbuf->convert_info, link)
+        {
+            if (cur->cvt == (void*)cvt)
+            {
+                xorg_list_del (&cur->link);
+                free (cur);
+                return TRUE;
+            }
+        }
+
+        XDBG_ERROR (MCVT, "failed: %ld not found in %ld.\n", cvt->stamp, vbuf->stamp);
+        return FALSE;
+    }
+    else
+    {
+        ConvertInfo *info = NULL, *next = NULL;
+
+        xorg_list_for_each_entry_safe (info, next, &vbuf->convert_info, link)
+        {
+            if (info->cvt == (void*)cvt)
+            {
+                XDBG_ERROR (MCVT, "failed: %ld already converting %ld.\n", cvt->stamp, vbuf->stamp);
+                return FALSE;
+            }
+        }
+
+        info = calloc (1, sizeof (ConvertInfo));
+        XDBG_RETURN_VAL_IF_FAIL (info != NULL, FALSE);
+
+        info->cvt = (void*)cvt;
+
+        xorg_list_add (&info->link, &vbuf->convert_info);
+
+        return TRUE;
+    }
+}
+
+#if 0
+static void
+_printBufIndices (SECCvt *cvt, SECCvtType type, char *str)
+{
+    struct xorg_list *bufs;
+    SECCvtBuf *cur, *next;
+    char nums[128];
+
+    bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs;
+
+    snprintf (nums, 128, "bufs:");
+
+    list_rev_for_each_entry_safe (cur, next, bufs, link)
+    {
+        snprintf (nums, 128, "%s %d", nums, cur->index);
+    }
+
+    ErrorF ("%s: cvt(%p) %s(%s). \n", str, cvt,
+               (type == CVT_TYPE_SRC)?"SRC":"DST", nums);
+}
+#endif
+
+static int
+_secCvtGetEmptyIndex (SECCvt *cvt, SECCvtType type)
+{
+#if INCREASE_NUM
+    int ret;
+
+    if(type == CVT_TYPE_SRC)
+    {
+        ret = cvt->src_index++;
+        if (cvt->src_index >= CVT_BUF_MAX)
+            cvt->src_index = 0;
+    }
+    else
+    {
+        ret = cvt->dst_index++;
+        if (cvt->dst_index >= CVT_BUF_MAX)
+            cvt->dst_index = 0;
+    }
+
+    return ret;
+#else
+    struct xorg_list *bufs;
+    SECCvtBuf *cur = NULL, *next = NULL;
+    int ret = 0;
+
+    bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs;
+
+    while (1)
+    {
+        Bool found = FALSE;
+
+        xorg_list_for_each_entry_safe (cur, next, bufs, link)
+        {
+            if (ret == cur->index)
+            {
+                found = TRUE;
+                break;
+            }
+        }
+
+        if (!found)
+            break;
+
+        ret++;
+    }
+
+    return ret;
+#endif
+}
+
+static SECCvtBuf*
+_secCvtFindBuf (SECCvt *cvt, SECCvtType type, int index)
+{
+    struct xorg_list *bufs;
+    SECCvtBuf *cur = NULL, *next = NULL;
+
+    bufs = (type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs;
+
+    xorg_list_for_each_entry_safe (cur, next, bufs, link)
+    {
+        if (index == cur->index)
+            return cur;
+    }
+
+    XDBG_ERROR (MCVT, "cvt(%p), type(%d), index(%d) not found.\n", cvt, type, index);
+
+    return NULL;
+}
+
+static Bool
+_secCvtQueue (SECCvt *cvt, SECCvtBuf *cbuf)
+{
+    struct drm_exynos_ipp_queue_buf buf = {0,};
+    struct xorg_list *bufs;
+    int i;
+    int index = _secCvtGetEmptyIndex (cvt, cbuf->type);
+
+    buf.prop_id = cvt->prop_id;
+    buf.ops_id = (cbuf->type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST;
+    buf.buf_type = IPP_BUF_ENQUEUE;
+    buf.buf_id = cbuf->index = index;
+    buf.user_data = (__u64)cvt->stamp;
+
+    for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++)
+        buf.handle[i] = (__u32)cbuf->handles[i];
+
+    if (!secDrmIppQueueBuf (cvt->pScrn, &buf))
+        return FALSE;
+
+    bufs = (cbuf->type == CVT_TYPE_SRC) ? &cvt->src_bufs : &cvt->dst_bufs;
+    xorg_list_add (&cbuf->link, bufs);
+
+    _SetVbufConverting (cbuf->vbuf, cvt, TRUE);
+
+#if 0
+    if (cbuf->type == CVT_TYPE_SRC)
+        _printBufIndices (cvt, CVT_TYPE_SRC, "in");
+#endif
+
+    XDBG_DEBUG (MCVT, "cvt(%p), cbuf(%p), type(%d), index(%d) vbuf(%p) converting(%d)\n",
+                cvt, cbuf, cbuf->type, index, cbuf->vbuf, VBUF_IS_CONVERTING (cbuf->vbuf));
+
+    return TRUE;
+}
+
+static void
+_secCvtDequeue (SECCvt *cvt, SECCvtBuf *cbuf)
+{
+    struct drm_exynos_ipp_queue_buf buf = {0,};
+    int i;
+
+    if (!_secCvtFindBuf (cvt, cbuf->type, cbuf->index))
+    {
+        XDBG_WARNING (MCVT, "cvt(%p) type(%d), index(%d) already dequeued!\n",
+                      cvt, cbuf->type, cbuf->index);
+        return;
+    }
+
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (cbuf->vbuf));
+
+    buf.prop_id = cvt->prop_id;
+    buf.ops_id = (cbuf->type == CVT_TYPE_SRC) ? EXYNOS_DRM_OPS_SRC : EXYNOS_DRM_OPS_DST;
+    buf.buf_type = IPP_BUF_DEQUEUE;
+    buf.buf_id = cbuf->index;
+    buf.user_data = (__u64)cvt->stamp;
+
+    for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++)
+        buf.handle[i] = (__u32)cbuf->handles[i];
+
+    if (!secDrmIppQueueBuf (cvt->pScrn, &buf))
+        return;
+}
+
+static void
+_secCvtDequeued (SECCvt *cvt, SECCvtType type, int index)
+{
+    SECCvtBuf *cbuf = _secCvtFindBuf (cvt, type, index);
+
+    if (!cbuf)
+    {
+        XDBG_WARNING (MCVT, "cvt(%p) type(%d), index(%d) already dequeued!\n",
+                      cvt, type, index);
+        return;
+    }
+
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (cbuf->vbuf));
+
+    _SetVbufConverting (cbuf->vbuf, cvt, FALSE);
+
+    XDBG_DEBUG (MCVT, "cvt(%p) type(%d) index(%d) vbuf(%p) converting(%d)\n",
+                cvt, type, index, cbuf->vbuf, VBUF_IS_CONVERTING (cbuf->vbuf));
+
+    xorg_list_del (&cbuf->link);
+
+#if 0
+    if (cbuf->type == CVT_TYPE_SRC)
+        _printBufIndices (cvt, CVT_TYPE_SRC, "out");
+#endif
+
+    secUtilVideoBufferUnref (cbuf->vbuf);
+    free (cbuf);
+}
+
+static void
+_secCvtDequeueAll (SECCvt *cvt)
+{
+    SECCvtBuf *cur = NULL, *next = NULL;
+
+    xorg_list_for_each_entry_safe (cur, next, &cvt->src_bufs, link)
+    {
+        _secCvtDequeue (cvt, cur);
+    }
+
+    xorg_list_for_each_entry_safe (cur, next, &cvt->dst_bufs, link)
+    {
+        _secCvtDequeue (cvt, cur);
+    }
+}
+
+static void
+_secCvtDequeuedAll (SECCvt *cvt)
+{
+    SECCvtBuf *cur = NULL, *next = NULL;
+
+    xorg_list_for_each_entry_safe (cur, next, &cvt->src_bufs, link)
+    {
+        _secCvtDequeued (cvt, EXYNOS_DRM_OPS_SRC, cur->index);
+    }
+
+    xorg_list_for_each_entry_safe (cur, next, &cvt->dst_bufs, link)
+    {
+        _secCvtDequeued (cvt, EXYNOS_DRM_OPS_DST, cur->index);
+    }
+}
+
+static void
+_secCvtStop (SECCvt *cvt)
+{
+    struct drm_exynos_ipp_cmd_ctrl ctrl = {0,};
+
+    XDBG_RETURN_IF_FAIL (cvt != NULL);
+
+    if (!cvt->started)
+        return;
+
+    _secCvtDequeueAll (cvt);
+
+    ctrl.prop_id = cvt->prop_id;
+    ctrl.ctrl = IPP_CTRL_STOP;
+
+    secDrmIppCmdCtrl (cvt->pScrn, &ctrl);
+
+    _secCvtDequeuedAll (cvt);
+
+    XDBG_TRACE (MCVT, "cvt(%p)\n", cvt);
+
+    cvt->prop_id = -1;
+
+    memset (cvt->props, 0, sizeof (SECCvtProp) * CVT_TYPE_MAX);
+
+#if INCREASE_NUM
+    cvt->src_index = 0;
+    cvt->dst_index = 0;
+#endif
+    cvt->started = FALSE;
+
+    return;
+}
+
+Bool
+secCvtSupportFormat (SECCvtOp op, int id)
+{
+    unsigned int *drmfmts;
+    int i, size, num = 0;
+    unsigned int drmfmt = secUtilGetDrmFormat (id);
+
+    XDBG_RETURN_VAL_IF_FAIL (op >= 0 && op < CVT_OP_MAX, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (id > 0, FALSE);
+
+    size = sizeof (formats) / sizeof (unsigned int);
+
+    for (i = 0; i < size; i++)
+        if (formats[i] == id)
+            break;
+
+    if (i == size)
+    {
+        XDBG_ERROR (MCVT, "converter(op:%d) not support : '%c%c%c%c'.\n",
+                    op, FOURCC_STR (id));
+        return FALSE;
+    }
+
+    drmfmts = secDrmIppGetFormatList (&num);
+    if (!drmfmts)
+    {
+        XDBG_ERROR (MCVT, "no drm format list.\n");
+        return FALSE;
+    }
+
+    for (i = 0; i < num; i++)
+        if (drmfmts[i] == drmfmt)
+        {
+            free (drmfmts);
+            return TRUE;
+        }
+
+    XDBG_ERROR (MCVT, "drm ipp not support : '%c%c%c%c'.\n", FOURCC_STR (id));
+
+    free (drmfmts);
+
+    return FALSE;
+}
+
+Bool
+secCvtEnsureSize (SECCvtProp *src, SECCvtProp *dst)
+{
+    if (src)
+    {
+        int type = secUtilGetColorType (src->id);
+
+        XDBG_RETURN_VAL_IF_FAIL (src->width >= 16, FALSE);
+        XDBG_RETURN_VAL_IF_FAIL (src->height >= 8, FALSE);
+        XDBG_RETURN_VAL_IF_FAIL (src->crop.width >= 16, FALSE);
+        XDBG_RETURN_VAL_IF_FAIL (src->crop.height >= 8, FALSE);
+
+        if (src->width % 16)
+        {
+            if (!IS_ZEROCOPY (src->id))
+            {
+                int new_width = (src->width + 16) & (~0xF);
+                XDBG_DEBUG (MCVT, "src's width : %d to %d.\n", src->width, new_width);
+                src->width = new_width;
+            }
+        }
+
+        if (type == TYPE_YUV420 && src->height % 2)
+            XDBG_WARNING (MCVT, "src's height(%d) is not multiple of 2!!!\n", src->height);
+
+        if (type == TYPE_YUV420 || type == TYPE_YUV422)
+        {
+            src->crop.x = src->crop.x & (~0x1);
+            src->crop.width = src->crop.width & (~0x1);
+        }
+
+        if (type == TYPE_YUV420)
+            src->crop.height = src->crop.height & (~0x1);
+
+        if (src->crop.x + src->crop.width > src->width)
+            src->crop.width = src->width - src->crop.x;
+        if (src->crop.y + src->crop.height > src->height)
+            src->crop.height = src->height - src->crop.y;
+    }
+
+    if (dst)
+    {
+        int type = secUtilGetColorType (dst->id);
+
+        XDBG_RETURN_VAL_IF_FAIL (dst->width >= 16, FALSE);
+        XDBG_RETURN_VAL_IF_FAIL (dst->height >= 8, FALSE);
+        XDBG_RETURN_VAL_IF_FAIL (dst->crop.width >= 16, FALSE);
+        XDBG_RETURN_VAL_IF_FAIL (dst->crop.height >= 4, FALSE);
+
+        if (dst->width % 16)
+        {
+            int new_width = (dst->width + 16) & (~0xF);
+            XDBG_DEBUG (MCVT, "dst's width : %d to %d.\n", dst->width, new_width);
+            dst->width = new_width;
+        }
+
+        dst->height = dst->height & (~0x1);
+
+        if (type == TYPE_YUV420 && dst->height % 2)
+            XDBG_WARNING (MCVT, "dst's height(%d) is not multiple of 2!!!\n", dst->height);
+
+        if (type == TYPE_YUV420 || type == TYPE_YUV422)
+        {
+            dst->crop.x = dst->crop.x & (~0x1);
+            dst->crop.width = dst->crop.width & (~0x1);
+        }
+
+        if (type == TYPE_YUV420)
+            dst->crop.height = dst->crop.height & (~0x1);
+
+        if (dst->crop.x + dst->crop.width > dst->width)
+            dst->crop.width = dst->width - dst->crop.x;
+        if (dst->crop.y + dst->crop.height > dst->height)
+            dst->crop.height = dst->height - dst->crop.y;
+    }
+
+    return TRUE;
+}
+
+SECCvt*
+secCvtCreate (ScrnInfoPtr pScrn, SECCvtOp op)
+{
+    SECCvt *cvt;
+    CARD32 stamp = GetTimeInMillis ();
+
+    _initList ();
+
+    XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (op >= 0 && op < CVT_OP_MAX, NULL);
+
+    while (_findCvt (stamp))
+        stamp++;
+
+    cvt = calloc (1, sizeof (SECCvt));
+    XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, NULL);
+
+    cvt->stamp = stamp;
+
+    cvt->pScrn = pScrn;
+    cvt->op = op;
+    cvt->prop_id = -1;
+
+    xorg_list_init (&cvt->func_datas);
+    xorg_list_init (&cvt->src_bufs);
+    xorg_list_init (&cvt->dst_bufs);
+
+    XDBG_TRACE (MCVT, "op(%d), cvt(%p) stamp(%ld)\n", op, cvt, stamp);
+
+    xorg_list_add (&cvt->link, &cvt_list);
+
+    return cvt;
+}
+
+void
+secCvtDestroy (SECCvt *cvt)
+{
+    SECCvtFuncData *cur = NULL, *next = NULL;
+
+    if (!cvt)
+        return;
+
+    _secCvtStop (cvt);
+
+    xorg_list_del (&cvt->link);
+
+    xorg_list_for_each_entry_safe (cur, next, &cvt->func_datas, link)
+    {
+        xorg_list_del (&cur->link);
+        free (cur);
+    }
+
+    XDBG_TRACE (MCVT, "cvt(%p)\n", cvt);
+
+    free (cvt);
+}
+
+SECCvtOp
+secCvtGetOp (SECCvt *cvt)
+{
+    XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, CVT_OP_M2M);
+
+    return cvt->op;
+}
+
+Bool
+secCvtSetProperpty (SECCvt *cvt, SECCvtProp *src, SECCvtProp *dst)
+{
+    if (cvt->started)
+        return TRUE;
+
+    struct drm_exynos_ipp_property property;
+
+    XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (src != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (dst != NULL, FALSE);
+
+    if (!secCvtEnsureSize (src, dst))
+        return FALSE;
+
+    if (dst->crop.x + dst->crop.width > dst->width)
+    {
+        XDBG_ERROR (MCVT, "dst(%d+%d > %d). !\n", dst->crop.x, dst->crop.width, dst->width);
+    }
+
+    if (!secCvtSupportFormat (cvt->op, src->id))
+    {
+        XDBG_ERROR (MCVT, "cvt(%p) src '%c%c%c%c' not supported.\n",
+                    cvt, FOURCC_STR (src->id));
+        return FALSE;
+    }
+
+    if (!secCvtSupportFormat (cvt->op, dst->id))
+    {
+        XDBG_ERROR (MCVT, "cvt(%p) dst '%c%c%c%c' not supported.\n",
+                    cvt, FOURCC_STR (dst->id));
+        return FALSE;
+    }
+
+    memcpy (&cvt->props[CVT_TYPE_SRC], src, sizeof (SECCvtProp));
+    memcpy (&cvt->props[CVT_TYPE_DST], dst, sizeof (SECCvtProp));
+
+    CLEAR (property);
+    _FillConfig (CVT_TYPE_SRC, &cvt->props[CVT_TYPE_SRC], &property.config[0]);
+    _FillConfig (CVT_TYPE_DST, &cvt->props[CVT_TYPE_DST], &property.config[1]);
+    property.cmd = _drmCommand (cvt->op);
+#ifdef _F_WEARABLE_FEATURE_
+    property.type = IPP_EVENT_DRIVEN;
+#endif
+    property.prop_id = cvt->prop_id;
+    property.protect = dst->secure;
+    property.range = dst->csc_range;
+
+    XDBG_TRACE (MCVT, "cvt(%p) src('%c%c%c%c', '%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
+                cvt, FOURCC_STR(src->id), FOURCC_STR(secUtilGetDrmFormat(src->id)),
+                src->width, src->height,
+                src->crop.x, src->crop.y, src->crop.width, src->crop.height,
+                src->degree, src->hflip, src->vflip,
+                src->secure, src->csc_range);
+
+    XDBG_TRACE (MCVT, "cvt(%p) dst('%c%c%c%c', '%c%c%c%c',%dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
+                cvt, FOURCC_STR(dst->id), FOURCC_STR(secUtilGetDrmFormat(dst->id)),
+                dst->width, dst->height,
+                dst->crop.x, dst->crop.y, dst->crop.width, dst->crop.height,
+                dst->degree, dst->hflip, dst->vflip,
+                dst->secure, dst->csc_range);
+
+    cvt->prop_id = secDrmIppSetProperty (cvt->pScrn, &property);
+    XDBG_RETURN_VAL_IF_FAIL (cvt->prop_id >= 0, FALSE);
+
+    return TRUE;
+}
+
+void
+secCvtGetProperpty (SECCvt *cvt, SECCvtProp *src, SECCvtProp *dst)
+{
+    XDBG_RETURN_IF_FAIL (cvt != NULL);
+
+    if (src)
+        *src = cvt->props[CVT_TYPE_SRC];
+
+    if (dst)
+        *dst = cvt->props[CVT_TYPE_DST];
+}
+
+Bool
+secCvtConvert (SECCvt *cvt, SECVideoBuf *src, SECVideoBuf *dst)
+{
+    SECCvtBuf *src_cbuf = NULL, *dst_cbuf = NULL;
+    SECCvtProp src_prop, dst_prop;
+
+    XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (cvt->op == CVT_OP_M2M, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (src != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (dst != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (src), FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (dst), FALSE);
+
+    _fillProperty (cvt, CVT_TYPE_SRC, src, &src_prop);
+    _fillProperty (cvt, CVT_TYPE_DST, dst, &dst_prop);
+
+    if (memcmp (&cvt->props[CVT_TYPE_SRC], &src_prop, sizeof (SECCvtProp)) ||
+        memcmp (&cvt->props[CVT_TYPE_DST], &dst_prop, sizeof (SECCvtProp)))
+    {
+        XDBG_ERROR (MCVT, "cvt(%p) prop changed!\n", cvt);
+        XDBG_TRACE (MCVT, "cvt(%p) src_old('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
+                    cvt, FOURCC_STR(cvt->props[CVT_TYPE_SRC].id),
+                    cvt->props[CVT_TYPE_SRC].width, cvt->props[CVT_TYPE_SRC].height,
+                    cvt->props[CVT_TYPE_SRC].crop.x, cvt->props[CVT_TYPE_SRC].crop.y,
+                    cvt->props[CVT_TYPE_SRC].crop.width, cvt->props[CVT_TYPE_SRC].crop.height,
+                    cvt->props[CVT_TYPE_SRC].degree,
+                    cvt->props[CVT_TYPE_SRC].hflip, cvt->props[CVT_TYPE_SRC].vflip,
+                    cvt->props[CVT_TYPE_SRC].secure, cvt->props[CVT_TYPE_SRC].csc_range);
+        XDBG_TRACE (MCVT, "cvt(%p) src_new('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
+                    cvt, FOURCC_STR(src_prop.id), src_prop.width, src_prop.height,
+                    src_prop.crop.x, src_prop.crop.y, src_prop.crop.width, src_prop.crop.height,
+                    src_prop.degree, src_prop.hflip, src_prop.vflip,
+                    src_prop.secure, src_prop.csc_range);
+        XDBG_TRACE (MCVT, "cvt(%p) dst_old('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
+                    cvt, FOURCC_STR(cvt->props[CVT_TYPE_DST].id),
+                    cvt->props[CVT_TYPE_DST].width, cvt->props[CVT_TYPE_DST].height,
+                    cvt->props[CVT_TYPE_DST].crop.x, cvt->props[CVT_TYPE_DST].crop.y,
+                    cvt->props[CVT_TYPE_DST].crop.width, cvt->props[CVT_TYPE_DST].crop.height,
+                    cvt->props[CVT_TYPE_DST].degree,
+                    cvt->props[CVT_TYPE_DST].hflip, cvt->props[CVT_TYPE_DST].vflip,
+                    cvt->props[CVT_TYPE_DST].secure, cvt->props[CVT_TYPE_DST].csc_range);
+        XDBG_TRACE (MCVT, "cvt(%p) dst_new('%c%c%c%c', %dx%d, %d,%d %dx%d, %d, %d&%d, %d, %d)\n",
+                    cvt, FOURCC_STR(dst_prop.id), dst_prop.width, dst_prop.height,
+                    dst_prop.crop.x, dst_prop.crop.y, dst_prop.crop.width, dst_prop.crop.height,
+                    dst_prop.degree, dst_prop.hflip, dst_prop.vflip,
+                    dst_prop.secure, dst_prop.csc_range);
+        return FALSE;
+    }
+
+    XDBG_GOTO_IF_FAIL (cvt->prop_id >= 0, fail_to_convert);
+    XDBG_GOTO_IF_FAIL (src->handles[0] > 0, fail_to_convert);
+    XDBG_GOTO_IF_FAIL (dst->handles[0] > 0, fail_to_convert);
+
+    src_cbuf = calloc (1, sizeof (SECCvtBuf));
+    XDBG_GOTO_IF_FAIL (src_cbuf != NULL, fail_to_convert);
+    dst_cbuf = calloc (1, sizeof (SECCvtBuf));
+    XDBG_GOTO_IF_FAIL (dst_cbuf != NULL, fail_to_convert);
+
+    src_cbuf->type = CVT_TYPE_SRC;
+    src_cbuf->vbuf = secUtilVideoBufferRef (src);
+    memcpy (src_cbuf->handles, src->handles, sizeof (unsigned int) * EXYNOS_DRM_PLANAR_MAX);
+
+    if (!_secCvtQueue (cvt, src_cbuf))
+    {
+        secUtilVideoBufferUnref (src_cbuf->vbuf);
+        goto fail_to_convert;
+    }
+
+    XDBG_DEBUG (MCVT, "cvt(%p) srcbuf(%p) converting(%d)\n",
+                cvt, src, VBUF_IS_CONVERTING (src));
+
+    dst_cbuf->type = CVT_TYPE_DST;
+    dst_cbuf->vbuf = secUtilVideoBufferRef (dst);
+    memcpy (dst_cbuf->handles, dst->handles, sizeof (unsigned int) * EXYNOS_DRM_PLANAR_MAX);
+
+    if (!_secCvtQueue (cvt, dst_cbuf))
+    {
+        secUtilVideoBufferUnref (dst_cbuf->vbuf);
+        goto fail_to_convert;
+    }
+
+    XDBG_DEBUG (MCVT, "cvt(%p) dstbuf(%p) converting(%d)\n",
+                cvt, dst, VBUF_IS_CONVERTING (dst));
+
+    XDBG_DEBUG (MVBUF, "==> ipp (%ld,%d,%d : %ld,%d,%d) \n",
+                src->stamp, VBUF_IS_CONVERTING (src), src->showing,
+                dst->stamp, VBUF_IS_CONVERTING (dst), dst->showing);
+
+    if (!cvt->started)
+    {
+        struct drm_exynos_ipp_cmd_ctrl ctrl = {0,};
+
+        ctrl.prop_id = cvt->prop_id;
+        ctrl.ctrl = IPP_CTRL_PLAY;
+
+        if (!secDrmIppCmdCtrl (cvt->pScrn, &ctrl))
+            goto fail_to_convert;
+
+        XDBG_TRACE (MCVT, "cvt(%p) start.\n", cvt);
+
+        cvt->started = TRUE;
+    }
+
+    dst->dirty = TRUE;
+
+    SECPtr pSec = SECPTR (cvt->pScrn);
+    if (pSec->xvperf_mode & XBERC_XVPERF_MODE_CVT)
+        src_cbuf->begin = GetTimeInMillis ();
+
+    return TRUE;
+
+fail_to_convert:
+
+    if (src_cbuf)
+        free (src_cbuf);
+    if (dst_cbuf)
+        free (dst_cbuf);
+
+    _secCvtStop (cvt);
+
+    return FALSE;
+}
+
+Bool
+secCvtAddCallback (SECCvt *cvt, CvtFunc func, void *data)
+{
+    SECCvtFuncData *func_data;
+
+    XDBG_RETURN_VAL_IF_FAIL (cvt != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (func != NULL, FALSE);
+
+    func_data = calloc (1, sizeof (SECCvtFuncData));
+    XDBG_RETURN_VAL_IF_FAIL (func_data != NULL, FALSE);
+
+    xorg_list_add (&func_data->link, &cvt->func_datas);
+
+    func_data->func = func;
+    func_data->data = data;
+
+    return TRUE;
+}
+
+void
+secCvtRemoveCallback (SECCvt *cvt, CvtFunc func, void *data)
+{
+    SECCvtFuncData *cur = NULL, *next = NULL;
+
+    XDBG_RETURN_IF_FAIL (cvt != NULL);
+    XDBG_RETURN_IF_FAIL (func != NULL);
+
+    xorg_list_for_each_entry_safe (cur, next, &cvt->func_datas, link)
+    {
+        if (cur->func == func && cur->data == data)
+        {
+            xorg_list_del (&cur->link);
+            free (cur);
+        }
+    }
+}
+
+void
+secCvtHandleIppEvent (int fd, unsigned int *buf_idx, void *data, Bool error)
+{
+    CARD32 stamp = (CARD32)data;
+    SECCvt *cvt;
+    SECCvtBuf *src_cbuf, *dst_cbuf;
+    SECVideoBuf *src_vbuf, *dst_vbuf;
+    SECCvtFuncData *curr = NULL, *next = NULL;
+
+    XDBG_RETURN_IF_FAIL (buf_idx != NULL);
+
+    cvt = _findCvt (stamp);
+    if (!cvt)
+    {
+        XDBG_DEBUG (MCVT, "invalid cvt's stamp (%ld).\n", stamp);
+        return;
+    }
+
+    XDBG_DEBUG (MCVT, "cvt(%p) index(%d, %d)\n",
+                cvt, buf_idx[EXYNOS_DRM_OPS_SRC], buf_idx[EXYNOS_DRM_OPS_DST]);
+
+#if 0
+    char temp[64];
+    snprintf (temp, 64, "%d,%d", buf_idx[EXYNOS_DRM_OPS_SRC], buf_idx[EXYNOS_DRM_OPS_DST]);
+    _printBufIndices (cvt, CVT_TYPE_SRC, temp);
+#endif
+
+#if DEQUEUE_FORCE
+    SECCvtBuf *cur = NULL, *prev = NULL;
+
+    list_rev_for_each_entry_safe (cur, prev, &cvt->src_bufs, link)
+    {
+        if (buf_idx[EXYNOS_DRM_OPS_SRC] != cur->index)
+        {
+            unsigned int indice[EXYNOS_DRM_OPS_MAX] = {cur->index, cur->index};
+
+            XDBG_WARNING (MCVT, "cvt(%p) event(%d,%d) has been skipped!! \n",
+                          cvt, cur->index, cur->index);
+
+            /* To make sure all events are received, _secCvtDequeued should be called
+             * for every event. If a event has been skipped, to call _secCvtDequeued
+             * forcely, we call secCvtHandleIppEvent recursivly.
+             */
+            secCvtHandleIppEvent (0, indice, (void*)cvt->stamp, TRUE);
+        }
+        else
+            break;
+    }
+#endif
+
+    src_cbuf = _secCvtFindBuf (cvt, EXYNOS_DRM_OPS_SRC, buf_idx[EXYNOS_DRM_OPS_SRC]);
+    XDBG_RETURN_IF_FAIL (src_cbuf != NULL);
+
+    dst_cbuf = _secCvtFindBuf (cvt, EXYNOS_DRM_OPS_DST, buf_idx[EXYNOS_DRM_OPS_DST]);
+    XDBG_RETURN_IF_FAIL (dst_cbuf != NULL);
+
+    SECPtr pSec = SECPTR (cvt->pScrn);
+    if (pSec->xvperf_mode & XBERC_XVPERF_MODE_CVT)
+    {
+        CARD32 cur, sub;
+        cur = GetTimeInMillis ();
+        sub = cur - src_cbuf->begin;
+        ErrorF ("cvt(%p)   ipp interval  : %6ld ms\n", cvt, sub);
+    }
+
+    src_vbuf = src_cbuf->vbuf;
+    dst_vbuf = dst_cbuf->vbuf;
+
+    XDBG_DEBUG (MVBUF, "<== ipp (%ld,%d,%d : %ld,%d,%d) \n",
+                src_vbuf->stamp, VBUF_IS_CONVERTING (src_vbuf), src_vbuf->showing,
+                dst_vbuf->stamp, VBUF_IS_CONVERTING (dst_vbuf), dst_vbuf->showing);
+
+    if (!cvt->first_event)
+    {
+        XDBG_DEBUG (MCVT, "cvt(%p) got a IPP event. \n", cvt);
+        cvt->first_event = TRUE;
+    }
+
+    xorg_list_for_each_entry_safe (curr, next, &cvt->func_datas, link)
+    {
+        if (curr->func)
+            curr->func (cvt, src_vbuf, dst_vbuf, curr->data, error);
+    }
+
+    _secCvtDequeued (cvt, EXYNOS_DRM_OPS_SRC, buf_idx[EXYNOS_DRM_OPS_SRC]);
+    _secCvtDequeued (cvt, EXYNOS_DRM_OPS_DST, buf_idx[EXYNOS_DRM_OPS_DST]);
+}
diff --git a/src/ipp/sec_converter.h b/src/ipp/sec_converter.h
new file mode 100644 (file)
index 0000000..b1b147d
--- /dev/null
@@ -0,0 +1,90 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_CONVERTER_H__
+#define __SEC_CONVERTER_H__
+
+#include <fbdevhw.h>
+#include <exynos_drm.h>
+
+typedef struct _SECCvt SECCvt;
+
+typedef enum
+{
+    CVT_OP_M2M,
+    CVT_OP_OUTPUT,
+    CVT_OP_MAX,
+} SECCvtOp;
+
+typedef enum
+{
+    CVT_TYPE_SRC,
+    CVT_TYPE_DST,
+    CVT_TYPE_MAX,
+} SECCvtType;
+
+typedef struct _SECCvtProp
+{
+    unsigned int id;
+
+    int          width;
+    int          height;
+    xRectangle   crop;
+
+    int          degree;
+    Bool         vflip;
+    Bool         hflip;
+    Bool         secure;
+    int          csc_range;
+} SECCvtProp;
+
+typedef struct _SECCvtFmt
+{
+    unsigned int id;
+
+} SECCvtFmt;
+
+Bool     secCvtSupportFormat  (SECCvtOp op, int id);
+Bool     secCvtEnsureSize     (SECCvtProp *src, SECCvtProp *dst);
+
+SECCvt*  secCvtCreate         (ScrnInfoPtr pScrn, SECCvtOp op);
+void     secCvtDestroy        (SECCvt *cvt);
+SECCvtOp secCvtGetOp          (SECCvt *cvt);
+Bool     secCvtSetProperpty   (SECCvt *cvt, SECCvtProp *src, SECCvtProp *dst);
+void     secCvtGetProperpty   (SECCvt *cvt, SECCvtProp *src, SECCvtProp *dst);
+Bool     secCvtConvert        (SECCvt *cvt, SECVideoBuf *src, SECVideoBuf *dst);
+
+typedef void (*CvtFunc) (SECCvt *cvt, SECVideoBuf *src, SECVideoBuf *dst, void *cvt_data, Bool error);
+Bool     secCvtAddCallback    (SECCvt *cvt, CvtFunc func, void *data);
+void     secCvtRemoveCallback (SECCvt *cvt, CvtFunc func, void *data);
+
+void     secCvtHandleIppEvent (int fd, unsigned int *buf_idx, void *data, Bool error);
+
+#endif  /* __SEC_CONVERTER_H__ */
diff --git a/src/ipp/sec_drm_ipp.c b/src/ipp/sec_drm_ipp.c
new file mode 100644 (file)
index 0000000..cb50826
--- /dev/null
@@ -0,0 +1,165 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include <sys/ioctl.h>
+
+#include "sec.h"
+#include "sec_util.h"
+#include "sec_video_types.h"
+#include "sec_video_fourcc.h"
+#include "sec_drm_ipp.h"
+
+#include <drm_fourcc.h>
+
+static unsigned int drmfmt_list[] =
+{
+    /* packed */
+    DRM_FORMAT_RGB565,
+    DRM_FORMAT_XRGB8888,
+    DRM_FORMAT_YUYV,
+    DRM_FORMAT_UYVY,
+
+    /* 2 plane */
+    DRM_FORMAT_NV12,
+    DRM_FORMAT_NV21,
+    DRM_FORMAT_NV12MT,
+
+    /* 3 plane */
+    DRM_FORMAT_YVU420,
+    DRM_FORMAT_YUV420,
+    DRM_FORMAT_YUV444,
+};
+
+/* A drmfmt list newly allocated. should be freed. */
+unsigned int*
+secDrmIppGetFormatList (int *num)
+{
+    unsigned int *drmfmts;
+
+    XDBG_RETURN_VAL_IF_FAIL (num != NULL, NULL);
+
+    drmfmts = malloc (sizeof (drmfmt_list));
+    XDBG_RETURN_VAL_IF_FAIL (drmfmts != NULL, NULL);
+
+    memcpy (drmfmts, drmfmt_list, sizeof (drmfmt_list));
+    *num = sizeof (drmfmt_list) / sizeof (unsigned int);
+
+    return drmfmts;
+}
+
+int
+secDrmIppSetProperty (ScrnInfoPtr pScrn, struct drm_exynos_ipp_property *property)
+{
+    int ret = 0;
+
+    XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, -1);
+    XDBG_RETURN_VAL_IF_FAIL (property != NULL, -1);
+
+    if (property->prop_id == (__u32)-1)
+        property->prop_id = 0;
+
+    XDBG_DEBUG (MDRM, "src : flip(%x) deg(%d) fmt(%c%c%c%c) sz(%dx%d) pos(%d,%d %dx%d)  \n",
+                property->config[0].flip, property->config[0].degree, FOURCC_STR (property->config[0].fmt),
+                property->config[0].sz.hsize, property->config[0].sz.vsize,
+                property->config[0].pos.x, property->config[0].pos.y, property->config[0].pos.w, property->config[0].pos.h);
+    XDBG_DEBUG (MDRM, "dst : flip(%x) deg(%d) fmt(%c%c%c%c) sz(%dx%d) pos(%d,%d %dx%d)  \n",
+                property->config[1].flip, property->config[1].degree, FOURCC_STR (property->config[1].fmt),
+                property->config[1].sz.hsize, property->config[1].sz.vsize,
+                property->config[1].pos.x, property->config[1].pos.y, property->config[1].pos.w, property->config[1].pos.h);
+
+#ifdef _F_WEARABLE_FEATURE_
+    XDBG_DEBUG (MDRM, "cmd(%d) type(%d) ipp_id(%d) prop_id(%d) hz(%d) protect(%d) range(%d) blending(%x)\n",
+                property->cmd, property->type, property->ipp_id, property->prop_id, property->refresh_rate,
+                property->protect, property->range, property->blending);
+#else
+    XDBG_DEBUG (MDRM, "cmd(%d) ipp_id(%d) prop_id(%d) hz(%d) protect(%d) range(%d)\n",
+                property->cmd, property->ipp_id, property->prop_id, property->refresh_rate,
+                property->protect, property->range);
+#endif
+
+    ret = ioctl (SECPTR (pScrn)->drm_fd, DRM_IOCTL_EXYNOS_IPP_SET_PROPERTY, property);
+    if (ret)
+    {
+        XDBG_ERRNO (MDRM, "failed. \n");
+        return -1;
+    }
+
+    XDBG_TRACE (MDRM, "success. prop_id(%d) \n", property->prop_id);
+
+    return property->prop_id;
+}
+
+Bool
+secDrmIppQueueBuf (ScrnInfoPtr pScrn, struct drm_exynos_ipp_queue_buf *buf)
+{
+    int ret = 0;
+
+    XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (buf != NULL, FALSE);
+
+    XDBG_DEBUG (MDRM, "prop_id(%d) ops_id(%d) ctrl(%d) id(%d) handles(%x %x %x). \n",
+                buf->prop_id, buf->ops_id, buf->buf_type, buf->buf_id,
+                buf->handle[0], buf->handle[1], buf->handle[2]);
+
+    ret = ioctl (SECPTR (pScrn)->drm_fd, DRM_IOCTL_EXYNOS_IPP_QUEUE_BUF, buf);
+    if (ret)
+    {
+        XDBG_ERRNO (MDRM, "failed. prop_id(%d) op(%d) buf(%d) id(%d)\n",
+                    buf->prop_id, buf->ops_id, buf->buf_type, buf->buf_id);
+        return FALSE;
+    }
+
+    XDBG_DEBUG (MDRM, "success. prop_id(%d) \n", buf->prop_id);
+
+    return TRUE;
+}
+
+Bool
+secDrmIppCmdCtrl (ScrnInfoPtr pScrn, struct drm_exynos_ipp_cmd_ctrl *ctrl)
+{
+    int ret = 0;
+
+    XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (ctrl != NULL, FALSE);
+
+    XDBG_TRACE (MDRM, "prop_id(%d) ctrl(%d). \n", ctrl->prop_id, ctrl->ctrl);
+
+    ret = ioctl (SECPTR (pScrn)->drm_fd, DRM_IOCTL_EXYNOS_IPP_CMD_CTRL, ctrl);
+    if (ret)
+    {
+        XDBG_ERRNO (MDRM, "failed. prop_id(%d) ctrl(%d)\n",
+                    ctrl->prop_id, ctrl->ctrl);
+        return FALSE;
+    }
+
+    XDBG_DEBUG (MDRM, "success. prop_id(%d) \n", ctrl->prop_id);
+
+    return TRUE;
+}
diff --git a/src/ipp/sec_drm_ipp.h b/src/ipp/sec_drm_ipp.h
new file mode 100644 (file)
index 0000000..e344c4f
--- /dev/null
@@ -0,0 +1,44 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_DRM_IPP_H__
+#define __SEC_DRM_IPP_H__
+
+#include <fbdevhw.h>
+#include <exynos_drm.h>
+
+/* A drmfmt list newly allocated. should be freed. */
+unsigned int* secDrmIppGetFormatList (int *num);
+
+int     secDrmIppSetProperty   (ScrnInfoPtr pScrn, struct drm_exynos_ipp_property *property);
+Bool    secDrmIppQueueBuf      (ScrnInfoPtr pScrn, struct drm_exynos_ipp_queue_buf *buf);
+Bool    secDrmIppCmdCtrl       (ScrnInfoPtr pScrn, struct drm_exynos_ipp_cmd_ctrl *ctrl);
+
+#endif  /* __SEC_DRM_IPP_H__ */
diff --git a/src/ipp/sec_wb.c b/src/ipp/sec_wb.c
new file mode 100644 (file)
index 0000000..b1f708e
--- /dev/null
@@ -0,0 +1,1338 @@
+/*
+ * xserver-xorg-video-exynos
+ *
+ * Copyright 2004 Keith Packard
+ * Copyright 2005 Eric Anholt
+ * Copyright 2006 Nokia Corporation
+ * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+ *
+ * Contact: Boram Park <boram1288.park@samsung.com>
+ *
+ * Permission to use, copy, modify, distribute and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of the authors and/or copyright holders
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  The authors and
+ * copyright holders make no representations about the suitability of this
+ * software for any purpose.  It is provided "as is" without any express
+ * or implied warranty.
+ *
+ * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/time.h>
+
+#include <X11/Xatom.h>
+#include <xace.h>
+#include <xacestr.h>
+
+#include "exynos_drm.h"
+
+#include "sec.h"
+#include "sec_util.h"
+#include "sec_crtc.h"
+#include "sec_video_fourcc.h"
+#include "sec_video_tvout.h"
+#include "sec_wb.h"
+#include "sec_drm_ipp.h"
+#include "sec_converter.h"
+
+#include <drm_fourcc.h>
+
+#define WB_BUF_MAX      5
+#define WB_BUF_DEFAULT  3
+#define WB_BUF_MIN      2
+
+enum
+{
+    PENDING_NONE,
+    PENDING_ROTATE,
+    PENDING_STOP,
+    PENDING_CLOSE,
+};
+
+enum
+{
+    STATUS_STARTED,
+    STATUS_STOPPED,
+};
+
+typedef struct _SECWbNotifyFuncInfo
+{
+    SECWbNotify   noti;
+    WbNotifyFunc  func;
+    void         *user_data;
+
+    struct _SECWbNotifyFuncInfo *next;
+} SECWbNotifyFuncInfo;
+
+struct _SECWb
+{
+    int  prop_id;
+
+    ScrnInfoPtr pScrn;
+
+    unsigned int id;
+
+    int     rotate;
+
+    int     width;
+    int     height;
+    xRectangle  drm_dst;
+    xRectangle  tv_dst;
+
+    SECVideoBuf *dst_buf[WB_BUF_MAX];
+    Bool         queued[WB_BUF_MAX];
+    int          buf_num;
+
+    int     wait_show;
+    int     now_showing;
+
+    SECWbNotifyFuncInfo *info_list;
+
+    /* for tvout */
+    Bool        tvout;
+    SECVideoTv *tv;
+    SECLayerPos lpos;
+
+    Bool       need_rotate_hook;
+    OsTimerPtr rotate_timer;
+
+    /* count */
+    unsigned int put_counts;
+    unsigned int last_counts;
+    OsTimerPtr timer;
+
+    OsTimerPtr event_timer;
+    OsTimerPtr ipp_timer;
+
+    Bool scanout;
+    int  hz;
+
+    int     status;
+    Bool    secure;
+    CARD32  prev_time;
+};
+
+static unsigned int formats[] =
+{
+    FOURCC_RGB32,
+    FOURCC_ST12,
+    FOURCC_SN12,
+};
+
+static SECWb *keep_wb;
+static Atom atom_wb_rotate;
+
+static void _secWbQueue (SECWb *wb, int index);
+static Bool _secWbRegisterRotateHook (SECWb *wb, Bool hook);
+static void _secWbCloseDrmDstBuffer (SECWb *wb);
+static void _secWbCloseDrm (SECWb *wb);
+
+static CARD32
+_secWbCountPrint (OsTimerPtr timer, CARD32 now, pointer arg)
+{
+    SECWb *wb = (SECWb*)arg;
+
+    ErrorF ("IppEvent : %d fps. \n", wb->put_counts - wb->last_counts);
+
+    wb->last_counts = wb->put_counts;
+
+    wb->timer = TimerSet (wb->timer, 0, 1000, _secWbCountPrint, arg);
+
+    return 0;
+}
+
+static void
+_secWbCountFps (SECWb *wb)
+{
+    wb->put_counts++;
+
+    if (wb->timer)
+        return;
+
+    wb->timer = TimerSet (NULL, 0, 1000, _secWbCountPrint, wb);
+}
+
+static void
+_secWbCountStop (SECWb *wb)
+{
+    if (wb->timer)
+    {
+        TimerFree (wb->timer);
+        wb->timer = NULL;
+    }
+
+    wb->put_counts = 0;
+    wb->last_counts = 0;
+}
+
+static unsigned int
+_secWbSupportFormat (int id)
+{
+    unsigned int *drmfmts;
+    int i, size, num = 0;
+    unsigned int drmfmt = secUtilGetDrmFormat (id);
+
+    size = sizeof (formats) / sizeof (unsigned int);
+
+    for (i = 0; i < size; i++)
+        if (formats[i] == id)
+            break;
+
+    if (i == size)
+    {
+        XDBG_ERROR (MWB, "wb not support : '%c%c%c%c'.\n", FOURCC_STR (id));
+        return 0;
+    }
+
+    drmfmts = secDrmIppGetFormatList (&num);
+    if (!drmfmts)
+    {
+        XDBG_ERROR (MWB, "no drm format list.\n");
+        return 0;
+    }
+
+    for (i = 0; i < num; i++)
+        if (drmfmts[i] == drmfmt)
+        {
+            free (drmfmts);
+            return drmfmt;
+        }
+
+    XDBG_ERROR (MWB, "drm ipp not support : '%c%c%c%c'.\n", FOURCC_STR (id));
+
+    free (drmfmts);
+
+    return 0;
+}
+
+static void
+_secWbCallNotifyFunc (SECWb *wb, SECWbNotify noti, void *noti_data)
+{
+    SECWbNotifyFuncInfo *info;
+
+    nt_list_for_each_entry (info, wb->info_list, next)
+    {
+        if (info->noti == noti && info->func)
+            info->func (wb, noti, noti_data, info->user_data);
+    }
+}
+
+static void
+_secWbLayerNotifyFunc (SECLayer *layer, int type, void *type_data, void *data)
+{
+    SECWb *wb = (SECWb*)data;
+    SECVideoBuf *vbuf = (SECVideoBuf*)type_data;
+
+    if (type != LAYER_VBLANK)
+        return;
+
+    XDBG_RETURN_IF_FAIL (wb != NULL);
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (vbuf));
+
+    if (wb->wait_show >= 0 && wb->dst_buf[wb->wait_show] != vbuf)
+        XDBG_WARNING (MWB, "wait_show(%d,%p) != showing_vbuf(%p). \n",
+                      wb->wait_show, wb->dst_buf[wb->wait_show], vbuf);
+
+    if (wb->now_showing >= 0)
+        _secWbQueue (wb, wb->now_showing);
+
+    wb->now_showing = wb->wait_show;
+    wb->wait_show = -1;
+
+    XDBG_DEBUG (MWB, "now_showing(%d,%p). \n", wb->now_showing, vbuf);
+}
+
+static Bool
+_secWbCalTvoutRect (SECWb *wb)
+{
+    SECModePtr pSecMode = (SECModePtr) SECPTR (wb->pScrn)->pSecMode;
+    int src_w, src_h, dst_w, dst_h;
+
+    if (!wb->tvout)
+    {
+        if (wb->width == 0 || wb->height == 0)
+        {
+            wb->width = pSecMode->main_lcd_mode.hdisplay;
+            wb->height = pSecMode->main_lcd_mode.vdisplay;
+        }
+
+        src_w = pSecMode->main_lcd_mode.hdisplay;
+        src_h = pSecMode->main_lcd_mode.vdisplay;
+        dst_w = wb->width;
+        dst_h = wb->height;
+        XDBG_RETURN_VAL_IF_FAIL (src_w > 0 && src_h > 0, FALSE);
+        XDBG_RETURN_VAL_IF_FAIL (dst_w > 0 && dst_h > 0, FALSE);
+
+        if (wb->rotate % 180)
+            SWAP (src_w, src_h);
+
+        secUtilAlignRect (src_w, src_h, dst_w, dst_h, &wb->drm_dst, TRUE);
+    }
+    else
+    {
+        src_w = (int)pSecMode->main_lcd_mode.hdisplay;
+        src_h = (int)pSecMode->main_lcd_mode.vdisplay;
+        dst_w = (int)pSecMode->ext_connector_mode.hdisplay;
+        dst_h = (int)pSecMode->ext_connector_mode.vdisplay;
+        XDBG_RETURN_VAL_IF_FAIL (src_w > 0 && src_h > 0, FALSE);
+        XDBG_RETURN_VAL_IF_FAIL (dst_w > 0 && dst_h > 0, FALSE);
+
+        if (wb->rotate % 180)
+            SWAP (src_w, src_h);
+
+        if (wb->lpos == LAYER_UPPER)
+        {
+            /* Mixer can't scale. */
+            wb->width = dst_w;
+            wb->height = dst_h;
+            wb->tv_dst.width = wb->width;
+            wb->tv_dst.height = wb->height;
+
+            secUtilAlignRect (src_w, src_h, dst_w, dst_h, &wb->drm_dst, TRUE);
+        }
+        else /* LAYER_LOWER1 */
+        {
+            /* VP can scale */
+            secUtilAlignRect (src_w, src_h, dst_w, dst_h, &wb->tv_dst, TRUE);
+
+            wb->width = src_w;
+            wb->height = src_h;
+
+            wb->drm_dst.width = wb->width;
+            wb->drm_dst.height = wb->height;
+        }
+    }
+
+    XDBG_TRACE (MWB, "tvout(%d) lpos(%d) src(%dx%d) drm_dst(%d,%d %dx%d) tv_dst(%d,%d %dx%d).\n",
+                wb->tvout, wb->lpos, wb->width, wb->height,
+                wb->drm_dst.x, wb->drm_dst.y, wb->drm_dst.width, wb->drm_dst.height,
+                wb->tv_dst.x, wb->tv_dst.y, wb->tv_dst.width, wb->tv_dst.height);
+
+    return TRUE;
+}
+
+static void
+_secWbQueue (SECWb *wb, int index)
+{
+    struct drm_exynos_ipp_queue_buf buf;
+    int j;
+
+    if (index < 0)
+        return;
+
+    XDBG_RETURN_IF_FAIL (wb->dst_buf[index]->showing == FALSE);
+
+    CLEAR (buf);
+    buf.ops_id = EXYNOS_DRM_OPS_DST;
+    buf.buf_type = IPP_BUF_ENQUEUE;
+    buf.prop_id = wb->prop_id;
+    buf.buf_id = index;
+    buf.user_data = (__u64)(unsigned int)wb;
+
+    for (j = 0; j < PLANAR_CNT; j++)
+        buf.handle[j] = wb->dst_buf[index]->handles[j];
+
+    if (!secDrmIppQueueBuf (wb->pScrn, &buf))
+        return;
+
+    wb->queued[index] = TRUE;
+    wb->dst_buf[index]->dirty = TRUE;
+
+    XDBG_DEBUG (MWB, "index(%d)\n", index);
+}
+
+static int
+_secWbDequeued (SECWb *wb, Bool skip_put, int index)
+{
+    int i, remain = 0;
+
+    XDBG_RETURN_VAL_IF_FAIL (index < wb->buf_num, -1);
+    XDBG_WARNING_IF_FAIL (wb->dst_buf[index]->showing == FALSE);
+
+    XDBG_DEBUG (MWB, "skip_put(%d) index(%d)\n", skip_put, index);
+
+    if (!wb->queued[index])
+        XDBG_WARNING (MWB, "buf(%d) already dequeued.\n", index);
+
+    wb->queued[index] = FALSE;
+
+    for (i = 0; i< wb->buf_num; i++)
+    {
+        if (wb->queued[i])
+            remain++;
+    }
+
+    /* the count of remain buffers should be more than 2. */
+    if (remain >= WB_BUF_MIN)
+        _secWbCallNotifyFunc (wb, WB_NOTI_IPP_EVENT, (void*)wb->dst_buf[index]);
+    else
+        XDBG_DEBUG (MWB, "remain buffer count: %d\n", remain);
+
+    if (wb->tvout)
+    {
+        if (!wb->tv)
+        {
+            if (wb->tv_dst.width > 0 && wb->tv_dst.height > 0)
+                wb->tv = secVideoTvConnect (wb->pScrn, wb->id, wb->lpos);
+
+            if (wb->tv && !secUtilEnsureExternalCrtc (wb->pScrn))
+            {
+                wb->tvout = FALSE;
+                secVideoTvDisconnect (wb->tv);
+                wb->tv = NULL;
+            }
+
+            if (wb->tv)
+            {
+                SECLayer *layer = secVideoTvGetLayer (wb->tv);
+                secLayerEnableVBlank (layer, TRUE);
+                secLayerAddNotifyFunc (layer, _secWbLayerNotifyFunc, wb);
+            }
+        }
+
+        if (!skip_put && wb->tv)
+        {
+            wb->wait_show = index;
+            secVideoTvPutImage (wb->tv, wb->dst_buf[index], &wb->tv_dst, 0);
+        }
+    }
+
+    if (remain == 0)
+        XDBG_ERROR (MWB, "*** wb's buffer empty!! *** \n");
+
+    XDBG_DEBUG (MWB, "tv(%p) wait_show(%d) remain(%d)\n", wb->tv,
+                wb->wait_show, remain);
+
+    return index;
+}
+
+static CARD32
+_secWbIppRetireTimeout (OsTimerPtr timer, CARD32 now, pointer arg)
+{
+    SECWb *wb = (SECWb*)arg;
+
+    if (wb->ipp_timer)
+    {
+        TimerFree (wb->ipp_timer);
+        wb->ipp_timer = NULL;
+    }
+
+    XDBG_ERROR (MWB, "failed : +++ WB IPP Retire Timeout!!\n");
+
+    return 0;
+}
+
+unsigned int
+secWbGetPropID (void)
+{
+    if (!keep_wb)
+        return -1;
+
+    return keep_wb->prop_id;
+}
+
+void
+secWbHandleIppEvent (int fd, unsigned int *buf_idx, void *data)
+{
+    SECWb *wb = (SECWb*)data;
+    SECPtr pSec;
+    int index = buf_idx[EXYNOS_DRM_OPS_DST];
+
+    if (!wb)
+    {
+        XDBG_ERROR (MWB, "data is %p \n", data);
+        return;
+    }
+
+    if (keep_wb != wb)
+    {
+        XDBG_WARNING (MWB, "Useless ipp event! (%p) \n", wb);
+        return;
+    }
+
+    if (wb->event_timer)
+    {
+        TimerFree (wb->event_timer);
+        wb->event_timer = NULL;
+    }
+
+    if (wb->status == STATUS_STOPPED)
+    {
+        XDBG_ERROR (MWB, "stopped. ignore a event.\n", data);
+        return;
+    }
+
+    if (wb->ipp_timer)
+    {
+        TimerFree (wb->ipp_timer);
+        wb->ipp_timer = NULL;
+    }
+
+    wb->ipp_timer = TimerSet (wb->ipp_timer, 0, 2000, _secWbIppRetireTimeout, wb);
+
+    XDBG_DEBUG (MWB, "=============== wb(%p) !\n", wb);
+
+    pSec = SECPTR (wb->pScrn);
+
+    if (pSec->xvperf_mode & XBERC_XVPERF_MODE_WB)
+    {
+        CARD32 cur, sub;
+        cur = GetTimeInMillis ();
+        sub = cur - wb->prev_time;
+        wb->prev_time = cur;
+        ErrorF ("wb evt interval  : %6ld ms\n", sub);
+    }
+
+    if (pSec->wb_fps)
+        _secWbCountFps (wb);
+    else
+        _secWbCountStop (wb);
+
+    if (wb->rotate_timer)
+    {
+        _secWbDequeued (wb, TRUE, index);
+        _secWbQueue (wb, index);
+    }
+    else
+    {
+        if (wb->wait_show >= 0)
+        {
+            _secWbDequeued (wb, TRUE, index);
+            _secWbQueue (wb, index);
+        }
+        else
+        {
+            _secWbDequeued (wb, FALSE, index);
+
+            if (wb->wait_show < 0 && !wb->dst_buf[index]->showing)
+                _secWbQueue (wb, index);
+        }
+    }
+
+    _secWbCallNotifyFunc (wb, WB_NOTI_IPP_EVENT_DONE, NULL);
+
+    XDBG_DEBUG (MWB, "=============== !\n");
+}
+
+static Bool
+_secWbEnsureDrmDstBuffer (SECWb *wb)
+{
+    int i;
+
+    for (i = 0; i < wb->buf_num; i++)
+    {
+        if (wb->dst_buf[i])
+        {
+            secUtilClearVideoBuffer (wb->dst_buf[i]);
+            continue;
+        }
+
+        wb->dst_buf[i] = secUtilAllocVideoBuffer (wb->pScrn, wb->id,
+                                                  wb->width, wb->height,
+                                                  keep_wb->scanout, TRUE,
+                                                  secVideoIsSecureMode (wb->pScrn));
+        XDBG_GOTO_IF_FAIL (wb->dst_buf[i] != NULL, fail_to_ensure);
+    }
+
+    return TRUE;
+fail_to_ensure:
+    _secWbCloseDrmDstBuffer (wb);
+
+    return FALSE;
+}
+
+static void
+_secWbCloseDrmDstBuffer (SECWb *wb)
+{
+    int i;
+
+    for (i = 0; i < wb->buf_num; i++)
+    {
+        if (wb->dst_buf[i])
+        {
+            secUtilVideoBufferUnref (wb->dst_buf[i]);
+            wb->dst_buf[i] = NULL;
+        }
+    }
+}
+
+static void
+_secWbClearDrmDstBuffer (SECWb *wb)
+{
+    int i;
+
+    for (i = 0; i < wb->buf_num; i++)
+    {
+        if (wb->dst_buf[i])
+        {
+            if (!wb->dst_buf[i]->showing && wb->dst_buf[i]->need_reset)
+                secUtilClearVideoBuffer (wb->dst_buf[i]);
+            else
+                wb->dst_buf[i]->need_reset = TRUE;
+        }
+    }
+}
+
+static CARD32
+_secWbEventTimeout (OsTimerPtr timer, CARD32 now, pointer arg)
+{
+    SECWb *wb = (SECWb*) arg;
+
+    if (!wb)
+        return 0;
+
+    if (wb->event_timer)
+    {
+        TimerFree (wb->event_timer);
+        wb->event_timer = NULL;
+    }
+
+    XDBG_ERROR (MWB, "*** ipp event not happen!! \n");
+
+    return 0;
+}
+
+static Bool
+_secWbOpenDrm (SECWb *wb)
+{
+    SECPtr pSec = SECPTR (wb->pScrn);
+    SECModePtr pSecMode = (SECModePtr)pSec->pSecMode;
+    int i;
+    unsigned int drmfmt = 0;
+    struct drm_exynos_ipp_property property;
+    enum drm_exynos_degree degree;
+    struct drm_exynos_ipp_cmd_ctrl ctrl;
+
+    if (wb->need_rotate_hook)
+        _secWbRegisterRotateHook (wb, TRUE);
+
+    if (!_secWbCalTvoutRect (wb))
+        goto fail_to_open;
+
+    drmfmt = _secWbSupportFormat (wb->id);
+    XDBG_GOTO_IF_FAIL (drmfmt > 0, fail_to_open);
+
+    if ((wb->rotate) % 360 == 90)
+        degree = EXYNOS_DRM_DEGREE_90;
+    else if ((wb->rotate) % 360 == 180)
+        degree = EXYNOS_DRM_DEGREE_180;
+    else if ((wb->rotate) % 360 == 270)
+        degree = EXYNOS_DRM_DEGREE_270;
+    else
+        degree = EXYNOS_DRM_DEGREE_0;
+
+    CLEAR (property);
+    property.config[0].ops_id = EXYNOS_DRM_OPS_SRC;
+    property.config[0].fmt = DRM_FORMAT_YUV444;
+    property.config[0].sz.hsize = (__u32)pSecMode->main_lcd_mode.hdisplay;
+    property.config[0].sz.vsize = (__u32)pSecMode->main_lcd_mode.vdisplay;
+    property.config[0].pos.x = 0;
+    property.config[0].pos.y = 0;
+    property.config[0].pos.w = (__u32)pSecMode->main_lcd_mode.hdisplay;
+    property.config[0].pos.h = (__u32)pSecMode->main_lcd_mode.vdisplay;
+    property.config[1].ops_id = EXYNOS_DRM_OPS_DST;
+    property.config[1].degree = degree;
+    property.config[1].fmt = drmfmt;
+    property.config[1].sz.hsize = wb->width;
+    property.config[1].sz.vsize = wb->height;
+    property.config[1].pos.x = (__u32)wb->drm_dst.x;
+    property.config[1].pos.y = (__u32)wb->drm_dst.y;
+    property.config[1].pos.w = (__u32)wb->drm_dst.width;
+    property.config[1].pos.h = (__u32)wb->drm_dst.height;
+    property.cmd = IPP_CMD_WB;
+#ifdef _F_WEARABLE_FEATURE_
+    property.type = IPP_EVENT_DRIVEN;
+#endif
+    property.prop_id = wb->prop_id;
+    property.refresh_rate = wb->hz;
+    property.protect = wb->secure;
+
+    wb->prop_id = secDrmIppSetProperty (wb->pScrn, &property);
+    XDBG_GOTO_IF_FAIL (wb->prop_id >= 0, fail_to_open);
+
+    XDBG_TRACE (MWB, "prop_id(%d) drmfmt(%c%c%c%c) size(%dx%d) crop(%d,%d %dx%d) rotate(%d)\n",
+                wb->prop_id, FOURCC_STR(drmfmt), wb->width, wb->height,
+                wb->drm_dst.x, wb->drm_dst.y, wb->drm_dst.width, wb->drm_dst.height,
+                wb->rotate);
+
+    if (!_secWbEnsureDrmDstBuffer (wb))
+        goto fail_to_open;
+
+    for (i = 0; i < wb->buf_num; i++)
+    {
+        struct drm_exynos_ipp_queue_buf buf;
+        int j;
+
+        if (wb->dst_buf[i]->showing)
+        {
+            XDBG_DEBUG (MWB, "%d. name(%d) is showing\n", i, wb->dst_buf[i]->keys[0]);
+            continue;
+        }
+
+        CLEAR (buf);
+        buf.ops_id = EXYNOS_DRM_OPS_DST;
+        buf.buf_type = IPP_BUF_ENQUEUE;
+        buf.prop_id = wb->prop_id;
+        buf.buf_id = i;
+        buf.user_data = (__u64)(unsigned int)wb;
+
+        XDBG_GOTO_IF_FAIL (wb->dst_buf[i] != NULL, fail_to_open);
+
+        for (j = 0; j < PLANAR_CNT; j++)
+            buf.handle[j] = wb->dst_buf[i]->handles[j];
+
+        if (!secDrmIppQueueBuf (wb->pScrn, &buf))
+            goto fail_to_open;
+
+        wb->queued[i] = TRUE;
+    }
+
+    CLEAR (ctrl);
+    ctrl.prop_id = wb->prop_id;
+    ctrl.ctrl = IPP_CTRL_PLAY;
+    if (!secDrmIppCmdCtrl (wb->pScrn, &ctrl))
+        goto fail_to_open;
+
+    wb->event_timer = TimerSet (wb->event_timer, 0, 3000, _secWbEventTimeout, wb);
+
+    return TRUE;
+
+fail_to_open:
+
+    _secWbCloseDrm (wb);
+
+    _secWbCloseDrmDstBuffer (wb);
+
+    return FALSE;
+}
+
+static void
+_secWbCloseDrm (SECWb *wb)
+{
+    struct drm_exynos_ipp_cmd_ctrl ctrl;
+    int i;
+
+    _secWbCountStop (wb);
+
+    XDBG_TRACE (MWB, "now_showing(%d) \n", wb->now_showing);
+
+    if (wb->tv)
+    {
+        secVideoTvDisconnect (wb->tv);
+        wb->tv = NULL;
+        wb->wait_show = -1;
+        wb->now_showing = -1;
+    }
+
+    for (i = 0; i < wb->buf_num; i++)
+    {
+        struct drm_exynos_ipp_queue_buf buf;
+        int j;
+
+        CLEAR (buf);
+        buf.ops_id = EXYNOS_DRM_OPS_DST;
+        buf.buf_type = IPP_BUF_DEQUEUE;
+        buf.prop_id = wb->prop_id;
+        buf.buf_id = i;
+
+        if (wb->dst_buf[i])
+            for (j = 0; j < EXYNOS_DRM_PLANAR_MAX && j < PLANAR_CNT; j++)
+                buf.handle[j] = wb->dst_buf[i]->handles[j];
+
+        secDrmIppQueueBuf (wb->pScrn, &buf);
+
+        wb->queued[i] = FALSE;
+    }
+
+    CLEAR (ctrl);
+    ctrl.prop_id = wb->prop_id;
+    ctrl.ctrl = IPP_CTRL_STOP;
+    secDrmIppCmdCtrl (wb->pScrn, &ctrl);
+
+    wb->prop_id = -1;
+
+    if (wb->rotate_timer)
+    {
+        TimerFree (wb->rotate_timer);
+        wb->rotate_timer = NULL;
+    }
+
+    if (wb->event_timer)
+    {
+        TimerFree (wb->event_timer);
+        wb->event_timer = NULL;
+    }
+
+    if (wb->ipp_timer)
+    {
+        TimerFree (wb->ipp_timer);
+        wb->ipp_timer = NULL;
+    }
+
+    if (wb->need_rotate_hook)
+        _secWbRegisterRotateHook (wb, FALSE);
+}
+
+static CARD32
+_secWbRotateTimeout (OsTimerPtr timer, CARD32 now, pointer arg)
+{
+    SECWb *wb = (SECWb*) arg;
+    PropertyPtr rotate_prop;
+
+    if (!wb)
+        return 0;
+
+    if (wb->rotate_timer)
+    {
+        TimerFree (wb->rotate_timer);
+        wb->rotate_timer = NULL;
+    }
+
+    rotate_prop = secUtilGetWindowProperty (wb->pScrn->pScreen->root, "_E_ILLUME_ROTATE_ROOT_ANGLE");
+    if (rotate_prop)
+    {
+        int rotate = *(int*)rotate_prop->data;
+
+        XDBG_TRACE (MWB, "timeout : rotate(%d)\n", rotate);
+
+        if (wb->rotate != rotate)
+            if (!secWbSetRotate (wb, rotate))
+                return 0;
+    }
+
+    /* make sure streaming is on. */
+    secWbStart (wb);
+
+    return 0;
+}
+
+static void
+_secWbRotateHook (CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+    SECWb *wb = (SECWb*) unused;
+    ScrnInfoPtr pScrn;
+
+    XDBG_RETURN_IF_FAIL (wb != NULL);
+
+    XacePropertyAccessRec *rec = (XacePropertyAccessRec*)calldata;
+    PropertyPtr pProp = *rec->ppProp;
+    Atom name = pProp->propertyName;
+
+    pScrn = wb->pScrn;
+
+    if (rec->pWin != pScrn->pScreen->root)  //Check Rootwindow
+        return;
+
+    if (name == atom_wb_rotate && (rec->access_mode & DixWriteAccess))
+    {
+        int rotate = *(int*)pProp->data;
+        SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+
+        if (wb->rotate == rotate)
+            return;
+
+        XDBG_TRACE (MWB, "Change root angle(%d)\n", rotate);
+
+        if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+            secWbStop (wb, FALSE);
+        else
+            secWbStop (wb, TRUE);
+
+        wb->rotate_timer = TimerSet (wb->rotate_timer, 0, 800,
+                                     _secWbRotateTimeout,
+                                     wb);
+    }
+
+    return;
+}
+
+static Bool
+_secWbRegisterRotateHook (SECWb *wb, Bool hook)
+{
+    ScrnInfoPtr pScrn = wb->pScrn;
+
+    XDBG_TRACE (MWB, "hook(%d) \n", hook);
+
+    if (hook)
+    {
+        PropertyPtr rotate_prop;
+
+        rotate_prop = secUtilGetWindowProperty (pScrn->pScreen->root, "_E_ILLUME_ROTATE_ROOT_ANGLE");
+        if (rotate_prop)
+        {
+            int rotate = *(int*)rotate_prop->data;
+            secWbSetRotate (wb, rotate);
+        }
+
+        /* Hook for window rotate */
+        if (atom_wb_rotate == None)
+            atom_wb_rotate = MakeAtom ("_E_ILLUME_ROTATE_ROOT_ANGLE",
+                                       strlen ("_E_ILLUME_ROTATE_ROOT_ANGLE"), FALSE);
+
+        if (atom_wb_rotate != None)
+        {
+            if (!XaceRegisterCallback (XACE_PROPERTY_ACCESS, _secWbRotateHook, wb))
+                XDBG_ERROR (MWB, "fail to XaceRegisterCallback.\n");
+        }
+        else
+            XDBG_WARNING (MWB, "Cannot find _E_ILLUME_ROTATE_ROOT_ANGLE\n");
+    }
+    else
+        XaceDeleteCallback (XACE_PROPERTY_ACCESS, _secWbRotateHook, wb);
+
+    return TRUE;
+}
+
+Bool
+secWbIsOpened (void)
+{
+    return (keep_wb) ? TRUE : FALSE;
+}
+
+Bool
+secWbIsRunning (void)
+{
+    if (!keep_wb)
+        return FALSE;
+
+    return (keep_wb->status == STATUS_STARTED) ? TRUE : FALSE;
+}
+
+SECWb*
+_secWbOpen (ScrnInfoPtr pScrn, unsigned int id, int width, int height,
+            Bool scanout, int hz, Bool need_rotate_hook, const char *func)
+{
+    SECModePtr pSecMode = SECPTR (pScrn)->pSecMode;
+
+    XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL);
+
+    if (keep_wb)
+    {
+        XDBG_ERROR (MWB, "WB already opened. \n");
+        return NULL;
+    }
+
+    if (_secWbSupportFormat (id) == 0)
+    {
+        XDBG_ERROR (MWB, "'%c%c%c%c' not supported. \n", FOURCC_STR (id));
+        return NULL;
+    }
+
+    if (SECPTR (pScrn)->isLcdOff)
+    {
+        XDBG_ERROR (MWB, "Can't open wb during DPMS off. \n");
+        return NULL;
+    }
+
+    if (!keep_wb)
+        keep_wb = calloc (sizeof (SECWb), 1);
+
+    XDBG_RETURN_VAL_IF_FAIL (keep_wb != NULL, FALSE);
+
+    keep_wb->prop_id = -1;
+    keep_wb->pScrn = pScrn;
+    keep_wb->id = id;
+
+    keep_wb->wait_show = -1;
+    keep_wb->now_showing = -1;
+
+    keep_wb->width = width;
+    keep_wb->height = height;
+    keep_wb->status = STATUS_STOPPED;
+
+    keep_wb->scanout = scanout;
+    keep_wb->hz = (hz > 0) ? hz : 60;
+
+    if (pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI &&
+        keep_wb->hz > pSecMode->ext_connector_mode.vrefresh)
+        keep_wb->buf_num = WB_BUF_MAX;
+    else
+        keep_wb->buf_num = WB_BUF_DEFAULT;
+
+    if (id == FOURCC_RGB32)
+        keep_wb->lpos = LAYER_UPPER;
+    else
+        keep_wb->lpos = LAYER_LOWER1;
+
+    keep_wb->need_rotate_hook = need_rotate_hook;
+
+    XDBG_SECURE (MWB, "wb(%p) id(%c%c%c%c) size(%dx%d) scanout(%d) hz(%d) rhoot(%d) buf_num(%d): %s\n", keep_wb,
+                 FOURCC_STR(id), keep_wb->width, keep_wb->height, scanout, hz,
+                 need_rotate_hook, keep_wb->buf_num, func);
+
+    return keep_wb;
+}
+
+void
+_secWbClose (SECWb *wb, const char *func)
+{
+    SECWbNotifyFuncInfo *info, *tmp;
+
+    XDBG_RETURN_IF_FAIL (wb != NULL);
+    XDBG_RETURN_IF_FAIL (keep_wb == wb);
+
+    secWbStop (wb, TRUE);
+
+    XDBG_SECURE (MWB, "wb(%p): %s \n", wb, func);
+
+    _secWbCallNotifyFunc (wb, WB_NOTI_CLOSED, NULL);
+
+    nt_list_for_each_entry_safe (info, tmp, wb->info_list, next)
+    {
+        nt_list_del (info, wb->info_list, SECWbNotifyFuncInfo, next);
+        free (info);
+    }
+
+    free (wb);
+    keep_wb = NULL;
+}
+
+Bool
+_secWbStart (SECWb *wb, const char *func)
+{
+    SECPtr pSec;
+
+    XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE);
+
+    pSec = SECPTR (wb->pScrn);
+    if (pSec->isLcdOff)
+    {
+        XDBG_ERROR (MWB, "Can't start wb(%p) during DPMS off. \n", wb);
+        return FALSE;
+    }
+
+    if (wb->status == STATUS_STARTED)
+        return TRUE;
+
+    if (!_secWbOpenDrm (wb))
+    {
+        XDBG_ERROR (MWB, "open fail. \n");
+        return FALSE;
+    }
+
+    wb->status = STATUS_STARTED;
+
+    _secWbCallNotifyFunc (wb, WB_NOTI_START, NULL);
+
+    XDBG_TRACE (MWB, "start: %s \n", func);
+
+    return TRUE;
+}
+
+void
+_secWbStop (SECWb *wb, Bool close_buf,const char *func)
+{
+    XDBG_RETURN_IF_FAIL (wb != NULL);
+
+    if (wb->status == STATUS_STOPPED)
+    {
+        if (wb->rotate_timer)
+        {
+            TimerFree (wb->rotate_timer);
+            wb->rotate_timer = NULL;
+        }
+        return;
+    }
+
+    _secWbCloseDrm (wb);
+
+    if (close_buf)
+        _secWbCloseDrmDstBuffer (wb);
+    else
+        _secWbClearDrmDstBuffer (wb);
+
+    wb->status = STATUS_STOPPED;
+
+    _secWbCallNotifyFunc (wb, WB_NOTI_STOP, NULL);
+
+    XDBG_TRACE (MWB, "stop: %s \n", func);
+}
+
+Bool
+secWbSetBuffer (SECWb *wb, SECVideoBuf **vbufs, int bufnum)
+{
+    int i;
+
+    XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (wb->status != STATUS_STARTED, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (vbufs != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (wb->buf_num <= bufnum, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (bufnum <= WB_BUF_MAX, FALSE);
+
+    for (i = 0; i < WB_BUF_MAX; i++)
+    {
+        if (wb->dst_buf[i])
+        {
+            XDBG_ERROR (MWB, "already has %d buffers\n", wb->buf_num);
+            return FALSE;
+        }
+    }
+
+    for (i = 0; i < bufnum; i++)
+    {
+        XDBG_GOTO_IF_FAIL (wb->id == vbufs[i]->id, fail_set_buffer);
+        XDBG_GOTO_IF_FAIL (wb->width == vbufs[i]->width, fail_set_buffer);
+        XDBG_GOTO_IF_FAIL (wb->height == vbufs[i]->height, fail_set_buffer);
+        XDBG_GOTO_IF_FAIL (wb->scanout == vbufs[i]->scanout, fail_set_buffer);
+
+        wb->dst_buf[i] = secUtilVideoBufferRef (vbufs[i]);
+        XDBG_GOTO_IF_FAIL (wb->dst_buf[i] != NULL, fail_set_buffer);
+
+        if (!wb->dst_buf[i]->showing && wb->dst_buf[i]->need_reset)
+            secUtilClearVideoBuffer (wb->dst_buf[i]);
+        else
+            wb->dst_buf[i]->need_reset = TRUE;
+    }
+
+    wb->buf_num = bufnum;
+
+    return TRUE;
+
+fail_set_buffer:
+    for (i = 0; i < WB_BUF_MAX; i++)
+    {
+        if (wb->dst_buf[i])
+        {
+            secUtilVideoBufferUnref (wb->dst_buf[i]);
+            wb->dst_buf[i] = NULL;
+        }
+    }
+
+    return FALSE;
+}
+
+Bool
+secWbSetRotate (SECWb *wb, int rotate)
+{
+    XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL ((rotate % 90) == 0, FALSE);
+
+    if (wb->rotate == rotate)
+        return TRUE;
+
+    XDBG_DEBUG (MWB, "rotate(%d) \n", rotate);
+
+    wb->rotate = rotate;
+
+    if (wb->status == STATUS_STARTED)
+    {
+        SECModePtr pSecMode = (SECModePtr) SECPTR (wb->pScrn)->pSecMode;
+
+        if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+            secWbStop (wb, FALSE);
+        else
+            secWbStop (wb, TRUE);
+
+        if (!secWbStart (wb))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+int
+secWbGetRotate (SECWb *wb)
+{
+    XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE);
+
+    return wb->rotate;
+}
+
+void
+secWbSetTvout (SECWb *wb, Bool enable)
+{
+    XDBG_RETURN_IF_FAIL (wb != NULL);
+
+    enable = (enable > 0) ? TRUE : FALSE;
+
+    XDBG_TRACE (MWB, "tvout(%d) \n", enable);
+
+    wb->tvout = enable;
+
+    if (wb->status == STATUS_STARTED)
+    {
+        secWbStop (wb, FALSE);
+
+        if (!secWbStart (wb))
+            return;
+    }
+}
+
+Bool
+secWbGetTvout (SECWb *wb)
+{
+    XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE);
+
+    return wb->tvout;
+}
+
+void
+secWbSetSecure (SECWb *wb, Bool secure)
+{
+    XDBG_RETURN_IF_FAIL (wb != NULL);
+
+    secure = (secure > 0) ? TRUE : FALSE;
+
+    if (wb->secure == secure)
+        return;
+
+    XDBG_TRACE (MWB, "secure(%d) \n", secure);
+
+    wb->secure = secure;
+
+    if (wb->status == STATUS_STARTED)
+    {
+        secWbStop (wb, TRUE);
+
+        if (!secWbStart (wb))
+            return;
+    }
+}
+
+Bool
+secWbGetSecure (SECWb *wb)
+{
+    XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE);
+
+    return wb->secure;
+}
+
+void
+secWbGetSize (SECWb *wb, int *width, int *height)
+{
+    XDBG_RETURN_IF_FAIL (wb != NULL);
+
+    if (width)
+        *width = wb->width;
+
+    if (height)
+        *height = wb->height;
+}
+
+Bool
+secWbCanDequeueBuffer (SECWb *wb)
+{
+    int i, remain = 0;
+
+    XDBG_RETURN_VAL_IF_FAIL (wb != NULL, FALSE);
+
+    for (i = 0; i< wb->buf_num; i++)
+        if (wb->queued[i])
+            remain++;
+
+    XDBG_DEBUG (MWB, "buf_num(%d) remain(%d)\n", wb->buf_num, remain);
+
+    return (remain > WB_BUF_MIN) ? TRUE : FALSE;
+}
+
+void
+secWbQueueBuffer (SECWb *wb, SECVideoBuf *vbuf)
+{
+    int i;
+
+    XDBG_RETURN_IF_FAIL (wb != NULL);
+    XDBG_RETURN_IF_FAIL (vbuf != NULL);
+    XDBG_RETURN_IF_FAIL (vbuf->showing == FALSE);
+
+    if (wb->prop_id == -1)
+        return;
+
+    for (i = 0; i < wb->buf_num; i++)
+        if (wb->dst_buf[i] == vbuf)
+        {
+            XDBG_DEBUG (MWB, "%d queueing.\n", i);
+            _secWbQueue (wb, i);
+        }
+}
+
+void
+secWbAddNotifyFunc (SECWb *wb, SECWbNotify noti, WbNotifyFunc func, void *user_data)
+{
+    SECWbNotifyFuncInfo *info;
+
+    XDBG_RETURN_IF_FAIL (wb != NULL);
+
+    if (!func)
+        return;
+
+    nt_list_for_each_entry (info, wb->info_list, next)
+    {
+        if (info->func == func)
+            return;
+    }
+
+    XDBG_DEBUG (MWB, "noti(%d) func(%p) user_data(%p) \n", noti, func, user_data);
+
+    info = calloc (1, sizeof (SECWbNotifyFuncInfo));
+    XDBG_RETURN_IF_FAIL (info != NULL);
+
+    info->noti = noti;
+    info->func = func;
+    info->user_data = user_data;
+
+    if (wb->info_list)
+        nt_list_append (info, wb->info_list, SECWbNotifyFuncInfo, next);
+    else
+        wb->info_list = info;
+}
+
+void
+secWbRemoveNotifyFunc (SECWb *wb, WbNotifyFunc func)
+{
+    SECWbNotifyFuncInfo *info;
+
+    XDBG_RETURN_IF_FAIL (wb != NULL);
+
+    if (!func)
+        return;
+
+    nt_list_for_each_entry (info, wb->info_list, next)
+    {
+        if (info->func == func)
+        {
+            XDBG_DEBUG (MWB, "func(%p) \n", func);
+            nt_list_del(info, wb->info_list, SECWbNotifyFuncInfo, next);
+            free (info);
+            return;
+        }
+    }
+}
+
+SECWb*
+secWbGet (void)
+{
+    return keep_wb;
+}
+
+void
+secWbDestroy (void)
+{
+    if (!keep_wb)
+        return;
+
+    secWbClose (keep_wb);
+}
diff --git a/src/ipp/sec_wb.h b/src/ipp/sec_wb.h
new file mode 100644 (file)
index 0000000..38b9752
--- /dev/null
@@ -0,0 +1,95 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+#ifndef __SEC_WB_H__
+#define __SEC_WB_H__
+
+#include <sys/types.h>
+#include <xf86str.h>
+
+#include "sec_video_types.h"
+
+typedef struct _SECWb SECWb;
+
+typedef enum
+{
+    WB_NOTI_INIT,
+    WB_NOTI_START,
+    WB_NOTI_IPP_EVENT,
+    WB_NOTI_IPP_EVENT_DONE,
+    WB_NOTI_STOP,
+    WB_NOTI_CLOSED,
+} SECWbNotify;
+
+typedef void (*WbNotifyFunc) (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data);
+
+/* Don't close the wb from secWbGet */
+SECWb* secWbGet       (void);
+
+/* If width, height is 0, they will be main display size. */
+SECWb* _secWbOpen     (ScrnInfoPtr pScrn,
+                      unsigned int id, int width, int height,
+                      Bool scanout, int hz, Bool need_rotate_hook,
+                      const char *func);
+void   _secWbClose    (SECWb *wb, const char *func);
+Bool   _secWbStart    (SECWb *wb, const char *func);
+void   _secWbStop     (SECWb *wb, Bool close_buf, const char *func);
+
+#define secWbOpen(s,i,w,h,c,z,n)    _secWbOpen(s,i,w,h,c,z,n,__FUNCTION__)
+#define secWbClose(w)               _secWbClose(w,__FUNCTION__)
+#define secWbStart(w)               _secWbStart(w,__FUNCTION__)
+#define secWbStop(w,c)              _secWbStop(w,c,__FUNCTION__)
+
+Bool   secWbSetBuffer (SECWb *wb, SECVideoBuf **vbufs, int bufnum);
+
+Bool   secWbSetRotate (SECWb *wb, int rotate);
+int    secWbGetRotate (SECWb *wb);
+
+void   secWbSetTvout (SECWb *wb, Bool enable);
+Bool   secWbGetTvout (SECWb *wb);
+
+void   secWbSetSecure (SECWb *wb, Bool secure);
+Bool   secWbGetSecure (SECWb *wb);
+
+void   secWbGetSize  (SECWb *wb, int *width, int *height);
+
+Bool   secWbCanDequeueBuffer (SECWb *wb);
+void   secWbQueueBuffer (SECWb *wb, SECVideoBuf *vbuf);
+
+void   secWbAddNotifyFunc (SECWb *wb, SECWbNotify noti, WbNotifyFunc func, void *user_data);
+void   secWbRemoveNotifyFunc (SECWb *wb, WbNotifyFunc func);
+
+Bool   secWbIsOpened  (void);
+Bool   secWbIsRunning (void);
+void   secWbDestroy   (void);
+
+unsigned int secWbGetPropID (void);
+void   secWbHandleIppEvent (int fd, unsigned int *buf_idx, void *data);
+
+#endif // __SEC_WB_H__
diff --git a/src/memory/sec_memory_flush.c b/src/memory/sec_memory_flush.c
new file mode 100644 (file)
index 0000000..ad7d631
--- /dev/null
@@ -0,0 +1,141 @@
+/**************************************************************************\r
+\r
+xserver-xorg-video-exynos\r
+\r
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.\r
+\r
+Contact: SooChan Lim <sc1.lim@samsung.com>\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a\r
+copy of this software and associated documentation files (the\r
+"Software"), to deal in the Software without restriction, including\r
+without limitation the rights to use, copy, modify, merge, publish,\r
+distribute, sub license, and/or sell copies of the Software, and to\r
+permit persons to whom the Software is furnished to do so, subject to\r
+the following conditions:\r
+\r
+The above copyright notice and this permission notice (including the\r
+next paragraph) shall be included in all copies or substantial portions\r
+of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.\r
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR\r
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\r
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\r
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+**************************************************************************/\r
+\r
+#include "sec.h"\r
+#include <malloc.h>\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <strings.h>\r
+#include <malloc.h>\r
+\r
+#include "sec.h"\r
+#include "xace.h"\r
+#include "xacestr.h"\r
+\r
+#include <X11/extensions/dpmsconst.h>\r
+#include "sec_util.h"\r
+#include "sec_dpms.h"\r
+#include "sec_memory_flush.h"\r
+\r
+extern CallbackListPtr DPMSCallback;\r
+\r
+static void\r
+_secMemoryDPMS (CallbackListPtr *list, pointer closure, pointer calldata)\r
+{\r
+    SecDPMSPtr pDPMSInfo = (SecDPMSPtr) calldata;\r
+    ScrnInfoPtr pScrn;\r
+    //int mode = pDPMSInfo->mode;\r
+    //int flags = pDPMSInfo->flags;\r
+\r
+    if (!pDPMSInfo || !(pScrn = pDPMSInfo->pScrn))\r
+    {\r
+        XDBG_ERROR (MMEM, "[X11][%s] DPMS info or screen info is invalid !\n", __FUNCTION__);\r
+        return;\r
+    }\r
+\r
+    SECPtr pSec = SECPTR (pScrn);\r
+\r
+    switch (DPMSPowerLevel)\r
+    {\r
+    case DPMSModeOn:\r
+    case DPMSModeSuspend:\r
+        break;\r
+\r
+    case DPMSModeStandby://LCD on\r
+        if (pSec->isLcdOff == FALSE) break;\r
+        break;\r
+\r
+    case DPMSModeOff://LCD off\r
+        if (pSec->isLcdOff == TRUE) break;\r
+\r
+        //stack and heap memory trim\r
+        secMemoryStackTrim();\r
+        malloc_trim (0);\r
+\r
+        XDBG_DEBUG (MMEM, "[X11][%s] Memory flush done !\n", __FUNCTION__);\r
+        break;\r
+\r
+    default:\r
+        return;\r
+    }\r
+}\r
+\r
+static void\r
+_secMemoryClientStateEvent (CallbackListPtr *list, pointer closure, pointer calldata)\r
+{\r
+    static int chance = 0;\r
+    NewClientInfoRec *clientinfo = (NewClientInfoRec*)calldata;\r
+    ClientPtr pClient = clientinfo->client;\r
+\r
+    if (ClientStateGone == pClient->clientState)\r
+    {\r
+        int flush;\r
+\r
+        //memory flush will be done for every third client gone\r
+        chance++;\r
+        flush = !(chance = chance % 3);\r
+\r
+        if ( flush )\r
+        {\r
+            //stack and heap memory trim\r
+            secMemoryStackTrim();\r
+            malloc_trim (0);\r
+\r
+            XDBG_DEBUG (MMEM, "[X11][%s] Memory flush done !\n", __FUNCTION__);\r
+        }\r
+    }\r
+}\r
+\r
+Bool\r
+secMemoryInstallHooks (void)\r
+{\r
+    int ret = TRUE;\r
+    ret &= AddCallback (&ClientStateCallback, _secMemoryClientStateEvent, NULL);\r
+    ret &= AddCallback (&DPMSCallback, _secMemoryDPMS, NULL);\r
+\r
+    if (!ret)\r
+    {\r
+        XDBG_ERROR (MMEM, "secMemoryInstallHooks: Failed to register one or more callbacks\n");\r
+        return BadAlloc;\r
+    }\r
+\r
+    return Success;\r
+}\r
+\r
+\r
+Bool\r
+secMemoryUninstallHooks (void)\r
+{\r
+    DeleteCallback (&ClientStateCallback, _secMemoryClientStateEvent, NULL);\r
+    DeleteCallback (&DPMSCallback, _secMemoryDPMS, NULL);\r
+\r
+    return Success;\r
+}\r
diff --git a/src/memory/sec_memory_flush.h b/src/memory/sec_memory_flush.h
new file mode 100644 (file)
index 0000000..d9c1062
--- /dev/null
@@ -0,0 +1,85 @@
+/**************************************************************************\r
+\r
+xserver-xorg-video-exynos\r
+\r
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.\r
+\r
+Contact: SooChan Lim <sc1.lim@samsung.com>\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a\r
+copy of this software and associated documentation files (the\r
+"Software"), to deal in the Software without restriction, including\r
+without limitation the rights to use, copy, modify, merge, publish,\r
+distribute, sub license, and/or sell copies of the Software, and to\r
+permit persons to whom the Software is furnished to do so, subject to\r
+the following conditions:\r
+\r
+The above copyright notice and this permission notice (including the\r
+next paragraph) shall be included in all copies or substantial portions\r
+of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.\r
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR\r
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\r
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\r
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+**************************************************************************/\r
+\r
+#ifndef SEC_MEMORY_H\r
+#define SEC_MEMORY_H\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <sys/mman.h>\r
+#include <unistd.h>\r
+#include <X11/Xdefs.h> /* for Bool */\r
+\r
+#define GETSP() ({ unsigned int sp; asm volatile ("mov %0,sp " : "=r"(sp)); sp;})\r
+#define BUF_SIZE                               256\r
+#define _PAGE_SIZE                     (1 << 12)\r
+#define _ALIGN_UP(addr,size)    (((addr)+((size)-1))&(~((size)-1)))\r
+#define _ALIGN_DOWN(addr,size)  ((addr)&(~((size)-1)))\r
+#define PAGE_ALIGN(addr)        _ALIGN_DOWN(addr, _PAGE_SIZE)\r
+\r
+static inline void secMemoryStackTrim (void)\r
+{\r
+    unsigned int sp;\r
+    char buf[BUF_SIZE];\r
+    FILE* file;\r
+    unsigned int stacktop;\r
+    int found = 0;\r
+\r
+    sp = GETSP();\r
+\r
+    snprintf (buf, BUF_SIZE, "/proc/%d/maps", getpid());\r
+    file = fopen (buf,"r");\r
+\r
+    if (!file)\r
+        return;\r
+\r
+    while (fgets (buf, BUF_SIZE, file) != NULL)\r
+    {\r
+        if (strstr (buf, "[stack]"))\r
+        {\r
+            found = 1;\r
+            break;\r
+        }\r
+    }\r
+\r
+    fclose (file);\r
+\r
+    if (found)\r
+    {\r
+        sscanf (buf,"%x-",&stacktop);\r
+        if (madvise ((void*)PAGE_ALIGN (stacktop), PAGE_ALIGN (sp)-stacktop, MADV_DONTNEED) < 0)\r
+            perror ("stack madvise fail");\r
+    }\r
+}\r
+\r
+Bool secMemoryInstallHooks (void);\r
+Bool secMemoryUninstallHooks (void);\r
+\r
+#endif/* SEC_MEMORY_H */\r
diff --git a/src/neon/copy_area.c b/src/neon/copy_area.c
new file mode 100644 (file)
index 0000000..9bd2c71
--- /dev/null
@@ -0,0 +1,535 @@
+/**************************************************************************\r
+\r
+xserver-xorg-video-exynos\r
+\r
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.\r
+\r
+Contact: SooChan Lim <sc1.lim@samsung.com>\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a\r
+copy of this software and associated documentation files (the\r
+"Software"), to deal in the Software without restriction, including\r
+without limitation the rights to use, copy, modify, merge, publish,\r
+distribute, sub license, and/or sell copies of the Software, and to\r
+permit persons to whom the Software is furnished to do so, subject to\r
+the following conditions:\r
+\r
+The above copyright notice and this permission notice (including the\r
+next paragraph) shall be included in all copies or substantial portions\r
+of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.\r
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR\r
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\r
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\r
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+**************************************************************************/\r
+\r
+#include "neonmem.h"\r
+\r
+//#define _USE_LIBC\r
+//#define _X86_SSE2 // may not work on linux platform\r
+#define _ARM_NEON\r
+\r
+#ifdef _USE_LIBC\r
+#include <string.h>\r
+#endif\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+// General C implementation of copy functions\r
+//////////////////////////////////////////////////////////////////////////\r
+static inline void memcpy32 (unsigned long *dst, unsigned long *src, int size)\r
+{\r
+    while ( size > 0 )\r
+    {\r
+        *dst++ = *src++;\r
+        size--;\r
+    }\r
+}\r
+\r
+static inline void memcpy_forward_32 (unsigned long *dst, unsigned long *src, int size)\r
+{\r
+    while ( size > 0 )\r
+    {\r
+        *dst++ = *src++;\r
+        size--;\r
+    }\r
+}\r
+\r
+static inline void memcpy_backward_32 (unsigned long *dst, unsigned long *src, int size)\r
+{\r
+    dst = dst + size;\r
+    src = src + size;\r
+\r
+    while ( size > 0 )\r
+    {\r
+        *(--dst) = *(--src);\r
+        size--;\r
+    }\r
+}\r
+\r
+static inline void memcpy_forward_16 (unsigned short *dst, unsigned short *src, int size)\r
+{\r
+    while ( size > 0 )\r
+    {\r
+        *dst++ = *src++;\r
+        size--;\r
+    }\r
+}\r
+\r
+static inline void memcpy_backward_16 (unsigned short *dst, unsigned short *src, int size)\r
+{\r
+    dst = dst + size;\r
+    src = src + size;\r
+\r
+    while ( size > 0 )\r
+    {\r
+        *(--dst) = *(--src);\r
+        size--;\r
+    }\r
+}\r
+\r
+static inline void memcpy_forward (unsigned char *dst, unsigned char *src, int size)\r
+{\r
+    while ( size > 0 && ((unsigned long) dst & 3))\r
+    {\r
+        *(unsigned short*)dst = *(unsigned short*)src;\r
+        dst += 2;\r
+        src += 2;\r
+        size -= 2;\r
+    }\r
+\r
+    while ( size >= 4 )\r
+    {\r
+        *(unsigned long*)dst = *(unsigned long*)src;\r
+        dst += 4;\r
+        src += 4;\r
+        size -= 4;\r
+    }\r
+\r
+    while ( size > 0 )\r
+    {\r
+        *dst++ = *src++;\r
+        size--;\r
+    }\r
+}\r
+\r
+static inline void memcpy_backward (unsigned char *dst, unsigned char *src, int size)\r
+{\r
+    dst = dst + size;\r
+    src = src + size;\r
+\r
+    while ( size > 0 && ((unsigned long) dst & 3))\r
+    {\r
+        *(--dst) = *(--src);\r
+        size--;\r
+    }\r
+\r
+    while ( size >= 4 )\r
+    {\r
+        dst -= 4;\r
+        src -= 4;\r
+        size -= 4;\r
+        *(unsigned long*)dst = *(unsigned long*)src;\r
+    }\r
+\r
+    while ( size > 0 )\r
+    {\r
+        *(--dst) = *(--src);\r
+        size--;\r
+    }\r
+}\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+// ARM assembly implementation of copy functions\r
+//////////////////////////////////////////////////////////////////////////\r
+#ifdef _ARM_ASM\r
+static inline void memcpy_forward (unsigned char *dst, unsigned char *src, int size)\r
+{\r
+\r
+}\r
+\r
+static inline void memcpy_backward (unsigned char *dst, unsigned char *src, int size)\r
+{\r
+\r
+}\r
+#endif\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+// ARM NEON implementation of copy functions\r
+//////////////////////////////////////////////////////////////////////////\r
+#ifdef _ARM_NEON\r
+extern void memcpy_forward_32_neon (unsigned long *dst, unsigned long *src, int size);\r
+extern void memcpy_backward_32_neon (unsigned long *dst, unsigned long *src, int size);\r
+extern void memcpy_forward_16_neon (unsigned short *dst, unsigned short *src, int size);\r
+extern void memcpy_backward_16_neon (unsigned short *dst, unsigned short *src, int size);\r
+#endif\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+// X86 SSE2 copy functions\r
+//////////////////////////////////////////////////////////////////////////\r
+#ifdef _X86_SSE2\r
+#include <emmintrin.h>\r
+\r
+static inline void memcpy_forward_sse2 (unsigned char *dst, unsigned char *src, int size)\r
+{\r
+    while ( size > 0 && ((unsigned long) dst & 1))\r
+    {\r
+        *dst++ = *src++;\r
+        size--;\r
+    }\r
+\r
+    while ( size > 0 && ((unsigned long) dst & 3))\r
+    {\r
+        *(unsigned short*)dst = *(unsigned short*)src;\r
+        dst += 2;\r
+        src += 2;\r
+        size -= 2;\r
+    }\r
+\r
+    while ( size > 0 && ((unsigned long) dst & 63))\r
+    {\r
+        *(unsigned long*)dst = *(unsigned long*)src;\r
+        dst += 4;\r
+        src += 4;\r
+        size -= 4;\r
+    }\r
+\r
+    if ((reinterpret_cast<unsigned long> (src) & 15) == 0 )\r
+    {\r
+        while ( size >= 64 )\r
+        {\r
+            __m128 xmm0, xmm1, xmm2, xmm3;\r
+\r
+            //_mm_prefetch((const char*)(src+320), _MM_HINT_NTA);\r
+\r
+            xmm0 = _mm_load_ps ((float*)(src));\r
+            xmm1 = _mm_load_ps ((float*)(src + 16));\r
+            xmm2 = _mm_load_ps ((float*)(src + 32));\r
+            xmm3 = _mm_load_ps ((float*)(src + 48));\r
+\r
+            _mm_stream_ps ((float*)(dst), xmm0);\r
+            _mm_stream_ps ((float*)(dst + 16), xmm1);\r
+            _mm_stream_ps ((float*)(dst + 32), xmm2);\r
+            _mm_stream_ps ((float*)(dst + 48), xmm3);\r
+\r
+            src += 64;\r
+            dst += 64;\r
+            size -= 64;\r
+        }\r
+\r
+        while ( size >= 16 )\r
+        {\r
+            _mm_stream_ps ((float*)dst, _mm_load_ps ((float*)src));\r
+            dst += 16;\r
+            src += 16;\r
+            size -= 16;\r
+        }\r
+    }\r
+    else\r
+    {\r
+        while ( size >= 64 )\r
+        {\r
+            __m128 xmm0, xmm1, xmm2, xmm3;\r
+\r
+            //_mm_prefetch((const char*)(src+320), _MM_HINT_NTA);\r
+\r
+            xmm0 = _mm_loadu_ps ((float*)(src));\r
+            xmm1 = _mm_loadu_ps ((float*)(src + 16));\r
+            xmm2 = _mm_loadu_ps ((float*)(src + 32));\r
+            xmm3 = _mm_loadu_ps ((float*)(src + 48));\r
+\r
+            _mm_stream_ps ((float*)(dst), xmm0);\r
+            _mm_stream_ps ((float*)(dst + 16), xmm1);\r
+            _mm_stream_ps ((float*)(dst + 32), xmm2);\r
+            _mm_stream_ps ((float*)(dst + 48), xmm3);\r
+\r
+            src += 64;\r
+            dst += 64;\r
+            size -= 64;\r
+        }\r
+\r
+        while ( size >= 16 )\r
+        {\r
+            _mm_stream_ps ((float*)dst, _mm_loadu_ps ((float*)src));\r
+            dst += 16;\r
+            src += 16;\r
+            size -= 16;\r
+        }\r
+    }\r
+\r
+    while ( size >= 4 )\r
+    {\r
+        *(unsigned long*)dst = *(unsigned long*)src;\r
+        dst += 4;\r
+        src += 4;\r
+        size -= 4;\r
+    }\r
+\r
+    while ( size > 0 )\r
+    {\r
+        *dst++ = *src++;\r
+        size--;\r
+    }\r
+}\r
+\r
+static inline void memcpy_backward_sse2 (unsigned char *dst, unsigned char *src, int size)\r
+{\r
+    dst = dst + size;\r
+    src = src + size;\r
+\r
+    while ( size > 0 && ((unsigned long) dst & 1))\r
+    {\r
+        dst--;\r
+        src--;\r
+        size--;\r
+        *dst = *src;\r
+    }\r
+\r
+    while ( size > 0 && ((unsigned long) dst & 3))\r
+    {\r
+        dst -= 2;\r
+        src -= 2;\r
+        size -= 2;\r
+        *(unsigned short*)dst = *(unsigned short*)src;\r
+    }\r
+\r
+    while ( size > 0 && ((unsigned long) dst & 63))\r
+    {\r
+        dst -= 4;\r
+        src -= 4;\r
+        size -= 4;\r
+        *(unsigned long*)dst = *(unsigned long*)src;\r
+    }\r
+\r
+    if ((reinterpret_cast<unsigned long> (src) & 15) == 0 )\r
+    {\r
+        while ( size >= 64 )\r
+        {\r
+            __m128 xmm0, xmm1, xmm2, xmm3;\r
+\r
+            src -= 64;\r
+            dst -= 64;\r
+            size -= 64;\r
+\r
+            //_mm_prefetch((const char*)(src+16), _MM_HINT_NTA);\r
+\r
+            xmm0 = _mm_load_ps ((float*)(src));\r
+            xmm1 = _mm_load_ps ((float*)(src + 16));\r
+            xmm2 = _mm_load_ps ((float*)(src + 32));\r
+            xmm3 = _mm_load_ps ((float*)(src + 48));\r
+\r
+            _mm_stream_ps ((float*)(dst), xmm0);\r
+            _mm_stream_ps ((float*)(dst + 16), xmm1);\r
+            _mm_stream_ps ((float*)(dst + 32), xmm2);\r
+            _mm_stream_ps ((float*)(dst + 48), xmm3);\r
+        }\r
+\r
+        while ( size >= 16 )\r
+        {\r
+            dst -= 16;\r
+            src -= 16;\r
+            size -= 16;\r
+            _mm_stream_ps ((float*)dst, _mm_load_ps ((float*)src));\r
+        }\r
+    }\r
+    else\r
+    {\r
+        while ( size >= 64 )\r
+        {\r
+            __m128 xmm0, xmm1, xmm2, xmm3;\r
+\r
+            src -= 64;\r
+            dst -= 64;\r
+            size -= 64;\r
+\r
+            //_mm_prefetch((const char*)(src+16), _MM_HINT_NTA);\r
+\r
+            xmm0 = _mm_loadu_ps ((float*)(src));\r
+            xmm1 = _mm_loadu_ps ((float*)(src + 16));\r
+            xmm2 = _mm_loadu_ps ((float*)(src + 32));\r
+            xmm3 = _mm_loadu_ps ((float*)(src + 48));\r
+\r
+            _mm_stream_ps ((float*)(dst), xmm0);\r
+            _mm_stream_ps ((float*)(dst + 16), xmm1);\r
+            _mm_stream_ps ((float*)(dst + 32), xmm2);\r
+            _mm_stream_ps ((float*)(dst + 48), xmm3);\r
+        }\r
+\r
+        while ( size >= 16 )\r
+        {\r
+            dst -= 16;\r
+            src -= 16;\r
+            size -= 16;\r
+            _mm_stream_ps ((float*)dst, _mm_loadu_ps ((float*)src));\r
+        }\r
+    }\r
+\r
+    while ( size >= 4 )\r
+    {\r
+        dst -= 4;\r
+        src -= 4;\r
+        size -= 4;\r
+        *(unsigned long*)dst = *(unsigned long*)src;\r
+    }\r
+\r
+    while ( size > 0 )\r
+    {\r
+        dst--;\r
+        src--;\r
+        size--;\r
+        *dst = *src;\r
+    }\r
+}\r
+#endif\r
+\r
+static inline void move_memory_32 (unsigned long *dst, unsigned long *src, int size)\r
+{\r
+#ifdef _USE_LIBC\r
+    memmove (dst, src, size*4);\r
+#elif defined(_ARM_NEON)\r
+    if ( dst > src && dst < src + size )\r
+        memcpy_backward_32_neon (dst, src, size);\r
+    else\r
+        memcpy_forward_32_neon (dst, src, size);\r
+#else\r
+    if ( dst > src && dst < src + size )\r
+        memcpy_backward_32 (dst, src, size);\r
+    else\r
+        memcpy_forward_32 (dst, src, size);\r
+#endif\r
+}\r
+\r
+static inline void move_memory_16 (unsigned short *dst, unsigned short *src, int size)\r
+{\r
+#ifdef _USE_LIBC\r
+    memmove (dst, src, size*2);\r
+#elif defined(_ARM_NEON)\r
+    if ( dst > src && dst < src + size )\r
+        memcpy_backward_16_neon (dst, src, size);\r
+    else\r
+        memcpy_forward_16_neon (dst, src, size);\r
+#else\r
+    if ( dst > src && dst < src + size )\r
+        memcpy_backward_16 (dst, src, size);\r
+    else\r
+        memcpy_forward_16 (dst, src, size);\r
+#endif\r
+}\r
+\r
+/**\r
+ *     @brief Pixel block move function within one image buffer\r
+ *\r
+ *     @param bits                     buffer address of top-left corner\r
+ *     @param bpp                      bits per pixel, must be one of 16 and 32\r
+ *     @param stride           number of bytes to go next row (can be negative)\r
+ *     @param img_width        entire image width\r
+ *     @param img_height       entire image height\r
+ *     @param sx                       top-left x position of source area\r
+ *     @param sy                       top-left y position of source area\r
+ *     @param dx                       top-left x position of destination area\r
+ *     @param dy                       top-left y position of destination area\r
+ *     @param w                        width of area to copy\r
+ *     @param h                        height of area to copy\r
+ *\r
+ *     @remark This function supports overlapping in source and destination area.\r
+ *                     Any source or destination area which is outside given image will be cropped.\r
+ *                     Support negative stride.\r
+ *                     bits must be word aligned if bpp == 32 and half-word aligned if bpp == 16.\r
+ */\r
+int move_pixels (void *bits, int bpp, int stride, int img_width, int img_height,\r
+                 int sx, int sy, int dx, int dy, int w, int h)\r
+{\r
+    int bytes_per_pixel;\r
+    unsigned char *src_row;\r
+    unsigned char *dst_row;\r
+\r
+\r
+    //////////////////////////////////////////////////////////////////////////\r
+    // check validity of arguments\r
+    //////////////////////////////////////////////////////////////////////////\r
+    if ( !bits || img_width < 0 || img_height < 0 || w < 0 || h < 0 )\r
+        return 0;\r
+\r
+    if ( bpp == 32 )\r
+        bytes_per_pixel = 4;\r
+    else if ( bpp == 16 )\r
+        bytes_per_pixel = 2;\r
+    else // unsupported bpp\r
+        return 0;\r
+\r
+    if ( bytes_per_pixel*img_width < stride ) // invalid image\r
+        return 0;\r
+\r
+    // Wow thanks, we have nothing to do\r
+    if ( sx == dx && sy == dy )\r
+        return 1;\r
+\r
+\r
+    //////////////////////////////////////////////////////////////////////////\r
+    // Bounds check and cropping\r
+    //////////////////////////////////////////////////////////////////////////\r
+    while ( sx < 0 || dx < 0 )\r
+    {\r
+        sx++;\r
+        dx++;\r
+        w--;\r
+    }\r
+\r
+    while ( sy < 0 || dy < 0 )\r
+    {\r
+        sy++;\r
+        dy++;\r
+        h--;\r
+    }\r
+\r
+    while ( sx + w > img_width || dx + w > img_width )\r
+        w--;\r
+\r
+    while ( sy + h > img_height || dy + h > img_height )\r
+        h--;\r
+\r
+\r
+    //////////////////////////////////////////////////////////////////////////\r
+    // Check overlap and do copy\r
+    //////////////////////////////////////////////////////////////////////////\r
+\r
+    // No remaining area to copy\r
+    if ( w <= 0 || h <= 0 )\r
+        return 1;\r
+\r
+    src_row = (unsigned char*)bits + sy*stride + sx*bytes_per_pixel;\r
+    dst_row = (unsigned char*)bits + dy*stride + dx*bytes_per_pixel;\r
+\r
+    // Check if we need to reverse y order\r
+    if ( dy > sy && dy < sy + h )\r
+    {\r
+        src_row += (h - 1) *stride;\r
+        dst_row += (h - 1) *stride;\r
+        stride = -stride;\r
+    }\r
+\r
+    if ( bpp == 32 )\r
+    {\r
+        while ( h-- )\r
+        {\r
+            move_memory_32 ((unsigned long*)dst_row, (unsigned long*)src_row, w);\r
+            dst_row += stride;\r
+            src_row += stride;\r
+        }\r
+    }\r
+    else if ( bpp == 16 )\r
+    {\r
+        while ( h-- )\r
+        {\r
+            move_memory_16 ((unsigned short*)dst_row, (unsigned short*)src_row, w);\r
+            dst_row += stride;\r
+            src_row += stride;\r
+        }\r
+    }\r
+\r
+    return 1;\r
+}\r
diff --git a/src/neon/memcpy_neon.s b/src/neon/memcpy_neon.s
new file mode 100644 (file)
index 0000000..eb3e3b1
--- /dev/null
@@ -0,0 +1,1889 @@
+/*
+ *     Memory copy functions implemented using NEON
+ *
+ *     NOTICE:
+ *             pld instruction caused no changes in performance.
+ *             Does our processor actually deal with this??
+ *             Performance was dropped when src and dst pointers are close
+ *             to each other. (I don't know why, this was same for pixman_blt)
+ *
+ *     TODO:
+ *             Benchmark small block copy and make it better.
+ *             SW pipelining, proper prefetching.
+ */
+.fpu   neon
+.text
+
+.func memcpy_forward_32_neon
+.global        memcpy_forward_32_neon
+
+memcpy_forward_32_neon:
+       push    {r4}
+
+       mov             r3, r0
+
+       cmp             r2, #16
+       blt             2f
+
+0:
+       tst             r3, #15
+       ldrne   r4, [r1], #4
+       subne   r2, r2, #1
+       strne   r4, [r3], #4
+       bne             0b
+
+1:
+       vld1.8  {d0, d1, d2, d3}, [r1]!
+       sub             r2, r2, #8
+       cmp             r2, #8
+       vst1.32 {d0, d1, d2, d3}, [r3, :128]!
+       bge             1b
+
+2:
+       cmp             r2, #0
+       ble             3f
+       ldr             r4, [r1], #4
+       sub             r2, r2, #1
+       str             r4, [r3], #4
+       b               2b
+
+3:
+       pop             {r4}
+       bx              lr
+.endfunc
+
+
+.func memcpy_backward_32_neon
+.global        memcpy_backward_32_neon
+
+memcpy_backward_32_neon:
+       push    {r4}
+
+       mov             r3, r0
+
+       add             r3, r3, r2, asl #2
+       add             r1,     r1, r2, asl #2
+
+       cmp             r2, #16
+       blt             2f
+
+0:
+       tst             r3, #15
+       ldrne   r4, [r1, #-4]!
+       subne   r2, r2, #1
+       strne   r4, [r3, #-4]!
+       bne             0b
+
+1:
+       cmp             r2, #8
+       blt             2f
+       sub             r1, r1, #32
+       vld1.8  {d0, d1, d2, d3}, [r1]
+       sub             r3, r3, #32
+       sub             r2, r2, #8
+       vst1.32 {d0, d1, d2, d3}, [r3, :128]
+       b               1b
+
+2:
+       cmp             r2, #0
+       ble             3f
+       ldr             r4, [r1, #-4]!
+       sub             r2, r2, #1
+       str             r4, [r3, #-4]!
+       b               2b
+
+3:
+       pop             {r4}
+       bx              lr
+.endfunc
+
+.func memcpy_forward_16_neon
+.global        memcpy_forward_16_neon
+
+memcpy_forward_16_neon:
+       push    {r4}
+
+       mov             r3, r0
+
+       cmp             r2, #16
+       blt             2f
+
+0:
+       tst             r3, #15
+       ldrneh  r4, [r1], #2
+       subne   r2, r2, #1
+       strneh  r4, [r3], #2
+       bne             0b
+
+1:
+       cmp             r2, #8
+       blt             2f
+       vld1.8  {d0, d1}, [r1]!
+       sub             r2, r2, #8
+       vst1.32 {d0, d1}, [r3, :128]!
+       b               1b
+
+2:
+       cmp             r2, #0
+       ble             3f
+       ldrh    r4, [r1], #2
+       sub             r2, r2, #1
+       strh    r4, [r3], #2
+       b               2b
+
+3:
+       pop             {r4}
+       bx              lr
+.endfunc
+
+
+.func memcpy_backward_16_neon
+.global        memcpy_backward_16_neon
+
+memcpy_backward_16_neon:
+       push    {r4}
+
+       mov             r3, r0
+
+       add             r3, r3, r2, asl #1
+       add             r1,     r1, r2, asl #1
+
+       cmp             r2, #16
+       blt             2f
+
+0:
+       tst             r3, #15
+       ldrneh  r4, [r1, #-2]!
+       subne   r2, r2, #1
+       strneh  r4, [r3, #-2]!
+       bne             0b
+
+1:
+       cmp             r2, #8
+       blt             2f
+       sub             r1, r1, #16
+       vld1.8  {d0, d1}, [r1]
+       sub             r3, r3, #16
+       sub             r2, r2, #8
+       vst1.32 {d0, d1}, [r3, :128]
+       b               1b
+
+2:
+       cmp             r2, #0
+       ble             3f
+       ldrh    r4, [r1, #-2]!
+       sub             r2, r2, #1
+       strh    r4, [r3, #-2]!
+       b               2b
+
+3:
+       pop             {r4}
+       bx              lr
+.endfunc
+
+/*
+ *     Memory copy functions implemented using NEON
+ */
+               .text
+               .fpu    neon
+               .align  4
+
+memcpy_neon:
+        MOV      ip,r0
+
+        CMP      r2,#0x41
+        BCC      COPY_UNDER_64B
+
+               CMP              r2,#256
+               BHI              DST_ALIGN
+
+               SUB             r2,r2,#0x40
+COPY_BY_64B_s:
+        VLD1.8   {d0,d1,d2,d3},[r1]!
+               PLD             [r1,#0x60]
+        SUBS     r2,r2,#0x40
+        VST1.8   {d0,d1,d2,d3},[ip]!
+        VLD1.8   {d4,d5,d6,d7},[r1]!
+        VST1.8   {d4,d5,d6,d7},[ip]!
+        BGE      COPY_BY_64B_s
+               ANDS    r2,r2,#0x3f
+               BXEQ    lr
+               B               COPY_UNDER_64B          
+
+@              SUBS    r2,r2,#0x20
+@COPY_BY_32B_s
+@        VLD1.8   {d0,d1,d2,d3},[r1]!
+@              PLD             [r1,#0x40]
+@        SUBS     r2,r2,#0x20
+@        VST1.8   {d0,d1,d2,d3},[ip]!
+@        BGE      COPY_BY_32B_s
+@              ANDS    r2,r2,#0x1f
+@              B               COPY_UNDER_64B          
+
+
+DST_ALIGN:
+               @ dst memory align to 16-byte
+               TST      r0,#0xf
+               BEQ      BLOCK_COPY
+ALIGN_TO_1B:
+               TST      r0,#1
+               LDRNEB   r3,[r1],#1
+               STRNEB   r3,[ip],#1
+@              BEQ              ALIGN_TO_2B
+@              VLD1.8   {d7[0]},[r1]!
+@              VST1.8   {d7[0]},[ip]!
+               SUBNE    r2,r2,#1
+ALIGN_TO_2B:   
+               TST      ip,#2
+               LDRNEH   r3,[r1],#2
+               STRNEH   r3,[ip],#2
+@              BEQ              ALIGN_TO_4B
+@              VLD2.8   {d5[0],d6[0]},[r1]!
+@              VST2.8   {d5[0],d6[0]},[ip@16]!
+               SUBNE    r2,r2,#2
+ALIGN_TO_4B:
+               TST      ip,#4
+               LDRNE    r3,[r1],#4
+               STRNE    r3,[ip],#4
+@              BEQ      ALIGN_TO_16B@{pc} + 0x10  @ 0x48
+@              VLD4.8   {d0[0],d1[0],d2[0],d3[0]},[r1]!
+@              VST4.8   {d0[0],d1[0],d2[0],d3[0]},[ip,:32]!
+               SUBNE    r2,r2,#4
+ALIGN_TO_16B:
+               TST      ip,#8
+               LDRNE    r3,[r1],#4
+               STRNE    r3,[ip],#4
+               LDRNE    r3,[r1],#4
+               STRNE    r3,[ip],#4
+@              BEQ      BLOCK_COPY_CMP
+@              VLD1.8   {d0},[r1]!
+@              VST1.8   {d0},[ip@64]!
+               SUBNE    r2,r2,#8
+
+               @ from here
+BLOCK_COPY_CMP:
+               @ 16-byte align ????64 Ã«Â°\94ì\9d´???´í\95\98??ê²½ì\9a°?
+               CMP              r2,#0x41
+        BCC      COPY_UNDER_64B
+
+BLOCK_COPY:
+               SUBS    r2,r2,#0x40
+               MOV             r3,#0x40
+COPY_BY_64B:
+        VLD1.8   {d0,d1,d2,d3},[r1]!
+               CMP             r3,#0x320
+               PLD             [r1,r3]
+               ADDLE   r3,r3,#0x40
+        SUBS     r2,r2,#0x40
+        VST1.8   {d0,d1,d2,d3},[ip,:128]!
+        VLD1.8   {d4,d5,d6,d7},[r1]!
+        VST1.8   {d4,d5,d6,d7},[ip,:128]!
+        BGE      COPY_BY_64B
+               TST             r2,#0x3f
+               BXEQ    lr
+               TST             r2,#0x20
+               BEQ             COPY_UNDER_16B
+        VLD1.8   {d0,d1,d2,d3},[r1]!
+        VST1.8   {d0,d1,d2,d3},[ip,:128]!
+
+@              SUBS    r2,r2,#0x20
+@              MOV             r3,#0x20
+@COPY_BY_32B
+@        VLD1.8   {d0,d1,d2,d3},[r1]!
+@              CMP             r3,#0x140
+@              PLD             [r1,r3]
+@              ADDLE   r3,r3,#0x20
+@        SUBS     r2,r2,#0x20
+@        VST1.8   {d0,d1,d2,d3},[ip,:128]!
+@        BGE      COPY_BY_32B
+@              CMP             r2,#0x00
+@              BXEQ    lr
+
+
+COPY_UNDER_16B:
+               TST             r2,#0x10
+               BEQ             COPY_UNDER_15B
+               VLD1.8  {d0,d1},[r1]!
+               VST1.8  {d0,d1},[ip,:128]!
+
+COPY_UNDER_15B:
+               TST             r1,#0x03
+               BNE             COPY_UNDER_15B_UNALIGN
+COPY_UNDER_15B_ALIGN:
+               @ srcê°€ 4-byte align ??경우 
+               LSLS     r3,r2,#29
+               LDRCS    r3,[r1],#4
+               STRCS    r3,[ip],#4
+               LDRCS    r3,[r1],#4
+               STRCS    r3,[ip],#4
+               LDRMI    r3,[r1],#4
+               STRMI    r3,[ip],#4
+               LSLS     r2,r2,#31
+               LDRCSH   r3,[r1],#2
+               STRCSH   r3,[ip],#2
+               LDRMIB   r3,[r1],#1
+               STRMIB   r3,[ip],#1
+               BX              lr
+COPY_UNDER_15B_UNALIGN:
+               @ srcê°\80 4-byte align ???\84ë\8b\8c ÃªÂ²Â½Ã¬\9a°
+               LSLS     r3,r2,#29
+               BCC      COPY_UNDER_15B_UNALIGN_4B
+               @ neon ?\80ì²?ê°\80?
+               VLD1.8   {d0},[r1]!
+               VST1.8   {d0},[ip]!
+@              LDRBCS   r3,[r1],#1
+@              STRBCS   r3,[ip],#1
+@              LDRBCS   r3,[r1],#1
+@              STRBCS   r3,[ip],#1
+@              LDRBCS   r3,[r1],#1
+@              STRBCS   r3,[ip],#1
+@              LDRBCS   r3,[r1],#1
+@              STRBCS   r3,[ip],#1
+@              LDRBCS   r3,[r1],#1
+@              STRBCS   r3,[ip],#1
+@              LDRBCS   r3,[r1],#1
+@              STRBCS   r3,[ip],#1
+@              LDRBCS   r3,[r1],#1
+@              STRBCS   r3,[ip],#1
+@              LDRBCS   r3,[r1],#1
+@              STRBCS   r3,[ip],#1
+COPY_UNDER_15B_UNALIGN_4B:
+               BPL      COPY_UNDER_15B_UNALIGN_2B  
+               LDRMIB   r3,[r1],#1
+               STRMIB   r3,[ip],#1
+               LDRMIB   r3,[r1],#1
+               STRMIB   r3,[ip],#1
+               LDRMIB   r3,[r1],#1
+               STRMIB   r3,[ip],#1
+               LDRMIB   r3,[r1],#1
+               STRMIB   r3,[ip],#1
+COPY_UNDER_15B_UNALIGN_2B:
+               LSLS     r2,r2,#31
+               LDRCSB   r3,[r1],#1
+               STRCSB   r3,[ip],#1
+               LDRCSB   r3,[r1],#1
+               STRCSB   r3,[ip],#1
+               LDRMIB   r3,[r1],#1
+               STRMIB   r3,[ip],#1
+               BX              lr
+
+COPY_UNDER_64B:
+        ADDNE    pc,pc,r2,LSL #2
+        B        MEMCPY_WRAPUP
+        B        MEMCPY_WRAPUP
+        B        COPY_1B
+        B        COPY_2B
+        B        COPY_3B
+        B        COPY_4B
+        B        COPY_5B
+        B        COPY_6B
+        B        COPY_7B
+        B        COPY_8B
+        B        COPY_9B
+        B        COPY_10B
+        B        COPY_11B
+        B        COPY_12B
+        B        COPY_13B
+        B        COPY_14B
+        B        COPY_15B
+        B        COPY_16B
+        B        COPY_17B
+        B        COPY_18B
+        B        COPY_19B
+        B        COPY_20B
+        B        COPY_21B
+        B        COPY_22B
+        B        COPY_23B
+        B        COPY_24B
+        B        COPY_25B
+        B        COPY_26B
+        B        COPY_27B
+        B        COPY_28B
+        B        COPY_29B
+        B        COPY_30B
+        B        COPY_31B
+        B        COPY_32B
+        B        COPY_33B
+        B        COPY_34B
+        B        COPY_35B
+        B        COPY_36B
+        B        COPY_37B
+        B        COPY_38B
+        B        COPY_39B
+        B        COPY_40B
+        B        COPY_41B
+        B        COPY_42B
+        B        COPY_43B
+        B        COPY_44B
+        B        COPY_45B
+        B        COPY_46B
+        B        COPY_47B
+        B        COPY_48B
+        B        COPY_49B
+        B        COPY_50B
+        B        COPY_51B
+        B        COPY_52B
+        B        COPY_53B
+        B        COPY_54B
+        B        COPY_55B
+        B        COPY_56B
+        B        COPY_57B
+        B        COPY_58B
+        B        COPY_59B
+        B        COPY_60B
+        B        COPY_61B
+        B        COPY_62B
+        B        COPY_63B
+        B        COPY_64B
+
+@        ARM
+@        REQUIRE8
+@        PRESERVE8
+@
+@        AREA ||.text||, CODE, READONLY, ALIGN=4
+COPY_1B:
+               LDRB    r2,[r1]
+               STRB    r2,[ip]
+               BX              lr
+COPY_1B_:
+               VLD1.8    {d0[0]},[r1]
+               VST1.8    {d0[0]},[ip]
+               BX              lr
+COPY_2B:
+               ORR     r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_2B_
+               LDRH    r2,[r1]
+               STRH    r2,[ip]
+        BXEQ   lr
+COPY_2B_:
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r3,[r1],#1
+               STRB    r3,[ip],#1
+@              VLD2.8          {d0[0],d1[0]},[r1]
+@              VST2.8          {d0[0],d1[0]},[ip]
+        BX             lr
+COPY_3B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_3B_
+               LDRH    r2,[r1,#0x00]
+               STRH    r2,[ip,#0x00]
+               LDRB    r2,[r1,#0x02]
+               STRB    r2,[ip,#0x02]
+        BX             lr
+COPY_3B_:
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r3,[r1],#1
+               STRB    r3,[ip],#1
+@              VLD3.8          {d0[0],d1[0],d2[0]},[r1]
+@              VST3.8          {d0[0],d1[0],d2[0]},[ip]
+        BX             lr
+COPY_4B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_4B_
+               LDR             r2,[r1]
+               STR             r2,[ip]
+        BX             lr
+COPY_4B_:
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+@              VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]
+@              VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]
+        BX             lr
+COPY_5B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_5B_
+               LDR             r2,[r1],#0x04
+               STR             r2,[ip],#0x04
+               LDRB    r2,[r1]
+               STRB    r2,[ip]
+        BX             lr
+COPY_5B_:
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD1.8    {d4[0]},[r1]!
+               VST1.8    {d4[0]},[ip]!
+        BX             lr
+COPY_6B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_6B_
+               LDR             r2,[r1],#0x04
+               STR             r2,[ip],#0x04
+               LDRH    r3,[r1]
+               STRH    r3,[ip]
+        BX             lr
+COPY_6B_:
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+        BX             lr
+COPY_7B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_7B_
+               LDR             r2,[r1],#0x04
+               STR             r2,[ip],#0x04
+               LDRH    r2,[r1],#0x02
+               STRH    r2,[ip],#0x02
+               LDRB    r2,[r1]
+               STRB    r2,[ip]
+        BX             lr
+COPY_7B_:
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+@              VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+@              VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+@              VLD3.8    {d4[0],d5[0],d6[0]},[r1]!
+@              VST3.8    {d4[0],d5[0],d6[0]},[ip]!
+        BX             lr
+COPY_8B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_8B_
+               LDMEQ   r1!,{r2,r3}
+               STMEQ   ip!,{r2,r3}
+        BXEQ   lr
+COPY_8B_:
+               VLD1.8    {d0},[r1]
+               VST1.8    {d0},[ip]             
+        BX             lr
+COPY_9B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_9B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRB    r2,[r1]
+               STRB    r2,[ip]
+        BX             lr
+COPY_9B_:
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+@              VLD1.8    {d0},[r1]!
+@              VST1.8    {d0},[ip]!            
+@              VLD1.8    {d4[0]},[r1]
+@              VST1.8    {d4[0]},[ip]
+        BX             lr
+COPY_10B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_10B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r2,[r1]
+               STRH    r2,[ip]
+        BX             lr
+COPY_10B_:
+               VLD1.8    {d0},[r1]!
+               VST1.8    {d0},[ip]!            
+               VLD2.8    {d4[0],d5[0]},[r1]
+               VST2.8    {d4[0],d5[0]},[ip]
+        BX             lr
+COPY_11B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_11B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r2,[r1],#0x02
+               STRH    r2,[ip],#0x02
+               LDRB    r2,[r1]
+               STRB    r2,[ip]
+        BX             lr
+COPY_11B_:
+               VLD1.8    {d0},[r1]!
+               VST1.8    {d0},[ip]!
+               VLD3.8    {d4[0],d5[0],d6[0]},[r1]
+               VST3.8    {d4[0],d5[0],d6[0]},[ip]
+        BX             lr
+COPY_12B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_12B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDR             r2,[r1]
+               STR             r2,[ip]
+        BX             lr
+COPY_12B_:
+               VLD1.8    {d0},[r1]!
+               VST1.8    {d0},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]
+        BX             lr
+COPY_13B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_13B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDR             r2,[r1],#0x04
+               STR             r2,[ip],#0x04
+               LDRB    r3,[r1]
+               STRB    r3,[ip]
+        BX             lr
+COPY_13B_:
+               VLD1.8    {d0},[r1]!
+               VST1.8    {d0},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD1.8          {d2[0]},[r1]
+               VST1.8          {d2[0]},[ip]
+        BX             lr
+COPY_14B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_14B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDR             r2,[r1],#0x04
+               STR             r2,[ip],#0x04
+               LDRH    r3,[r1]
+               STRH    r3,[ip]
+        BX             lr
+COPY_14B_:
+               VLD1.8    {d0},[r1]!
+               VST1.8    {d0},[ip]!            
+               VLD4.8          {d1[0],d2[0],d3[0],d4[0]},[r1]!
+               VST4.8          {d1[0],d2[0],d3[0],d4[0]},[ip]!
+               VLD2.8          {d5[0],d6[0]},[r1]
+               VST2.8          {d5[0],d6[0]},[ip]
+        BX             lr
+COPY_15B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_15B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDR             r2,[r1],#0x04
+               STR             r2,[ip],#0x04
+               LDRH    r3,[r1],#0x02
+               STRH    r3,[ip],#0x02
+               LDRB    r2,[r1]
+               STRB    r2,[ip]
+        BX             lr
+COPY_15B_:
+               VLD1.8    {d0},[r1]!
+               VST1.8    {d0},[ip]!            
+               VLD4.8          {d1[0],d2[0],d3[0],d4[0]},[r1]!
+               VST4.8          {d1[0],d2[0],d3[0],d4[0]},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]
+        BX             lr
+COPY_16B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_16B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+        BX             lr
+COPY_16B_:
+               VLD1.8    {d0,d1},[r1]
+               VST1.8    {d0,d1},[ip]          
+        BX             lr
+COPY_17B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_17B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRB    r2,[r1]
+               STRB    r2,[ip]
+        BX             lr
+COPY_17B_:
+               VLD1.8    {d0,d1},[r1]!
+               VST1.8    {d0,d1},[ip]!         
+               VLD1.8          {d2[0]},[r1]
+               VST1.8          {d2[0]},[ip]
+        BX             lr
+COPY_18B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_18B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r2,[r1]
+               STRH    r2,[ip]
+        BX             lr
+COPY_18B_:
+               VLD1.8    {d0,d1},[r1]!
+               VST1.8    {d0,d1},[ip]!         
+               VLD2.8          {d0[0],d1[0]},[r1]
+               VST2.8          {d0[0],d1[0]},[ip]
+        BX             lr
+COPY_19B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_19B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+        BX             lr
+COPY_19B_:
+               VLD1.8    {d0,d1},[r1]!
+               VST1.8    {d0,d1},[ip]!         
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]
+        BX             lr
+COPY_20B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_20B_
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+        BX             lr
+COPY_20B_:
+               VLD1.8    {d0,d1},[r1]!
+               VST1.8    {d0,d1},[ip]!         
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]
+        BX             lr
+COPY_21B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_21B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRB    r4,[r1],#1
+               STRB    r4,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_21B_:
+               VLD1.8    {d0,d1},[r1]!
+               VST1.8    {d0,d1},[ip]!         
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD1.8          {d3[0]},[r1]!
+               VST1.8          {d3[0]},[ip]!
+        BX             lr
+COPY_22B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_22B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r4,[r1],#2
+               STRH    r4,[ip],#2
+               POP             {r4}
+        BX             lr
+COPY_22B_:
+               VLD1.8    {d0,d1},[r1]!
+               VST1.8    {d0,d1},[ip]!         
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD2.8          {d0[0],d1[0]},[r1]!
+               VST2.8          {d0[0],d1[0]},[ip]!
+        BX             lr
+COPY_23B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_23B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r4,[r1],#2
+               STRH    r4,[ip],#2
+               LDRB    r4,[r1],#1
+               STRB    r4,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_23B_:
+               VLD1.8    {d0,d1},[r1]!
+               VST1.8    {d0,d1},[ip]!         
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]
+        BX             lr
+COPY_24B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_24B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               POP             {r4}
+        BX             lr
+COPY_24B_:
+               VLD1.8    {d0,d1,d2},[r1]
+               VST1.8    {d0,d1,d2},[ip]
+        BX             lr
+COPY_25B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_25B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_25B_:
+               VLD1.8    {d0,d1,d2},[r1]!
+               VST1.8    {d0,d1,d2},[ip]!
+               VLD1.8          {d3[0]},[r1]
+               VST1.8          {d3[0]},[ip]
+        BX             lr
+COPY_26B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_26B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               POP             {r4}
+        BX             lr
+COPY_26B_:
+               VLD1.8    {d0,d1,d2},[r1]!
+               VST1.8    {d0,d1,d2},[ip]!
+               VLD2.8          {d0[0],d1[0]},[r1]
+               VST2.8          {d0[0],d1[0]},[ip]
+        BX             lr
+COPY_27B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_27B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_27B_:
+               VLD1.8    {d0,d1,d2},[r1]!
+               VST1.8    {d0,d1,d2},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]
+        BX             lr
+COPY_28B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_28B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               POP             {r4}
+        BX             lr
+COPY_28B_:
+               VLD1.8    {d0,d1,d2},[r1]!
+               VST1.8    {d0,d1,d2},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]
+        BX             lr
+COPY_29B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_29B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_29B_:
+               VLD1.8    {d0,d1,d2},[r1]!
+               VST1.8    {d0,d1,d2},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD1.8          {d4[0]},[r1]
+               VST1.8          {d4[0]},[ip]
+        BX             lr
+COPY_30B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_30B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               POP             {r4}
+        BX             lr
+COPY_30B_:
+               VLD1.8    {d0,d1,d2},[r1]!
+               VST1.8    {d0,d1,d2},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD2.8          {d0[0],d1[0]},[r1]
+               VST2.8          {d0[0],d1[0]},[ip]
+        BX             lr
+COPY_31B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_31B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_31B_:
+               VLD1.8    {d0,d1,d2},[r1]!
+               VST1.8    {d0,d1,d2},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]
+        BX             lr
+COPY_32B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_32B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               POP             {r4}
+        BX             lr
+COPY_32B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]
+               VST1.8    {d0,d1,d2,d3},[ip]
+        BX             lr
+COPY_33B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_33B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_33B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4[0]},[r1]
+               VST1.8    {d4[0]},[ip]
+        BX             lr
+COPY_34B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_34B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               POP             {r4}
+        BX             lr
+COPY_34B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD2.8          {d0[0],d1[0]},[r1]
+               VST2.8          {d0[0],d1[0]},[ip]
+        BX             lr
+COPY_35B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_35B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_35B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]
+        BX             lr
+COPY_36B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_36B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               POP             {r4}
+        BX             lr
+COPY_36B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+        BX             lr
+COPY_37B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_37B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_37B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD1.8    {d5[0]},[r1]!
+               VST1.8    {d5[0]},[ip]!
+        BX             lr
+COPY_38B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_38B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               POP             {r4}
+        BX             lr
+COPY_38B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD2.8          {d5[0],d6[0]},[r1]!
+               VST2.8          {d5[0],d6[0]},[ip]!
+               BX              lr
+COPY_39B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_39B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_39B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]!
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]!
+        BX             lr
+COPY_40B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_40B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               POP             {r4}
+        BX             lr
+COPY_40B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4},[r1]!
+               VST1.8    {d4},[ip]!
+        BX             lr
+COPY_41B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_41B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_41B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4},[r1]!
+               VST1.8    {d4},[ip]!
+               VLD1.8    {d5[0]},[r1]!
+               VST1.8    {d5[0]},[ip]!
+        BX             lr
+COPY_42B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_42B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               POP             {r4}
+        BX             lr
+COPY_42B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4},[r1]!
+               VST1.8    {d4},[ip]!
+               VLD2.8          {d0[0],d1[0]},[r1]!
+               VST2.8          {d0[0],d1[0]},[ip]!
+        BX             lr
+COPY_43B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_43B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_43B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4},[r1]!
+               VST1.8    {d4},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]!
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]!
+        BX             lr
+COPY_44B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_44B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               POP             {r4}
+        BX             lr
+COPY_44B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4},[r1]!
+               VST1.8    {d4},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+        BX             lr
+COPY_45B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_45B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_45B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4},[r1]!
+               VST1.8    {d4},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD1.8    {d6[0]},[r1]!
+               VST1.8    {d6[0]},[ip]!
+        BX             lr
+COPY_46B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_46B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               POP             {r4}
+        BX             lr
+COPY_46B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4},[r1]!
+               VST1.8    {d4},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD2.8    {d0[0],d1[0]},[r1]!
+               VST2.8    {d0[0],d1[0]},[ip]!
+        BX             lr
+COPY_47B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_47B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_47B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4},[r1]!
+               VST1.8    {d4},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]!
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]!
+        BX             lr
+COPY_48B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_48B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               POP             {r4}
+        BX             lr
+COPY_48B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5},[r1]!
+               VST1.8    {d4,d5},[ip]!
+        BX             lr
+COPY_49B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_49B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_49B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5},[r1]!
+               VST1.8    {d4,d5},[ip]!
+               VLD1.8    {d6[0]},[r1]!
+               VST1.8    {d6[0]},[ip]!
+        BX             lr
+COPY_50B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_50B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               POP             {r4}
+        BX             lr
+COPY_50B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5},[r1]!
+               VST1.8    {d4,d5},[ip]!
+               VLD2.8          {d0[0],d1[0]},[r1]!
+               VST2.8          {d0[0],d1[0]},[ip]!
+        BX             lr
+COPY_51B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_51B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_51B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5},[r1]!
+               VST1.8    {d4,d5},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]!
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]!
+        BX             lr
+COPY_52B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_52B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               POP             {r4}
+        BX             lr
+COPY_52B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5},[r1]!
+               VST1.8    {d4,d5},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+        BX             lr
+COPY_53B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_53B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_53B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5},[r1]!
+               VST1.8    {d4,d5},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD1.8    {d7[0]},[r1]!
+               VST1.8    {d7[0]},[ip]!
+        BX             lr
+COPY_54B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_54B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               LDRH    r2,[r1],#1
+               STRH    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_54B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5},[r1]!
+               VST1.8    {d4,d5},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD2.8          {d0[0],d1[0]},[r1]!
+               VST2.8          {d0[0],d1[0]},[ip]!
+        BX             lr
+COPY_55B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_55B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_55B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5},[r1]!
+               VST1.8    {d4,d5},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]!
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]!
+        BX             lr
+COPY_56B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_56B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               POP             {r4}
+        BX             lr
+COPY_56B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5,d6},[r1]!
+               VST1.8    {d4,d5,d6},[ip]!
+        BX             lr
+COPY_57B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_57B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_57B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5,d6},[r1]!
+               VST1.8    {d4,d5,d6},[ip]!
+               VLD1.8    {d7[0]},[r1]!
+               VST1.8    {d7[0]},[ip]!
+        BX             lr
+COPY_58B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_58B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               POP             {r4}
+        BX             lr
+COPY_58B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5,d6},[r1]!
+               VST1.8    {d4,d5,d6},[ip]!
+               VLD2.8          {d0[0],d1[0]},[r1]!
+               VST2.8          {d0[0],d1[0]},[ip]!
+        BX             lr
+COPY_59B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_59B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3}
+               STM             ip!,{r2,r3}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_59B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5,d6},[r1]!
+               VST1.8    {d4,d5,d6},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]!
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]!
+        BX             lr
+COPY_60B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_60B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               POP             {r4}
+        BX             lr
+COPY_60B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5,d6},[r1]!
+               VST1.8    {d4,d5,d6},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+        BX             lr
+COPY_61B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_61B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_61B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5,d6},[r1]!
+               VST1.8    {d4,d5,d6},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD1.8     {d0[0]},[r1]!
+               VST1.8     {d0[0]},[ip]!
+        BX             lr
+COPY_62B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_62B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               POP             {r4}
+        BX             lr
+COPY_62B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5,d6},[r1]!
+               VST1.8    {d4,d5,d6},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD2.8          {d0[0],d1[0]},[r1]!
+               VST2.8          {d0[0],d1[0]},[ip]!
+        BX             lr
+COPY_63B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_63B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4}
+               LDRH    r2,[r1],#2
+               STRH    r2,[ip],#2
+               LDRB    r2,[r1],#1
+               STRB    r2,[ip],#1
+               POP             {r4}
+        BX             lr
+COPY_63B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VLD1.8    {d4,d5,d6},[r1]!
+               VST1.8    {d4,d5,d6},[ip]!
+               VLD4.8          {d0[0],d1[0],d2[0],d3[0]},[r1]!
+               VST4.8          {d0[0],d1[0],d2[0],d3[0]},[ip]!
+               VLD3.8    {d5[0],d6[0],d7[0]},[r1]!
+               VST3.8    {d5[0],d6[0],d7[0]},[ip]!
+        BX             lr
+COPY_64B:
+               ORR             r3,ip,r1
+               TST             r3,#3
+               BNE             COPY_64B_
+               PUSH    {r4}
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4} @ 12
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4} @ 24
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4} @ 36
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4} @ 48
+               LDM             r1!,{r2,r3,r4}
+               STM             ip!,{r2,r3,r4} @ 60
+               LDR             r2,[r1],#4
+               STR             r2,[ip],#4
+               POP             {r4}
+        BX             lr
+COPY_64B_:
+               VLD1.8    {d0,d1,d2,d3},[r1]!
+               VLD1.8    {d4,d5,d6,d7},[r1]!
+               VST1.8    {d0,d1,d2,d3},[ip]!
+               VST1.8    {d4,d5,d6,d7},[ip]!
+        BX             lr
+
+MEMCPY_WRAPUP:
+        @MOV      r0,r5
+        @POP      {r4-r6,pc}
+               BX              lr
+
+               .global memcpy_neon
+
diff --git a/src/neon/neonmem.h b/src/neon/neonmem.h
new file mode 100644 (file)
index 0000000..626abec
--- /dev/null
@@ -0,0 +1,49 @@
+/**************************************************************************\r
+\r
+xserver-xorg-video-exynos\r
+\r
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.\r
+\r
+Contact: SooChan Lim <sc1.lim@samsung.com>\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a\r
+copy of this software and associated documentation files (the\r
+"Software"), to deal in the Software without restriction, including\r
+without limitation the rights to use, copy, modify, merge, publish,\r
+distribute, sub license, and/or sell copies of the Software, and to\r
+permit persons to whom the Software is furnished to do so, subject to\r
+the following conditions:\r
+\r
+The above copyright notice and this permission notice (including the\r
+next paragraph) shall be included in all copies or substantial portions\r
+of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.\r
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR\r
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\r
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\r
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+**************************************************************************/\r
+\r
+#ifndef _NEON_MEMCPY_HEADER_\r
+#define _NEON_MEMCPY_HEADER_\r
+\r
+#include <stddef.h>\r
+\r
+#ifdef memcpy\r
+#undef memcpy\r
+#endif\r
+\r
+#define memcpy memcpy_neon\r
+\r
+void *\r
+memcpy_neon (void *dst, const void *src, size_t count);\r
+\r
+int\r
+move_pixels (void *bits, int bpp, int stride, int img_width, int img_height,\r
+             int sx, int sy, int dx, int dy, int w, int h);\r
+#endif /*  _NEON_MEMCPY_HEADER_ */\r
+\r
diff --git a/src/sec.c b/src/sec.c
new file mode 100644 (file)
index 0000000..97166f7
--- /dev/null
+++ b/src/sec.c
@@ -0,0 +1,1772 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* all driver need this */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+#include "fb.h"
+#include "mipointer.h"
+#include "mibstore.h"
+#include "micmap.h"
+#include "colormapst.h"
+#include "xf86cmap.h"
+#include "xf86xv.h"
+#include "xf86Crtc.h"
+#include "sec.h"
+#include "sec_display.h"
+#include "sec_plane.h"
+#include "sec_accel.h"
+#include "sec_xberc.h"
+#include "sec_util.h"
+#include "sec_wb.h"
+#include <tbm_bufmgr.h>
+#include "fimg2d.h"
+
+#define OPTION_FLIP_BUFFERS 0
+
+/* prototypes */
+static const OptionInfoRec* SECAvailableOptions (int chipid, int busid);
+static void SECIdentify (int flags);
+static Bool SECProbe (DriverPtr pDrv, int flags);
+static Bool SECPreInit (ScrnInfoPtr pScrn, int flags);
+static Bool SECScreenInit (ScreenPtr pScreen, int argc, char **argv);
+static Bool SECSwitchMode (ScrnInfoPtr pScrn, DisplayModePtr pMode);
+static void SECAdjustFrame (ScrnInfoPtr pScrn, int x, int y);
+static Bool SECEnterVT (ScrnInfoPtr pScrn);
+static void SECLeaveVT (ScrnInfoPtr pScrn);
+static ModeStatus SECValidMode (ScrnInfoPtr pScrn, DisplayModePtr pMode, Bool verbose, int flags);
+static Bool SECCloseScreen (ScreenPtr pScreen);
+static Bool SECCreateScreenResources (ScreenPtr pScreen);
+#if HAVE_UDEV
+static void SECUdevEventsHandler (int fd, void *closure);
+#endif
+
+/* This DriverRec must be defined in the driver for Xserver to load this driver */
+_X_EXPORT DriverRec SEC =
+{
+    SEC_VERSION,
+    SEC_DRIVER_NAME,
+    SECIdentify,
+    SECProbe,
+    SECAvailableOptions,
+    NULL,
+    0,
+    NULL,
+};
+
+/* Supported "chipsets" */
+static SymTabRec SECChipsets[] =
+{
+    { 0, "exynos" },
+    {-1, NULL }
+};
+
+/* Supported options */
+typedef enum
+{
+    OPTION_DRI2,
+    OPTION_EXA,
+    OPTION_SWEXA,
+    OPTION_ROTATE,
+    OPTION_SNAPSHOT,
+    OPTION_WB,
+#if OPTION_FLIP_BUFFERS
+    OPTION_FLIPBUFS,
+#endif
+    OPTION_CACHABLE,
+    OPTION_SCANOUT,
+    OPTION_ACCEL2D,
+    OPTION_PARTIAL_UPDATE,
+} SECOpts;
+
+static const OptionInfoRec SECOptions[] =
+{
+    { OPTION_DRI2,     "dri2",       OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_EXA,      "exa",        OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_SWEXA,    "sw_exa",     OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_ROTATE,   "rotate",     OPTV_STRING,  {0}, FALSE },
+    { OPTION_SNAPSHOT, "snapshot",   OPTV_STRING,  {0}, FALSE },
+    { OPTION_WB,       "wb",         OPTV_BOOLEAN, {0}, FALSE },
+#if OPTION_FLIP_BUFFERS
+    { OPTION_FLIPBUFS, "flip_bufs",  OPTV_INTEGER, {0}, 3 },
+#endif
+    { OPTION_CACHABLE, "cachable",   OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_SCANOUT,  "scanout",    OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_ACCEL2D,  "accel_2d",   OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_PARTIAL_UPDATE,  "partial_update",    OPTV_BOOLEAN, {0}, FALSE },
+    { -1,              NULL,         OPTV_NONE,    {0}, FALSE }
+};
+
+/* -------------------------------------------------------------------- */
+#ifdef XFree86LOADER
+
+MODULESETUPPROTO (SECSetup);
+
+static XF86ModuleVersionInfo SECVersRec =
+{
+    "exynos",
+    MODULEVENDORSTRING,
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XORG_VERSION_CURRENT,
+    PACKAGE_VERSION_MAJOR,
+    PACKAGE_VERSION_MINOR,
+    PACKAGE_VERSION_PATCHLEVEL,
+    ABI_CLASS_VIDEODRV,
+    ABI_VIDEODRV_VERSION,
+    NULL,
+    {0,0,0,0}
+};
+
+_X_EXPORT XF86ModuleData exynosModuleData = { &SECVersRec, SECSetup, NULL };
+
+pointer
+SECSetup (pointer module, pointer opts, int *errmaj, int *errmin)
+{
+    static Bool setupDone = FALSE;
+
+    if (!setupDone)
+    {
+        setupDone = TRUE;
+        xf86AddDriver (&SEC, module, HaveDriverFuncs);
+        return (pointer) 1;
+    }
+    else
+    {
+        if (errmaj) *errmaj = LDR_ONCEONLY;
+        return NULL;
+    }
+}
+
+#endif /* XFree86LOADER */
+/* -------------------------------------------------------------------- */
+
+/* TODO:::check the fimd_drm */
+static Bool
+_has_drm_mode_setting()
+{
+    /* TODO:: check the sysfs dri2 device name */
+    return TRUE;
+}
+
+/*
+ * Probing the device with the device node, this probing depend on the specific hw.
+ * This function just verify whether the display hw is avaliable or not.
+ */
+static Bool
+_secHwProbe (struct pci_device * pPci, char *device,char **namep)
+{
+    if (!_has_drm_mode_setting())
+        return FALSE;
+
+    return TRUE;
+}
+
+static tbm_bufmgr
+_secInitBufmgr (int drm_fd, void * arg)
+{
+    tbm_bufmgr bufmgr = NULL;
+
+    /* get buffer manager */
+    setenv("BUFMGR_LOCK_TYPE", "once", 1);
+    setenv("BUFMGR_MAP_CACHE", "true", 1);
+    bufmgr = tbm_bufmgr_init (drm_fd);
+
+    if (bufmgr == NULL)
+        return NULL;
+
+    return bufmgr;
+}
+
+static void
+_secDeInitBufmgr (tbm_bufmgr bufmgr)
+{
+    if (bufmgr)
+        tbm_bufmgr_deinit (bufmgr);
+}
+
+/* open drm */
+static Bool
+_openDrmMaster (ScrnInfoPtr pScrn)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    int ret;
+
+    /* open drm */
+    pSec->drm_fd = drmOpen ("exynos", NULL);
+    if (pSec->drm_fd < 0)
+    {
+        struct udev *udev;
+        struct udev_enumerate *e;
+        struct udev_list_entry *entry;
+        struct udev_device *device, *drm_device;
+        const char *path, *device_seat;
+        const char *filename;
+
+        xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "[DRM] Cannot open drm device.. search by udev\n");
+
+        /* STEP 1: Find drm device */
+        udev = udev_new();
+        if (udev == NULL)
+        {
+            xf86DrvMsg (pScrn->scrnIndex, X_ERROR,"[DRM] fail to initialize udev context\n");
+            goto fail_to_open_drm_master;
+        }
+
+        e = udev_enumerate_new(udev);
+        udev_enumerate_add_match_subsystem(e, "drm");
+        udev_enumerate_add_match_sysname(e, "card[0-9]*");
+        udev_enumerate_scan_devices(e);
+
+        drm_device = NULL;
+        udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e))
+        {
+            path = udev_list_entry_get_name(entry);
+            device = udev_device_new_from_syspath(udev, path);
+            device_seat = udev_device_get_property_value(device, "ID_SEAT");
+            xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "[DRM] drm info: device:%p, patch:%s, seat:%s\n", device, path, device_seat);
+
+            if(!device_seat)
+                device_seat = "seat0";
+
+            if(strcmp(device_seat, "seat0") == 0)
+            {
+                drm_device = device;
+                break;
+            }
+            udev_device_unref(device);
+        }
+
+        if(drm_device == NULL)
+        {
+            xf86DrvMsg (pScrn->scrnIndex, X_ERROR,"[DRM] fail to find drm device\n");
+            goto fail_to_open_drm_master;
+        }
+
+        filename = udev_device_get_devnode(drm_device);
+
+        pSec->drm_fd  = open(filename, O_RDWR|O_CLOEXEC);
+        if (pSec->drm_fd < 0)
+        {
+            xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "[DRM] Cannot open drm device(%s)\n", filename);
+
+            udev_device_unref(drm_device);
+            udev_enumerate_unref(e);
+            udev_unref(udev);
+
+            goto fail_to_open_drm_master;
+        }
+        else
+        {
+            xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "[DRM] Succeed to open drm device(%s)\n", filename);
+        }
+
+        udev_device_unref(drm_device);
+        udev_enumerate_unref(e);
+        udev_unref(udev);
+    }
+    else
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "[DRM] Succeed to open drm device\n");
+    }
+
+    pSec->drm_device_name = drmGetDeviceNameFromFd (pSec->drm_fd);
+    xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "[DRM] Succeed get drm device name:%s\n",
+                pSec->drm_device_name);
+
+    /* enable drm vblank */
+    ret = drmCtlInstHandler (pSec->drm_fd, 217);
+    if (ret)
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                    "[DRM] Fail to enable drm VBlank(%d)\n", ret);
+        goto fail_to_open_drm_master;
+    }
+
+    xf86DrvMsg (pScrn->scrnIndex, X_CONFIG,
+                "[DRM] Enable drm VBlank(%d)\n", ret);
+
+    /* initialize drm bufmgr */
+    pSec->tbm_bufmgr = _secInitBufmgr (pSec->drm_fd, NULL);
+    if (pSec->tbm_bufmgr == NULL)
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                    "[DRM] Error : bufmgr initialization failed\n");
+        goto fail_to_open_drm_master;
+    }
+
+    xf86DrvMsg (pScrn->scrnIndex, X_CONFIG
+                , "[DRM] Enable buffer manager\n");
+
+    return TRUE;
+
+fail_to_open_drm_master:
+
+    if (pSec->tbm_bufmgr)
+    {
+        _secDeInitBufmgr (pSec->tbm_bufmgr);
+        pSec->tbm_bufmgr = NULL;
+    }
+
+    if (pSec->drm_device_name)
+    {
+        free (pSec->drm_device_name);
+        pSec->drm_device_name = NULL;
+    }
+
+    if (pSec->drm_fd >= 0)
+    {
+        drmClose (pSec->drm_fd);
+        pSec->drm_fd = -1;
+    }
+
+    return FALSE;
+}
+
+/* close drm */
+static void
+_closeDrmMaster (ScrnInfoPtr pScrn)
+{
+    SECPtr pSec = SECPTR (pScrn);
+
+    if (pSec->tbm_bufmgr)
+    {
+        _secDeInitBufmgr (pSec->tbm_bufmgr);
+        pSec->tbm_bufmgr = NULL;
+    }
+
+    if (pSec->drm_fd >= 0)
+    {
+        drmClose (pSec->drm_fd);
+        pSec->drm_fd = -1;
+    }
+
+    if (pSec->drm_device_name)
+    {
+        free (pSec->drm_device_name);
+        pSec->drm_device_name = NULL;
+    }
+}
+
+/*
+ * Initialize the device Probing the device with the device node,
+ * this probing depend on the specific hw.
+ * This function just verify whether the display hw is avaliable or not.
+ */
+static Bool
+_secHwInit (ScrnInfoPtr pScrn, struct pci_device *pPci, char *device)
+{
+    SECPtr pSec = SECPTR (pScrn);
+
+    /* init drm master */
+    if (_openDrmMaster (pScrn) == TRUE)
+        xf86DrvMsg (pScrn->scrnIndex, X_CONFIG
+                    , "DRM BLANK is enabled\n");
+    else
+        xf86DrvMsg (pScrn->scrnIndex, X_CONFIG
+                    , "DRM BLANK is disabled\n");
+
+
+    if(g2d_init (pSec->drm_fd))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_CONFIG
+                    , "G2D is enabled\n");
+        pSec->is_accel_2d = TRUE;
+    }
+    else
+        xf86DrvMsg (pScrn->scrnIndex, X_CONFIG
+                    , "G2D is disabled\n");
+
+    return TRUE;
+}
+
+/* SigHook */
+OsSigWrapperPtr old_sig_wrapper;
+int
+_secOsSigWrapper (int sig)
+{
+    XDBG_KLOG(MSEC,"Catch SIG: %d\n", sig);
+
+    return old_sig_wrapper(sig); /*Contiue*/
+}
+
+/*
+ * DeInitialize the hw
+ */
+static void
+_secHwDeinit (ScrnInfoPtr pScrn)
+{
+    g2d_fini ();
+
+    /* deinit drm master */
+    _closeDrmMaster (pScrn);
+
+    return;
+}
+
+static Bool
+_allocScrnPrivRec (ScrnInfoPtr pScrn)
+{
+    if (pScrn->driverPrivate != NULL)
+        return TRUE;
+
+    pScrn->driverPrivate = calloc (sizeof (SECRec), 1);
+    if (!pScrn->driverPrivate)
+        return FALSE;
+
+    return TRUE;
+}
+
+static void
+_freeScrnPrivRec (ScrnInfoPtr pScrn)
+{
+    if (pScrn->driverPrivate == NULL)
+        return;
+    free (pScrn->driverPrivate);
+    pScrn->driverPrivate = NULL;
+}
+
+/*
+ * Check the driver option.
+ * Set the option flags to the driver private
+ */
+static void
+_checkDriverOptions (ScrnInfoPtr pScrn)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    const char *s;
+    int flip_bufs = 3;
+
+    /* exa */
+    if (xf86ReturnOptValBool (pSec->Options, OPTION_EXA, FALSE))
+        pSec->is_exa = TRUE;
+
+    /* sw exa */
+    if (pSec->is_exa)
+    {
+        if (xf86ReturnOptValBool (pSec->Options, OPTION_SWEXA, TRUE))
+            pSec->is_sw_exa = TRUE;
+    }
+
+    /* dri2 */
+    if (xf86ReturnOptValBool (pSec->Options, OPTION_DRI2, FALSE))
+    {
+        pSec->is_dri2 = TRUE;
+
+        /* number of the flip buffers */
+#if OPTION_FLIP_BUFFERS
+        if (xf86GetOptValInteger (pSec->Options, OPTION_FLIPBUFS, &flip_bufs))
+            pSec->flip_bufs = flip_bufs;
+        else
+#endif
+        {
+            /* default is 3 */
+            flip_bufs = 3;
+            pSec->flip_bufs = flip_bufs;
+        }
+    }
+
+    /* rotate */
+    pSec->rotate = RR_Rotate_0;
+    if (( s= xf86GetOptValString (pSec->Options, OPTION_ROTATE)))
+    {
+        if (!xf86NameCmp (s, "CW"))
+        {
+            pSec->rotate = RR_Rotate_90;
+            xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "rotating screen clockwise\n");
+        }
+        else if (!xf86NameCmp (s, "CCW"))
+        {
+            pSec->rotate = RR_Rotate_270;
+            xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "rotating screen counter-clockwise\n");
+        }
+        else if (!xf86NameCmp (s, "UD"))
+        {
+            pSec->rotate = RR_Rotate_180;
+            xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "rotating screen upside-down\n");
+        }
+        else
+        {
+            xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "\"%s\" is not valid option", s);
+        }
+    }
+
+    /* wb */
+    if (xf86ReturnOptValBool (pSec->Options, OPTION_WB, FALSE))
+    {
+        if (xf86ReturnOptValBool (pSec->Options, OPTION_WB, TRUE))
+            pSec->is_wb_clone = TRUE;
+    }
+
+    /* cachable */
+    if (xf86ReturnOptValBool (pSec->Options, OPTION_CACHABLE, FALSE))
+    {
+        if (xf86ReturnOptValBool (pSec->Options, OPTION_CACHABLE, TRUE))
+        {
+            pSec->cachable = TRUE;
+            xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "Use cachable buffer.\n");
+        }
+    }
+
+    /* scanout */
+    if (xf86ReturnOptValBool (pSec->Options, OPTION_SCANOUT, FALSE))
+    {
+        if (xf86ReturnOptValBool (pSec->Options, OPTION_SCANOUT, TRUE))
+        {
+            pSec->scanout = TRUE;
+            xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "Use scanout buffer.\n");
+        }
+    }
+
+    /* hw_2d */
+    if (xf86ReturnOptValBool (pSec->Options, OPTION_ACCEL2D, FALSE))
+    {
+        if (xf86ReturnOptValBool (pSec->Options, OPTION_ACCEL2D, TRUE))
+        {
+            pSec->is_accel_2d = TRUE;
+            xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "Use 2d accelerator.\n");
+        }
+    }
+
+    /* use_partial_update */
+    if (xf86ReturnOptValBool (pSec->Options, OPTION_PARTIAL_UPDATE, FALSE))
+    {
+        if (xf86ReturnOptValBool (pSec->Options, OPTION_PARTIAL_UPDATE, TRUE))
+        {
+            pSec->use_partial_update = TRUE;
+            xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "Use partial update.\n");
+        }
+    }
+}
+
+#if HAVE_UDEV
+static void
+_secUdevInit (ScrnInfoPtr pScrn)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    struct udev *u;
+    struct udev_monitor *mon;
+
+    xf86DrvMsg (pScrn->scrnIndex, X_CONFIG, "hotplug detection\n");
+
+    u = udev_new();
+    if(!u)
+        return;
+
+    mon = udev_monitor_new_from_netlink(u, "udev");
+    if(!mon)
+    {
+        udev_unref(u);
+        return;
+    }
+
+    if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") > 0 ||
+            udev_monitor_enable_receiving(mon) < 0)
+    {
+        udev_monitor_unref(mon);
+        udev_unref(u);
+        return;
+    }
+
+    pSec->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon), SECUdevEventsHandler, pScrn);
+    if (!pSec->uevent_handler)
+    {
+        udev_monitor_unref(mon);
+        udev_unref(u);
+        return;
+    }
+
+    pSec->uevent_monitor = mon;
+}
+
+static void
+_secUdevDeinit (ScrnInfoPtr pScrn)
+{
+    SECPtr pSec = SECPTR (pScrn);
+
+    if (pSec->uevent_handler)
+    {
+        struct udev *u = udev_monitor_get_udev(pSec->uevent_monitor);
+
+        udev_monitor_unref(pSec->uevent_monitor);
+        udev_unref(u);
+        pSec->uevent_handler = NULL;
+        pSec->uevent_monitor = NULL;
+    }
+
+}
+
+static Bool
+SECSaveScreen (ScreenPtr pScreen, int mode)
+{
+    /* dummpy save screen */
+    return TRUE;
+}
+
+static void
+SECUdevEventsHandler (int fd, void *closure)
+{
+    ScrnInfoPtr pScrn = closure;
+    SECPtr pSec = SECPTR (pScrn);
+    struct udev_device *dev;
+    const char *hotplug;
+    struct stat s;
+    dev_t udev_devnum;
+    int ret;
+
+    dev = udev_monitor_receive_device (pSec->uevent_monitor);
+    if (!dev)
+        return;
+
+    udev_devnum = udev_device_get_devnum(dev);
+
+    ret = fstat (pSec->drm_fd, &s);
+    if (ret == -1)
+        return;
+
+    /*
+     * Check to make sure this event is directed at our
+     * device (by comparing dev_t values), then make
+     * sure it's a hotplug event (HOTPLUG=1)
+     */
+    hotplug = udev_device_get_property_value (dev, "HOTPLUG");
+
+    if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
+            hotplug && atoi(hotplug) == 1)
+    {
+        XDBG_INFO(MSEC, "SEC-UDEV: HotPlug\n");
+        RRGetInfo (screenInfo.screens[pScrn->scrnIndex], TRUE);
+    }
+
+    udev_device_unref(dev);
+}
+#endif /* UDEV_HAVE */
+
+static const OptionInfoRec *
+SECAvailableOptions (int chipid, int busid)
+{
+    return SECOptions;
+}
+
+static void
+SECIdentify (int flags)
+{
+    xf86PrintChipsets (SEC_NAME, "driver for Exynos Chipsets", SECChipsets);
+}
+
+
+/* The purpose of this function is to identify all instances of hardware supported
+ * by the driver. The probe must find the active device sections that match the driver
+ * by calling xf86MatchDevice().
+ */
+static Bool
+SECProbe (DriverPtr pDrv, int flags)
+{
+    int i;
+    ScrnInfoPtr pScrn;
+    GDevPtr *ppDevSections;
+    int numDevSections;
+    int entity;
+    Bool foundScreen = FALSE;
+
+    /* check the drm mode setting */
+    if (!_secHwProbe (NULL, NULL, NULL))
+    {
+        return FALSE;
+    }
+
+    /* For now, just bail out for PROBE_DETECT. */
+    if (flags & PROBE_DETECT)
+        return FALSE;
+
+    if ((numDevSections = xf86MatchDevice (SEC_DRIVER_NAME, &ppDevSections)) <= 0)
+        return FALSE;
+
+    for (i = 0; i < numDevSections; i++)
+    {
+        entity = xf86ClaimNoSlot (pDrv, 0, ppDevSections[i], TRUE);
+
+        pScrn = xf86AllocateScreen (pDrv, flags);
+        xf86AddEntityToScreen (pScrn, entity);
+
+        if (pScrn)
+        {
+            foundScreen = TRUE;
+
+            pScrn->driverVersion  = SEC_VERSION;
+            pScrn->driverName     = SEC_DRIVER_NAME;
+            pScrn->name           = SEC_NAME;
+            pScrn->Probe          = SECProbe;
+            pScrn->PreInit        = SECPreInit;
+            pScrn->ScreenInit     = SECScreenInit;
+            pScrn->SwitchMode     = SECSwitchMode;
+            pScrn->AdjustFrame    = SECAdjustFrame;
+            pScrn->EnterVT        = SECEnterVT;
+            pScrn->LeaveVT        = SECLeaveVT;
+            pScrn->ValidMode      = SECValidMode;
+
+            xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+                        "using drm mode setting device\n");
+        }
+    }
+    free (ppDevSections);
+
+    return foundScreen;
+}
+
+/*
+ * This is called before ScreenInit to probe the screen configuration.
+ * The main tasks to do in this funtion are probing, module loading, option handling,
+ * card mapping, and mode setting setup.
+ */
+static Bool
+SECPreInit (ScrnInfoPtr pScrn, int flags)
+{
+    SECPtr pSec;
+    Gamma defualt_gamma = {0.0, 0.0, 0.0};
+    rgb default_weight = {0, 0, 0};
+    int flag24;
+
+    if (flags & PROBE_DETECT)
+        return FALSE;
+
+    /* allocate private */
+    if (!_allocScrnPrivRec (pScrn))
+        return FALSE;
+    pSec = SECPTR (pScrn);
+
+    /* Check the number of entities, and fail if it isn't one. */
+    if (pScrn->numEntities != 1)
+        return FALSE;
+
+    pSec->pEnt = xf86GetEntityInfo (pScrn->entityList[0]);
+
+    /* initialize the hardware specifics */
+    if (!_secHwInit (pScrn, NULL, NULL))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                    "fail to initialize hardware\n");
+        goto bail1;
+    }
+
+    pScrn->displayWidth = 640; /*default width */
+    pScrn->monitor = pScrn->confScreen->monitor;
+    pScrn->progClock = TRUE;
+    pScrn->rgbBits   = 8;
+
+    /* set the depth and the bpp to pScrn */
+    flag24 = Support24bppFb | Support32bppFb;
+    if (!xf86SetDepthBpp (pScrn, 0, 0, 0, flag24))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                    "fail to find the depth\n");
+        goto bail1;
+    }
+    xf86PrintDepthBpp (pScrn); /* just print out the depth and the bpp */
+
+    /* color weight */
+    if (!xf86SetWeight (pScrn, default_weight, default_weight))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR ,
+                    "fail to set the color weight of RGB\n");
+        goto bail1;
+    }
+
+    /* visual init, make a TrueColor, -1 */
+    if (!xf86SetDefaultVisual (pScrn, -1))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR ,
+                    "fail to initialize the default visual\n");
+        goto bail1;
+    }
+
+    /* Collect all the option flags (fill in pScrn->options) */
+    xf86CollectOptions (pScrn, NULL);
+
+    /*
+     * Process the options based on the information SECOptions.
+     * The results are written to pSec->Options. If all the options
+     * processing is done within this fuction a local variable "options"
+     * can be used instead of pSec->Options
+     */
+    if (!(pSec->Options = malloc (sizeof (SECOptions))))
+        goto bail1;
+    memcpy (pSec->Options, SECOptions, sizeof (SECOptions));
+    xf86ProcessOptions (pScrn->scrnIndex, pSec->pEnt->device->options,
+                        pSec->Options);
+
+    /* Check with the driver options */
+    _checkDriverOptions (pScrn);
+
+    /* use a fake root pixmap when rotation angle is 90 or 270 */
+    pSec->fake_root = ((pSec->rotate &(RR_Rotate_90|RR_Rotate_270)) != 0);
+
+    /* drm mode init:: Set the Crtc,  the default Output, and the current Mode */
+    if (!secModePreInit (pScrn, pSec->drm_fd))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR ,
+                    "fail to initialize drm mode setting\n");
+        goto bail1;
+    }
+
+    /* set gamma */
+    if (!xf86SetGamma (pScrn,defualt_gamma))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR ,
+                    "fail to set the gamma\n");
+        goto bail1;
+    }
+
+    pScrn->currentMode = pScrn->modes;
+    pScrn->displayWidth = pScrn->virtualX;
+    xf86PrintModes (pScrn); /* just print the current mode */
+
+    /* set dpi */
+    xf86SetDpi (pScrn, 0, 0);
+
+    /* Load modules */
+    if (!xf86LoadSubModule (pScrn, "fb"))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR ,
+                    "fail to load fb module\n");
+        goto bail1;
+    }
+
+    if (!xf86LoadSubModule (pScrn, "exa"))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR ,
+                    "fail to load exa module\n");
+        goto bail1;
+    }
+
+    if (!xf86LoadSubModule (pScrn, "dri2"))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR ,
+                    "fail to load dri2 module\n");
+        goto bail1;
+    }
+
+    old_sig_wrapper = OsRegisterSigWrapper(_secOsSigWrapper);
+    return TRUE;
+
+bail1:
+    _freeScrnPrivRec (pScrn);
+    _secHwDeinit (pScrn);
+    return FALSE;
+}
+
+
+
+
+static Bool
+SECScreenInit (ScreenPtr pScreen, int argc, char **argv)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+    VisualPtr visual;
+    int init_picture = 0;
+    SECFbPtr pFb = NULL;
+
+    xf86DrvMsg (pScrn->scrnIndex,X_INFO,
+                "Infomation of Visual is \n\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n"
+                "\tmask: %x,%x,%x, offset: %d,%d,%d\n",
+                pScrn->bitsPerPixel,
+                pScrn->depth,
+                xf86GetVisualName (pScrn->defaultVisual),
+                (unsigned int) pScrn->mask.red,
+                (unsigned int) pScrn->mask.green,
+                (unsigned int) pScrn->mask.blue,
+                (int) pScrn->offset.red,
+                (int) pScrn->offset.green,
+                (int) pScrn->offset.blue);
+
+    /* initialize the framebuffer */
+    /* soolim :: think rotations */
+
+    pFb = secFbAllocate (pScrn, pScrn->virtualX, pScrn->virtualY);
+    if  (!pFb)
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "cannot allocate framebuffer\n");
+        return FALSE;
+    }
+    pSec->pFb = pFb;
+
+    /* mi layer */
+    miClearVisualTypes();
+    if (!miSetVisualTypes (pScrn->depth, TrueColorMask, pScrn->rgbBits, TrueColor))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                    "visual type setup failed for %d bits per pixel [1]\n",
+                    pScrn->bitsPerPixel);
+        return FALSE;
+    }
+
+    if (!miSetPixmapDepths())
+    {
+        xf86DrvMsg (pScrn->scrnIndex,X_ERROR ,
+                    "pixmap depth setup failed\n");
+        return FALSE;
+    }
+
+    switch (pScrn->bitsPerPixel)
+    {
+    case 16:
+    case 24:
+    case 32:
+        if (! fbScreenInit (pScreen, (void*)ROOT_FB_ADDR,
+                            pScrn->virtualX, pScrn->virtualY,
+                            pScrn->xDpi, pScrn->yDpi,
+                            pScrn->virtualX, /*Pixel width for framebuffer*/
+                            pScrn->bitsPerPixel))
+            return FALSE;
+
+        init_picture = 1;
+
+        break;
+    default:
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                    "internal error: invalid number of bits per pixel (%d) encountered\n",
+                    pScrn->bitsPerPixel);
+        break;
+    }
+
+    if (pScrn->bitsPerPixel > 8)
+    {
+        /* Fixup RGB ordering */
+        visual = pScreen->visuals + pScreen->numVisuals;
+        while (--visual >= pScreen->visuals)
+        {
+            if ((visual->class | DynamicClass) == DirectColor)
+            {
+                visual->offsetRed   = pScrn->offset.red;
+                visual->offsetGreen = pScrn->offset.green;
+                visual->offsetBlue  = pScrn->offset.blue;
+                visual->redMask     = pScrn->mask.red;
+                visual->greenMask   = pScrn->mask.green;
+                visual->blueMask    = pScrn->mask.blue;
+            }
+        }
+    }
+
+    /* must be after RGB ordering fixed */
+    if (init_picture && !fbPictureInit (pScreen, NULL, 0))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
+                    "Render extension initialisation failed\n");
+    }
+
+    /* init the exa */
+    if (pSec->is_exa)
+    {
+        if (!secExaInit (pScreen))
+        {
+            xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
+                        "EXA initialization failed\n");
+        }
+        else
+        {
+            /* init the dri2 */
+            if (pSec->is_dri2)
+            {
+                if (!secDri2Init (pScreen))
+                {
+                    xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
+                                "DRI2 initialization failed\n");
+                }
+            }
+        }
+    }
+
+    /* XVideo Initiailization here */
+    if (!secVideoInit (pScreen))
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+                    "XVideo extention initialization failed\n");
+
+    xf86SetBlackWhitePixels (pScreen);
+    miInitializeBackingStore (pScreen);
+    xf86SetBackingStore (pScreen);
+
+    /* use dummy hw_cursro instead of sw_cursor */
+    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO
+                , "Initializing HW Cursor\n");
+
+    if (!xf86_cursors_init (pScreen, SEC_CURSOR_W, SEC_CURSOR_H,
+                            (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+                             HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
+                             HARDWARE_CURSOR_INVERT_MASK |
+                             HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
+                             HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+                             HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
+                             HARDWARE_CURSOR_ARGB)))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR
+                    , "Hardware cursor initialization failed\n");
+    }
+
+    /* crtc init */
+    if (!xf86CrtcScreenInit (pScreen))
+        return FALSE;
+
+    /* set the desire mode : set the mode to xf86crtc here */
+    xf86SetDesiredModes (pScrn);
+
+    /* colormap */
+    if (!miCreateDefColormap (pScreen))
+    {
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR
+                    , "internal error: miCreateDefColormap failed \n");
+        return FALSE;
+    }
+
+    if (!xf86HandleColormaps (pScreen, 256, 8, secModeLoadPalette, NULL,
+                              CMAP_PALETTED_TRUECOLOR))
+        return FALSE;
+
+    /* dpms */
+    xf86DPMSInit (pScreen, xf86DPMSSet, 0);
+
+    /* screen saver */
+    pScreen->SaveScreen = SECSaveScreen;
+
+    secModeInit(pScrn);
+
+    /* Wrap the current CloseScreen function */
+    pSec->CloseScreen = pScreen->CloseScreen;
+    pScreen->CloseScreen = SECCloseScreen;
+
+    /* Wrap the current CloseScreen function */
+    pSec->CreateScreenResources = pScreen->CreateScreenResources;
+    pScreen->CreateScreenResources = SECCreateScreenResources;
+
+#if HAVE_UDEV
+    _secUdevInit(pScrn);
+#endif
+
+#if 0
+    /* Init Hooks for memory flush */
+    secMemoryInstallHooks();
+#endif
+
+#if USE_XDBG
+    xDbgLogPListInit (pScreen);
+#endif
+
+    XDBG_KLOG(MSEC, "Init Screen\n");
+    return TRUE;
+}
+
+static Bool
+SECSwitchMode (ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+    return xf86SetSingleMode (pScrn, pMode, RR_Rotate_0);
+}
+
+static void
+SECAdjustFrame (ScrnInfoPtr pScrn, int x, int y)
+{
+}
+
+static Bool
+SECEnterVT (ScrnInfoPtr pScrn)
+{
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO
+                , "EnterVT::Hardware state at EnterVT:\n");
+
+    return TRUE;
+}
+
+static void
+SECLeaveVT (ScrnInfoPtr pScrn)
+{
+    xf86DrvMsg (pScrn->scrnIndex, X_INFO
+                , "LeaveVT::Hardware state at LeaveVT:\n");
+}
+
+static ModeStatus
+SECValidMode (ScrnInfoPtr pScrn, DisplayModePtr pMode, Bool verbose, int flags)
+{
+    return MODE_OK;
+}
+
+
+/**
+ * Adjust the screen pixmap for the current location of the front buffer.
+ * This is done at EnterVT when buffers are bound as long as the resources
+ * have already been created, but the first EnterVT happens before
+ * CreateScreenResources.
+ */
+static Bool
+SECCreateScreenResources (ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+
+    pScreen->CreateScreenResources = pSec->CreateScreenResources;
+    if (!(*pScreen->CreateScreenResources) (pScreen))
+        return FALSE;
+
+    /*
+     * [TODO]:::::
+     * create screen resources
+     * set the bo to the screen pixamp private here
+     * or create the shadow pixmap for the screen pixamp here
+     * or set the fake rotated screen infomation here.
+     */
+
+    return TRUE;
+}
+
+static Bool
+SECCloseScreen (ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = SECPTR (pScrn);
+
+    secWbDestroy ();
+
+#if HAVE_UDEV
+    _secUdevDeinit(pScrn);
+#endif
+
+    secVideoFini (pScreen);
+    secExaDeinit (pScreen);
+    secModeDeinit (pScrn);
+
+    if (pSec->pFb)
+    {
+        secFbFree (pSec->pFb);
+        pSec->pFb = NULL;
+    }
+
+    _secHwDeinit (pScrn);
+
+    pScrn->vtSema = FALSE;
+
+    pScreen->CreateScreenResources = pSec->CreateScreenResources;
+    pScreen->CloseScreen = pSec->CloseScreen;
+
+    XDBG_KLOG(MSEC, "Close Screen\n");
+    return (*pScreen->CloseScreen) (pScreen);
+}
+
+
+#define CONV_POINT_TO_KEY(x, y, key)   key = (unsigned long)((((unsigned short)(x&0xFFFF)) << 16) | ((unsigned short)(y&0xFFFF )))
+#define CONT_KEY_TO_POINT(key, x, y)   x = (unsigned short)((key&0xFFFF0000)>>16); y=(unsigned short)(key&0xFFFF)
+
+typedef struct{
+    tbm_bo bo;
+    struct xorg_list link;
+}SecFbBoItem, *SecFbBoItemPtr;
+
+static void
+_secFbFreeBoData(void* data)
+{
+    XDBG_RETURN_IF_FAIL(data != NULL);
+
+    ScrnInfoPtr pScrn;
+    SECPtr pSec;
+    SECFbBoDataPtr bo_data = (SECFbBoDataPtr)data;
+
+    pScrn = bo_data->pScrn;
+    pSec = SECPTR (pScrn);
+
+    XDBG_DEBUG (MFB, "FreeRender bo_data gem:%d, fb_id:%d, %dx%d+%d+%d\n",
+                bo_data->gem_handle, bo_data->fb_id,
+                bo_data->pos.x2-bo_data->pos.x1, bo_data->pos.y2-bo_data->pos.y1,
+                bo_data->pos.x1, bo_data->pos.y1);
+
+    if (bo_data->fb_id)
+    {
+        drmModeRmFB (pSec->drm_fd, bo_data->fb_id);
+        bo_data->fb_id = 0;
+    }
+
+    if (bo_data->pPixmap)
+    {
+        pScrn->pScreen->DestroyPixmap (bo_data->pPixmap);
+        bo_data->pPixmap = NULL;
+    }
+
+    free (bo_data);
+    bo_data = NULL;
+}
+
+
+static tbm_bo
+_secFbCreateBo (SECFbPtr pFb, int x, int y, int width, int height)
+{
+    XDBG_RETURN_VAL_IF_FAIL ((pFb != NULL), NULL);
+    XDBG_RETURN_VAL_IF_FAIL ((width > 0), NULL);
+    XDBG_RETURN_VAL_IF_FAIL ((height > 0), NULL);
+
+    SECPtr pSec = SECPTR (pFb->pScrn);
+
+    tbm_bo bo = NULL;
+    tbm_bo_handle bo_handle1, bo_handle2;
+    SECFbBoDataPtr bo_data=NULL;
+    unsigned int pitch;
+    unsigned int fb_id = 0;
+    int ret;
+    int flag;
+
+    pitch = width * 4;
+
+    if (!pSec->cachable)
+        flag = TBM_BO_WC;
+    else
+        flag = TBM_BO_DEFAULT;
+
+    bo = tbm_bo_alloc (pSec->tbm_bufmgr, pitch*height, flag);
+    XDBG_GOTO_IF_FAIL (bo != NULL, fail);
+
+    /* memset 0x0 */
+    bo_handle1 = tbm_bo_map (bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+    XDBG_RETURN_VAL_IF_FAIL (bo_handle1.ptr != NULL, NULL);
+
+    memset (bo_handle1.ptr, 0x0, pitch*height);
+    tbm_bo_unmap (bo);
+
+    bo_handle2 = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT);
+
+    /* Create drm fb */
+    ret = drmModeAddFB(pSec->drm_fd
+                       , width, height
+                       , pFb->pScrn->bitsPerPixel
+                       , pFb->pScrn->bitsPerPixel
+                       , pitch
+                       , bo_handle2.u32
+                       , &fb_id);
+    XDBG_GOTO_IF_ERRNO(ret == Success, fail, -ret);
+
+    if(x == -1) x = 0;
+    if(y == -1) y = 0;
+
+    /* Set bo user data */
+    bo_data = calloc(1, sizeof(SECFbBoDataRec));
+    bo_data->pFb = pFb;
+    bo_data->gem_handle = bo_handle2.u32;
+    bo_data->pitch = pitch;
+    bo_data->fb_id = fb_id;
+    bo_data->pos.x1 = x;
+    bo_data->pos.y1 = y;
+    bo_data->pos.x2 = x+width;
+    bo_data->pos.y2 = y+height;
+    bo_data->size = tbm_bo_size(bo);
+    bo_data->pScrn = pFb->pScrn;
+    XDBG_GOTO_IF_FAIL(tbm_bo_add_user_data(bo, TBM_BO_DATA_FB, _secFbFreeBoData), fail);
+    XDBG_GOTO_IF_FAIL(tbm_bo_set_user_data(bo, TBM_BO_DATA_FB, (void *)bo_data), fail);
+
+    XDBG_DEBUG (MFB, "CreateRender bo(name:%d, gem:%d, fb_id:%d, %dx%d+%d+%d\n",
+                tbm_bo_export (bo), bo_data->gem_handle, bo_data->fb_id,
+                bo_data->pos.x2-bo_data->pos.x1, bo_data->pos.y2-bo_data->pos.y1,
+                bo_data->pos.x1, bo_data->pos.y1);
+
+    return bo;
+fail:
+    if (bo)
+    {
+        secRenderBoUnref(bo);
+    }
+
+    if (fb_id)
+    {
+        drmModeRmFB(pSec->drm_fd, fb_id);
+    }
+
+    if (bo_data)
+    {
+        free (bo_data);
+        bo_data = NULL;
+    }
+
+    return NULL;
+}
+
+static tbm_bo
+_secFbRefBo (tbm_bo bo)
+{
+    return tbm_bo_ref(bo);
+}
+
+static int
+_secFbUnrefBo(tbm_bo bo)
+{
+    tbm_bo_unref(bo);
+    bo = NULL;
+
+    return TRUE;
+}
+
+SECFbPtr
+secFbAllocate (ScrnInfoPtr pScrn, int width, int height)
+{
+    //secLogSetLevel(MFB, 0);
+
+    XDBG_RETURN_VAL_IF_FAIL((pScrn != NULL), NULL);
+    XDBG_RETURN_VAL_IF_FAIL((width > 0), NULL);
+    XDBG_RETURN_VAL_IF_FAIL((height > 0), NULL);
+
+    SECFbPtr  pFb = calloc (1, sizeof(SECFbRec));
+    XDBG_GOTO_IF_FAIL ((pFb != NULL), fail);
+
+    pFb->pScrn = pScrn;
+    pFb->num_bo = 0;
+    pFb->width = width;
+    pFb->height = height;
+
+    xorg_list_init(&pFb->list_bo);
+
+    /* Create default buffer */
+    pFb->default_bo = _secFbCreateBo(pFb, 0, 0, width, height);
+
+    XDBG_TRACE (MFB,"Allocate %dx%d\n", width, height);
+
+    return pFb;
+
+fail:
+
+    return NULL;
+}
+
+void
+secFbFree (SECFbPtr pFb)
+{
+    XDBG_RETURN_IF_FAIL(pFb != NULL);
+
+    XDBG_TRACE (MFB,"Free %dx%d, num:%d\n", pFb->width, pFb->height, pFb->num_bo);
+
+    if (!xorg_list_is_empty(&pFb->list_bo))
+    {
+        SecFbBoItemPtr item = NULL, tmp = NULL;
+
+        xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link)
+        {
+            xorg_list_del(&item->link);
+            _secFbUnrefBo(item->bo);
+            free(item);
+            item=NULL;
+        }
+    }
+
+    if (pFb->default_bo)
+    {
+        secRenderBoUnref(pFb->default_bo);
+        pFb->default_bo = NULL;
+    }
+
+    free (pFb);
+    pFb = NULL;
+}
+
+tbm_bo
+secFbGetBo (SECFbPtr pFb, int x, int y, int width, int height, Bool onlyIfExists)
+{
+    SECFbBoDataPtr bo_data=NULL;
+    tbm_bo bo = NULL;
+    _X_UNUSED unsigned long key;
+    BoxRec box;
+    BoxPtr b1, b2;
+    int ret = rgnOUT;
+
+    box.x1 = x;
+    box.y1 = y;
+    box.x2 = x+width;
+    box.y2 = y+height;
+    b2 = &box;
+
+    if(!xorg_list_is_empty(&pFb->list_bo))
+    {
+        SecFbBoItemPtr item = NULL, tmp = NULL;
+        xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link)
+        {
+            bo = item->bo;
+
+            tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data);
+            b1 = &bo_data->pos;
+
+            ret = secUtilBoxInBox(b1, b2);
+
+            if(ret == rgnIN || ret == rgnSAME)
+            {
+                return bo;
+            }
+            else if(ret == rgnPART)
+            {
+                if (!onlyIfExists) continue;
+
+                int r2 = secUtilBoxInBox(b2, b1);
+                if(r2 == rgnIN)
+                {
+                    xorg_list_del(&item->link);
+                    _secFbUnrefBo(bo);
+                    free(item);
+                    item=NULL;
+                    pFb->num_bo--;
+                    ret = rgnOUT;
+                    break;
+                }
+            }
+            else if(ret == rgnOUT)
+            {
+                continue;
+            }
+            else
+            {
+                return NULL;
+            }
+        }
+    }
+
+    if (ret == rgnOUT && !onlyIfExists)
+    {
+        SecFbBoItemPtr item;
+        CONV_POINT_TO_KEY(x, y, key);
+
+        item = calloc(1, sizeof(SecFbBoItem));
+        if(width == pFb->width &&
+           height == pFb->height &&
+           x == 0 &&
+           y == 0)
+        {
+            bo = _secFbRefBo(pFb->default_bo);
+        }
+        else
+        {
+            bo = _secFbCreateBo(pFb, x, y, width, height);
+            if (!bo)
+            {
+                free (item);
+                item = NULL;
+                return NULL;
+            }
+        }
+
+        item->bo = bo;
+        xorg_list_add(&item->link, &pFb->list_bo);
+        pFb->num_bo++;
+
+        XDBG_TRACE (MFB, "GetBO num:%d bo:%p name:%d, %dx%d+%d+%d\n",
+                    pFb->num_bo, bo, tbm_bo_export (bo), width, height, x,y);
+        return bo;
+    }
+
+    return NULL;
+}
+
+tbm_bo
+secFbSwapBo (SECFbPtr pFb, tbm_bo back_bo)
+{
+    SECFbBoDataPtr back_bo_data = NULL;
+    SECFbBoDataPtr bo_data = NULL;
+    SECFbBoDataRec tmp_bo_data;
+    tbm_bo bo;
+    BoxPtr b1, b2;
+    SecFbBoItemPtr item = NULL, tmp = NULL;
+
+    XDBG_RETURN_VAL_IF_FAIL(pFb != NULL, NULL);
+    XDBG_RETURN_VAL_IF_FAIL(FALSE == xorg_list_is_empty(&pFb->list_bo), NULL);
+    XDBG_RETURN_VAL_IF_FAIL(tbm_bo_get_user_data(back_bo, TBM_BO_DATA_FB, (void * *)&back_bo_data), NULL);
+    XDBG_RETURN_VAL_IF_FAIL(back_bo_data, NULL);
+
+    b2 = &back_bo_data->pos;
+
+    xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link)
+    {
+        bo = item->bo;
+
+        tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data);
+        b1 = &bo_data->pos;
+        if(rgnSAME == secUtilBoxInBox(b1, b2))
+        {
+            XDBG_DEBUG(MFB, "SwapBO(Back:%d, Front:%d)\n",
+                       tbm_bo_export (back_bo), tbm_bo_export (bo));
+
+            if(tbm_bo_swap(bo, back_bo))
+            {
+                memcpy(&tmp_bo_data, bo_data, sizeof(SECFbBoDataRec));
+                memcpy(bo_data, back_bo_data, sizeof(SECFbBoDataRec));
+                memcpy(back_bo_data, &tmp_bo_data, sizeof(SECFbBoDataRec));
+            }
+            else
+                return NULL;
+
+            return bo;
+        }
+    }
+
+    return NULL;
+}
+
+void
+secFbResize (SECFbPtr pFb, int width, int height)
+{
+    XDBG_RETURN_IF_FAIL(pFb != NULL);
+
+    SECFbBoDataPtr bo_data=NULL;
+    tbm_bo bo, old_bo;
+    int ret;
+    BoxRec box;
+    BoxPtr b1, b2;
+
+    if (pFb->width == width && pFb->height == height)
+        return;
+
+    old_bo = pFb->default_bo;
+
+    pFb->width = width;
+    pFb->height = height;
+    XDBG_TRACE (MFB,"Resize %dx%d, num:%d\n", pFb->width, pFb->height, pFb->num_bo);
+
+    box.x1=0;
+    box.y1=0;
+    box.x2=width;
+    box.y2=height;
+    b1 = &box;
+
+    if (!xorg_list_is_empty (&pFb->list_bo))
+    {
+        SecFbBoItemPtr item = NULL, tmp = NULL;
+
+        xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link)
+        {
+            bo = item->bo;
+
+            tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data);
+            b2 = &bo_data->pos;
+            ret = secUtilBoxInBox(b1, b2);
+
+            if(ret == rgnIN || ret ==rgnSAME)
+                continue;
+
+            /* Remove bo */
+            XDBG_DEBUG (MFB, "\t unref bo(name:%d, gem:%d, fb_id:%d, %dx%d+%d+%d\n",
+                        tbm_bo_export (bo), bo_data->gem_handle, bo_data->fb_id,
+                        bo_data->pos.x2-bo_data->pos.x1, bo_data->pos.y2-bo_data->pos.y1,
+                        bo_data->pos.x1, bo_data->pos.y1);
+
+            xorg_list_del(&item->link);
+            secRenderBoUnref(bo);
+            pFb->num_bo--;
+            free(item);
+            item=NULL;
+        }
+    }
+
+    pFb->default_bo = _secFbCreateBo(pFb, 0, 0, width, height);
+    if(old_bo)
+        secRenderBoUnref(old_bo);
+}
+
+int
+secFbFindBo (SECFbPtr pFb, int x, int y, int width, int height, int *num_bo, tbm_bo** bos)
+{
+    SECFbBoDataPtr bo_data=NULL;
+    int num=0;
+    tbm_bo *l=NULL;
+    tbm_bo bo;
+    int ret = rgnOUT;
+    BoxRec box;
+    BoxPtr b1, b2;
+    SecFbBoItemPtr item = NULL, tmp = NULL;
+
+    if(xorg_list_is_empty(&pFb->list_bo))
+    {
+        return rgnOUT;
+    }
+
+    box.x1=x;
+    box.y1=y;
+    box.x2=x+width;
+    box.y2=y+height;
+    b2 = &box;
+
+    l = calloc(pFb->num_bo, sizeof(tbm_bo));
+
+    xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link)
+    {
+        bo = item->bo;
+
+        tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data);
+        if (bo_data == NULL)
+        {
+            free (l);
+            return rgnOUT;
+        }
+
+        b1 = &bo_data->pos;
+        ret = secUtilBoxInBox(b1, b2);
+        XDBG_DEBUG(MFB, "[%d/%d] ret:%d bo(%d,%d,%d,%d) fb(%d,%d,%d,%d)\n",
+                   num+1, pFb->num_bo, ret,
+                   b1->x1,b1->y1,b1->x2,b1->y2,
+                   b2->x1,b2->y1,b2->x2,b2->y2);
+
+        if(ret == rgnSAME || ret == rgnIN)
+        {
+            l[num++] = bo;
+            break;
+        }
+        else if(ret == rgnPART)
+        {
+            l[num++] = bo;
+        }
+        else
+        {
+            ;
+        }
+    }
+
+    if(num_bo) *num_bo = num;
+    if(bos)
+    {
+        *bos = l;
+    }
+    else
+    {
+        free(l);
+    }
+
+    return ret;
+}
+
+tbm_bo
+secFbFindBoByPoint (SECFbPtr pFb, int x, int y)
+{
+    SECFbBoDataPtr bo_data=NULL;
+    tbm_bo bo;
+    SecFbBoItemPtr item = NULL, tmp = NULL;
+
+    if(xorg_list_is_empty(&pFb->list_bo))
+    {
+        return NULL;
+    }
+
+    xorg_list_for_each_entry_safe(item, tmp, &pFb->list_bo, link)
+    {
+        bo = item->bo;
+        tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void * *)&bo_data);
+        if ((x >= bo_data->pos.x1) &&
+            (x < bo_data->pos.x2) &&
+            (y >= bo_data->pos.y1) &&
+            (y < bo_data->pos.y2))
+        {
+            return bo;
+        }
+    }
+
+    return NULL;
+}
+
+PixmapPtr
+secRenderBoGetPixmap (SECFbPtr pFb, tbm_bo bo)
+{
+    ScreenPtr pScreen = pFb->pScrn->pScreen;
+    PixmapPtr pPixmap;
+    SECFbBoDataPtr bo_data;
+    int ret;
+
+    XDBG_RETURN_VAL_IF_FAIL(bo != NULL, NULL);
+    XDBG_RETURN_VAL_IF_FAIL(tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void**)&bo_data), NULL);
+
+    if(bo_data->pPixmap == NULL)
+    {
+        pPixmap = pScreen->CreatePixmap(pFb->pScrn->pScreen, 0,0,
+                                        pFb->pScrn->depth,
+                                        CREATE_PIXMAP_USAGE_SUB_FB);
+        XDBG_GOTO_IF_FAIL(pPixmap != NULL, fail);
+
+        ret = pScreen->ModifyPixmapHeader(pPixmap,
+                                          bo_data->pos.x2 - bo_data->pos.x1,
+                                          bo_data->pos.y2 - bo_data->pos.y1,
+                                          pFb->pScrn->depth,
+                                          pFb->pScrn->bitsPerPixel,
+                                          bo_data->pitch, (void*)bo);
+        XDBG_GOTO_IF_FAIL(ret != FALSE, fail);
+        bo_data->pPixmap = pPixmap;
+        XDBG_DEBUG(MFB, "CreateRenderPixmap:%p\n", pPixmap);
+    }
+
+    return bo_data->pPixmap;
+
+fail:
+    XDBG_ERROR(MFB, "ERR: CreateRenderPixmap\n");
+    if(pPixmap)
+    {
+        pScreen->DestroyPixmap(pPixmap);
+    }
+    return NULL;
+}
+
+tbm_bo
+secRenderBoCreate (ScrnInfoPtr pScrn, int width, int height)
+{
+    SECPtr pSec = SECPTR (pScrn);
+
+    return _secFbCreateBo(pSec->pFb, -1, -1, width, height);
+}
+
+tbm_bo
+secRenderBoRef (tbm_bo bo)
+{
+       return _secFbRefBo (bo);
+}
+
+void
+secRenderBoUnref (tbm_bo bo)
+{
+    _secFbUnrefBo(bo);
+}
+
+void
+secRenderBoSetPos (tbm_bo bo, int x, int y)
+{
+    SECFbBoDataPtr bo_data;
+    int width, height;
+
+    XDBG_RETURN_IF_FAIL(bo != NULL);
+    XDBG_RETURN_IF_FAIL(x >= 0);
+    XDBG_RETURN_IF_FAIL(y >= 0);
+    XDBG_RETURN_IF_FAIL(tbm_bo_get_user_data(bo, TBM_BO_DATA_FB, (void**)&bo_data));
+
+    width = bo_data->pos.x2 - bo_data->pos.x1;
+    height = bo_data->pos.y2 - bo_data->pos.y1;
+
+    bo_data->pos.x1 = x;
+    bo_data->pos.y1 = y;
+    bo_data->pos.x2 = x+width;
+    bo_data->pos.y2 = y+height;
+}
diff --git a/src/sec.h b/src/sec.h
new file mode 100644 (file)
index 0000000..de04a1b
--- /dev/null
+++ b/src/sec.h
@@ -0,0 +1,230 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef SEC_H
+#define SEC_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include "xorg-server.h"
+#include "xf86.h"
+#include "xf86xv.h"
+#include "xf86_OSproc.h"
+#include "xf86drm.h"
+#include "X11/Xatom.h"
+#include "tbm_bufmgr.h"
+#include "sec_display.h"
+#include "sec_accel.h"
+#include "sec_video.h"
+#include "sec_wb.h"
+#include "sec_util.h"
+#if HAVE_UDEV
+#include <libudev.h>
+#endif
+
+#define USE_XDBG 1
+
+/* drm bo data type */
+typedef enum
+{
+    TBM_BO_DATA_FB = 1,
+} TBM_BO_DATA;
+
+/* framebuffer infomation */
+typedef struct
+{
+    ScrnInfoPtr pScrn;
+
+    int width;
+    int height;
+
+    int num_bo;
+    struct xorg_list list_bo;
+    void* tbl_bo;              /* bo hash table: key=(x,y)position */
+
+    tbm_bo default_bo;
+} SECFbRec, *SECFbPtr;
+
+/* framebuffer bo data */
+typedef struct
+{
+    SECFbPtr pFb;
+    BoxRec pos;
+    uint32_t gem_handle;
+    int fb_id;
+    int pitch;
+    int size;
+    PixmapPtr   pPixmap;
+    ScrnInfoPtr pScrn;
+} SECFbBoDataRec, *SECFbBoDataPtr;
+
+/* sec screen private information */
+typedef struct
+{
+    EntityInfoPtr pEnt;
+    Bool fake_root; /* screen rotation status */
+
+    /* driver options */
+    OptionInfoPtr Options;
+    Bool is_exa;
+    Bool is_dri2;
+    Bool is_sw_exa;
+    Bool is_accel_2d;
+    Bool is_wb_clone;
+    Bool is_tfb;        /* triple flip buffer */
+    Bool cachable;      /* if use cachable buffer */
+    Bool scanout;       /* if use scanout buffer */
+    int flip_bufs;      /* number of the flip buffers */
+    Rotation rotate;
+    Bool use_partial_update;
+    Bool is_fb_touched; /* whether framebuffer is touched or not */
+
+    /* drm */
+    int drm_fd;
+    char *drm_device_name;
+    tbm_bufmgr tbm_bufmgr;
+
+    /* main fb information */
+    SECFbPtr pFb;
+
+    /* mode setting info private */
+    SECModePtr pSecMode;
+
+    /* exa private */
+    SECExaPrivPtr pExaPriv;
+
+    /* video private */
+    SECVideoPrivPtr pVideoPriv;
+
+    Bool isLcdOff; /* lvds connector on/off status */
+
+    /* screen wrapper functions */
+    CloseScreenProcPtr CloseScreen;
+    CreateScreenResourcesProcPtr CreateScreenResources;
+
+#if HAVE_UDEV
+    struct udev_monitor *uevent_monitor;
+    InputHandlerProc uevent_handler;
+#endif
+
+    /* DRI2 */
+    Atom atom_use_dri2;
+    Bool useAsyncSwap;
+    DrawablePtr flipDrawable;
+
+    /* pending flip handler cause of lcd off */
+    Bool pending_flip_handler;
+    unsigned int frame;
+    unsigned int tv_sec;
+    unsigned int tv_usec;
+    void *event_data;
+
+    /* overlay drawable */
+    DamagePtr ovl_damage;
+    DrawablePtr ovl_drawable;
+
+    SECDisplaySetMode set_mode;
+    OsTimerPtr resume_timer;
+
+    SECWb *wb_clone;
+    Bool   wb_fps;
+    int    wb_hz;
+
+    /* Cursor */
+    Bool enableCursor;
+
+    /* dump */
+    int dump_mode;
+    long dump_xid;
+    void *dump_info;
+    char *dump_str;
+    char dump_type[16];
+    int   xvperf_mode;
+    char *xvperf;
+
+    int scale;
+    int cpu;
+    int flip_cnt;
+
+    /* mem debug
+       Normal pixmap
+       CREATE_PIXMAP_USAGE_BACKING_PIXMAP
+       CREATE_PIXMAP_USAGE_OVERLAY
+       CREATE_PIXMAP_USAGE_XVIDEO
+       CREATE_PIXMAP_USAGE_DRI2_FILP_BACK
+       CREATE_PIXMAP_USAGE_FB
+       CREATE_PIXMAP_USAGE_SUB_FB
+       CREATE_PIXMAP_USAGE_DRI2_BACK
+     */
+    int pix_normal;
+    int pix_backing_pixmap;
+    int pix_overlay;
+    int pix_dri2_flip_back;
+    int pix_fb;
+    int pix_sub_fb;
+    int pix_dri2_back;
+} SECRec, *SECPtr;
+
+/* get a private screen of ScrnInfo */
+#define SECPTR(p) ((SECPtr)((p)->driverPrivate))
+
+/* the version of the driver */
+#define SEC_VERSION 1000
+
+/* the name used to prefix messages */
+#define SEC_NAME "exynos"
+
+/* the driver name used in display.conf file. exynos_drv.so */
+#define SEC_DRIVER_NAME "exynos"
+
+#define ROOT_FB_ADDR (~0UL)
+
+#define SEC_CURSOR_W 64
+#define SEC_CURSOR_H 64
+
+/* sec framebuffer */
+SECFbPtr      secFbAllocate      (ScrnInfoPtr pScrn, int width, int height);
+void          secFbFree          (SECFbPtr pFb);
+void          secFbResize        (SECFbPtr pFb, int width, int height);
+tbm_bo    secFbGetBo         (SECFbPtr pFb, int x, int y, int width, int height, Bool onlyIfExists);
+int           secFbFindBo        (SECFbPtr pFb, int x, int y, int width, int height, int *num_bo, tbm_bo** bos);
+tbm_bo    secFbFindBoByPoint (SECFbPtr pFb, int x, int y);
+tbm_bo    secFbSwapBo        (SECFbPtr pFb, tbm_bo back_bo);
+
+tbm_bo    secRenderBoCreate    (ScrnInfoPtr pScrn, int width, int height);
+tbm_bo    secRenderBoRef       (tbm_bo bo);
+void          secRenderBoUnref     (tbm_bo bo);
+void          secRenderBoSetPos    (tbm_bo bo, int x, int y);
+PixmapPtr     secRenderBoGetPixmap (SECFbPtr pFb, tbm_bo bo);
+
+#endif /* SEC_H */
diff --git a/src/util/sec_util.c b/src/util/sec_util.c
new file mode 100644 (file)
index 0000000..f8045fe
--- /dev/null
@@ -0,0 +1,2342 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <sys/ipc.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <X11/XWDFile.h>
+
+#include "sec.h"
+#include "sec_util.h"
+#include "sec_output.h"
+#include "sec_video_fourcc.h"
+#include <exynos_drm.h>
+#include <list.h>
+
+#include "fimg2d.h"
+
+#define DUMP_SCALE_RATIO  2
+
+int secUtilDumpBmp (const char * file, const void * data, int width, int height)
+{
+    int i;
+
+    struct
+    {
+        unsigned char magic[2];
+    } bmpfile_magic = { {'B', 'M'} };
+
+    struct
+    {
+        unsigned int filesz;
+        unsigned short creator1;
+        unsigned short creator2;
+        unsigned int bmp_offset;
+    } bmpfile_header = { 0, 0, 0, 0x36 };
+
+    struct
+    {
+        unsigned int header_sz;
+        unsigned int width;
+        unsigned int height;
+        unsigned short nplanes;
+        unsigned short bitspp;
+        unsigned int compress_type;
+        unsigned int bmp_bytesz;
+        unsigned int hres;
+        unsigned int vres;
+        unsigned int ncolors;
+        unsigned int nimpcolors;
+    } bmp_dib_v3_header_t = { 0x28, 0, 0, 1, 24, 0, 0, 0, 0, 0, 0 };
+    unsigned int * blocks;
+
+    XDBG_RETURN_VAL_IF_FAIL (data != NULL, UTIL_DUMP_ERR_INTERNAL);
+    XDBG_RETURN_VAL_IF_FAIL (width > 0, UTIL_DUMP_ERR_INTERNAL);
+    XDBG_RETURN_VAL_IF_FAIL (height > 0, UTIL_DUMP_ERR_INTERNAL);
+
+    XDBG_TRACE (MSEC, "%s : width(%d) height(%d)\n",
+                __FUNCTION__, width, height);
+
+    FILE * fp = fopen (file, "w+");
+    if (fp == NULL)
+    {
+        return UTIL_DUMP_ERR_OPENFILE;
+    }
+    else
+    {
+        bmpfile_header.filesz = sizeof (bmpfile_magic) + sizeof (bmpfile_header) +
+                                sizeof (bmp_dib_v3_header_t) + width * height * 3;
+        bmp_dib_v3_header_t.header_sz = sizeof (bmp_dib_v3_header_t);
+        bmp_dib_v3_header_t.width = width;
+        bmp_dib_v3_header_t.height = -height;
+        bmp_dib_v3_header_t.nplanes = 1;
+        bmp_dib_v3_header_t.bmp_bytesz = width * height * 3;
+
+        fwrite (&bmpfile_magic, sizeof (bmpfile_magic), 1, fp);
+        fwrite (&bmpfile_header, sizeof (bmpfile_header), 1, fp);
+        fwrite (&bmp_dib_v3_header_t, sizeof (bmp_dib_v3_header_t), 1, fp);
+
+        blocks = (unsigned int*)data;
+        for (i=0; i<height * width; i++)
+            fwrite (&blocks[i], 3, 1, fp);
+
+        fclose (fp);
+    }
+
+    return UTIL_DUMP_OK;
+}
+
+int secUtilDumpShm (int shmid, const void * data, int width, int height)
+{
+    char * addr;
+    struct shmid_ds ds;
+
+    addr = shmat (shmid, 0, 0);
+    if (addr == (void*)-1)
+    {
+        return UTIL_DUMP_ERR_SHMATTACH;
+    }
+
+    if ((shmctl (shmid, IPC_STAT, &ds) < 0) || (ds.shm_segsz < width*height*4))
+    {
+        shmctl (shmid, IPC_RMID, NULL);
+        shmdt (addr);
+
+        return UTIL_DUMP_ERR_SEGSIZE;
+    }
+
+    memcpy (addr, data, width*height*4);
+
+    shmctl (shmid, IPC_RMID, NULL);
+    shmdt (addr);
+
+    return UTIL_DUMP_OK;
+}
+
+int secUtilDumpRaw (const char * file, const void * data, int size)
+{
+//     int i;
+    unsigned int * blocks;
+
+    FILE * fp = fopen (file, "w+");
+    if (fp == NULL)
+    {
+        return UTIL_DUMP_ERR_OPENFILE;
+    }
+    else
+    {
+        blocks = (unsigned int*)data;
+        fwrite (blocks, 1, size, fp);
+
+        fclose (fp);
+    }
+
+    return UTIL_DUMP_OK;
+}
+
+int
+secUtilDumpPixmap (const char * file, PixmapPtr pPixmap)
+{
+    SECPixmapPriv *privPixmap;
+    Bool need_finish = FALSE;
+    int ret;
+
+    XDBG_RETURN_VAL_IF_FAIL (pPixmap != NULL, UTIL_DUMP_ERR_INTERNAL);
+    XDBG_RETURN_VAL_IF_FAIL (file != NULL, UTIL_DUMP_ERR_INTERNAL);
+
+    privPixmap = exaGetPixmapDriverPrivate (pPixmap);
+
+    if (!privPixmap->bo)
+    {
+        need_finish = TRUE;
+        secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
+        XDBG_RETURN_VAL_IF_FAIL (privPixmap->bo != NULL, UTIL_DUMP_ERR_INTERNAL);
+    }
+
+    ret = secUtilDumpBmp (file, tbm_bo_get_handle (privPixmap->bo, TBM_DEVICE_CPU).ptr,
+                          pPixmap->devKind/(pPixmap->drawable.bitsPerPixel >> 3),
+                          pPixmap->drawable.height);
+
+    if (need_finish)
+        secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
+
+    return ret;
+}
+
+typedef struct _DumpBufInfo
+{
+    int    index;
+
+    tbm_bo bo;
+    int    bo_size;
+
+    char   file[128];
+    Bool   dirty;
+    Bool   dump_bmp;
+
+    int    width;
+    int    height;
+    xRectangle rect;
+    int    size;
+
+    struct xorg_list link;
+} DumpBufInfo;
+
+typedef struct _DumpInfo
+{
+    ScrnInfoPtr pScrn;
+
+    struct xorg_list *cursor;
+    struct xorg_list  bufs;
+} DumpInfo;
+
+static Bool
+_calculateSize (int width, int height, xRectangle *crop)
+{
+    if (crop->x < 0)
+    {
+        crop->width += (crop->x);
+        crop->x = 0;
+    }
+    if (crop->y < 0)
+    {
+        crop->height += (crop->y);
+        crop->y = 0;
+    }
+
+    XDBG_GOTO_IF_FAIL (width > 0 && height > 0, fail_cal);
+    XDBG_GOTO_IF_FAIL (crop->width > 0 && crop->height > 0, fail_cal);
+    XDBG_GOTO_IF_FAIL (crop->x >= 0 && crop->x < width, fail_cal);
+    XDBG_GOTO_IF_FAIL (crop->y >= 0 && crop->y < height, fail_cal);
+
+    if (crop->x + crop->width > width)
+        crop->width = width - crop->x;
+
+    if (crop->y + crop->height > height)
+        crop->height = height - crop->y;
+
+    return TRUE;
+fail_cal:
+    XDBG_ERROR (MSEC, "(%dx%d : %d,%d %dx%d)\n",
+                width, height, crop->x, crop->y, crop->width, crop->height);
+
+    return FALSE;
+}
+
+static void
+_secUtilConvertBosG2D (tbm_bo src_bo, int sw, int sh, xRectangle *sr, int sstride,
+                       tbm_bo dst_bo, int dw, int dh, xRectangle *dr, int dstride,
+                       Bool composite, int rotate)
+{
+    G2dImage *srcImg = NULL, *dstImg = NULL;
+    tbm_bo_handle src_bo_handle = {0,};
+    tbm_bo_handle dst_bo_handle = {0,};
+    G2dColorKeyMode mode;
+    G2dOp op;
+
+    mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+    src_bo_handle = tbm_bo_map (src_bo, TBM_DEVICE_2D, TBM_OPTION_READ);
+    XDBG_GOTO_IF_FAIL (src_bo_handle.s32 > 0, access_done);
+
+    dst_bo_handle = tbm_bo_map (dst_bo, TBM_DEVICE_2D, TBM_OPTION_WRITE);
+    XDBG_GOTO_IF_FAIL (dst_bo_handle.s32 > 0, access_done);
+
+    srcImg = g2d_image_create_bo (mode, sw, sh, src_bo_handle.s32, sstride);
+    XDBG_GOTO_IF_FAIL (srcImg != NULL, access_done);
+
+    dstImg = g2d_image_create_bo (mode, dw, dh, dst_bo_handle.s32, dstride);
+    XDBG_GOTO_IF_FAIL (dstImg != NULL, access_done);
+
+    if (!composite)
+        op = G2D_OP_SRC;
+    else
+        op = G2D_OP_OVER;
+
+    if (rotate == 270)
+        srcImg->rotate_90 = 1;
+    else if (rotate == 180)
+    {
+        srcImg->xDir = 1;
+        srcImg->yDir = 1;
+    }
+    else if (rotate == 90)
+    {
+        srcImg->rotate_90 = 1;
+        srcImg->xDir = 1;
+        srcImg->yDir = 1;
+    }
+
+    util_g2d_blend_with_scale (op, srcImg, dstImg,
+                               (int)sr->x, (int)sr->y, sr->width, sr->height,
+                               (int)dr->x, (int)dr->y, dr->width, dr->height,
+                               FALSE);
+    g2d_exec ();
+
+access_done:
+    if (src_bo_handle.s32)
+        tbm_bo_unmap (src_bo);
+    if (dst_bo_handle.s32)
+        tbm_bo_unmap (dst_bo);
+    if (srcImg)
+        g2d_image_free (srcImg);
+    if (dstImg)
+        g2d_image_free (dstImg);
+}
+
+static void
+_secUtilConvertBosPIXMAN (tbm_bo src_bo, int sw, int sh, xRectangle *sr, int sstride,
+                          tbm_bo dst_bo, int dw, int dh, xRectangle *dr, int dstride,
+                          Bool composite, int rotate)
+{
+    tbm_bo_handle src_bo_handle = {0,};
+    tbm_bo_handle dst_bo_handle = {0,};
+    pixman_op_t op;
+
+    src_bo_handle = tbm_bo_map (src_bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
+    XDBG_GOTO_IF_FAIL (src_bo_handle.ptr != NULL, access_done);
+
+    dst_bo_handle = tbm_bo_map (dst_bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+    XDBG_GOTO_IF_FAIL (dst_bo_handle.ptr != NULL, access_done);
+
+    if (!composite)
+        op = PIXMAN_OP_SRC;
+    else
+        op = PIXMAN_OP_OVER;
+
+    secUtilConvertImage (op, src_bo_handle.ptr, dst_bo_handle.ptr,
+                         PIXMAN_a8r8g8b8, PIXMAN_a8r8g8b8,
+                         sw, sh, sr,
+                         dw, dh, dr,
+                         NULL,
+                         rotate, FALSE, FALSE);
+
+access_done:
+    if (src_bo_handle.ptr)
+        tbm_bo_unmap (src_bo);
+    if (dst_bo_handle.ptr)
+        tbm_bo_unmap (dst_bo);
+}
+
+/* support only RGB  */
+void
+secUtilConvertBos (ScrnInfoPtr pScrn,
+                   tbm_bo src_bo, int sw, int sh, xRectangle *sr, int sstride,
+                   tbm_bo dst_bo, int dw, int dh, xRectangle *dr, int dstride,
+                   Bool composite, int rotate)
+{
+    SECPtr pSec = SECPTR (pScrn);
+
+    XDBG_RETURN_IF_FAIL (pScrn != NULL);
+    XDBG_RETURN_IF_FAIL (src_bo != NULL);
+    XDBG_RETURN_IF_FAIL (dst_bo != NULL);
+    XDBG_RETURN_IF_FAIL (sr != NULL);
+    XDBG_RETURN_IF_FAIL (dr != NULL);
+
+    pSec = SECPTR (pScrn);
+    XDBG_RETURN_IF_FAIL (pSec != NULL);
+
+    if (!_calculateSize (sw, sh, sr))
+        return;
+    if (!_calculateSize (dw, dh, dr))
+        return;
+
+    if (rotate < 0)
+        rotate += 360;
+
+    XDBG_DEBUG (MVA, "[%dx%d (%d,%d %dx%d) %d] => [%dx%d (%d,%d %dx%d) %d] comp(%d) rot(%d) G2D(%d)\n",
+                sw, sh, sr->x, sr->y, sr->width, sr->height, sstride,
+                dw, dh, dr->x, dr->y, dr->width, dr->height, dstride,
+                composite, rotate, pSec->is_accel_2d);
+
+    if (pSec->is_accel_2d)
+        _secUtilConvertBosG2D (src_bo, sw, sh, sr, sstride,
+                               dst_bo, dw, dh, dr, dstride,
+                               composite, rotate);
+    else
+    {
+        _secUtilConvertBosPIXMAN (src_bo, sw, sh, sr, sstride,
+                                  dst_bo, dw, dh, dr, dstride,
+                                  composite, rotate);
+        tbm_bo_map(src_bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+        tbm_bo_unmap(src_bo);
+    }
+}
+
+void*
+secUtilPrepareDump (ScrnInfoPtr pScrn, int bo_size, int buf_cnt)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    DumpInfo *dump;
+    int i;
+
+    dump = calloc (1, sizeof (DumpInfo));
+    XDBG_RETURN_VAL_IF_FAIL (dump != NULL, NULL);
+
+    bo_size = bo_size / DUMP_SCALE_RATIO;
+
+    dump->pScrn = pScrn;
+
+    xorg_list_init (&dump->bufs);
+
+    for (i = 0; i < buf_cnt; i++)
+    {
+        tbm_bo bo = tbm_bo_alloc (pSec->tbm_bufmgr, bo_size, TBM_BO_DEFAULT);
+        XDBG_GOTO_IF_FAIL (bo != NULL, fail_prepare);
+
+        DumpBufInfo *buf_info = calloc (1, sizeof (DumpBufInfo));
+        if (!buf_info)
+        {
+            tbm_bo_unref (bo);
+            XDBG_WARNING_IF_FAIL (buf_info != NULL);
+            goto fail_prepare;
+        }
+
+        buf_info->index = i;
+        buf_info->bo = bo;
+        buf_info->bo_size = bo_size;
+
+        tbm_bo_handle handle = tbm_bo_map (bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+        memset (handle.ptr, 0x00, buf_info->bo_size);
+        tbm_bo_unmap (bo);
+
+        xorg_list_add (&buf_info->link, &dump->bufs);
+    }
+
+    dump->cursor = &dump->bufs;
+
+    return (void*)dump;
+
+fail_prepare:
+    secUtilFinishDump (dump);
+    return NULL;
+}
+
+void
+secUtilDoDumpRaws (void *d, tbm_bo *bo, int *size, int bo_cnt, const char *file)
+{
+    DumpInfo *dump = (DumpInfo*)d;
+    DumpBufInfo *next = NULL;
+    struct xorg_list *next_cursor;
+    void *src_ptr, *dst_ptr;
+    int i, remain_size, need_size;
+
+    if (!dump || !bo)
+        return;
+
+    CARD32 prev = GetTimeInMillis ();
+
+    next_cursor = dump->cursor->next;
+    XDBG_RETURN_IF_FAIL (next_cursor != NULL);
+
+    if (next_cursor == &dump->bufs)
+    {
+        next_cursor = next_cursor->next;
+        XDBG_RETURN_IF_FAIL (next_cursor != NULL);
+    }
+
+    next = xorg_list_entry (next_cursor, DumpBufInfo, link);
+    XDBG_RETURN_IF_FAIL (next != NULL);
+
+    need_size = 0;
+    for (i = 0; i < bo_cnt; i++)
+        need_size += size[i];
+    if (need_size > next->bo_size)
+    {
+        SECPtr pSec = SECPTR (dump->pScrn);
+        tbm_bo new_bo = tbm_bo_alloc (pSec->tbm_bufmgr, need_size, TBM_BO_DEFAULT);
+        XDBG_RETURN_IF_FAIL (new_bo != NULL);
+        tbm_bo_unref (next->bo);
+        next->bo = new_bo;
+        next->bo_size = need_size;
+    }
+
+    dst_ptr = tbm_bo_map (next->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE).ptr;
+    XDBG_RETURN_IF_FAIL (dst_ptr != NULL);
+
+    remain_size = next->bo_size;
+    for (i = 0; i < bo_cnt; i++)
+    {
+        XDBG_GOTO_IF_FAIL (size[i] <= remain_size, end_dump_raws);
+
+        src_ptr = tbm_bo_map (bo[i], TBM_DEVICE_CPU, TBM_OPTION_READ).ptr;
+        XDBG_GOTO_IF_FAIL (src_ptr != NULL, end_dump_raws);
+
+        memcpy (dst_ptr, src_ptr, size[i]);
+        dst_ptr += size[i];
+
+        if (i == 0)
+            next->size = 0;
+
+        next->size += size[i];
+        remain_size -= size[i];
+
+        tbm_bo_unmap (bo[i]);
+    }
+
+    snprintf (next->file, sizeof (next->file), "%.3f_%s", GetTimeInMillis()/1000.0, file);
+    memset (&next->rect, 0, sizeof (xRectangle));
+    next->dirty = TRUE;
+    next->dump_bmp = FALSE;
+
+    XDBG_TRACE (MSEC, "DumpRaws: %ld(%d)\n", GetTimeInMillis () - prev, next->index);
+
+    dump->cursor = next_cursor;
+
+end_dump_raws:
+    tbm_bo_unmap (next->bo);
+
+    return;
+}
+
+void
+secUtilDoDumpBmps (void *d, tbm_bo bo, int w, int h, xRectangle *crop, const char *file)
+{
+    DumpInfo *dump = (DumpInfo*)d;
+    DumpBufInfo *next = NULL;
+    struct xorg_list *next_cursor;
+    int scale_w = w / DUMP_SCALE_RATIO;
+    int scale_h = h / DUMP_SCALE_RATIO;
+    xRectangle temp = {0,};
+
+    if (!dump || !bo)
+        return;
+
+    next_cursor = dump->cursor->next;
+    XDBG_RETURN_IF_FAIL (next_cursor != NULL);
+
+    if (next_cursor == &dump->bufs)
+    {
+        next_cursor = next_cursor->next;
+        XDBG_RETURN_IF_FAIL (next_cursor != NULL);
+    }
+
+    next = xorg_list_entry (next_cursor, DumpBufInfo, link);
+    XDBG_RETURN_IF_FAIL (next != NULL);
+
+    tbm_bo_handle src_handle = tbm_bo_get_handle (bo, TBM_DEVICE_CPU);
+    tbm_bo_handle dst_handle = tbm_bo_get_handle (next->bo, TBM_DEVICE_CPU);
+    XDBG_RETURN_IF_FAIL (src_handle.ptr != NULL);
+    XDBG_RETURN_IF_FAIL (dst_handle.ptr != NULL);
+    XDBG_RETURN_IF_FAIL (scale_w*scale_h*4 <= next->bo_size);
+
+    CARD32 prev = GetTimeInMillis ();
+
+    snprintf (next->file, sizeof (next->file), "%.3f_%s", GetTimeInMillis()/1000.0, file);
+
+    next->dirty = TRUE;
+    next->dump_bmp = TRUE;
+    next->size = scale_w*scale_h*4;
+
+    next->width = scale_w;
+    next->height = scale_h;
+    next->rect.x = 0;
+    next->rect.y = 0;
+    next->rect.width = (crop)?(crop->width/DUMP_SCALE_RATIO):next->width;
+    next->rect.height = (crop)?(crop->height/DUMP_SCALE_RATIO):next->height;
+
+    temp.width = (crop)?crop->width:w;
+    temp.height = (crop)?crop->height:h;
+
+    secUtilConvertBos (dump->pScrn, bo, w, h, &temp, w*4,
+                       next->bo, scale_w, scale_h, &next->rect, scale_w*4,
+                       FALSE, 0);
+
+    XDBG_TRACE (MSEC, "DumpBmps: %ld(%d)\n", GetTimeInMillis () - prev, next->index);
+
+    dump->cursor = next_cursor;
+
+    return;
+}
+
+void
+secUtilDoDumpPixmaps (void *d, PixmapPtr pPixmap, const char *file)
+{
+    SECPixmapPriv *privPixmap;
+    xRectangle rect = {0,};
+    Bool need_finish = FALSE;
+
+    XDBG_RETURN_IF_FAIL (d != NULL);
+    XDBG_RETURN_IF_FAIL (pPixmap != NULL);
+    XDBG_RETURN_IF_FAIL (file != NULL);
+
+    privPixmap = exaGetPixmapDriverPrivate (pPixmap);
+
+    if (!privPixmap->bo)
+    {
+        need_finish = TRUE;
+        secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
+        XDBG_RETURN_IF_FAIL (privPixmap->bo != NULL);
+    }
+
+    rect.width = pPixmap->drawable.width;
+    rect.height = pPixmap->drawable.height;
+
+    secUtilDoDumpBmps (d, privPixmap->bo,
+                       pPixmap->devKind/(pPixmap->drawable.bitsPerPixel >> 3),
+                       pPixmap->drawable.height, &rect, file);
+
+    if (need_finish)
+        secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
+}
+
+void
+secUtilDoDumpVBuf (void *d, SECVideoBuf *vbuf, const char *file)
+{
+    XDBG_RETURN_IF_FAIL (d != NULL);
+    XDBG_RETURN_IF_FAIL (vbuf != NULL);
+    XDBG_RETURN_IF_FAIL (file != NULL);
+    XDBG_RETURN_IF_FAIL (vbuf->secure == FALSE);
+
+    if (IS_RGB (vbuf->id))
+        secUtilDoDumpBmps (d, vbuf->bo[0], vbuf->width, vbuf->height, &vbuf->crop, file);
+    else if (vbuf->id == FOURCC_SN12 || vbuf->id == FOURCC_ST12)
+        secUtilDoDumpRaws (d, vbuf->bo, vbuf->lengths, 2, file);
+    else
+        secUtilDoDumpRaws (d, vbuf->bo, &vbuf->size, 1, file);
+}
+
+void
+secUtilFlushDump (void *d)
+{
+    static Bool is_dir = FALSE;
+    char *dir = DUMP_DIR;
+    DumpInfo *dump = (DumpInfo*)d;
+    DumpBufInfo *cur = NULL, *next = NULL;
+
+    if (!dump)
+        return;
+
+    if (!is_dir)
+    {
+        DIR *dp;
+        mkdir (dir, 0755);
+        if (!(dp = opendir (dir)))
+        {
+            ErrorF ("failed: open'%s'\n", dir);
+            return;
+        }
+        else
+            closedir (dp);
+        is_dir = TRUE;
+    }
+
+    xorg_list_for_each_entry_safe (cur, next, &dump->bufs, link)
+    {
+        if (cur->dirty)
+        {
+            if (cur->bo)
+            {
+                char file[128];
+
+                snprintf (file, sizeof(file), "%s/%s", dir, cur->file);
+
+                if (cur->dump_bmp)
+                {
+                    unsigned int *p;
+                    tbm_bo_handle handle = tbm_bo_map (cur->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
+                    XDBG_GOTO_IF_FAIL (handle.ptr != NULL, reset_dump);
+
+                    /* fill magenta color(#FF00FF) for background */
+                    p = (unsigned int*)handle.ptr;
+                    if (p)
+                    {
+                        int i, j;
+                        for (j = 0; j < cur->height; j++)
+                            for (i = cur->rect.width; i < cur->width ; i++)
+                                p[i + j * cur->width] = 0xFFFF00FF;
+                    }
+
+                    secUtilDumpBmp (file, handle.ptr, cur->width, cur->height);
+
+                    tbm_bo_unmap (cur->bo);
+                }
+                else
+                {
+                    tbm_bo_handle handle = tbm_bo_map (cur->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
+                    XDBG_GOTO_IF_FAIL (handle.ptr != NULL, reset_dump);
+
+                    secUtilDumpRaw (file, handle.ptr, cur->size);
+
+                    tbm_bo_unmap (cur->bo);
+                }
+
+                XDBG_ERROR (MSEC, "%s saved\n", file);
+            }
+
+reset_dump:
+            {
+                tbm_bo_handle handle = tbm_bo_map (cur->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+                memset (handle.ptr, 0x00, cur->bo_size);
+                tbm_bo_unmap (cur->bo);
+            }
+            cur->width = 0;
+            cur->height = 0;
+            cur->size = 0;
+            memset (&cur->rect, 0, sizeof (xRectangle));
+            cur->file[0] = '\0';
+            cur->dirty = FALSE;
+            cur->dump_bmp = FALSE;
+        }
+    }
+}
+
+void
+secUtilFinishDump (void *d)
+{
+    DumpInfo *dump = (DumpInfo*)d;
+    DumpBufInfo *cur = NULL, *next = NULL;
+
+    if (!dump)
+        return;
+
+    xorg_list_for_each_entry_safe (cur, next, &dump->bufs, link)
+    {
+        if (cur->bo)
+            tbm_bo_unref (cur->bo);
+        xorg_list_del (&cur->link);
+        free (cur);
+    }
+    free (dump);
+}
+
+#ifndef RR_Rotate_All
+#define RR_Rotate_All  (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270)
+#endif
+
+int secUtilDegreeToRotate (int degree)
+{
+    int rotate;
+
+    switch (degree)
+    {
+    case 0:
+        rotate = RR_Rotate_0;
+        break;
+    case 90:
+        rotate = RR_Rotate_90;
+        break;
+    case 180:
+        rotate = RR_Rotate_180;
+        break;
+    case 270:
+        rotate = RR_Rotate_270;
+        break;
+    default:
+        rotate = 0;    /* ERROR */
+        break;
+    }
+
+    return rotate;
+}
+
+int secUtilRotateToDegree (int rotate)
+{
+    int degree;
+
+    switch (rotate & RR_Rotate_All)
+    {
+    case RR_Rotate_0:
+        degree = 0;
+        break;
+    case RR_Rotate_90:
+        degree = 90;
+        break;
+    case RR_Rotate_180:
+        degree = 180;
+        break;
+    case RR_Rotate_270:
+        degree = 270;
+        break;
+    default:
+        degree = -1;   /* ERROR */
+        break;
+    }
+
+    return degree;
+}
+
+static int
+_secUtilRotateToInt (int rot)
+{
+    switch (rot & RR_Rotate_All)
+    {
+    case RR_Rotate_0:
+        return 0;
+    case RR_Rotate_90:
+        return 1;
+    case RR_Rotate_180:
+        return 2;
+    case RR_Rotate_270:
+        return 3;
+    }
+
+    return 0;
+}
+
+int secUtilRotateAdd (int rot_a, int rot_b)
+{
+    int a = _secUtilRotateToInt (rot_a);
+    int b = _secUtilRotateToInt (rot_b);
+
+    return (int) ((1 << ((a+b) %4)) &RR_Rotate_All);
+}
+
+void
+secUtilCacheFlush (ScrnInfoPtr scrn)
+{
+    struct drm_exynos_gem_cache_op cache_op;
+    SECPtr pSec;
+    int ret;
+
+    XDBG_RETURN_IF_FAIL (scrn != NULL);
+
+    pSec = SECPTR (scrn);
+
+    CLEAR (cache_op);
+    cache_op.flags = EXYNOS_DRM_CACHE_FSH_ALL | EXYNOS_DRM_ALL_CACHES_CORES;
+    cache_op.usr_addr = 0;
+    cache_op.size = 0;
+
+    ret = drmCommandWriteRead (pSec->drm_fd, DRM_EXYNOS_GEM_CACHE_OP,
+                               &cache_op, sizeof(cache_op));
+    if (ret)
+        xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+                    "cache flush failed. (%s)\n", strerror(errno));
+}
+
+const PropertyPtr
+secUtilGetWindowProperty (WindowPtr pWin, const char* prop_name)
+{
+    int rc;
+    Mask prop_mode = DixReadAccess;
+    Atom property;
+    PropertyPtr pProp;
+
+    if (!prop_name)
+        return NULL;
+
+    property = MakeAtom (prop_name, strlen (prop_name), FALSE);
+    if (property == None)
+        return NULL;
+
+    rc = dixLookupProperty (&pProp, pWin, property, serverClient, prop_mode);
+    if (rc == Success && pProp->data)
+    {
+        return pProp;
+    }
+
+    return NULL;
+}
+
+static void *
+_copy_one_channel (int width, int height,
+                   char *s, int s_size_w, int s_pitches,
+                   char *d, int d_size_w, int d_pitches)
+{
+    uchar *src = (uchar*)s;
+    uchar *dst = (uchar*)d;
+
+    if (d_size_w == width && s_size_w == width)
+        memcpy (dst, src, s_pitches * height);
+    else
+    {
+        int i;
+
+        for (i = 0; i < height; i++)
+        {
+            memcpy (dst, src, s_pitches);
+            src += s_pitches;
+            dst += d_pitches;
+        }
+    }
+
+    return dst;
+}
+
+void*
+secUtilCopyImage (int width, int height,
+                  char *s, int s_size_w, int s_size_h,
+                  int *s_pitches, int *s_offsets, int *s_lengths,
+                  char *d, int d_size_w, int d_size_h,
+                  int *d_pitches, int *d_offsets, int *d_lengths,
+                  int channel, int h_sampling, int v_sampling)
+{
+    int i;
+
+    for (i = 0; i < channel; i++)
+    {
+        int c_width = width;
+        int c_height = height;
+
+        if (i > 0)
+        {
+            c_width = c_width / h_sampling;
+            c_height = c_height / v_sampling;
+        }
+
+        _copy_one_channel (c_width, c_height,
+                           s, s_size_w, s_pitches[i],
+                           d, d_size_w, d_pitches[i]);
+
+        s = s + s_lengths[i];
+        d = d + d_lengths[i];
+    }
+
+    return d;
+}
+
+/*
+ * RR_Rotate_90:  Target turns to 90. UI turns to 270.
+ * RR_Rotate_270: Target turns to 270. UI turns to 90.
+ *
+ *     [Target]            ----------
+ *                         |        |
+ *     Top (RR_Rotate_90)  |        |  Top (RR_Rotate_270)
+ *                         |        |
+ *                         ----------
+ *     [UI,FIMC]           ----------
+ *                         |        |
+ *      Top (degree: 270)  |        |  Top (degree: 90)
+ *                         |        |
+ *                         ----------
+ */
+void
+secUtilRotateArea (int *width, int *height, xRectangle *rect, int degree)
+{
+//    int old_w, old_h;
+
+    XDBG_RETURN_IF_FAIL (width != NULL);
+    XDBG_RETURN_IF_FAIL (height != NULL);
+    XDBG_RETURN_IF_FAIL (rect != NULL);
+
+    if (degree == 0)
+        return;
+
+    secUtilRotateRect (*width, *height, rect, degree);
+
+//    old_w = *width;
+//    old_h = *height;
+
+    if (degree % 180)
+        SWAP (*width, *height);
+
+//    ErrorF ("%d: (%dx%d) => (%dx%d)\n", degree, old_w, old_h, *width, *height);
+}
+
+void
+secUtilRotateRect2 (int width, int height, xRectangle *rect, int degree, const char *func)
+{
+    xRectangle new_rect = {0,};
+
+    XDBG_RETURN_IF_FAIL (rect != NULL);
+
+    if (degree == 0)
+        return;
+
+    degree = (degree + 360) % 360;
+
+    switch (degree)
+    {
+    case 90:
+        new_rect.x = height - (rect->y + rect->height);
+        new_rect.y = rect->x;
+        new_rect.width  = rect->height;
+        new_rect.height = rect->width;
+        break;
+    case 180:
+        new_rect.x = width  - (rect->x + rect->width);
+        new_rect.y = height - (rect->y + rect->height);
+        new_rect.width  = rect->width;
+        new_rect.height = rect->height;
+        break;
+    case 270:
+        new_rect.x = rect->y;
+        new_rect.y = width - (rect->x + rect->width);
+        new_rect.width  = rect->height;
+        new_rect.height = rect->width;
+        break;
+    }
+
+//    ErrorF ("%d: %dx%d (%d,%d %dx%d) => (%d,%d %dx%d)   %s\n",
+//            degree, width, height,
+//            rect->x, rect->y, rect->width, rect->height,
+//            new_rect.x, new_rect.y, new_rect.width, new_rect.height, func);
+
+    *rect = new_rect;
+}
+
+void
+secUtilRotateRegion (int width, int height, RegionPtr region, int degree)
+{
+    RegionRec new_region;
+    int    nbox;
+    BoxPtr pBox;
+
+    if (!region)
+        return;
+
+    nbox = RegionNumRects (region);
+    pBox = RegionRects (region);
+
+    if (nbox == 0)
+        return;
+
+    RegionInit (&new_region, NULL, 0);
+
+    while (nbox--)
+    {
+        if (pBox)
+        {
+            xRectangle temp;
+            RegionPtr temp_region;
+            temp.x = pBox->x1;
+            temp.y = pBox->y1;
+            temp.width  = pBox->x2 - pBox->x1;
+            temp.height = pBox->y2 - pBox->y1;
+            secUtilRotateRect (width, height, &temp, degree);
+            temp_region = RegionFromRects (1, &temp, 0);
+            RegionUnion (&new_region, &new_region, temp_region);
+            RegionDestroy (temp_region);
+        }
+
+        pBox++;
+    }
+
+    RegionCopy (region, &new_region);
+    RegionUninit (&new_region);
+}
+
+void
+secUtilAlignRect (int src_w, int src_h, int dst_w, int dst_h, xRectangle *fit, Bool hw)
+{
+    int fit_width;
+    int fit_height;
+    float rw, rh, max;
+
+    if (!fit)
+        return;
+
+    XDBG_RETURN_IF_FAIL (src_w > 0 && src_h > 0);
+    XDBG_RETURN_IF_FAIL (dst_w > 0 && dst_h > 0);
+
+    rw = (float)src_w / dst_w;
+    rh = (float)src_h / dst_h;
+    max = MAX (rw, rh);
+
+    fit_width = src_w / max;
+    fit_height = src_h / max;
+
+    if (hw)
+        fit_width &= (~0x3);
+
+    fit->x = (dst_w - fit_width) / 2;
+    fit->y = (dst_h - fit_height) / 2;
+    fit->width = fit_width;
+    fit->height = fit_height;
+}
+
+void
+secUtilScaleRect (int src_w, int src_h, int dst_w, int dst_h, xRectangle *scale)
+{
+    float ratio;
+    xRectangle fit;
+
+    XDBG_RETURN_IF_FAIL (scale != NULL);
+    XDBG_RETURN_IF_FAIL (src_w > 0 && src_h > 0);
+    XDBG_RETURN_IF_FAIL (dst_w > 0 && dst_h > 0);
+
+    if ((src_w == dst_w) && (src_h == dst_h))
+        return;
+
+    secUtilAlignRect (src_w, src_h, dst_w, dst_h, &fit, FALSE);
+
+    ratio = (float)fit.width / src_w;
+
+    scale->x = scale->x * ratio + fit.x;
+    scale->y = scale->y * ratio + fit.y;
+    scale->width = scale->width * ratio;
+    scale->height = scale->height * ratio;
+}
+
+/*  true iff two Boxes overlap */
+#define EXTENTCHECK(r1, r2)       \
+    (!( ((r1)->x2 <= (r2)->x1)  || \
+        ((r1)->x1 >= (r2)->x2)  || \
+        ((r1)->y2 <= (r2)->y1)  || \
+        ((r1)->y1 >= (r2)->y2) ) )
+
+/* true iff (x,y) is in Box */
+#define INBOX(r, x, y) \
+    ( ((r)->x2 >  x) && \
+      ((r)->x1 <= x) && \
+      ((r)->y2 >  y) && \
+      ((r)->y1 <= y) )
+
+/* true iff Box r1 contains Box r2 */
+#define SUBSUMES(r1, r2)       \
+    ( ((r1)->x1 <= (r2)->x1) && \
+      ((r1)->x2 >= (r2)->x2) && \
+      ((r1)->y1 <= (r2)->y1) && \
+      ((r1)->y2 >= (r2)->y2) )
+
+int
+secUtilBoxInBox (BoxPtr base, BoxPtr box)
+{
+    XDBG_RETURN_VAL_IF_FAIL(base != NULL, -1);
+    XDBG_RETURN_VAL_IF_FAIL(box != NULL, -1);
+
+    if(base->x1 == box->x1 && base->y1 == box->y1 && base->x2 == box->x2 && base->y2 == box->y2)
+    {
+        return rgnSAME;
+    }
+    else if(SUBSUMES(base, box))
+    {
+        return rgnIN;
+    }
+    else if(EXTENTCHECK(base, box))
+    {
+        return rgnPART;
+    }
+    else
+        return rgnOUT;
+
+    return -1;
+}
+
+int
+secUtilBoxArea(BoxPtr pBox)
+{
+    return (int) (pBox->x2 - pBox->x1) *(int) (pBox->y2 -pBox->y1);
+}
+
+int
+secUtilBoxIntersect(BoxPtr pDstBox, BoxPtr pBox1, BoxPtr pBox2)
+{
+    pDstBox->x1 = pBox1->x1 > pBox2->x1 ? pBox1->x1 : pBox2->x1;
+    pDstBox->x2 = pBox1->x2 < pBox2->x2 ? pBox1->x2 : pBox2->x2;
+    pDstBox->y1 = pBox1->y1 > pBox2->y1 ? pBox1->y1 : pBox2->y1;
+    pDstBox->y2 = pBox1->y2 < pBox2->y2 ? pBox1->y2 : pBox2->y2;
+
+    if (pDstBox->x1 >= pDstBox->x2 || pDstBox->y1 >= pDstBox->y2)
+    {
+        pDstBox->x1 = 0;
+        pDstBox->x2 = 0;
+        pDstBox->y1 = 0;
+        pDstBox->y2 = 0;
+        return rgnOUT;
+    }
+
+    if (pDstBox->x1 == pBox2->x1 &&
+        pDstBox->y1 == pBox2->y1 &&
+        pDstBox->x2 == pBox2->x2 &&
+        pDstBox->y2 == pBox2->y2)
+        return rgnIN;
+
+    return rgnPART;
+}
+
+void
+secUtilBoxMove(BoxPtr pBox, int dx, int dy)
+{
+    if(dx == 0 && dy == 0) return;
+
+    pBox->x1 += dx;
+    pBox->x2 += dx;
+    pBox->y1 += dy;
+    pBox->y2 += dy;
+}
+
+
+Bool
+secUtilRectIntersect (xRectanglePtr pDest, xRectanglePtr pRect1, xRectanglePtr pRect2)
+{
+    int dest_x, dest_y;
+    int dest_x2, dest_y2;
+
+    if (!pDest)
+        return FALSE;
+
+    dest_x = MAX (pRect1->x, pRect2->x);
+    dest_y = MAX (pRect1->y, pRect2->y);
+    dest_x2 = MIN (pRect1->x + pRect1->width, pRect2->x + pRect2->width);
+    dest_y2 = MIN (pRect1->y + pRect1->height, pRect2->y + pRect2->height);
+
+    if (dest_x2 > dest_x && dest_y2 > dest_y)
+    {
+        pDest->x = dest_x;
+        pDest->y = dest_y;
+        pDest->width = dest_x2 - dest_x;
+        pDest->height = dest_y2 - dest_y;
+    }
+    else
+    {
+        pDest->width = 0;
+        pDest->height = 0;
+    }
+
+    return TRUE;
+}
+
+
+void
+secUtilSaveImage (pixman_image_t *image, char *path)
+{
+    void *data;
+    int width, height;
+
+    XDBG_RETURN_IF_FAIL (image != NULL);
+    XDBG_RETURN_IF_FAIL (path != NULL);
+
+    width = pixman_image_get_width (image);
+    height = pixman_image_get_height (image);
+
+    data = pixman_image_get_data (image);
+    XDBG_RETURN_IF_FAIL (data != NULL);
+
+    secUtilDumpBmp (path, data, width, height);
+}
+
+Bool
+secUtilConvertImage (pixman_op_t op, uchar *srcbuf, uchar *dstbuf,
+                     pixman_format_code_t src_format, pixman_format_code_t dst_format,
+                     int sw, int sh, xRectangle *sr,
+                     int dw, int dh, xRectangle *dr,
+                     RegionPtr dst_clip_region,
+                     int rotate, int hflip, int vflip)
+{
+    pixman_image_t    *src_img;
+    pixman_image_t    *dst_img;
+    int                src_stride, dst_stride;
+    int                src_bpp;
+    int                dst_bpp;
+    double             scale_x, scale_y;
+    int                rotate_step;
+    int                ret = FALSE;
+    pixman_transform_t t;
+    struct pixman_f_transform ft;
+
+    src_bpp = PIXMAN_FORMAT_BPP (src_format) / 8;
+    XDBG_RETURN_VAL_IF_FAIL (src_bpp > 0, FALSE);
+
+    dst_bpp = PIXMAN_FORMAT_BPP (dst_format) / 8;
+    XDBG_RETURN_VAL_IF_FAIL (dst_bpp > 0, FALSE);
+
+    src_stride = sw * src_bpp;
+    dst_stride = dw * dst_bpp;
+
+    src_img = pixman_image_create_bits (src_format, sw, sh,
+                                        (uint32_t*)srcbuf, src_stride);
+    dst_img = pixman_image_create_bits (dst_format, dw, dh,
+                                        (uint32_t*)dstbuf, dst_stride);
+
+    XDBG_GOTO_IF_FAIL (src_img != NULL, CANT_CONVERT);
+    XDBG_GOTO_IF_FAIL (dst_img != NULL, CANT_CONVERT);
+
+    pixman_f_transform_init_identity (&ft);
+
+    if (hflip)
+    {
+        pixman_f_transform_scale (&ft, NULL, -1, 1);
+        pixman_f_transform_translate (&ft, NULL, dr->width, 0);
+    }
+
+    if (vflip)
+    {
+        pixman_f_transform_scale (&ft, NULL, 1, -1);
+        pixman_f_transform_translate (&ft, NULL, 0, dr->height);
+    }
+
+    rotate_step = (rotate + 360) / 90 % 4;
+
+    if (rotate_step > 0)
+    {
+        int c, s, tx = 0, ty = 0;
+        switch (rotate_step)
+        {
+        case 1:
+            /* 90 degrees */
+            c = 0;
+            s = -1;
+            tx = -dr->width;
+            break;
+        case 2:
+            /* 180 degrees */
+            c = -1;
+            s = 0;
+            tx = -dr->width;
+            ty = -dr->height;
+            break;
+        case 3:
+            /* 270 degrees */
+            c = 0;
+            s = 1;
+            ty = -dr->height;
+            break;
+        default:
+            /* 0 degrees */
+            c = 0;
+            s = 0;
+            break;
+        }
+
+        pixman_f_transform_translate (&ft, NULL, tx, ty);
+        pixman_f_transform_rotate (&ft, NULL, c, s);
+    }
+
+    if (rotate_step % 2 == 0)
+    {
+        scale_x = (double)sr->width / dr->width;
+        scale_y = (double)sr->height / dr->height;
+    }
+    else
+    {
+        scale_x = (double)sr->width / dr->height;
+        scale_y = (double)sr->height / dr->width;
+    }
+
+    pixman_f_transform_scale (&ft, NULL, scale_x, scale_y);
+    pixman_f_transform_translate (&ft, NULL, sr->x, sr->y);
+
+    pixman_transform_from_pixman_f_transform (&t, &ft);
+    pixman_image_set_transform (src_img, &t);
+
+    pixman_image_composite (op, src_img, NULL, dst_img, 0, 0, 0, 0,
+                            dr->x, dr->y, dr->width, dr->height);
+
+    ret = TRUE;
+
+CANT_CONVERT:
+    if (src_img)
+        pixman_image_unref (src_img);
+    if (dst_img)
+        pixman_image_unref (dst_img);
+
+    return ret;
+}
+
+void
+secUtilFreeHandle (ScrnInfoPtr scrn, unsigned int handle)
+{
+    struct drm_gem_close close;
+    SECPtr pSec;
+
+    XDBG_RETURN_IF_FAIL (scrn != NULL);
+
+    pSec = SECPTR (scrn);
+
+    CLEAR (close);
+    close.handle = handle;
+    if (drmIoctl (pSec->drm_fd, DRM_IOCTL_GEM_CLOSE, &close))
+    {
+        XDBG_ERRNO (MSEC, "DRM_IOCTL_GEM_CLOSE failed.\n");
+    }
+}
+
+Bool
+secUtilConvertPhyaddress (ScrnInfoPtr scrn, unsigned int phy_addr, int size,
+                          unsigned int *handle)
+{
+    struct drm_exynos_gem_phy_imp phy_imp = {0,};
+    SECPtr pSec;
+
+    XDBG_RETURN_VAL_IF_FAIL (scrn != NULL, FALSE);
+
+    if (!phy_addr || size <= 0 || !handle)
+        return FALSE;
+
+    pSec = SECPTR (scrn);
+    phy_imp.phy_addr = (unsigned long)phy_addr;
+    phy_imp.size = (unsigned long)size;
+
+    if (pSec->drm_fd)
+        if (ioctl(pSec->drm_fd, DRM_IOCTL_EXYNOS_GEM_PHY_IMP, &phy_imp) < 0)
+        {
+            XDBG_ERRNO (MSEC, "DRM_IOCTL_EXYNOS_GEM_PHY_IMP failed. %p(%d)\n",
+                        (void*)phy_addr, size);
+            return FALSE;
+        }
+
+    *handle = phy_imp.gem_handle;
+
+    return TRUE;
+}
+
+Bool
+secUtilConvertHandle (ScrnInfoPtr scrn, unsigned int handle,
+                      unsigned int *phy_addr, int *size)
+{
+    struct drm_exynos_gem_get_phy get_phy;
+    SECPtr pSec;
+
+    XDBG_RETURN_VAL_IF_FAIL (scrn != NULL, FALSE);
+
+    if (handle == 0 || (!phy_addr && !size))
+        return FALSE;
+
+    pSec = SECPTR (scrn);
+    memset (&get_phy, 0, sizeof (struct drm_exynos_gem_get_phy));
+    get_phy.gem_handle = handle;
+
+    if (pSec->drm_fd)
+        if (ioctl(pSec->drm_fd, DRM_IOCTL_EXYNOS_GEM_GET_PHY, &get_phy) < 0)
+        {
+            XDBG_DEBUG (MLYR, "DRM_IOCTL_EXYNOS_GEM_GET_PHY failed. (%d)(%s,%d)\n",
+                        handle, strerror(errno), errno);
+            return FALSE;
+        }
+
+    if (phy_addr)
+        *phy_addr = (unsigned int)get_phy.phy_addr;
+
+    if (size)
+        *size = (int)((unsigned int)get_phy.size);
+
+    return TRUE;
+}
+
+typedef struct _ListData
+{
+    void *key;
+    void *data;
+
+    struct xorg_list link;
+} ListData;
+
+static ListData*
+_secUtilListGet (void *list, void *key)
+{
+    ListData *data = NULL, *next = NULL;
+
+    if (!list)
+        return NULL;
+
+    xorg_list_for_each_entry_safe (data, next, (struct xorg_list*)list, link)
+    {
+        if (data->key == key)
+            return data;
+    }
+    return NULL;
+}
+
+void*
+secUtilListAdd (void *list, void *key, void *user_data)
+{
+    ListData *data;
+
+    XDBG_RETURN_VAL_IF_FAIL (key != NULL, NULL);
+
+    if (!list)
+    {
+        list = calloc (sizeof (struct xorg_list), 1);
+        xorg_list_init ((struct xorg_list*)list);
+    }
+    XDBG_RETURN_VAL_IF_FAIL (list != NULL, NULL);
+
+    if (_secUtilListGet (list, key))
+        return list;
+
+    data = malloc (sizeof (ListData));
+    data->key = key;
+    data->data = user_data;
+
+    xorg_list_add (&data->link, (struct xorg_list*)list);
+
+    return list;
+}
+
+void*
+secUtilListRemove (void *list, void *key)
+{
+    ListData *data;
+
+    XDBG_RETURN_VAL_IF_FAIL (key != NULL, NULL);
+
+    data = _secUtilListGet (list, key);
+    if (data)
+    {
+        xorg_list_del (&data->link);
+        free (data);
+
+        if (xorg_list_is_empty ((struct xorg_list*)list))
+        {
+            free (list);
+            return NULL;
+        }
+    }
+
+    return list;
+}
+
+void*
+secUtilListGetData (void *list, void *key)
+{
+    ListData *data;
+
+    XDBG_RETURN_VAL_IF_FAIL (key != NULL, NULL);
+
+    data = _secUtilListGet (list, key);
+    if (data)
+        return data->data;
+
+    return NULL;
+}
+
+Bool
+secUtilListIsEmpty (void *list)
+{
+    if (!list)
+        return FALSE;
+
+    return xorg_list_is_empty ((struct xorg_list*)list);
+}
+
+void
+secUtilListDestroyData (void *list, DestroyDataFunc func, void *func_data)
+{
+    ListData *cur = NULL, *next = NULL;
+    struct xorg_list *l;
+
+    if (!list || !func)
+        return;
+
+    l = (struct xorg_list*)list;
+    xorg_list_for_each_entry_safe (cur, next, l, link)
+    {
+        func (func_data, cur->data);
+    }
+}
+
+void
+secUtilListDestroy (void *list)
+{
+    ListData *data = NULL, *next = NULL;
+    struct xorg_list *l;
+
+    if (!list)
+        return;
+
+    l = (struct xorg_list*)list;
+    xorg_list_for_each_entry_safe (data, next, l, link)
+    {
+        xorg_list_del (&data->link);
+        free (data);
+    }
+
+    free (list);
+}
+
+Bool
+secUtilSetDrmProperty (SECModePtr pSecMode, unsigned int obj_id, unsigned int obj_type,
+                       const char *prop_name, unsigned int value)
+{
+    drmModeObjectPropertiesPtr props;
+    unsigned int i;
+
+    XDBG_RETURN_VAL_IF_FAIL (pSecMode != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (obj_id > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (obj_type > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (prop_name != NULL, FALSE);
+
+    props = drmModeObjectGetProperties (pSecMode->fd, obj_id, obj_type);
+    if (!props)
+    {
+        XDBG_ERRNO (MPLN, "fail : drmModeObjectGetProperties.\n");
+        return FALSE;
+    }
+
+    for (i = 0; i < props->count_props; i++)
+    {
+        drmModePropertyPtr prop = drmModeGetProperty (pSecMode->fd, props->props[i]);
+        int ret;
+
+        if (!prop)
+        {
+            XDBG_ERRNO (MPLN, "fail : drmModeGetProperty.\n");
+            drmModeFreeObjectProperties (props);
+            return FALSE;
+        }
+
+        if (!strcmp (prop->name, prop_name))
+        {
+            ret = drmModeObjectSetProperty (pSecMode->fd, obj_id, obj_type, prop->prop_id, value);
+            if (ret < 0)
+            {
+                XDBG_ERRNO (MPLN, "fail : drmModeObjectSetProperty.\n");
+                drmModeFreeProperty(prop);
+                drmModeFreeObjectProperties (props);
+                return FALSE;
+            }
+
+            drmModeFreeProperty(prop);
+            drmModeFreeObjectProperties (props);
+
+            return TRUE;
+        }
+
+        drmModeFreeProperty(prop);
+    }
+
+    XDBG_ERROR (MPLN, "fail : drm set property.\n");
+
+    drmModeFreeObjectProperties (props);
+
+    return FALSE;
+}
+
+Bool
+secUtilEnsureExternalCrtc (ScrnInfoPtr scrn)
+{
+    SECModePtr pSecMode;
+    SECOutputPrivPtr pOutputPriv = NULL;
+
+    XDBG_RETURN_VAL_IF_FAIL (scrn != NULL, FALSE);
+
+    pSecMode = (SECModePtr) SECPTR (scrn)->pSecMode;
+
+    if (pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI)
+    {
+        pOutputPriv = secOutputGetPrivateForConnType (scrn, DRM_MODE_CONNECTOR_HDMIA);
+        if (!pOutputPriv)
+            pOutputPriv = secOutputGetPrivateForConnType (scrn, DRM_MODE_CONNECTOR_HDMIB);
+    }
+    else
+        pOutputPriv = secOutputGetPrivateForConnType (scrn, DRM_MODE_CONNECTOR_VIRTUAL);
+
+    XDBG_RETURN_VAL_IF_FAIL (pOutputPriv != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (pOutputPriv->mode_encoder != NULL, FALSE);
+
+    if (pOutputPriv->mode_encoder->crtc_id > 0)
+        return TRUE;
+
+    secDisplayDeinitDispMode (scrn);
+
+    return secDisplayInitDispMode (scrn, pSecMode->conn_mode);
+}
+
+typedef struct _VBufFreeFuncInfo
+{
+    FreeVideoBufFunc  func;
+    void             *data;
+    struct xorg_list  link;
+} VBufFreeFuncInfo;
+
+static SECFormatTable format_table[] =
+{
+    { FOURCC_RGB565, DRM_FORMAT_RGB565,    TYPE_RGB    },
+    { FOURCC_SR16,   DRM_FORMAT_RGB565,    TYPE_RGB    },
+    { FOURCC_RGB32,  DRM_FORMAT_XRGB8888,  TYPE_RGB    },
+    { FOURCC_SR32,   DRM_FORMAT_XRGB8888,  TYPE_RGB    },
+    { FOURCC_YV12,   DRM_FORMAT_YVU420,    TYPE_YUV420 },
+    { FOURCC_I420,   DRM_FORMAT_YUV420,    TYPE_YUV420 },
+    { FOURCC_S420,   DRM_FORMAT_YUV420,    TYPE_YUV420 },
+    { FOURCC_ST12,   DRM_FORMAT_NV12MT,    TYPE_YUV420 },
+    { FOURCC_SN12,   DRM_FORMAT_NV12,      TYPE_YUV420 },
+    { FOURCC_NV12,   DRM_FORMAT_NV12,      TYPE_YUV420 },
+    { FOURCC_SN21,   DRM_FORMAT_NV21,      TYPE_YUV420 },
+    { FOURCC_NV21,   DRM_FORMAT_NV21,      TYPE_YUV420 },
+    { FOURCC_YUY2,   DRM_FORMAT_YUYV,      TYPE_YUV422 },
+    { FOURCC_SUYV,   DRM_FORMAT_YUYV,      TYPE_YUV422 },
+    { FOURCC_UYVY,   DRM_FORMAT_UYVY,      TYPE_YUV422 },
+    { FOURCC_SYVY,   DRM_FORMAT_UYVY,      TYPE_YUV422 },
+    { FOURCC_ITLV,   DRM_FORMAT_UYVY,      TYPE_YUV422 },
+};
+
+static struct xorg_list vbuf_lists;
+
+#define VBUF_RETURN_IF_FAIL(cond) \
+    {if (!(cond)) { XDBG_ERROR (MVBUF, "[%s] : '%s' failed. (%s)\n", __FUNCTION__, #cond, func); return; }}
+#define VBUF_RETURN_VAL_IF_FAIL(cond, val) \
+    {if (!(cond)) { XDBG_ERROR (MVBUF, "[%s] : '%s' failed. (%s)\n", __FUNCTION__, #cond, func); return val; }}
+
+static void
+_secUtilInitVbuf (void)
+{
+    static Bool init = FALSE;
+    if (!init)
+    {
+        xorg_list_init (&vbuf_lists);
+        init = TRUE;
+    }
+}
+
+static void
+_secUtilYUV420BlackFrame (unsigned char *buf, int buf_size, int width, int height)
+{
+    int i;
+    int y_len = 0;
+    int yuv_len = 0;
+
+    y_len = width * height;
+    yuv_len = (width * height * 3) >> 1;
+
+    if (buf_size < yuv_len)
+        return;
+
+    if (width % 4)
+    {
+        for (i = 0 ; i < y_len ; i++)
+            buf[i] = 0x10;
+
+        for ( ; i < yuv_len ; i++)
+            buf[i] = 0x80;
+    }
+    else
+    {
+        /* faster way */
+        int *ibuf = NULL;
+        short *sbuf = NULL;
+        ibuf = (int *)buf;
+
+        for (i = 0 ; i < y_len / 4 ; i++)
+            ibuf[i] = 0x10101010; /* set YYYY */
+
+        sbuf = (short*)(&buf[y_len]);
+
+        for (i = 0 ; i < (yuv_len - y_len) / 2 ; i++)
+            sbuf[i] = 0x8080; /* set UV */
+    }
+
+    return;
+}
+
+static void
+_secUtilYUV422BlackFrame (int id, unsigned char *buf, int buf_size, int width, int height)
+{
+    /* YUYV */
+    int i;
+    int yuv_len = 0;
+    int *ibuf = NULL;
+
+    ibuf = (int *)buf;
+
+    yuv_len = (width * height * 2);
+
+    if (buf_size < yuv_len)
+        return;
+
+    for (i = 0 ; i < yuv_len / 4 ; i++)
+        if (id == FOURCC_UYVY || id == FOURCC_SYVY || id == FOURCC_ITLV)
+            ibuf[i] = 0x80108010; /* YUYV -> 0xVYUY */
+        else
+            ibuf[i] = 0x10801080; /* YUYV -> 0xVYUY */
+
+    return;
+}
+
+static tbm_bo
+_secUtilAllocNormalBuffer (ScrnInfoPtr scrn, int size, int flags)
+{
+    SECPtr pSec = SECPTR (scrn);
+
+    return tbm_bo_alloc (pSec->tbm_bufmgr, size, flags);
+}
+
+static tbm_bo
+_secUtilAllocSecureBuffer (ScrnInfoPtr scrn, int size, int flags)
+{
+    SECPtr pSec = SECPTR (scrn);
+    struct tzmem_get_region tzmem_get = {0,};
+    struct drm_prime_handle arg_handle = {0,};
+    struct drm_gem_flink arg_flink = {0,};
+    struct drm_gem_close arg_close = {0,};
+    tbm_bo bo = NULL;
+    int tzmem_fd;
+
+    tzmem_fd = -1;
+    tzmem_get.fd = -1;
+
+    tzmem_fd = open ("/dev/tzmem", O_EXCL);
+    XDBG_GOTO_IF_FAIL (tzmem_fd >= 0, done_secure_buffer);
+
+    tzmem_get.key = "fimc";
+    tzmem_get.size = size;
+    if (ioctl (tzmem_fd, TZMEM_IOC_GET_TZMEM, &tzmem_get))
+    {
+        XDBG_ERRNO (MVBUF, "failed : create tzmem (%d)\n", size);
+        goto done_secure_buffer;
+    }
+    XDBG_GOTO_IF_FAIL (tzmem_get.fd >= 0, done_secure_buffer);
+
+    arg_handle.fd = (__s32)tzmem_get.fd;
+    if (drmIoctl (pSec->drm_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg_handle))
+    {
+        XDBG_ERRNO (MVBUF, "failed : convert to gem (%d)\n", tzmem_get.fd);
+        goto done_secure_buffer;
+    }
+    XDBG_GOTO_IF_FAIL (arg_handle.handle > 0, done_secure_buffer);
+
+    arg_flink.handle = arg_handle.handle;
+    if (drmIoctl (pSec->drm_fd, DRM_IOCTL_GEM_FLINK, &arg_flink))
+    {
+        XDBG_ERRNO (MVBUF, "failed : flink gem (%ld)\n", arg_handle.handle);
+        goto done_secure_buffer;
+    }
+    XDBG_GOTO_IF_FAIL (arg_flink.name > 0, done_secure_buffer);
+
+    bo = tbm_bo_import (pSec->tbm_bufmgr, arg_flink.name);
+    XDBG_GOTO_IF_FAIL (bo != NULL, done_secure_buffer);
+
+done_secure_buffer:
+    if (arg_handle.handle > 0)
+    {
+        arg_close.handle = arg_handle.handle;
+        if (drmIoctl (pSec->drm_fd, DRM_IOCTL_GEM_CLOSE, &arg_close))
+            XDBG_ERRNO (MVBUF, "failed : close gem (%ld)\n", arg_handle.handle);
+    }
+
+    if (tzmem_get.fd >= 0)
+        close (tzmem_get.fd);
+
+    if (tzmem_fd >= 0)
+        close (tzmem_fd);
+
+    return bo;
+}
+
+/*
+ * # planar #
+ * format: YV12    Y/V/U 420
+ * format: I420    Y/U/V 420 #YU12, S420
+ * format: NV12    Y/UV  420
+ * format: NV12M   Y/UV  420 #SN12
+ * format: NV12MT  Y/UV  420 #ST12
+ * format: NV21    Y/VU  420
+ * format: Y444    YUV   444
+ * # packed #
+ * format: YUY2  YUYV  422 #YUYV, SUYV, SUY2
+ * format: YVYU  YVYU  422
+ * format: UYVY  UYVY  422 #SYVY
+ */
+G2dColorMode
+secUtilGetG2dFormat (unsigned int id)
+{
+    G2dColorMode g2dfmt = 0;
+
+    switch (id)
+    {
+    case FOURCC_NV12:
+    case FOURCC_SN12:
+        g2dfmt = G2D_COLOR_FMT_YCbCr420 | G2D_YCbCr_2PLANE | G2D_YCbCr_ORDER_CrCb;
+        break;
+    case FOURCC_NV21:
+    case FOURCC_SN21:
+        g2dfmt = G2D_COLOR_FMT_YCbCr420 | G2D_YCbCr_2PLANE | G2D_YCbCr_ORDER_CbCr;
+        break;
+    case FOURCC_SUYV:
+    case FOURCC_YUY2:
+        g2dfmt = G2D_COLOR_FMT_YCbCr422 | G2D_YCbCr_ORDER_Y1CbY0Cr;
+        break;
+    case FOURCC_SYVY:
+    case FOURCC_UYVY:
+        g2dfmt = G2D_COLOR_FMT_YCbCr422 | G2D_YCbCr_ORDER_CbY1CrY0;
+        break;
+    case FOURCC_SR16:
+    case FOURCC_RGB565:
+        g2dfmt = G2D_COLOR_FMT_RGB565 | G2D_ORDER_AXRGB;
+        break;
+    case FOURCC_SR32:
+    case FOURCC_RGB32:
+        g2dfmt = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
+        break;
+    case FOURCC_YV12:
+    case FOURCC_I420:
+    case FOURCC_S420:
+    case FOURCC_ITLV:
+    case FOURCC_ST12:
+    default:
+        XDBG_NEVER_GET_HERE (MVA);
+        return 0;
+    }
+
+    return g2dfmt;
+}
+
+unsigned int
+secUtilGetDrmFormat (unsigned int id)
+{
+    int i, size;
+
+    size = sizeof (format_table) / sizeof (SECFormatTable);
+
+    for (i = 0; i < size; i++)
+        if (format_table[i].id == id)
+            return format_table[i].drmfmt;
+
+    return 0;
+}
+
+SECFormatType
+secUtilGetColorType (unsigned int id)
+{
+    int i, size;
+
+    size = sizeof (format_table) / sizeof (SECFormatTable);
+
+    for (i = 0; i < size; i++)
+        if (format_table[i].id == id)
+            return format_table[i].type;
+
+    return TYPE_NONE;
+}
+
+static SECVideoBuf*
+_findVideoBuffer (CARD32 stamp)
+{
+    SECVideoBuf *cur = NULL, *next = NULL;
+
+    _secUtilInitVbuf ();
+
+    if (!vbuf_lists.next)
+        return NULL;
+
+    xorg_list_for_each_entry_safe (cur, next, &vbuf_lists, valid_link)
+    {
+        if (cur->stamp == stamp)
+            return cur;
+    }
+
+    return NULL;
+}
+
+SECVideoBuf*
+_secUtilAllocVideoBuffer (ScrnInfoPtr scrn, int id, int width, int height,
+                          Bool scanout, Bool reset, Bool secure, const char *func)
+{
+    SECPtr pSec = SECPTR (scrn);
+    SECVideoBuf *vbuf = NULL;
+    int flags = 0;
+    int i;
+    tbm_bo_handle bo_handle;
+    CARD32 stamp;
+
+    XDBG_RETURN_VAL_IF_FAIL (scrn != NULL, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (id > 0, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (width > 0, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (height > 0, NULL);
+
+    vbuf = calloc (1, sizeof (SECVideoBuf));
+    XDBG_GOTO_IF_FAIL (vbuf != NULL, alloc_fail);
+
+    vbuf->ref_cnt = 1;
+
+    vbuf->pScrn = scrn;
+    vbuf->id = id;
+    vbuf->width = width;
+    vbuf->height = height;
+    vbuf->crop.width = width;
+    vbuf->crop.height = height;
+
+    vbuf->size = secVideoQueryImageAttrs (scrn, id, &width, &height,
+                                          vbuf->pitches, vbuf->offsets, vbuf->lengths);
+    XDBG_GOTO_IF_FAIL (vbuf->size > 0, alloc_fail);
+
+    for (i = 0; i < PLANAR_CNT; i++)
+    {
+        int alloc_size = 0;
+
+        if (id == FOURCC_SN12 || id == FOURCC_SN21 || id == FOURCC_ST12)
+            alloc_size = vbuf->lengths[i];
+        else if (i == 0)
+            alloc_size = vbuf->size;
+
+        if (alloc_size <= 0)
+            continue;
+
+        /* if i > 1, do check. */
+        if (id == FOURCC_SN12 || id == FOURCC_SN21 || id == FOURCC_ST12)
+        {
+            XDBG_GOTO_IF_FAIL (i <= 1, alloc_fail);
+        }
+        else
+            XDBG_GOTO_IF_FAIL (i == 0, alloc_fail);
+
+        if (scanout)
+            flags = TBM_BO_SCANOUT|TBM_BO_WC;
+        else if (!pSec->cachable)
+            flags = TBM_BO_WC;
+        else
+            flags = TBM_BO_DEFAULT;
+
+        if (!secure)
+            vbuf->bo[i] = _secUtilAllocNormalBuffer (scrn, alloc_size, flags);
+        else
+            vbuf->bo[i] = _secUtilAllocSecureBuffer (scrn, alloc_size, flags);
+        XDBG_GOTO_IF_FAIL (vbuf->bo[i] != NULL, alloc_fail);
+
+        vbuf->keys[i] = tbm_bo_export (vbuf->bo[i]);
+        XDBG_GOTO_IF_FAIL (vbuf->keys[i] > 0, alloc_fail);
+
+        bo_handle = tbm_bo_get_handle (vbuf->bo[i], TBM_DEVICE_DEFAULT);
+        vbuf->handles[i] = bo_handle.u32;
+        XDBG_GOTO_IF_FAIL (vbuf->handles[i] > 0, alloc_fail);
+
+        if (scanout)
+            secUtilConvertHandle (scrn, vbuf->handles[i], &vbuf->phy_addrs[i], NULL);
+
+        XDBG_DEBUG (MVBUF, "handle(%d) => phy_addrs(%d) \n", vbuf->handles[i], vbuf->phy_addrs[i]);
+    }
+
+    if (reset)
+        secUtilClearVideoBuffer (vbuf);
+
+    vbuf->secure = secure;
+    vbuf->dirty = TRUE;
+
+    xorg_list_init (&vbuf->convert_info);
+    xorg_list_init (&vbuf->free_funcs);
+
+    _secUtilInitVbuf ();
+    xorg_list_add (&vbuf->valid_link, &vbuf_lists);
+
+    stamp = GetTimeInMillis ();
+    while (_findVideoBuffer (stamp))
+        stamp++;
+    vbuf->stamp = stamp;
+
+    vbuf->func = strdup (func);
+    vbuf->flags = flags;
+    vbuf->scanout = scanout;
+
+    XDBG_DEBUG (MVBUF, "%ld alloc(flags:%x, scanout:%d): %s\n", vbuf->stamp, flags, scanout, func);
+
+    return vbuf;
+
+alloc_fail:
+    if (vbuf)
+    {
+        for (i = 0; i < PLANAR_CNT && vbuf->bo[i]; i++)
+            tbm_bo_unref (vbuf->bo[i]);
+
+        free (vbuf);
+    }
+
+    return NULL;
+}
+
+SECVideoBuf*
+_secUtilCreateVideoBuffer (ScrnInfoPtr scrn, int id, int width, int height, Bool secure, const char *func)
+{
+    SECVideoBuf *vbuf = NULL;
+    CARD32 stamp;
+
+    XDBG_RETURN_VAL_IF_FAIL (scrn != NULL, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (id > 0, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (width > 0, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (height > 0, NULL);
+
+    vbuf = calloc (1, sizeof (SECVideoBuf));
+    XDBG_GOTO_IF_FAIL (vbuf != NULL, alloc_fail);
+
+    vbuf->ref_cnt = 1;
+
+    vbuf->pScrn = scrn;
+    vbuf->id = id;
+    vbuf->width = width;
+    vbuf->height = height;
+    vbuf->crop.width = width;
+    vbuf->crop.height = height;
+
+    vbuf->size = secVideoQueryImageAttrs (scrn, id, &width, &height,
+                                          vbuf->pitches, vbuf->offsets, vbuf->lengths);
+    XDBG_GOTO_IF_FAIL (vbuf->size > 0, alloc_fail);
+
+    vbuf->secure = secure;
+
+    xorg_list_init (&vbuf->convert_info);
+    xorg_list_init (&vbuf->free_funcs);
+
+    _secUtilInitVbuf ();
+    xorg_list_add (&vbuf->valid_link, &vbuf_lists);
+
+    stamp = GetTimeInMillis ();
+    while (_findVideoBuffer (stamp))
+        stamp++;
+    vbuf->stamp = stamp;
+
+    vbuf->func = strdup (func);
+    vbuf->flags = -1;
+
+    XDBG_DEBUG (MVBUF, "%ld create: %s\n", vbuf->stamp, func);
+
+    return vbuf;
+
+alloc_fail:
+    if (vbuf)
+        secUtilFreeVideoBuffer (vbuf);
+
+    return NULL;
+}
+
+SECVideoBuf*
+secUtilVideoBufferRef (SECVideoBuf *vbuf)
+{
+    if (!vbuf)
+        return NULL;
+
+    XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), NULL);
+
+    vbuf->ref_cnt++;
+
+    return vbuf;
+}
+
+void
+_secUtilVideoBufferUnref (SECVideoBuf *vbuf, const char *func)
+{
+    if (!vbuf)
+        return;
+
+    VBUF_RETURN_IF_FAIL (_secUtilIsVbufValid (vbuf, func));
+
+    vbuf->ref_cnt--;
+    if (vbuf->ref_cnt == 0)
+        _secUtilFreeVideoBuffer (vbuf, func);
+}
+
+void
+_secUtilFreeVideoBuffer (SECVideoBuf *vbuf, const char *func)
+{
+    VBufFreeFuncInfo *cur = NULL, *next = NULL;
+    int i;
+
+    if (!vbuf)
+        return;
+
+    VBUF_RETURN_IF_FAIL (_secUtilIsVbufValid (vbuf, func));
+    VBUF_RETURN_IF_FAIL (!VBUF_IS_CONVERTING (vbuf));
+    VBUF_RETURN_IF_FAIL (vbuf->showing == FALSE);
+
+    xorg_list_for_each_entry_safe (cur, next, &vbuf->free_funcs, link)
+    {
+        /* call before tmb_bo_unref and drmModeRmFB. */
+        if (cur->func)
+            cur->func (vbuf, cur->data);
+        xorg_list_del (&cur->link);
+        free (cur);
+    }
+
+    for (i = 0; i < PLANAR_CNT; i++)
+    {
+        if (vbuf->bo[i])
+            tbm_bo_unref (vbuf->bo[i]);
+    }
+
+    if (vbuf->fb_id > 0)
+    {
+        XDBG_DEBUG (MVBUF, "vbuf(%ld) fb_id(%d) removed. \n", vbuf->stamp, vbuf->fb_id);
+        drmModeRmFB (SECPTR(vbuf->pScrn)->drm_fd, vbuf->fb_id);
+    }
+
+    xorg_list_del (&vbuf->valid_link);
+
+    XDBG_DEBUG (MVBUF, "%ld freed: %s\n", vbuf->stamp, func);
+
+    vbuf->stamp = 0;
+
+    if (vbuf->func)
+        free (vbuf->func);
+
+    free (vbuf);
+}
+
+static void
+_secUtilClearNormalVideoBuffer (SECVideoBuf *vbuf)
+{
+    int i;
+    tbm_bo_handle bo_handle;
+
+    if (!vbuf)
+        return;
+
+    for (i = 0; i < PLANAR_CNT; i++)
+    {
+        int size = 0;
+
+        if (vbuf->id == FOURCC_SN12 || vbuf->id == FOURCC_SN21 || vbuf->id == FOURCC_ST12)
+            size = vbuf->lengths[i];
+        else if (i == 0)
+            size = vbuf->size;
+
+        if (size <= 0 || !vbuf->bo[i])
+            continue;
+
+        bo_handle = tbm_bo_map (vbuf->bo[i], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+        XDBG_RETURN_IF_FAIL (bo_handle.ptr != NULL);
+
+        if (vbuf->id == FOURCC_SN12 || vbuf->id == FOURCC_SN21 || vbuf->id == FOURCC_ST12)
+        {
+            if (i == 0)
+                memset (bo_handle.ptr, 0x10, size);
+            else if (i == 1)
+                memset (bo_handle.ptr, 0x80, size);
+        }
+        else
+        {
+            int type = secUtilGetColorType (vbuf->id);
+
+            if (type == TYPE_YUV420)
+                _secUtilYUV420BlackFrame (bo_handle.ptr, size, vbuf->width, vbuf->height);
+            else if (type == TYPE_YUV422)
+                _secUtilYUV422BlackFrame (vbuf->id, bo_handle.ptr, size, vbuf->width, vbuf->height);
+            else if (type == TYPE_RGB)
+                memset (bo_handle.ptr, 0, size);
+            else
+                XDBG_NEVER_GET_HERE (MSEC);
+        }
+
+        tbm_bo_unmap (vbuf->bo[i]);
+    }
+
+    secUtilCacheFlush (vbuf->pScrn);
+}
+
+static void
+_secUtilClearSecureVideoBuffer (SECVideoBuf *vbuf)
+{
+}
+
+void
+secUtilClearVideoBuffer (SECVideoBuf *vbuf)
+{
+    if (!vbuf)
+        return;
+
+    if (!vbuf->secure)
+        _secUtilClearNormalVideoBuffer (vbuf);
+    else
+        _secUtilClearSecureVideoBuffer (vbuf);
+
+    vbuf->dirty = FALSE;
+    vbuf->need_reset = FALSE;
+}
+
+Bool
+_secUtilIsVbufValid (SECVideoBuf *vbuf, const char *func)
+{
+    SECVideoBuf *cur = NULL, *next = NULL;
+
+    _secUtilInitVbuf ();
+
+    VBUF_RETURN_VAL_IF_FAIL (vbuf != NULL, FALSE);
+    VBUF_RETURN_VAL_IF_FAIL (vbuf->stamp != 0, FALSE);
+
+    xorg_list_for_each_entry_safe (cur, next, &vbuf_lists, valid_link)
+    {
+        if (cur->stamp == vbuf->stamp)
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+static VBufFreeFuncInfo*
+_secUtilFindFreeVideoBufferFunc (SECVideoBuf *vbuf, FreeVideoBufFunc func, void *data)
+{
+    VBufFreeFuncInfo *cur = NULL, *next = NULL;
+
+    xorg_list_for_each_entry_safe (cur, next, &vbuf->free_funcs, link)
+    {
+        if (cur->func == func && cur->data == data)
+            return cur;
+    }
+
+    return NULL;
+}
+
+void
+secUtilAddFreeVideoBufferFunc (SECVideoBuf *vbuf, FreeVideoBufFunc func, void *data)
+{
+    VBufFreeFuncInfo *info;
+
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (vbuf));
+    XDBG_RETURN_IF_FAIL (func != NULL);
+
+    info = _secUtilFindFreeVideoBufferFunc (vbuf, func, data);
+    if (info)
+        return;
+
+    info = calloc (1, sizeof (VBufFreeFuncInfo));
+    XDBG_RETURN_IF_FAIL (info != NULL);
+
+    info->func = func;
+    info->data = data;
+
+    xorg_list_add (&info->link, &vbuf->free_funcs);
+}
+
+void
+secUtilRemoveFreeVideoBufferFunc (SECVideoBuf *vbuf, FreeVideoBufFunc func, void *data)
+{
+    VBufFreeFuncInfo *info;
+
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (vbuf));
+    XDBG_RETURN_IF_FAIL (func != NULL);
+
+    info = _secUtilFindFreeVideoBufferFunc (vbuf, func, data);
+    if (!info)
+        return;
+
+    xorg_list_del (&info->link);
+
+    free (info);
+}
+
+char*
+secUtilDumpVideoBuffer (char *reply, int *len)
+{
+    SECVideoBuf *cur = NULL, *next = NULL;
+
+    _secUtilInitVbuf ();
+
+    if (xorg_list_is_empty (&vbuf_lists))
+        return reply;
+
+    XDBG_REPLY ("\nVideo buffers:\n");
+    XDBG_REPLY ("id\tsize\t\t\tformat\tflags\trefcnt\tsecure\tstamp\tfunc\n");
+
+    xorg_list_for_each_entry_safe (cur, next, &vbuf_lists, valid_link)
+    {
+        XDBG_REPLY ("%d\t(%dx%d,%d)\t%c%c%c%c\t%d\t%d\t%d\t%ld\t%s\n",
+                    cur->fb_id, cur->width, cur->height, cur->size,
+                    FOURCC_STR (cur->id),
+                    cur->flags, cur->ref_cnt, cur->secure, cur->stamp, cur->func);
+    }
+
+    return reply;
+}
+
diff --git a/src/util/sec_util.h b/src/util/sec_util.h
new file mode 100644 (file)
index 0000000..0b0cb8f
--- /dev/null
@@ -0,0 +1,193 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_UTIL_H__
+#define __SEC_UTIL_H__
+
+#include <fbdevhw.h>
+#include <pixman.h>
+#include <list.h>
+#include <xdbg.h>
+#include "fimg2d.h"
+
+#include "sec.h"
+#include "property.h"
+#include "sec_display.h"
+#include "sec_video_types.h"
+#include "sec_xberc.h"
+
+#define MFB     XDBG_M('F','B',0,0)
+#define MDISP   XDBG_M('D','I','S','P')
+#define MLYR    XDBG_M('L','Y','R',0)
+#define MPLN    XDBG_M('P','L','N',0)
+#define MSEC    XDBG_M('S','E','C',0)
+#define MEXA    XDBG_M('E','X','A',0)
+#define MEXAS   XDBG_M('E','X','A','S')
+#define MEVT    XDBG_M('E','V','T',0)
+#define MDRI2   XDBG_M('D','R','I','2')
+#define MCRS    XDBG_M('C','R','S',0)
+#define MFLIP   XDBG_M('F','L','I','P')
+#define MDPMS   XDBG_M('D','P','M','S')
+#define MVDO    XDBG_M('V','D','O',0)
+#define MDA     XDBG_M('D','A',0,0)
+#define MTVO    XDBG_M('T','V','O',0)
+#define MWB     XDBG_M('W','B',0,0)
+#define MVA     XDBG_M('V','A',0,0)
+#define MPROP   XDBG_M('P','R','O','P')
+#define MXBRC   XDBG_M('X','B','R','C')
+#define MVBUF   XDBG_M('V','B','U','F')
+#define MDRM    XDBG_M('D','R','M',0)
+#define MACCE   XDBG_M('A','C','C','E')
+#define MCVT    XDBG_M('C','V','T',0)
+#define MEXAH   XDBG_M('E','X','A','H')
+#define MG2D    XDBG_M('G','2','D',0)
+
+#define _XID(win)   ((unsigned int)(((WindowPtr)win)->drawable.id))
+
+#define UTIL_DUMP_OK             0
+#define UTIL_DUMP_ERR_OPENFILE   1
+#define UTIL_DUMP_ERR_SHMATTACH  2
+#define UTIL_DUMP_ERR_SEGSIZE    3
+#define UTIL_DUMP_ERR_CONFIG     4
+#define UTIL_DUMP_ERR_INTERNAL   5
+
+#define rgnSAME        3
+
+#define DUMP_DIR "/tmp/xdump"
+
+int secUtilDumpBmp (const char * file, const void * data, int width, int height);
+int secUtilDumpRaw (const char * file, const void * data, int size);
+int secUtilDumpShm (int shmid, const void * data, int width, int height);
+int secUtilDumpPixmap (const char * file, PixmapPtr pPixmap);
+
+void* secUtilPrepareDump (ScrnInfoPtr pScrn, int bo_size, int buf_cnt);
+void  secUtilDoDumpRaws  (void *dump, tbm_bo *bo, int *size, int bo_cnt, const char *file);
+void  secUtilDoDumpBmps  (void *d, tbm_bo bo, int w, int h, xRectangle *crop, const char *file);
+void  secUtilDoDumpPixmaps (void *d, PixmapPtr pPixmap, const char *file);
+void  secUtilDoDumpVBuf  (void *d, SECVideoBuf *vbuf, const char *file);
+void  secUtilFlushDump   (void *dump);
+void  secUtilFinishDump  (void *dump);
+
+int secUtilDegreeToRotate (int degree);
+int secUtilRotateToDegree (int rotate);
+int secUtilRotateAdd (int rot_a, int rot_b);
+
+void secUtilCacheFlush (ScrnInfoPtr scrn);
+
+void*   secUtilCopyImage     (int width, int height,
+                              char *s, int s_size_w, int s_size_h,
+                              int *s_pitches, int *s_offsets, int *s_lengths,
+                              char *d, int d_size_w, int d_size_h,
+                              int *d_pitches, int *d_offsets, int *d_lengths,
+                              int channel, int h_sampling, int v_sampling);
+
+void secUtilRotateArea (int *width, int *height, xRectangle *rect, int degree);
+void secUtilRotateRect2 (int width, int height, xRectangle *rect, int degree, const char *func);
+#define secUtilRotateRect(w,h,r,d) secUtilRotateRect2(w,h,r,d,__FUNCTION__)
+void secUtilRotateRegion (int width, int height, RegionPtr region, int degree);
+
+void    secUtilAlignRect (int src_w, int src_h, int dst_w, int dst_h, xRectangle *fit, Bool hw);
+void    secUtilScaleRect (int src_w, int src_h, int dst_w, int dst_h, xRectangle *scale);
+
+const PropertyPtr secUtilGetWindowProperty (WindowPtr pWin, const char* prop_name);
+
+int secUtilBoxInBox (BoxPtr base, BoxPtr box);
+int secUtilBoxArea(BoxPtr pBox);
+int secUtilBoxIntersect(BoxPtr pDstBox, BoxPtr pBox1, BoxPtr pBox2);
+void secUtilBoxMove(BoxPtr pBox, int dx, int dy);
+
+Bool secUtilRectIntersect (xRectanglePtr pDest, xRectanglePtr pRect1, xRectanglePtr pRect2);
+
+void secUtilSaveImage (pixman_image_t *image, char *path);
+Bool secUtilConvertImage (pixman_op_t op, uchar *srcbuf, uchar *dstbuf,
+                          pixman_format_code_t src_format, pixman_format_code_t dst_format,
+                          int sw, int sh, xRectangle *sr,
+                          int dw, int dh, xRectangle *dr,
+                          RegionPtr dst_clip_region,
+                          int rotate, int hflip, int vflip);
+void secUtilConvertBos (ScrnInfoPtr pScrn,
+                        tbm_bo src_bo, int sw, int sh, xRectangle *sr, int sstride,
+                        tbm_bo dst_bo, int dw, int dh, xRectangle *dr, int dstride,
+                        Bool composite, int rotate);
+
+void secUtilFreeHandle        (ScrnInfoPtr scrn, unsigned int handle);
+Bool secUtilConvertPhyaddress (ScrnInfoPtr scrn, unsigned int phy_addr, int size, unsigned int *handle);
+Bool secUtilConvertHandle     (ScrnInfoPtr scrn, unsigned int handle, unsigned int *phy_addr, int *size);
+
+typedef void (*DestroyDataFunc) (void *func_data, void *key_data);
+
+void* secUtilListAdd     (void *list, void *key, void *key_data);
+void* secUtilListRemove  (void *list, void *key);
+void* secUtilListGetData (void *list, void *key);
+Bool  secUtilListIsEmpty (void *list);
+void  secUtilListDestroyData (void *list, DestroyDataFunc func, void *func_data);
+void  secUtilListDestroy (void *list);
+
+Bool  secUtilSetDrmProperty (SECModePtr pSecMode, unsigned int obj_id, unsigned int obj_type,
+                             const char *prop_name, unsigned int value);
+
+Bool  secUtilEnsureExternalCrtc (ScrnInfoPtr scrn);
+
+G2dColorMode  secUtilGetG2dFormat (unsigned int id);
+unsigned int  secUtilGetDrmFormat (unsigned int id);
+SECFormatType secUtilGetColorType (unsigned int id);
+
+SECVideoBuf* _secUtilAllocVideoBuffer  (ScrnInfoPtr scrn, int id, int width, int height,
+                                        Bool scanout, Bool reset, Bool secure, const char *func);
+SECVideoBuf* _secUtilCreateVideoBuffer (ScrnInfoPtr scrn, int id, int width, int height,
+                                        Bool secure, const char *func);
+SECVideoBuf* secUtilVideoBufferRef     (SECVideoBuf *vbuf);
+void         _secUtilVideoBufferUnref  (SECVideoBuf *vbuf, const char *func);
+void         _secUtilFreeVideoBuffer   (SECVideoBuf *vbuf, const char *func);
+void         secUtilClearVideoBuffer   (SECVideoBuf *vbuf);
+Bool         _secUtilIsVbufValid       (SECVideoBuf *vbuf, const char *func);
+
+typedef void (*FreeVideoBufFunc) (SECVideoBuf *vbuf, void *data);
+void         secUtilAddFreeVideoBufferFunc     (SECVideoBuf *vbuf, FreeVideoBufFunc func, void *data);
+void         secUtilRemoveFreeVideoBufferFunc  (SECVideoBuf *vbuf, FreeVideoBufFunc func, void *data);
+
+#define secUtilAllocVideoBuffer(s,i,w,h,c,r,d)  _secUtilAllocVideoBuffer(s,i,w,h,c,r,d,__FUNCTION__)
+#define secUtilCreateVideoBuffer(s,i,w,h,d)     _secUtilCreateVideoBuffer(s,i,w,h,d,__FUNCTION__)
+#define secUtilVideoBufferUnref(v)  _secUtilVideoBufferUnref(v,__FUNCTION__)
+#define secUtilFreeVideoBuffer(v)   _secUtilFreeVideoBuffer(v,__FUNCTION__)
+#define secUtilIsVbufValid(v)       _secUtilIsVbufValid(v,__FUNCTION__)
+#define VBUF_IS_VALID(v)            secUtilIsVbufValid(v)
+#define VSTMAP(v)            ((v)?(v)->stamp:0)
+#define VBUF_IS_CONVERTING(v)       (!xorg_list_is_empty (&((v)->convert_info)))
+
+/* for debug */
+char*  secUtilDumpVideoBuffer (char *reply, int *len);
+
+#define list_rev_for_each_entry_safe(pos, tmp, head, member) \
+    for (pos = __container_of((head)->prev, pos, member), tmp = __container_of(pos->member.prev, pos, member);\
+         &pos->member != (head);\
+         pos = tmp, tmp = __container_of(pos->member.prev, tmp, member))
+
+#endif /* __SEC_UTIL_H__ */
diff --git a/src/xv/sec_video.c b/src/xv/sec_video.c
new file mode 100644 (file)
index 0000000..29c14cc
--- /dev/null
@@ -0,0 +1,3091 @@
+/*
+ * xserver-xorg-video-exynos
+ *
+ * Copyright 2004 Keith Packard
+ * Copyright 2005 Eric Anholt
+ * Copyright 2006 Nokia Corporation
+ * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+ *
+ * Contact: Boram Park <boram1288.park@samsung.com>
+ *
+ * Permission to use, copy, modify, distribute and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of the authors and/or copyright holders
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  The authors and
+ * copyright holders make no representations about the suitability of this
+ * software for any purpose.  It is provided "as is" without any express
+ * or implied warranty.
+ *
+ * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#include <pixman.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvproto.h>
+#include <fourcc.h>
+
+#include <fb.h>
+#include <fbdevhw.h>
+#include <damage.h>
+
+#include <xf86xv.h>
+
+#include "sec.h"
+
+#include "sec_accel.h"
+#include "sec_display.h"
+#include "sec_crtc.h"
+#include "sec_output.h"
+#include "sec_video.h"
+#include "sec_prop.h"
+#include "sec_util.h"
+#include "sec_wb.h"
+#include "sec_video_virtual.h"
+#include "sec_video_display.h"
+#include "sec_video_tvout.h"
+#include "sec_video_fourcc.h"
+#include "sec_converter.h"
+#include "sec_plane.h"
+#include "sec_xberc.h"
+
+#include "xv_types.h"
+
+#include <exynos_drm.h>
+
+#define DONT_FILL_ALPHA     -1
+#define SEC_MAX_PORT        16
+
+#define INBUF_NUM           6
+#define OUTBUF_NUM          3
+#define NUM_HW_LAYER        2
+
+#define OUTPUT_LCD   (1 << 0)
+#define OUTPUT_EXT   (1 << 1)
+#define OUTPUT_FULL  (1 << 8)
+
+static XF86VideoEncodingRec dummy_encoding[] =
+{
+    { 0, "XV_IMAGE", -1, -1, { 1, 1 } },
+    { 1, "XV_IMAGE", 4224, 4224, { 1, 1 } },
+};
+
+static XF86ImageRec images[] =
+{
+    XVIMAGE_YUY2,
+    XVIMAGE_SUYV,
+    XVIMAGE_UYVY,
+    XVIMAGE_SYVY,
+    XVIMAGE_ITLV,
+    XVIMAGE_YV12,
+    XVIMAGE_I420,
+    XVIMAGE_S420,
+    XVIMAGE_ST12,
+    XVIMAGE_NV12,
+    XVIMAGE_SN12,
+    XVIMAGE_NV21,
+    XVIMAGE_SN21,
+    XVIMAGE_RGB32,
+    XVIMAGE_SR32,
+    XVIMAGE_RGB565,
+    XVIMAGE_SR16,
+};
+
+static XF86VideoFormatRec formats[] =
+{
+    { 16, TrueColor },
+    { 24, TrueColor },
+    { 32, TrueColor },
+};
+
+static XF86AttributeRec attributes[] =
+{
+    { 0, 0, 270, "_USER_WM_PORT_ATTRIBUTE_ROTATION" },
+    { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_HFLIP" },
+    { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_VFLIP" },
+    { 0, -1, 1, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION" },
+    { 0, 0, OUTPUT_MODE_EXT_ONLY, "_USER_WM_PORT_ATTRIBUTE_OUTPUT" },
+    { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_SECURE" },
+    { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_CSC_RANGE" },
+};
+
+typedef enum
+{
+    PAA_MIN,
+    PAA_ROTATION,
+    PAA_HFLIP,
+    PAA_VFLIP,
+    PAA_PREEMPTION,
+    PAA_OUTPUT,
+    PAA_SECURE,
+    PAA_CSC_RANGE,
+    PAA_MAX
+} SECPortAttrAtom;
+
+static struct
+{
+    SECPortAttrAtom  paa;
+    const char      *name;
+    Atom             atom;
+} atoms[] =
+{
+    { PAA_ROTATION, "_USER_WM_PORT_ATTRIBUTE_ROTATION", None },
+    { PAA_HFLIP, "_USER_WM_PORT_ATTRIBUTE_HFLIP", None },
+    { PAA_VFLIP, "_USER_WM_PORT_ATTRIBUTE_VFLIP", None },
+    { PAA_PREEMPTION, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION", None },
+    { PAA_OUTPUT, "_USER_WM_PORT_ATTRIBUTE_OUTPUT", None },
+    { PAA_SECURE, "_USER_WM_PORT_ATTRIBUTE_SECURE", None },
+    { PAA_CSC_RANGE, "_USER_WM_PORT_ATTRIBUTE_CSC_RANGE", None },
+};
+
+enum
+{
+    ON_NONE,
+    ON_FB,
+    ON_WINDOW,
+    ON_PIXMAP
+};
+
+static char *drawing_type[4] = {"NONE", "FB", "WIN", "PIX"};
+
+typedef struct _PutData
+{
+    unsigned int id;
+    int          width;
+    int          height;
+    xRectangle   src;
+    xRectangle   dst;
+    void        *buf;
+    Bool         sync;
+    RegionPtr    clip_boxes;
+    void        *data;
+    DrawablePtr  pDraw;
+} PutData;
+
+/* SEC port information structure */
+typedef struct
+{
+    CARD32 prev_time;
+    int index;
+
+    /* attributes */
+    int rotate;
+    int hflip;
+    int vflip;
+    int preemption;     /* 1:high, 0:default, -1:low */
+    Bool secure;
+    int csc_range;
+
+    ScrnInfoPtr pScrn;
+    PutData d;
+    PutData old_d;
+
+    /* draw inform */
+    int          drawing;
+    int          hw_rotate;
+
+    int           in_width;
+    int           in_height;
+    xRectangle    in_crop;
+    SECVideoBuf  *inbuf[INBUF_NUM];
+    Bool          inbuf_is_fb;
+
+    /* converter */
+    SECCvt       *cvt;
+
+    /* layer */
+    SECLayer     *layer;
+    int           out_width;
+    int           out_height;
+    xRectangle    out_crop;
+    SECVideoBuf  *outbuf[OUTBUF_NUM];
+    int           outbuf_cvting;
+    DrawablePtr   pDamageDrawable[OUTBUF_NUM];
+
+    /* tvout */
+    int usr_output;
+    int old_output;
+    int grab_tvout;
+    SECVideoTv *tv;
+    void       *gem_list;
+    Bool skip_tvout;
+    Bool need_start_wb;
+    SECVideoBuf  *wait_vbuf;
+    CARD32 tv_prev_time;
+
+    /* count */
+    unsigned int put_counts;
+    OsTimerPtr timer;
+
+    Bool punched;
+    int  stream_cnt;
+    struct xorg_list link;
+} SECPortPriv, *SECPortPrivPtr;
+
+static RESTYPE event_drawable_type;
+
+typedef struct _SECVideoResource
+{
+    XID id;
+    RESTYPE type;
+
+    SECPortPrivPtr pPort;
+    ScrnInfoPtr pScrn;
+} SECVideoResource;
+
+typedef struct _SECVideoPortInfo
+{
+    ClientPtr client;
+    XvPortPtr pp;
+} SECVideoPortInfo;
+
+static int (*ddPutImage) (ClientPtr, DrawablePtr, struct _XvPortRec *, GCPtr,
+                          INT16, INT16, CARD16, CARD16,
+                          INT16, INT16, CARD16, CARD16,
+                          XvImagePtr, unsigned char *, Bool, CARD16, CARD16);
+
+static void _secVideoSendReturnBufferMessage (SECPortPrivPtr pPort, SECVideoBuf *vbuf, unsigned int *keys);
+static void SECVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit);
+static void _secVideoCloseInBuffer (SECPortPrivPtr pPort);
+static void _secVideoCloseOutBuffer (SECPortPrivPtr pPort, Bool close_layer);
+static void _secVideoCloseConverter (SECPortPrivPtr pPort);
+static Bool _secVideoSetOutputExternalProperty (DrawablePtr pDraw, Bool tvout);
+
+static int streaming_ports;
+static int registered_handler;
+static struct xorg_list layer_owners;
+
+static DevPrivateKeyRec video_port_key;
+#define VideoPortKey (&video_port_key)
+#define GetPortInfo(pDraw) ((SECVideoPortInfo*)dixLookupPrivate(&(pDraw)->devPrivates, VideoPortKey))
+
+#define NUM_IMAGES        (sizeof(images) / sizeof(images[0]))
+#define NUM_FORMATS       (sizeof(formats) / sizeof(formats[0]))
+#define NUM_ATTRIBUTES    (sizeof(attributes) / sizeof(attributes[0]))
+#define NUM_ATOMS         (sizeof(atoms) / sizeof(atoms[0]))
+
+#define ENSURE_AREA(off, lng, max) (lng = ((off + lng) > max ? (max - off) : lng))
+
+static CARD32
+_countPrint (OsTimerPtr timer, CARD32 now, pointer arg)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)arg;
+
+    if (pPort->timer)
+    {
+        TimerFree (pPort->timer);
+        pPort->timer = NULL;
+    }
+
+    ErrorF ("PutImage(%d) : %d fps. \n", pPort->index, pPort->put_counts);
+
+    pPort->put_counts = 0;
+
+    return 0;
+}
+
+static void
+_countFps (SECPortPrivPtr pPort)
+{
+    pPort->put_counts++;
+
+    if (pPort->timer)
+        return;
+
+    pPort->timer = TimerSet (NULL, 0, 1000, _countPrint, pPort);
+}
+
+static SECVideoPortInfo*
+_port_info (DrawablePtr pDraw)
+{
+    if (!pDraw)
+        return NULL;
+
+    if (pDraw->type == DRAWABLE_WINDOW)
+        return GetPortInfo ((WindowPtr)pDraw);
+    else
+       return GetPortInfo ((PixmapPtr)pDraw);
+}
+
+static PixmapPtr
+_getPixmap (DrawablePtr pDraw)
+{
+    if (pDraw->type == DRAWABLE_WINDOW)
+        return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw);
+    else
+        return (PixmapPtr) pDraw;
+}
+
+static XF86ImagePtr
+_get_image_info (int id)
+{
+    int i;
+
+    for (i = 0; i < NUM_IMAGES; i++)
+        if (images[i].id == id)
+            return &images[i];
+
+    return NULL;
+}
+
+static Atom
+_portAtom (SECPortAttrAtom paa)
+{
+    int i;
+
+    XDBG_RETURN_VAL_IF_FAIL (paa > PAA_MIN && paa < PAA_MAX, None);
+
+    for (i = 0; i < NUM_ATOMS; i++)
+    {
+        if (paa == atoms[i].paa)
+        {
+            if (atoms[i].atom == None)
+                atoms[i].atom = MakeAtom (atoms[i].name,
+                                          strlen (atoms[i].name), TRUE);
+
+            return atoms[i].atom;
+        }
+    }
+
+    XDBG_ERROR (MVDO, "Error: Unknown Port Attribute Name!\n");
+
+    return None;
+}
+
+static void
+_DestroyData (void *port, void *data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)port;
+    unsigned int handle = (unsigned int)data;
+
+    secUtilFreeHandle (pPort->pScrn, handle);
+}
+
+static Bool
+_secVideoGrabTvout (SECPortPrivPtr pPort)
+{
+    SECVideoPrivPtr pVideo = SECPTR(pPort->pScrn)->pVideoPriv;
+
+    if (pPort->grab_tvout)
+        return TRUE;
+
+    /* other port already grabbed */
+    if (pVideo->tvout_in_use)
+    {
+        XDBG_WARNING (MVDO, "*** pPort(%p) can't grab tvout. It's in use.\n", pPort);
+        return FALSE;
+    }
+
+    if (pPort->tv)
+    {
+        XDBG_ERROR (MVDO, "*** wrong handle if you reach here. %p \n", pPort->tv);
+        return FALSE;
+    }
+
+    pPort->grab_tvout = TRUE;
+    pVideo->tvout_in_use = TRUE;
+
+    XDBG_TRACE (MVDO, "pPort(%p) grabs tvout.\n", pPort);
+
+    return TRUE;
+}
+
+static void
+_secVideoUngrabTvout (SECPortPrivPtr pPort)
+{
+    if (pPort->tv)
+    {
+        secVideoTvDisconnect (pPort->tv);
+        pPort->tv = NULL;
+    }
+
+    /* This port didn't grab tvout */
+    if (!pPort->grab_tvout)
+        return;
+
+    _secVideoSetOutputExternalProperty (pPort->d.pDraw, FALSE);
+
+    if (pPort->need_start_wb)
+    {
+        SECWb *wb = secWbGet ();
+        if (wb)
+        {
+            secWbSetSecure (wb, pPort->secure);
+            secWbStart (wb);
+        }
+        pPort->need_start_wb = FALSE;
+    }
+
+    XDBG_TRACE (MVDO, "pPort(%p) ungrabs tvout.\n", pPort);
+
+    pPort->grab_tvout = FALSE;
+
+    if (pPort->pScrn)
+    {
+        SECVideoPrivPtr pVideo;
+        pVideo = SECPTR(pPort->pScrn)->pVideoPriv;
+        pVideo->tvout_in_use = FALSE;
+    }
+    pPort->wait_vbuf = NULL;
+}
+
+static int
+_secVideoGetTvoutMode (SECPortPrivPtr pPort)
+{
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pPort->pScrn)->pSecMode;
+    SECVideoPrivPtr pVideo = SECPTR(pPort->pScrn)->pVideoPriv;
+    SECDisplaySetMode disp_mode = secDisplayGetDispSetMode (pPort->pScrn);
+    int output = OUTPUT_LCD;
+
+    if (disp_mode == DISPLAY_SET_MODE_CLONE)
+    {
+        if (pPort->preemption > -1)
+        {
+            if (pVideo->video_output > 0 && streaming_ports == 1)
+            {
+                int video_output = pVideo->video_output - 1;
+
+                if (video_output == OUTPUT_MODE_DEFAULT)
+                    output = OUTPUT_LCD;
+                else if (video_output == OUTPUT_MODE_TVOUT)
+                    output = OUTPUT_LCD|OUTPUT_EXT|OUTPUT_FULL;
+                else
+                    output = OUTPUT_EXT|OUTPUT_FULL;
+            }
+            else if (streaming_ports == 1)
+            {
+                output = pPort->usr_output;
+                if (!(output & OUTPUT_FULL))
+                    output &= ~(OUTPUT_EXT);
+            }
+            else if (streaming_ports > 1)
+                output = OUTPUT_LCD;
+            else
+                XDBG_NEVER_GET_HERE (MVDO);
+        }
+        else
+            output = OUTPUT_LCD;
+    }
+    else if (disp_mode == DISPLAY_SET_MODE_EXT)
+    {
+        if (pPort->drawing == ON_PIXMAP)
+            output = OUTPUT_LCD;
+        else
+        {
+            xf86CrtcPtr pCrtc = secCrtcGetAtGeometry (pPort->pScrn,
+                          (int)pPort->d.pDraw->x, (int)pPort->d.pDraw->y,
+                          (int)pPort->d.pDraw->width, (int)pPort->d.pDraw->height);
+            int c = secCrtcGetConnectType (pCrtc);
+
+            if (c == DRM_MODE_CONNECTOR_LVDS || c == DRM_MODE_CONNECTOR_Unknown)
+                output = OUTPUT_LCD;
+            else if (c == DRM_MODE_CONNECTOR_HDMIA || c == DRM_MODE_CONNECTOR_HDMIB)
+                output = OUTPUT_EXT;
+            else if (c == DRM_MODE_CONNECTOR_VIRTUAL)
+                output = OUTPUT_EXT;
+            else
+                XDBG_NEVER_GET_HERE (MVDO);
+        }
+    }
+    else /* DISPLAY_SET_MODE_OFF */
+    {
+        output = OUTPUT_LCD;
+    }
+
+    if (pPort->drawing == ON_PIXMAP)
+        output = OUTPUT_LCD;
+
+    XDBG_DEBUG (MVDO, "drawing(%d) disp_mode(%d) preemption(%d) streaming_ports(%d) conn_mode(%d) usr_output(%d) video_output(%d) output(%x) skip(%d)\n",
+                pPort->drawing, disp_mode, pPort->preemption, streaming_ports, pSecMode->conn_mode,
+                pPort->usr_output, pVideo->video_output, output, pPort->skip_tvout);
+
+    return output;
+}
+
+static int
+_secVideodrawingOn (SECPortPrivPtr pPort)
+{
+    if (pPort->old_d.pDraw != pPort->d.pDraw)
+        pPort->drawing = ON_NONE;
+
+    if (pPort->drawing != ON_NONE)
+        return pPort->drawing;
+
+    if (pPort->d.pDraw->type == DRAWABLE_PIXMAP)
+        return ON_PIXMAP;
+    else if (pPort->d.pDraw->type == DRAWABLE_WINDOW)
+    {
+        PropertyPtr prop = secUtilGetWindowProperty ((WindowPtr)pPort->d.pDraw,
+                                                     "XV_ON_DRAWABLE");
+        if (prop && *(int*)prop->data > 0)
+            return ON_WINDOW;
+    }
+
+    return ON_FB;
+}
+
+static void
+_secVideoGetRotation (SECPortPrivPtr pPort, int *hw_rotate)
+{
+    SECVideoPrivPtr pVideo = SECPTR(pPort->pScrn)->pVideoPriv;
+
+    /*
+     * RR_Rotate_90:  Target turns to 90. UI turns to 270.
+     * RR_Rotate_270: Target turns to 270. UI turns to 90.
+     *
+     *     [Target]            ----------
+     *                         |        |
+     *     Top (RR_Rotate_90)  |        |  Top (RR_Rotate_270)
+     *                         |        |
+     *                         ----------
+     *     [UI,FIMC]           ----------
+     *                         |        |
+     *      Top (degree: 270)  |        |  Top (degree: 90)
+     *                         |        |
+     *                         ----------
+     */
+
+    if (pPort->drawing == ON_FB)
+        *hw_rotate = (pPort->rotate + pVideo->screen_rotate_degree) % 360;
+    else
+        *hw_rotate = pPort->rotate % 360;
+}
+
+static int
+_secVideoGetKeys (SECPortPrivPtr pPort, unsigned int *keys, unsigned int *type)
+{
+    XV_DATA_PTR data = (XV_DATA_PTR) pPort->d.buf;
+    int valid = XV_VALIDATE_DATA (data);
+
+    if (valid == XV_HEADER_ERROR)
+    {
+        XDBG_ERROR (MVDO, "XV_HEADER_ERROR\n");
+        return valid;
+    }
+    else if (valid == XV_VERSION_MISMATCH)
+    {
+        XDBG_ERROR (MVDO, "XV_VERSION_MISMATCH\n");
+        return valid;
+    }
+
+    if (keys)
+    {
+        keys[0] = data->YBuf;
+        keys[1] = data->CbBuf;
+        keys[2] = data->CrBuf;
+    }
+
+    if (type)
+        *type = data->BufType;
+
+    return 0;
+}
+
+static void
+_secVideoFreeInbuf (SECVideoBuf *vbuf, void *data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)data;
+    int i;
+
+    XDBG_RETURN_IF_FAIL (pPort->drawing != ON_NONE);
+
+    for (i = 0; i < INBUF_NUM; i++)
+        if (pPort->inbuf[i] == vbuf)
+        {
+            _secVideoSendReturnBufferMessage (pPort, vbuf, NULL);
+            pPort->inbuf[i] = NULL;
+            return;
+        }
+
+    XDBG_NEVER_GET_HERE (MVDO);
+}
+
+static void
+_secVideoFreeOutbuf (SECVideoBuf *vbuf, void *data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)data;
+    int i;
+
+    XDBG_RETURN_IF_FAIL (pPort->drawing != ON_NONE);
+
+    for (i = 0; i < OUTBUF_NUM; i++)
+        if (pPort->outbuf[i] == vbuf)
+        {
+            pPort->pDamageDrawable[i] = NULL;
+            pPort->outbuf[i] = NULL;
+            return;
+        }
+
+    XDBG_NEVER_GET_HERE (MVDO);
+}
+
+static SECLayer*
+_secVideoCreateLayer (SECPortPrivPtr pPort)
+{
+    ScrnInfoPtr pScrn = pPort->pScrn;
+    SECVideoPrivPtr pVideo = SECPTR(pScrn)->pVideoPriv;
+    DrawablePtr pDraw = pPort->d.pDraw;
+    xf86CrtcConfigPtr pCrtcConfig;
+    xf86OutputPtr pOutput = NULL;
+    int i;
+    xf86CrtcPtr pCrtc;
+    SECLayer   *layer;
+    Bool full = TRUE;
+    xRectangle src, dst;
+
+    pCrtc = secCrtcGetAtGeometry (pScrn, pDraw->x, pDraw->y, pDraw->width, pDraw->height);
+    XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, NULL);
+
+    pCrtcConfig = XF86_CRTC_CONFIG_PTR (pCrtc->scrn);
+    XDBG_RETURN_VAL_IF_FAIL (pCrtcConfig != NULL, NULL);
+
+    for (i = 0; i < pCrtcConfig->num_output; i++)
+    {
+        xf86OutputPtr pTemp = pCrtcConfig->output[i];
+        if (pTemp->crtc == pCrtc)
+        {
+            pOutput = pTemp;
+            break;
+        }
+    }
+    XDBG_RETURN_VAL_IF_FAIL (pOutput != NULL, NULL);
+
+    SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+    SECLayerOutput output = LAYER_OUTPUT_LCD;
+
+    if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+        pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown)
+    {
+        output = LAYER_OUTPUT_LCD;
+    }
+    else if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+             pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB ||
+             pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)
+    {
+        output = LAYER_OUTPUT_EXT;
+    }
+    else
+        XDBG_NEVER_GET_HERE (MVDO);
+
+    if (!secLayerFind (output, LAYER_LOWER2) || !secLayerFind (output, LAYER_LOWER1))
+        full = FALSE;
+
+    if (full)
+        return NULL;
+
+    layer = secLayerCreate (pScrn, output, LAYER_NONE);
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL);
+
+    src = dst = pPort->out_crop;
+    dst.x = pPort->d.dst.x;
+    dst.y = pPort->d.dst.y;
+
+    secLayerSetRect (layer, &src, &dst);
+    secLayerEnableVBlank (layer, TRUE);
+
+    xorg_list_add (&pPort->link, &layer_owners);
+
+    secLayerSetOffset (layer, pVideo->video_offset_x, pVideo->video_offset_y);
+
+    return layer;
+}
+
+static SECVideoBuf*
+_secVideoGetInbufZeroCopy (SECPortPrivPtr pPort, unsigned int *names, unsigned int buf_type)
+{
+    SECVideoBuf *inbuf = NULL;
+    int i, empty;
+    tbm_bo_handle bo_handle;
+
+    for (empty = 0; empty < INBUF_NUM; empty++)
+        if (!pPort->inbuf[empty])
+            break;
+
+    if (empty == INBUF_NUM)
+    {
+        XDBG_ERROR (MVDO, "now all inbufs in use!\n");
+        return NULL;
+    }
+
+    /* make sure both widths are same.*/
+    XDBG_RETURN_VAL_IF_FAIL (pPort->d.width == pPort->in_width, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (pPort->d.height == pPort->in_height, NULL);
+
+    inbuf = secUtilCreateVideoBuffer (pPort->pScrn, pPort->d.id,
+                                      pPort->in_width, pPort->in_height,
+                                      pPort->secure);
+    XDBG_RETURN_VAL_IF_FAIL (inbuf != NULL, NULL);
+
+    inbuf->crop = pPort->in_crop;
+
+    for (i = 0; i < PLANAR_CNT; i++)
+    {
+        if (names[i] > 0)
+        {
+            inbuf->keys[i] = names[i];
+
+            if (buf_type == XV_BUF_TYPE_LEGACY)
+            {
+                void *data = secUtilListGetData (pPort->gem_list, (void*)names[i]);
+                if (!data)
+                {
+                    secUtilConvertPhyaddress (pPort->pScrn, names[i], inbuf->lengths[i], &inbuf->handles[i]);
+
+                    pPort->gem_list = secUtilListAdd (pPort->gem_list, (void*)names[i],
+                                                      (void*)inbuf->handles[i]);
+                }
+                else
+                    inbuf->handles[i] = (unsigned int)data;
+
+                XDBG_DEBUG (MVDO, "%d, %p => %d \n", i, (void*)names[i], inbuf->handles[i]);
+            }
+            else
+            {
+                XDBG_GOTO_IF_FAIL (inbuf->lengths[i] > 0, fail_dma);
+                XDBG_GOTO_IF_FAIL (inbuf->bo[i] == NULL, fail_dma);
+
+                inbuf->bo[i] = tbm_bo_import (SECPTR (pPort->pScrn)->tbm_bufmgr, inbuf->keys[i]);
+                XDBG_GOTO_IF_FAIL (inbuf->bo[i] != NULL, fail_dma);
+
+                bo_handle = tbm_bo_get_handle(inbuf->bo[i], TBM_DEVICE_DEFAULT);
+                inbuf->handles[i] = bo_handle.u32;
+                XDBG_GOTO_IF_FAIL (inbuf->handles[i] > 0, fail_dma);
+
+                XDBG_DEBUG (MVDO, "%d, key(%d) => bo(%p) handle(%d)\n",
+                            i, inbuf->keys[i], inbuf->bo[i], inbuf->handles[i]);
+            }
+        }
+    }
+
+    /* not increase ref_cnt to free inbuf when converting/showing is done. */
+    pPort->inbuf[empty] = inbuf;
+
+    secUtilAddFreeVideoBufferFunc (inbuf, _secVideoFreeInbuf, pPort);
+
+    return inbuf;
+
+fail_dma:
+    if (inbuf)
+        secUtilFreeVideoBuffer (inbuf);
+
+    return NULL;
+}
+
+static SECVideoBuf*
+_secVideoGetInbufRAW (SECPortPrivPtr pPort)
+{
+    SECVideoBuf *inbuf = NULL;
+    void *vir_addr = NULL;
+    int i;
+    tbm_bo_handle bo_handle;
+
+    /* we can't access virtual pointer. */
+    XDBG_RETURN_VAL_IF_FAIL (pPort->secure == FALSE, NULL);
+
+    for (i = 0; i < INBUF_NUM; i++)
+    {
+        if (pPort->inbuf[i])
+            continue;
+
+        pPort->inbuf[i] = secUtilAllocVideoBuffer (pPort->pScrn, pPort->d.id,
+                                                   pPort->in_width, pPort->in_height,
+                                                   FALSE, FALSE, pPort->secure);
+        XDBG_GOTO_IF_FAIL (pPort->inbuf[i] != NULL, fail_raw_alloc);
+    }
+
+    for (i = 0; i < INBUF_NUM; i++)
+    {
+        XDBG_DEBUG (MVDO, "? inbuf(%d,%p) converting(%d) showing(%d)\n", i,
+                    pPort->inbuf[i], VBUF_IS_CONVERTING (pPort->inbuf[i]), pPort->inbuf[i]->showing);
+
+        if (pPort->inbuf[i] && !VBUF_IS_CONVERTING (pPort->inbuf[i]) && !pPort->inbuf[i]->showing)
+        {
+            /* increase ref_cnt to keep inbuf until stream_off. */
+            inbuf = secUtilVideoBufferRef (pPort->inbuf[i]);
+            break;
+        }
+    }
+
+    if (!inbuf)
+    {
+        XDBG_ERROR (MVDO, "now all inbufs in use!\n");
+        return NULL;
+    }
+
+    inbuf->crop = pPort->in_crop;
+
+    bo_handle = tbm_bo_map (inbuf->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+    vir_addr = bo_handle.ptr;
+    XDBG_RETURN_VAL_IF_FAIL (vir_addr != NULL, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (inbuf->size > 0, NULL);
+
+    if (pPort->d.width != pPort->in_width || pPort->d.height != pPort->in_height)
+    {
+        XF86ImagePtr image_info = _get_image_info (pPort->d.id);
+        int pitches[3] = {0,};
+        int offsets[3] = {0,};
+        int lengths[3] = {0,};
+        int width, height;
+
+        width = pPort->d.width;
+        height = pPort->d.height;
+
+        secVideoQueryImageAttrs (pPort->pScrn, pPort->d.id,
+                                 &width, &height,
+                                 pitches, offsets, lengths);
+
+        secUtilCopyImage (width, height,
+                          pPort->d.buf, width, height,
+                          pitches, offsets, lengths,
+                          vir_addr, inbuf->width, inbuf->height,
+                          inbuf->pitches, inbuf->offsets, inbuf->lengths,
+                          image_info->num_planes,
+                          image_info->horz_u_period,
+                          image_info->vert_u_period);
+    }
+    else
+        memcpy (vir_addr, pPort->d.buf, inbuf->size);
+
+    tbm_bo_unmap (inbuf->bo[0]);
+    secUtilCacheFlush (pPort->pScrn);
+    return inbuf;
+
+fail_raw_alloc:
+    _secVideoCloseInBuffer (pPort);
+    return NULL;
+}
+
+static SECVideoBuf*
+_secVideoGetInbuf (SECPortPrivPtr pPort)
+{
+    unsigned int keys[PLANAR_CNT] = {0,};
+    unsigned int buf_type = 0;
+    SECVideoBuf *inbuf = NULL;
+    SECPtr pSec = SECPTR (pPort->pScrn);
+
+    if (IS_ZEROCOPY (pPort->d.id))
+    {
+        if (_secVideoGetKeys (pPort, keys, &buf_type))
+            return NULL;
+
+        XDBG_RETURN_VAL_IF_FAIL (keys[0] > 0, NULL);
+
+        if (pPort->d.id == FOURCC_SN12 || pPort->d.id == FOURCC_ST12)
+            XDBG_RETURN_VAL_IF_FAIL (keys[1] > 0, NULL);
+
+        inbuf = _secVideoGetInbufZeroCopy (pPort, keys, buf_type);
+
+        XDBG_TRACE (MVDO, "keys: %d,%d,%d. stamp(%ld)\n", keys[0], keys[1], keys[2], inbuf->stamp);
+    }
+    else
+        inbuf = _secVideoGetInbufRAW (pPort);
+
+    if ((pSec->dump_mode & XBERC_DUMP_MODE_IA) && pSec->dump_info)
+    {
+        char file[128];
+        static int i;
+        snprintf (file, sizeof(file), "xvin_%c%c%c%c_%dx%d_p%d_%03d.%s",
+                  FOURCC_STR(inbuf->id),
+                  inbuf->width, inbuf->height, pPort->index, i++,
+                  IS_RGB(inbuf->id)?"bmp":"yuv");
+        secUtilDoDumpVBuf (pSec->dump_info, inbuf, file);
+    }
+
+    if (pSec->xvperf_mode & XBERC_XVPERF_MODE_IA)
+        inbuf->put_time = GetTimeInMillis ();
+
+    return inbuf;
+}
+
+static SECVideoBuf*
+_secVideoGetOutbufDrawable (SECPortPrivPtr pPort)
+{
+    ScrnInfoPtr pScrn = pPort->pScrn;
+    DrawablePtr pDraw = pPort->d.pDraw;
+    PixmapPtr pPixmap = (PixmapPtr)_getPixmap (pDraw);
+    SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPixmap);
+    Bool need_finish = FALSE;
+    SECVideoBuf *outbuf = NULL;
+    int empty;
+    tbm_bo_handle bo_handle;
+
+    for (empty = 0; empty < OUTBUF_NUM; empty++)
+        if (!pPort->outbuf[empty])
+            break;
+
+    if (empty == OUTBUF_NUM)
+    {
+        XDBG_ERROR (MVDO, "now all outbufs in use!\n");
+        return NULL;
+    }
+
+    if ((pDraw->width % 16) && (pPixmap->usage_hint != CREATE_PIXMAP_USAGE_XVIDEO))
+    {
+        ScreenPtr pScreen = pScrn->pScreen;
+        SECFbBoDataPtr bo_data = NULL;
+
+        pPixmap->usage_hint = CREATE_PIXMAP_USAGE_XVIDEO;
+        pScreen->ModifyPixmapHeader (pPixmap,
+                                     pDraw->width, pDraw->height,
+                                     pDraw->depth,
+                                     pDraw->bitsPerPixel,
+                                     pPixmap->devKind, 0);
+        XDBG_RETURN_VAL_IF_FAIL (privPixmap->bo != NULL, NULL);
+
+        tbm_bo_get_user_data(privPixmap->bo, TBM_BO_DATA_FB, (void**)&bo_data);
+        XDBG_RETURN_VAL_IF_FAIL (bo_data != NULL, NULL);
+        XDBG_RETURN_VAL_IF_FAIL ((bo_data->pos.x2 - bo_data->pos.x1) == pPort->out_width, NULL);
+        XDBG_RETURN_VAL_IF_FAIL ((bo_data->pos.y2 - bo_data->pos.y1) == pPort->out_height, NULL);
+    }
+
+    if (!privPixmap->bo)
+    {
+        need_finish = TRUE;
+        secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
+        XDBG_GOTO_IF_FAIL (privPixmap->bo != NULL, fail_drawable);
+    }
+
+    outbuf = secUtilCreateVideoBuffer (pScrn, FOURCC_RGB32,
+                                       pPort->out_width,
+                                       pPort->out_height,
+                                       pPort->secure);
+    XDBG_GOTO_IF_FAIL (outbuf != NULL, fail_drawable);
+    outbuf->crop = pPort->out_crop;
+
+    XDBG_TRACE (MVDO, "outbuf(%p)(%dx%d) created. [%s]\n",
+                outbuf, pPort->out_width, pPort->out_height,
+                (pPort->drawing==ON_PIXMAP)?"PIX":"WIN");
+
+    outbuf->bo[0] = tbm_bo_ref (privPixmap->bo);
+
+    bo_handle = tbm_bo_get_handle (outbuf->bo[0], TBM_DEVICE_DEFAULT);
+    outbuf->handles[0] = bo_handle.u32;
+    XDBG_GOTO_IF_FAIL (outbuf->handles[0] > 0, fail_drawable);
+
+    if (need_finish)
+        secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
+
+    pPort->pDamageDrawable[empty] = pPort->d.pDraw;
+
+//    RegionTranslate (pPort->d.clip_boxes, -pPort->d.dst.x, -pPort->d.dst.y);
+
+    /* not increase ref_cnt to free outbuf when converting/showing is done. */
+    pPort->outbuf[empty] = outbuf;
+
+    secUtilAddFreeVideoBufferFunc (outbuf, _secVideoFreeOutbuf, pPort);
+
+    return outbuf;
+
+fail_drawable:
+    if (outbuf)
+        secUtilFreeVideoBuffer (outbuf);
+
+    return NULL;
+}
+
+static SECVideoBuf*
+_secVideoGetOutbufFB (SECPortPrivPtr pPort)
+{
+    ScrnInfoPtr pScrn = pPort->pScrn;
+    SECVideoBuf *outbuf = NULL;
+    int i, next;
+
+    if (!pPort->layer)
+    {
+        pPort->layer = _secVideoCreateLayer (pPort);
+        XDBG_RETURN_VAL_IF_FAIL (pPort->layer != NULL, NULL);
+    }
+    else
+    {
+        SECVideoBuf *vbuf = secLayerGetBuffer (pPort->layer);
+        if (vbuf && (vbuf->width == pPort->out_width && vbuf->height == pPort->out_height))
+        {
+            xRectangle src = {0,}, dst = {0,};
+
+            secLayerGetRect (pPort->layer, &src, &dst);
+
+            /* CHECK */
+            if (pPort->d.dst.x != dst.x || pPort->d.dst.y != dst.y)
+            {
+                /* x,y can be changed when window is moved. */
+                dst.x = pPort->d.dst.x;
+                dst.y = pPort->d.dst.y;
+                secLayerSetRect (pPort->layer, &src, &dst);
+            }
+        }
+    }
+
+    for (i = 0; i < OUTBUF_NUM; i++)
+    {
+        SECPtr pSec = SECPTR (pPort->pScrn);
+
+        if (pPort->outbuf[i])
+            continue;
+
+        pPort->outbuf[i] = secUtilAllocVideoBuffer (pScrn, FOURCC_RGB32,
+                                                    pPort->out_width, pPort->out_height,
+                                                    (pSec->scanout)?TRUE:FALSE,
+                                                    FALSE, pPort->secure);
+        XDBG_GOTO_IF_FAIL (pPort->outbuf[i] != NULL, fail_fb);
+        pPort->outbuf[i]->crop = pPort->out_crop;
+
+        XDBG_TRACE (MVDO, "out bo(%p, %d, %dx%d) created. [FB]\n",
+                    pPort->outbuf[i]->bo[0], pPort->outbuf[i]->handles[0],
+                    pPort->out_width, pPort->out_height);
+    }
+
+    next = ++pPort->outbuf_cvting;
+    if (next >= OUTBUF_NUM)
+        next = 0;
+
+    for (i = 0; i < OUTBUF_NUM; i++)
+    {
+        XDBG_DEBUG (MVDO, "? outbuf(%d,%p) converting(%d)\n", next,
+                    pPort->outbuf[next], VBUF_IS_CONVERTING (pPort->outbuf[next]));
+
+        if (pPort->outbuf[next] && !VBUF_IS_CONVERTING (pPort->outbuf[next]))
+        {
+            /* increase ref_cnt to keep outbuf until stream_off. */
+            outbuf = secUtilVideoBufferRef (pPort->outbuf[next]);
+            break;
+        }
+
+        next++;
+        if (next >= OUTBUF_NUM)
+            next = 0;
+    }
+
+    if (!outbuf)
+    {
+        XDBG_ERROR (MVDO, "now all outbufs in use!\n");
+        return NULL;
+    }
+
+    pPort->outbuf_cvting = next;
+
+    return outbuf;
+
+fail_fb:
+    _secVideoCloseConverter (pPort);
+    _secVideoCloseOutBuffer (pPort, TRUE);
+
+    return NULL;
+}
+
+static SECVideoBuf*
+_secVideoGetOutbuf (SECPortPrivPtr pPort)
+{
+    if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
+        return _secVideoGetOutbufDrawable (pPort);
+    else /* ON_FB */
+        return _secVideoGetOutbufFB (pPort);
+}
+
+static void
+_secVideoCloseInBuffer (SECPortPrivPtr pPort)
+{
+    int i;
+
+    _secVideoUngrabTvout (pPort);
+
+    if (pPort->gem_list)
+    {
+        secUtilListDestroyData (pPort->gem_list, _DestroyData, pPort);
+        secUtilListDestroy (pPort->gem_list);
+        pPort->gem_list = NULL;
+    }
+
+    if (!IS_ZEROCOPY (pPort->d.id))
+        for (i = 0; i < INBUF_NUM; i++)
+        {
+            if (pPort->inbuf[i])
+            {
+                secUtilVideoBufferUnref (pPort->inbuf[i]);
+                pPort->inbuf[i] = NULL;
+            }
+        }
+
+    pPort->in_width = 0;
+    pPort->in_height = 0;
+    memset (&pPort->in_crop, 0, sizeof (xRectangle));
+
+    XDBG_DEBUG (MVDO, "done\n");
+}
+
+static void
+_secVideoCloseOutBuffer (SECPortPrivPtr pPort, Bool close_layer)
+{
+    int i;
+
+    /* before close outbuf, layer/cvt should be finished. */
+    if (close_layer && pPort->layer)
+    {
+        secLayerUnref (pPort->layer);
+        pPort->layer = NULL;
+        xorg_list_del (&pPort->link);
+    }
+
+    for (i = 0; i < OUTBUF_NUM; i++)
+    {
+        if (pPort->outbuf[i])
+        {
+            if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
+                XDBG_NEVER_GET_HERE (MVDO);
+
+            secUtilVideoBufferUnref (pPort->outbuf[i]);
+            pPort->outbuf[i] = NULL;
+        }
+    }
+
+    pPort->out_width = 0;
+    pPort->out_height = 0;
+    memset (&pPort->out_crop, 0, sizeof (xRectangle));
+    pPort->outbuf_cvting = -1;
+
+    XDBG_DEBUG (MVDO, "done\n");
+}
+
+static void
+_secVideoSendReturnBufferMessage (SECPortPrivPtr pPort, SECVideoBuf *vbuf, unsigned int *keys)
+{
+    static Atom return_atom = None;
+    SECVideoPortInfo *info = _port_info (pPort->d.pDraw);
+
+    if (return_atom == None)
+        return_atom = MakeAtom ("XV_RETURN_BUFFER",
+                                strlen ("XV_RETURN_BUFFER"), TRUE);
+
+    if (!info)
+        return;
+
+    xEvent event;
+
+    CLEAR (event);
+    event.u.u.type = ClientMessage;
+    event.u.u.detail = 32;
+    event.u.clientMessage.u.l.type = return_atom;
+    if (vbuf)
+    {
+        event.u.clientMessage.u.l.longs0 = (INT32)vbuf->keys[0];
+        event.u.clientMessage.u.l.longs1 = (INT32)vbuf->keys[1];
+        event.u.clientMessage.u.l.longs2 = (INT32)vbuf->keys[2];
+
+        XDBG_TRACE (MVDO, "%ld: %d,%d,%d out. diff(%ld)\n", vbuf->stamp,
+                    vbuf->keys[0], vbuf->keys[1], vbuf->keys[2], GetTimeInMillis()-vbuf->stamp);
+    }
+    else if (keys)
+    {
+        event.u.clientMessage.u.l.longs0 = (INT32)keys[0];
+        event.u.clientMessage.u.l.longs1 = (INT32)keys[1];
+        event.u.clientMessage.u.l.longs2 = (INT32)keys[2];
+
+        XDBG_TRACE (MVDO, "%d,%d,%d out. \n",
+                    keys[0], keys[1], keys[2]);
+    }
+    else
+        XDBG_NEVER_GET_HERE (MVDO);
+
+    WriteEventsToClient(info->client, 1, (xEventPtr) &event);
+
+    SECPtr pSec = SECPTR (pPort->pScrn);
+    if (pSec->xvperf_mode & XBERC_XVPERF_MODE_IA)
+    {
+        if (vbuf)
+        {
+            CARD32 cur, sub;
+            cur = GetTimeInMillis ();
+            sub = cur - vbuf->put_time;
+            ErrorF ("vbuf(%d,%d,%d)         retbuf  : %6ld ms\n",
+                    vbuf->keys[0], vbuf->keys[1], vbuf->keys[2], sub);
+        }
+        else if (keys)
+            ErrorF ("vbuf(%d,%d,%d)         retbuf  : 0 ms\n",
+                    keys[0], keys[1], keys[2]);
+        else
+            XDBG_NEVER_GET_HERE (MVDO);
+    }
+}
+
+static void
+_secVideoCvtCallback (SECCvt *cvt,
+                      SECVideoBuf *src,
+                      SECVideoBuf *dst,
+                      void *cvt_data,
+                      Bool error)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)cvt_data;
+    DrawablePtr pDamageDrawable = NULL;
+    int out_index;
+
+    XDBG_RETURN_IF_FAIL (pPort != NULL);
+    XDBG_RETURN_IF_FAIL (cvt != NULL);
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (src));
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (dst));
+    XDBG_DEBUG (MVDO, "++++++++++++++++++++++++ \n");
+    XDBG_DEBUG (MVDO, "cvt(%p) src(%p) dst(%p)\n", cvt, src, dst);
+
+    for (out_index = 0; out_index < OUTBUF_NUM; out_index++)
+        if (pPort->outbuf[out_index] == dst)
+            break;
+    XDBG_RETURN_IF_FAIL (out_index < OUTBUF_NUM);
+
+    if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
+        pDamageDrawable = pPort->pDamageDrawable[out_index];
+    else
+        pDamageDrawable = pPort->d.pDraw;
+
+    XDBG_RETURN_IF_FAIL (pDamageDrawable != NULL);
+
+    if (error)
+    {
+        DamageDamageRegion (pDamageDrawable, pPort->d.clip_boxes);
+        return;
+    }
+
+    SECPtr pSec = SECPTR (pPort->pScrn);
+    if ((pSec->dump_mode & XBERC_DUMP_MODE_IA) && pSec->dump_info)
+    {
+        char file[128];
+        static int i;
+        snprintf (file, sizeof(file), "xvout_p%d_%03d.bmp", pPort->index, i++);
+        secUtilDoDumpVBuf (pSec->dump_info, dst, file);
+    }
+
+    if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
+    {
+        DamageDamageRegion (pDamageDrawable, pPort->d.clip_boxes);
+    }
+    else if (pPort->layer)
+    {
+        SECVideoBuf *vbuf = secLayerGetBuffer (pPort->layer);
+        Bool reset_layer = FALSE;
+        xRectangle src_rect, dst_rect;
+
+        if (vbuf)
+            if (vbuf->width != pPort->out_width || vbuf->height != pPort->out_height)
+                reset_layer = TRUE;
+
+        secLayerGetRect (pPort->layer, &src_rect, &dst_rect);
+        if (memcmp (&src_rect, &pPort->out_crop, sizeof(xRectangle)) ||
+            dst_rect.x != pPort->d.dst.x ||
+            dst_rect.y != pPort->d.dst.y ||
+            dst_rect.width != pPort->out_crop.width ||
+            dst_rect.height != pPort->out_crop.height)
+            reset_layer = TRUE;
+
+        if (reset_layer)
+        {
+            secLayerFreezeUpdate (pPort->layer, TRUE);
+
+            src_rect = pPort->out_crop;
+            dst_rect.x = pPort->d.dst.x;
+            dst_rect.y = pPort->d.dst.y;
+            dst_rect.width = pPort->out_crop.width;
+            dst_rect.height = pPort->out_crop.height;
+
+            secLayerSetRect (pPort->layer, &src_rect, &dst_rect);
+            secLayerFreezeUpdate (pPort->layer, FALSE);
+            secLayerSetBuffer (pPort->layer, dst);
+        }
+        else
+            secLayerSetBuffer (pPort->layer, dst);
+
+        if (!secLayerIsVisible (pPort->layer))
+            secLayerShow (pPort->layer);
+    }
+
+    XDBG_DEBUG (MVDO, "++++++++++++++++++++++++.. \n");
+}
+
+static void
+_secVideoTvoutCvtCallback (SECCvt *cvt,
+                           SECVideoBuf *src,
+                           SECVideoBuf *dst,
+                           void *cvt_data,
+                           Bool error)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)cvt_data;
+
+    XDBG_RETURN_IF_FAIL (pPort != NULL);
+    XDBG_RETURN_IF_FAIL (cvt != NULL);
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (src));
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (dst));
+
+    XDBG_DEBUG (MVDO, "######################## \n");
+    XDBG_DEBUG (MVDO, "cvt(%p) src(%p) dst(%p)\n", cvt, src, dst);
+
+    if (pPort->wait_vbuf != src)
+        XDBG_WARNING (MVDO, "wait_vbuf(%p) != src(%p). \n",
+                      pPort->wait_vbuf, src);
+
+    pPort->wait_vbuf = NULL;
+
+    XDBG_DEBUG (MVDO, "########################.. \n");
+}
+
+static void
+_secVideoLayerNotifyFunc (SECLayer *layer, int type, void *type_data, void *data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)data;
+    SECVideoBuf *vbuf = (SECVideoBuf*)type_data;
+
+    if (type != LAYER_VBLANK)
+        return;
+
+    XDBG_RETURN_IF_FAIL (pPort != NULL);
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (vbuf));
+
+    if (pPort->wait_vbuf != vbuf)
+        XDBG_WARNING (MVDO, "wait_vbuf(%p) != vbuf(%p). \n",
+                      pPort->wait_vbuf, vbuf);
+
+    XDBG_DEBUG (MVBUF, "now_showing(%p). \n", vbuf);
+
+    pPort->wait_vbuf = NULL;
+}
+
+static void
+_secVideoEnsureConverter (SECPortPrivPtr pPort)
+{
+    if (pPort->cvt)
+        return;
+
+    pPort->cvt = secCvtCreate (pPort->pScrn, CVT_OP_M2M);
+    XDBG_RETURN_IF_FAIL (pPort->cvt != NULL);
+
+    secCvtAddCallback (pPort->cvt, _secVideoCvtCallback, pPort);
+}
+
+static void
+_secVideoCloseConverter (SECPortPrivPtr pPort)
+{
+    if (pPort->cvt)
+    {
+        secCvtDestroy (pPort->cvt);
+        pPort->cvt = NULL;
+    }
+
+    XDBG_TRACE (MVDO, "done. \n");
+}
+
+static void
+_secVideoStreamOff (SECPortPrivPtr pPort)
+{
+    _secVideoCloseConverter (pPort);
+    _secVideoCloseInBuffer (pPort);
+    _secVideoCloseOutBuffer (pPort, TRUE);
+
+    SECWb *wb = secWbGet ();
+    if (wb)
+    {
+        if (pPort->need_start_wb)
+        {
+            secWbSetSecure (wb, FALSE);
+            secWbStart (wb);
+            pPort->need_start_wb = FALSE;
+        }
+        else
+            secWbSetSecure (wb, FALSE);
+    }
+
+    if (pPort->d.clip_boxes)
+    {
+        RegionDestroy (pPort->d.clip_boxes);
+        pPort->d.clip_boxes = NULL;
+    }
+
+    memset (&pPort->old_d, 0, sizeof (PutData));
+    memset (&pPort->d, 0, sizeof (PutData));
+
+    pPort->need_start_wb = FALSE;
+    pPort->skip_tvout = FALSE;
+    pPort->usr_output = OUTPUT_LCD|OUTPUT_EXT;
+    pPort->outbuf_cvting = -1;
+    pPort->drawing = 0;
+    pPort->tv_prev_time = 0;
+    pPort->secure = FALSE;
+    pPort->csc_range = 0;
+    pPort->inbuf_is_fb = FALSE;
+
+    if (pPort->stream_cnt > 0)
+    {
+        pPort->stream_cnt = 0;
+        XDBG_SECURE (MVDO, "pPort(%d) stream off. \n", pPort->index);
+
+        if (pPort->preemption > -1)
+            streaming_ports--;
+
+        XDBG_WARNING_IF_FAIL (streaming_ports >= 0);
+    }
+
+    XDBG_TRACE (MVDO, "done. \n");
+}
+
+static Bool
+_secVideoCalculateSize (SECPortPrivPtr pPort)
+{
+    SECCvtProp src_prop = {0,}, dst_prop = {0,};
+
+    src_prop.id = pPort->d.id;
+    src_prop.width = pPort->d.width;
+    src_prop.height = pPort->d.height;
+    src_prop.crop = pPort->d.src;
+
+     dst_prop.id = FOURCC_RGB32;
+    if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
+    {
+        dst_prop.width = pPort->d.pDraw->width;
+        dst_prop.height = pPort->d.pDraw->height;
+        dst_prop.crop = pPort->d.dst;
+        dst_prop.crop.x -= pPort->d.pDraw->x;
+        dst_prop.crop.y -= pPort->d.pDraw->y;
+    }
+    else
+    {
+        dst_prop.width = pPort->d.dst.width;
+        dst_prop.height = pPort->d.dst.height;
+        dst_prop.crop = pPort->d.dst;
+        dst_prop.crop.x = 0;
+        dst_prop.crop.y = 0;
+    }
+
+    XDBG_DEBUG (MVDO, "(%dx%d : %d,%d %dx%d) => (%dx%d : %d,%d %dx%d)\n",
+                src_prop.width, src_prop.height,
+                src_prop.crop.x, src_prop.crop.y, src_prop.crop.width, src_prop.crop.height,
+                dst_prop.width, dst_prop.height,
+                dst_prop.crop.x, dst_prop.crop.y, dst_prop.crop.width, dst_prop.crop.height);
+
+    if (!secCvtEnsureSize (&src_prop, &dst_prop))
+        return FALSE;
+
+    XDBG_DEBUG (MVDO, "(%dx%d : %d,%d %dx%d) => (%dx%d : %d,%d %dx%d)\n",
+                src_prop.width, src_prop.height,
+                src_prop.crop.x, src_prop.crop.y, src_prop.crop.width, src_prop.crop.height,
+                dst_prop.width, dst_prop.height,
+                dst_prop.crop.x, dst_prop.crop.y, dst_prop.crop.width, dst_prop.crop.height);
+
+    XDBG_RETURN_VAL_IF_FAIL (src_prop.width > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (src_prop.height > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (src_prop.crop.width > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (src_prop.crop.height > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (dst_prop.width > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (dst_prop.height > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (dst_prop.crop.width > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (dst_prop.crop.height > 0, FALSE);
+
+    pPort->in_width = src_prop.width;
+    pPort->in_height = src_prop.height;
+    pPort->in_crop = src_prop.crop;
+
+    pPort->out_width = dst_prop.width;
+    pPort->out_height = dst_prop.height;
+    pPort->out_crop = dst_prop.crop;
+
+    return TRUE;
+}
+
+static void
+_secVideoPunchDrawable (SECPortPrivPtr pPort)
+{
+    PixmapPtr pPixmap = _getPixmap (pPort->d.pDraw);
+    SECPtr pSec = SECPTR (pPort->pScrn);
+
+    if (pPort->drawing != ON_FB || !pSec->pVideoPriv->video_punch)
+        return;
+
+    if (!pPort->punched)
+    {
+        secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
+        if (pPixmap->devPrivate.ptr)
+            memset (pPixmap->devPrivate.ptr, 0,
+                    pPixmap->drawable.width * pPixmap->drawable.height * 4);
+        secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
+        XDBG_TRACE (MVDO, "Punched (%dx%d) %p. \n",
+                    pPixmap->drawable.width, pPixmap->drawable.height,
+                    pPixmap->devPrivate.ptr);
+        pPort->punched = TRUE;
+        DamageDamageRegion (pPort->d.pDraw, pPort->d.clip_boxes);
+    }
+}
+
+static Bool
+_secVideoSupportID (int id)
+{
+    int i;
+
+    for (i = 0; i < NUM_IMAGES; i++)
+        if (images[i].id == id)
+            if (secCvtSupportFormat (CVT_OP_M2M, id))
+                return TRUE;
+
+    return FALSE;
+}
+
+static Bool
+_secVideoInBranch (WindowPtr p, WindowPtr w)
+{
+    for (; w; w = w->parent)
+        if (w == p)
+            return TRUE;
+
+    return FALSE;
+}
+
+/* Return the child of 'p' which includes 'w'. */
+static WindowPtr
+_secVideoGetChild (WindowPtr p, WindowPtr w)
+{
+    WindowPtr c;
+
+    for (c = w, w = w->parent; w; c = w, w = w->parent)
+        if (w == p)
+            return c;
+
+    return NULL;
+}
+
+/* ancestor : Return the parent of 'a' and 'b'.
+ * ancestor_a : Return the child of 'ancestor' which includes 'a'.
+ * ancestor_b : Return the child of 'ancestor' which includes 'b'.
+ */
+static Bool
+_secVideoGetAncestors (WindowPtr a, WindowPtr b,
+                       WindowPtr *ancestor,
+                       WindowPtr *ancestor_a,
+                       WindowPtr *ancestor_b)
+{
+    WindowPtr child_a, child_b;
+
+    if (!ancestor || !ancestor_a || !ancestor_b)
+        return FALSE;
+
+    for (child_b = b, b = b->parent; b; child_b = b, b = b->parent)
+    {
+        child_a = _secVideoGetChild (b, a);
+        if (child_a)
+        {
+            *ancestor   = b;
+            *ancestor_a = child_a;
+            *ancestor_b = child_b;
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+static int
+_secVideoCompareWindow (WindowPtr pWin1, WindowPtr pWin2)
+{
+    WindowPtr a, a1, a2, c;
+
+    if (!pWin1 || !pWin2)
+        return -2;
+
+    if (pWin1 == pWin2)
+        return 0;
+
+    if (_secVideoGetChild (pWin1, pWin2))
+        return -1;
+
+    if (_secVideoGetChild (pWin2, pWin1))
+        return 1;
+
+    if (!_secVideoGetAncestors (pWin1, pWin2, &a, &a1, &a2))
+        return -3;
+
+    for (c = a->firstChild; c; c = c->nextSib)
+    {
+        if (c == a1)
+            return 1;
+        else if (c == a2)
+            return -1;
+    }
+
+    return -4;
+}
+
+static void
+_secVideoArrangeLayerPos (SECPortPrivPtr pPort, Bool by_notify)
+{
+    SECPortPrivPtr pCur = NULL, pNext = NULL;
+    SECPortPrivPtr pAnother = NULL;
+    int i = 0;
+
+    xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
+    {
+        if (pCur == pPort)
+            continue;
+
+        i++;
+
+        if (!pAnother)
+            pAnother = pCur;
+        else
+            XDBG_WARNING (MVDO, "There are 3 more V4L2 ports. (%d) \n", i);
+    }
+
+    if (!pAnother)
+    {
+        SECLayerPos lpos = secLayerGetPos (pPort->layer);
+
+        if (lpos == LAYER_NONE)
+            secLayerSetPos (pPort->layer, LAYER_LOWER2);
+    }
+    else
+    {
+        SECLayerPos lpos1 = LAYER_NONE;
+        SECLayerPos lpos2 = LAYER_NONE;
+
+        if (pAnother->layer)
+            lpos1 = secLayerGetPos (pAnother->layer);
+        if (pPort->layer)
+            lpos2 = secLayerGetPos (pPort->layer);
+
+        if (lpos2 == LAYER_NONE)
+        {
+            int comp = _secVideoCompareWindow ((WindowPtr)pAnother->d.pDraw,
+                                               (WindowPtr)pPort->d.pDraw);
+
+            XDBG_TRACE (MVDO, "0x%08x : 0x%08x => %d \n",
+                        _XID(pAnother->d.pDraw), _XID(pPort->d.pDraw), comp);
+
+            if (comp == 1)
+            {
+                if (lpos1 != LAYER_LOWER1)
+                    secLayerSetPos (pAnother->layer, LAYER_LOWER1);
+                secLayerSetPos (pPort->layer, LAYER_LOWER2);
+            }
+            else if (comp == -1)
+            {
+                if (lpos1 != LAYER_LOWER2)
+                    secLayerSetPos (pAnother->layer, LAYER_LOWER2);
+                secLayerSetPos (pPort->layer, LAYER_LOWER1);
+            }
+            else
+            {
+                if (lpos1 == LAYER_LOWER1)
+                    secLayerSetPos (pPort->layer, LAYER_LOWER2);
+                else
+                    secLayerSetPos (pPort->layer, LAYER_LOWER1);
+            }
+        }
+        else
+        {
+            if (!by_notify)
+                return;
+
+            int comp = _secVideoCompareWindow ((WindowPtr)pAnother->d.pDraw,
+                                               (WindowPtr)pPort->d.pDraw);
+
+            XDBG_TRACE (MVDO, "0x%08x : 0x%08x => %d \n",
+                        _XID(pAnother->d.pDraw), _XID(pPort->d.pDraw), comp);
+
+            if ((comp == 1 && lpos1 != LAYER_LOWER1) ||
+                (comp == -1 && lpos2 != LAYER_LOWER1))
+                secLayerSwapPos (pAnother->layer, pPort->layer);
+        }
+    }
+}
+
+static void
+_secVideoStopTvout (ScrnInfoPtr pScrn)
+{
+    SECPtr pSec = (SECPtr) pScrn->driverPrivate;
+    XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0];
+    int i;
+
+    for (i = 0; i < SEC_MAX_PORT; i++)
+    {
+        SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
+
+        if (pPort->grab_tvout)
+        {
+            _secVideoUngrabTvout (pPort);
+            return;
+        }
+    }
+}
+
+/* TRUE  : current frame will be shown on TV. free after vblank.
+ * FALSE : current frame won't be shown on TV.
+ */
+static Bool
+_secVideoPutImageTvout (SECPortPrivPtr pPort, int output, SECVideoBuf *inbuf)
+{
+    ScrnInfoPtr pScrn = pPort->pScrn;
+    SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+    xRectangle tv_rect = {0,};
+    Bool first_put = FALSE;
+
+    if (!(output & OUTPUT_EXT))
+        return FALSE;
+
+    if (pPort->skip_tvout)
+        return FALSE;
+
+    if (!_secVideoGrabTvout(pPort))
+        goto fail_to_put_tvout;
+
+    if (!pPort->tv)
+    {
+        SECCvt *tv_cvt;
+        SECWb  *wb;
+
+        if (!secUtilEnsureExternalCrtc (pScrn))
+        {
+            XDBG_ERROR (MVDO, "failed : pPort(%d) connect external crtc\n", pPort->index);
+            goto fail_to_put_tvout;
+        }
+
+        pPort->tv = secVideoTvConnect (pScrn, pPort->d.id, LAYER_LOWER1);
+        XDBG_GOTO_IF_FAIL (pPort->tv != NULL, fail_to_put_tvout);
+
+        wb = secWbGet ();
+        if (wb)
+        {
+            pPort->need_start_wb = TRUE;
+
+            /* in case of VIRTUAL, wb's buffer is used by tvout. */
+            if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+                secWbStop (wb, FALSE);
+            else
+                secWbStop (wb, TRUE);
+        }
+
+        if (secWbIsRunning ())
+        {
+            XDBG_ERROR (MVDO, "failed: wb still running\n");
+            goto fail_to_put_tvout;
+        }
+
+        tv_cvt = secVideoTvGetConverter (pPort->tv);
+        if (tv_cvt)
+        {
+            /* HDMI    : SN12
+             * VIRTUAL : SN12 or RGB32
+             */
+            if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+            {
+                if (pSecMode->set_mode == DISPLAY_SET_MODE_CLONE)
+                {
+                    SECVideoBuf **vbufs = NULL;
+                    int bufnum = 0;
+
+                    secVideoTvSetConvertFormat (pPort->tv, FOURCC_SN12);
+
+                    /* In case of virtual, we draw video on full-size buffer
+                     * for virtual-adaptor
+                     */
+                    secVideoTvSetSize (pPort->tv,
+                                       pSecMode->ext_connector_mode.hdisplay,
+                                       pSecMode->ext_connector_mode.vdisplay);
+
+                    secVirtualVideoGetBuffers (pPort->pScrn, FOURCC_SN12,
+                                               pSecMode->ext_connector_mode.hdisplay,
+                                               pSecMode->ext_connector_mode.vdisplay,
+                                               &vbufs, &bufnum);
+
+                    XDBG_GOTO_IF_FAIL (vbufs != NULL, fail_to_put_tvout);
+                    XDBG_GOTO_IF_FAIL (bufnum > 0, fail_to_put_tvout);
+
+                    secVideoTvSetBuffer (pPort->tv, vbufs, bufnum);
+                }
+                else /* desktop */
+                    secVideoTvSetConvertFormat (pPort->tv, FOURCC_RGB32);
+            }
+            else
+                secVideoTvSetConvertFormat (pPort->tv, FOURCC_SN12);
+
+            secCvtAddCallback (tv_cvt, _secVideoTvoutCvtCallback, pPort);
+        }
+        else
+        {
+            SECLayer *layer = secVideoTvGetLayer (pPort->tv);
+            XDBG_GOTO_IF_FAIL (layer != NULL, fail_to_put_tvout);
+
+            secLayerEnableVBlank (layer, TRUE);
+            secLayerAddNotifyFunc (layer, _secVideoLayerNotifyFunc, pPort);
+        }
+
+        first_put = TRUE;
+    }
+
+    SECPtr pSec = SECPTR (pPort->pScrn);
+    if (pPort->wait_vbuf)
+    {
+        if (pSec->pVideoPriv->video_fps)
+        {
+            CARD32 cur, sub;
+            cur = GetTimeInMillis ();
+            sub = cur - pPort->tv_prev_time;
+            pPort->tv_prev_time = cur;
+
+            XDBG_DEBUG (MVDO, "tvout skip : sub(%ld) vbuf(%ld:%d,%d,%d) \n",
+                        sub, inbuf->stamp,
+                        inbuf->keys[0], inbuf->keys[1], inbuf->keys[2]);
+        }
+
+        return FALSE;
+    }
+    else if (pSec->pVideoPriv->video_fps)
+        pPort->tv_prev_time = GetTimeInMillis ();
+
+    if (!(output & OUTPUT_FULL))
+    {
+        tv_rect.x = pPort->d.dst.x
+                    - pSecMode->main_lcd_mode.hdisplay;
+        tv_rect.y = pPort->d.dst.y;
+        tv_rect.width = pPort->d.dst.width;
+        tv_rect.height = pPort->d.dst.height;
+    }
+    else
+    {
+        secUtilAlignRect (pPort->d.src.width, pPort->d.src.height,
+                          pSecMode->ext_connector_mode.hdisplay,
+                          pSecMode->ext_connector_mode.vdisplay,
+                          &tv_rect, TRUE);
+    }
+
+    /* if secVideoTvPutImage returns FALSE, it means this frame won't show on TV. */
+    if (!secVideoTvPutImage (pPort->tv, inbuf, &tv_rect, pPort->csc_range))
+        return FALSE;
+
+    if (first_put && !(output & OUTPUT_LCD))
+        _secVideoSetOutputExternalProperty (pPort->d.pDraw, TRUE);
+
+    pPort->wait_vbuf = inbuf;
+
+    return TRUE;
+
+fail_to_put_tvout:
+    _secVideoUngrabTvout (pPort);
+
+    pPort->skip_tvout = TRUE;
+
+    XDBG_TRACE (MVDO, "pPort(%d) skip tvout \n", pPort->index);
+
+    return FALSE;
+}
+
+static Bool
+_secVideoPutImageInbuf (SECPortPrivPtr pPort, SECVideoBuf *inbuf)
+{
+    if (!pPort->layer)
+    {
+        pPort->layer = _secVideoCreateLayer (pPort);
+        XDBG_RETURN_VAL_IF_FAIL (pPort->layer != NULL, FALSE);
+
+        _secVideoArrangeLayerPos (pPort, FALSE);
+    }
+
+    secLayerSetBuffer (pPort->layer, inbuf);
+
+    if (!secLayerIsVisible (pPort->layer))
+        secLayerShow (pPort->layer);
+
+    return TRUE;
+}
+
+static Bool
+_secVideoPutImageInternal (SECPortPrivPtr pPort, SECVideoBuf *inbuf)
+{
+    SECPtr pSec = (SECPtr) pPort->pScrn->driverPrivate;
+    SECCvtProp src_prop = {0,}, dst_prop = {0,};
+    SECVideoBuf *outbuf = NULL;
+
+    outbuf = _secVideoGetOutbuf (pPort);
+    if (!outbuf)
+        return FALSE;
+
+    /* cacheflush here becasue dst buffer can be created in _secVideoGetOutbuf() */
+    if (pPort->stream_cnt == 1)
+        if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
+            secUtilCacheFlush (pPort->pScrn);
+
+    XDBG_DEBUG (MVDO, "'%c%c%c%c' preem(%d) rot(%d) \n",
+                FOURCC_STR (pPort->d.id),
+                pPort->preemption, pPort->hw_rotate);
+
+    if (pPort->layer)
+        _secVideoArrangeLayerPos (pPort, FALSE);
+
+    _secVideoEnsureConverter (pPort);
+    XDBG_GOTO_IF_FAIL (pPort->cvt != NULL, fail_to_put);
+
+    src_prop.id = pPort->d.id;
+    src_prop.width = pPort->in_width;
+    src_prop.height = pPort->in_height;
+    src_prop.crop = pPort->in_crop;
+
+    dst_prop.id = FOURCC_RGB32;
+    dst_prop.width = pPort->out_width;
+    dst_prop.height = pPort->out_height;
+    dst_prop.crop = pPort->out_crop;
+
+    dst_prop.degree = pPort->hw_rotate;
+    dst_prop.hflip = pPort->hflip;
+    dst_prop.vflip = pPort->vflip;
+    dst_prop.secure = pPort->secure;
+    dst_prop.csc_range = pPort->csc_range;
+
+    if (!secCvtEnsureSize (&src_prop, &dst_prop))
+        goto fail_to_put;
+
+    if (!secCvtSetProperpty (pPort->cvt, &src_prop, &dst_prop))
+        goto fail_to_put;
+
+    if (!secCvtConvert (pPort->cvt, inbuf, outbuf))
+        goto fail_to_put;
+
+    if (pSec->pVideoPriv->video_fps)
+        _countFps (pPort);
+
+    secUtilVideoBufferUnref (outbuf);
+
+    return TRUE;
+
+fail_to_put:
+    if (outbuf)
+        secUtilVideoBufferUnref (outbuf);
+
+    _secVideoCloseConverter (pPort);
+    _secVideoCloseOutBuffer (pPort, TRUE);
+
+    return FALSE;
+}
+
+static Bool
+_secVideoSetHWPortsProperty (ScreenPtr pScreen, int nums)
+{
+    WindowPtr pWin = pScreen->root;
+    Atom atom_hw_ports;
+
+    /* With "X_HW_PORTS", an application can know
+     * how many fimc devices XV uses.
+     */
+    if (!pWin || !serverClient)
+        return FALSE;
+
+    atom_hw_ports = MakeAtom ("XV_HW_PORTS", strlen ("XV_HW_PORTS"), TRUE);
+
+    dixChangeWindowProperty (serverClient,
+                             pWin, atom_hw_ports, XA_CARDINAL, 32,
+                             PropModeReplace, 1, (unsigned int*)&nums, FALSE);
+
+    return TRUE;
+}
+
+static Bool
+_secVideoSetOutputExternalProperty (DrawablePtr pDraw, Bool video_only)
+{
+    WindowPtr pWin;
+    Atom atom_external;
+
+    XDBG_RETURN_VAL_IF_FAIL (pDraw != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (pDraw->type == DRAWABLE_WINDOW, FALSE);
+
+    pWin = (WindowPtr)pDraw;
+
+    atom_external = MakeAtom ("XV_OUTPUT_EXTERNAL", strlen ("XV_OUTPUT_EXTERNAL"), TRUE);
+
+    dixChangeWindowProperty (clients[CLIENT_ID(pDraw->id)],
+                             pWin, atom_external, XA_CARDINAL, 32,
+                             PropModeReplace, 1, (unsigned int*)&video_only, TRUE);
+
+    XDBG_TRACE (MVDO, "pDraw(0x%08x) video-only(%s)\n",
+                pDraw->id, (video_only)?"ON":"OFF");
+
+    return TRUE;
+}
+
+static void
+_secVideoRestackWindow (WindowPtr pWin, WindowPtr pOldNextSib)
+{
+    ScreenPtr pScreen = ((DrawablePtr)pWin)->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = (SECPtr) pScrn->driverPrivate;
+    SECVideoPrivPtr pVideo = pSec->pVideoPriv;
+
+    if (pVideo->RestackWindow)
+    {
+        pScreen->RestackWindow = pVideo->RestackWindow;
+
+        if (pScreen->RestackWindow)
+            (*pScreen->RestackWindow)(pWin, pOldNextSib);
+
+        pVideo->RestackWindow = pScreen->RestackWindow;
+        pScreen->RestackWindow = _secVideoRestackWindow;
+    }
+
+    if (!xorg_list_is_empty (&layer_owners))
+    {
+        SECPortPrivPtr pCur = NULL, pNext = NULL;
+        xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
+        {
+            if (_secVideoInBranch (pWin, (WindowPtr)pCur->d.pDraw))
+            {
+                XDBG_TRACE (MVDO, "Do re-arrange. 0x%08x(0x%08x) \n",
+                            _XID(pWin), _XID(pCur->d.pDraw));
+                _secVideoArrangeLayerPos (pCur, TRUE);
+                break;
+            }
+        }
+    }
+}
+
+static void
+_secVideoBlockHandler (pointer data, OSTimePtr pTimeout, pointer pRead)
+{
+    ScreenPtr pScreen = ((ScrnInfoPtr)data)->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = (SECPtr) pScrn->driverPrivate;
+    SECVideoPrivPtr pVideo = pSec->pVideoPriv;
+
+    pVideo->RestackWindow = pScreen->RestackWindow;
+    pScreen->RestackWindow = _secVideoRestackWindow;
+
+    if(registered_handler && _secVideoSetHWPortsProperty (pScreen, NUM_HW_LAYER))
+    {
+        RemoveBlockAndWakeupHandlers(_secVideoBlockHandler,
+                                     (WakeupHandlerProcPtr)NoopDDA, data);
+        registered_handler = FALSE;
+    }
+}
+
+static Bool
+_secVideoAddDrawableEvent (SECPortPrivPtr pPort)
+{
+    SECVideoResource *resource;
+    void *ptr=NULL;
+    int ret;
+
+    ret = dixLookupResourceByType (&ptr, pPort->d.pDraw->id,
+                             event_drawable_type, NULL, DixWriteAccess);
+    if (ret == Success)
+    {
+        return TRUE;
+    }
+
+    resource = malloc (sizeof (SECVideoResource));
+    if (resource == NULL)
+        return FALSE;
+
+    if (!AddResource (pPort->d.pDraw->id, event_drawable_type, resource))
+    {
+        free (resource);
+        return FALSE;
+    }
+
+    XDBG_TRACE (MVDO, "id(0x%08lx). \n", pPort->d.pDraw->id);
+
+    resource->id = pPort->d.pDraw->id;
+    resource->type = event_drawable_type;
+    resource->pPort = pPort;
+    resource->pScrn = pPort->pScrn;
+
+    return TRUE;
+}
+
+static int
+_secVideoRegisterEventDrawableGone (void *data, XID id)
+{
+    SECVideoResource *resource = (SECVideoResource*)data;
+
+    XDBG_TRACE (MVDO, "id(0x%08lx). \n", id);
+
+    if (!resource)
+        return Success;
+
+    if (!resource->pPort || !resource->pScrn)
+        return Success;
+
+    SECVideoStop (resource->pScrn, (pointer)resource->pPort, 1);
+
+    free(resource);
+
+    return Success;
+}
+
+static Bool
+_secVideoRegisterEventResourceTypes (void)
+{
+    event_drawable_type = CreateNewResourceType (_secVideoRegisterEventDrawableGone, "Sec Video Drawable");
+
+    if (!event_drawable_type)
+        return FALSE;
+
+    return TRUE;
+}
+
+int
+secVideoQueryImageAttrs (ScrnInfoPtr  pScrn,
+                         int          id,
+                         int         *w,
+                         int         *h,
+                         int         *pitches,
+                         int         *offsets,
+                         int         *lengths)
+{
+    int size = 0, tmp = 0;
+
+    *w = (*w + 1) & ~1;
+    if (offsets)
+        offsets[0] = 0;
+
+    switch (id)
+    {
+    /* RGB565 */
+    case FOURCC_SR16:
+    case FOURCC_RGB565:
+        size += (*w << 1);
+        if (pitches)
+            pitches[0] = size;
+        size *= *h;
+        if (lengths)
+            lengths[0] = size;
+        break;
+    /* RGB32 */
+    case FOURCC_SR32:
+    case FOURCC_RGB32:
+        size += (*w << 2);
+        if (pitches)
+            pitches[0] = size;
+        size *= *h;
+        if (lengths)
+            lengths[0] = size;
+        break;
+    /* YUV420, 3 planar */
+    case FOURCC_I420:
+    case FOURCC_S420:
+    case FOURCC_YV12:
+        *h = (*h + 1) & ~1;
+        size = (*w + 3) & ~3;
+        if (pitches)
+            pitches[0] = size;
+
+        size *= *h;
+        if (offsets)
+            offsets[1] = size;
+        if (lengths)
+            lengths[0] = size;
+
+        tmp = ((*w >> 1) + 3) & ~3;
+        if (pitches)
+            pitches[1] = pitches[2] = tmp;
+
+        tmp *= (*h >> 1);
+        size += tmp;
+        if (offsets)
+            offsets[2] = size;
+        if (lengths)
+            lengths[1] = tmp;
+
+        size += tmp;
+        if (lengths)
+            lengths[2] = tmp;
+
+        break;
+    /* YUV422, packed */
+    case FOURCC_UYVY:
+    case FOURCC_SYVY:
+    case FOURCC_ITLV:
+    case FOURCC_SUYV:
+    case FOURCC_YUY2:
+        size = *w << 1;
+        if (pitches)
+            pitches[0] = size;
+
+        size *= *h;
+        if (lengths)
+            lengths[0] = size;
+        break;
+
+    /* YUV420, 2 planar */
+    case FOURCC_SN12:
+    case FOURCC_NV12:
+    case FOURCC_SN21:
+    case FOURCC_NV21:
+        if (pitches)
+            pitches[0] = *w;
+
+        size = (*w) * (*h);
+        if (offsets)
+            offsets[1] = size;
+        if (lengths)
+            lengths[0] = size;
+
+        if (pitches)
+            pitches[1] = *w >> 1;
+
+        tmp = (*w) * (*h >> 1);
+        size += tmp;
+        if (lengths)
+            lengths[1] = tmp;
+        break;
+
+    /* YUV420, 2 planar, tiled */
+    case FOURCC_ST12:
+        if (pitches)
+            pitches[0] = *w;
+
+        size = ALIGN_TO_8KB(ALIGN_TO_128B(*w) * ALIGN_TO_32B(*h));
+        if (offsets)
+            offsets[1] = size;
+        if (lengths)
+            lengths[0] = size;
+
+        if (pitches)
+            pitches[1] = *w >> 1;
+
+        tmp = ALIGN_TO_8KB(ALIGN_TO_128B(*w) * ALIGN_TO_32B(*h >> 1));
+        size += tmp;
+        if (lengths)
+            lengths[1] = tmp;
+        break;
+    default:
+        return 0;
+    }
+
+    return size;
+}
+
+static int
+SECVideoGetPortAttribute (ScrnInfoPtr pScrn,
+                          Atom        attribute,
+                          INT32      *value,
+                          pointer     data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+
+    if (attribute == _portAtom (PAA_ROTATION))
+    {
+        *value = pPort->rotate;
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_HFLIP))
+    {
+        *value = pPort->hflip;
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_VFLIP))
+    {
+        *value = pPort->vflip;
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_PREEMPTION))
+    {
+        *value = pPort->preemption;
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_OUTPUT))
+    {
+        *value = pPort->usr_output;
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_SECURE))
+    {
+        *value = pPort->secure;
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_CSC_RANGE))
+    {
+        *value = pPort->csc_range;
+        return Success;
+    }
+
+    return BadMatch;
+}
+
+static int
+SECVideoSetPortAttribute (ScrnInfoPtr pScrn,
+                          Atom        attribute,
+                          INT32       value,
+                          pointer     data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+
+    if (attribute == _portAtom (PAA_ROTATION))
+    {
+        pPort->rotate = value;
+        XDBG_DEBUG (MVDO, "rotate(%d) \n", value);
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_HFLIP))
+    {
+        pPort->hflip = value;
+        XDBG_DEBUG (MVDO, "hflip(%d) \n", value);
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_VFLIP))
+    {
+        pPort->vflip = value;
+        XDBG_DEBUG (MVDO, "vflip(%d) \n", value);
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_PREEMPTION))
+    {
+        pPort->preemption = value;
+        XDBG_DEBUG (MVDO, "preemption(%d) \n", value);
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_OUTPUT))
+    {
+        if (value == OUTPUT_MODE_TVOUT)
+            pPort->usr_output = OUTPUT_LCD|OUTPUT_EXT|OUTPUT_FULL;
+        else if (value == OUTPUT_MODE_EXT_ONLY)
+            pPort->usr_output = OUTPUT_EXT|OUTPUT_FULL;
+        else
+            pPort->usr_output = OUTPUT_LCD|OUTPUT_EXT;
+
+        XDBG_DEBUG (MVDO, "output (%d) \n", value);
+
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_SECURE))
+    {
+        pPort->secure = value;
+        XDBG_DEBUG (MVDO, "secure(%d) \n", value);
+        return Success;
+    }
+    else if (attribute == _portAtom (PAA_CSC_RANGE))
+    {
+        pPort->csc_range = value;
+        XDBG_DEBUG (MVDO, "csc_range(%d) \n", value);
+        return Success;
+    }
+
+    return Success;
+}
+
+static void
+SECVideoQueryBestSize (ScrnInfoPtr pScrn,
+                       Bool motion,
+                       short vid_w, short vid_h,
+                       short dst_w, short dst_h,
+                       uint *p_w, uint *p_h,
+                       pointer data)
+{
+    SECCvtProp prop = {0,};
+
+    if (!p_w && !p_h)
+        return;
+
+    prop.width = dst_w;
+    prop.height = dst_h;
+    prop.crop.width = dst_w;
+    prop.crop.height = dst_h;
+
+    if (secCvtEnsureSize (NULL, &prop))
+    {
+        if (p_w)
+            *p_w = prop.width;
+        if (p_h)
+            *p_h = prop.height;
+    }
+    else
+    {
+        if (p_w)
+            *p_w = dst_w;
+        if (p_h)
+            *p_h = dst_h;
+    }
+}
+
+/**
+ * Give image size and pitches.
+ */
+static int
+SECVideoQueryImageAttributes (ScrnInfoPtr    pScrn,
+                              int            id,
+                              unsigned short *w,
+                              unsigned short *h,
+                              int            *pitches,
+                              int            *offsets)
+{
+    int width, height, size;
+
+    if (!w || !h)
+        return 0;
+
+    width = (int)*w;
+    height = (int)*h;
+
+    size = secVideoQueryImageAttrs (pScrn, id, &width, &height, pitches, offsets, NULL);
+
+    *w = (unsigned short)width;
+    *h = (unsigned short)height;
+
+    return size;
+}
+
+/* coordinates : HW, SCREEN, PORT
+ * BadRequest : when video can't be shown or drawn.
+ * Success    : A damage event(pixmap) and inbuf should be return.
+ *              If can't return a damage event and inbuf, should be return
+ *              BadRequest.
+ */
+static int
+SECVideoPutImage (ScrnInfoPtr pScrn,
+                  short src_x, short src_y, short dst_x, short dst_y,
+                  short src_w, short src_h, short dst_w, short dst_h,
+                  int id, uchar *buf, short width, short height,
+                  Bool sync, RegionPtr clip_boxes, pointer data,
+                  DrawablePtr pDraw)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode = (SECModePtr)SECPTR (pScrn)->pSecMode;
+    SECVideoPrivPtr pVideo = SECPTR (pScrn)->pVideoPriv;
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+    int output, ret;
+    Bool tvout = FALSE, lcdout = FALSE;
+    SECVideoBuf *inbuf = NULL;
+    int old_drawing;
+
+    if (!_secVideoSupportID (id))
+    {
+        XDBG_ERROR (MVDO, "'%c%c%c%c' not supported.\n", FOURCC_STR (id));
+        return BadRequest;
+    }
+
+    XDBG_TRACE (MVDO, "======================================= \n");
+
+    pPort->pScrn = pScrn;
+    pPort->d.id = id;
+    pPort->d.buf = buf;
+
+    if (pSec->xvperf_mode & XBERC_XVPERF_MODE_IA)
+    {
+        unsigned int keys[PLANAR_CNT] = {0,};
+        CARD32 cur, sub;
+        char temp[64];
+        cur = GetTimeInMillis ();
+        sub = cur - pPort->prev_time;
+        pPort->prev_time = cur;
+        temp[0] = '\0';
+        if (IS_ZEROCOPY (id))
+        {
+            _secVideoGetKeys (pPort, keys, NULL);
+            snprintf (temp, sizeof(temp), "%d,%d,%d", keys[0], keys[1], keys[2]);
+        }
+        ErrorF ("pPort(%p) put interval(%s) : %6ld ms\n", pPort, temp, sub);
+    }
+
+    if (IS_ZEROCOPY (pPort->d.id))
+    {
+        unsigned int keys[PLANAR_CNT] = {0,};
+        int i;
+
+        if (_secVideoGetKeys (pPort, keys, NULL))
+            return BadRequest;
+
+        for (i = 0; i < INBUF_NUM; i++)
+            if (pPort->inbuf[i] && pPort->inbuf[i]->keys[0] == keys[0])
+            {
+                XDBG_WARNING (MVDO, "got flink_id(%d) twice!\n", keys[0]);
+                _secVideoSendReturnBufferMessage (pPort, NULL, keys);
+                return Success;
+            }
+    }
+
+    pPort->d.width = width;
+    pPort->d.height = height;
+    pPort->d.src.x = src_x;
+    pPort->d.src.y = src_y;
+    pPort->d.src.width = src_w;
+    pPort->d.src.height = src_h;
+    pPort->d.dst.x = dst_x;    /* included pDraw'x */
+    pPort->d.dst.y = dst_y;    /* included pDraw'y */
+    pPort->d.dst.width = dst_w;
+    pPort->d.dst.height = dst_h;
+    pPort->d.sync = FALSE;
+    if (sync)
+        XDBG_WARNING (MVDO, "not support sync.\n");
+    pPort->d.data = data;
+    pPort->d.pDraw = pDraw;
+    if (clip_boxes)
+    {
+        if (!pPort->d.clip_boxes)
+            pPort->d.clip_boxes = RegionCreate(NullBox, 0);
+        RegionCopy (pPort->d.clip_boxes, clip_boxes);
+    }
+
+    old_drawing = pPort->drawing;
+    pPort->drawing = _secVideodrawingOn (pPort);
+    if (old_drawing != pPort->drawing)
+    {
+        _secVideoCloseConverter (pPort);
+        _secVideoCloseOutBuffer (pPort, TRUE);
+    }
+
+    _secVideoGetRotation (pPort, &pPort->hw_rotate);
+
+    if (pPort->drawing == ON_FB && pVideo->screen_rotate_degree > 0)
+        secUtilRotateRect (pSecMode->main_lcd_mode.hdisplay,
+                           pSecMode->main_lcd_mode.vdisplay,
+                           &pPort->d.dst,
+                           pVideo->screen_rotate_degree);
+
+    if (pPort->secure)
+        if (pPort->drawing != ON_FB)
+        {
+            XDBG_ERROR (MVDO, "secure video should drawn on FB.\n");
+            return BadRequest;
+        }
+
+    if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
+        if (!_secVideoAddDrawableEvent (pPort))
+            return BadRequest;
+
+    if (pPort->stream_cnt == 0)
+    {
+        pPort->stream_cnt++;
+
+        if (pPort->preemption > -1)
+            streaming_ports++;
+
+        XDBG_SECURE (MVDO, "pPort(%d) streams(%d) rotate(%d) flip(%d,%d) secure(%d) range(%d) usr_output(%x) on(%s)\n",
+                     pPort->index, streaming_ports,
+                     pPort->rotate, pPort->hflip, pPort->vflip, pPort->secure, pPort->csc_range,
+                     pPort->usr_output, drawing_type[pPort->drawing]);
+        XDBG_SECURE (MVDO, "id(%c%c%c%c) sz(%dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d)\n",
+                     FOURCC_STR (id), width, height,
+                     src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
+
+        if (streaming_ports > 1)
+            _secVideoStopTvout (pPort->pScrn);
+    }
+    else if (pPort->stream_cnt == 1)
+        pPort->stream_cnt++;
+
+    if (pPort->cvt)
+    {
+        SECCvtProp dst_prop;
+
+        secCvtGetProperpty (pPort->cvt, NULL, &dst_prop);
+
+        if (pPort->d.id != pPort->old_d.id ||
+            pPort->d.width != pPort->old_d.width ||
+            pPort->d.height != pPort->old_d.height ||
+            memcmp (&pPort->d.src, &pPort->old_d.src, sizeof (xRectangle)) ||
+            dst_prop.degree != pPort->hw_rotate ||
+            dst_prop.hflip != pPort->hflip ||
+            dst_prop.vflip != pPort->vflip ||
+            dst_prop.secure != pPort->secure ||
+            dst_prop.csc_range != pPort->csc_range)
+        {
+            XDBG_DEBUG (MVDO, "pPort(%d) streams(%d) rotate(%d) flip(%d,%d) secure(%d) range(%d) usr_output(%x) on(%s)\n",
+                        pPort->index, streaming_ports,
+                        pPort->rotate, pPort->hflip, pPort->vflip, pPort->secure, pPort->csc_range,
+                        pPort->usr_output, drawing_type[pPort->drawing]);
+            XDBG_DEBUG (MVDO, "pPort(%d) old_src(%dx%d %d,%d %dx%d) : new_src(%dx%d %d,%d %dx%d)\n",
+                        pPort->index, pPort->old_d.width, pPort->old_d.height,
+                        pPort->old_d.src.x, pPort->old_d.src.y,
+                        pPort->old_d.src.width, pPort->old_d.src.height,
+                        pPort->d.width, pPort->d.height,
+                        pPort->d.src.x, pPort->d.src.y,
+                        pPort->d.src.width, pPort->d.src.height);
+            _secVideoCloseConverter (pPort);
+            _secVideoCloseInBuffer (pPort);
+            pPort->inbuf_is_fb = FALSE;
+        }
+    }
+
+    if (memcmp (&pPort->d.dst, &pPort->old_d.dst, sizeof (xRectangle)))
+    {
+        XDBG_DEBUG (MVDO, "pPort(%d) old_dst(%d,%d %dx%d) : new_dst(%dx%d %dx%d)\n",
+                    pPort->index,
+                    pPort->old_d.dst.x, pPort->old_d.dst.y,
+                    pPort->old_d.dst.width, pPort->old_d.dst.height,
+                    pPort->d.dst.x, pPort->d.dst.y,
+                    pPort->d.dst.width, pPort->d.dst.height);
+        _secVideoCloseConverter (pPort);
+        _secVideoCloseOutBuffer (pPort, FALSE);
+        pPort->inbuf_is_fb = FALSE;
+    }
+
+    if (!_secVideoCalculateSize (pPort))
+        return BadRequest;
+
+    output = _secVideoGetTvoutMode (pPort);
+    if (!(output & OUTPUT_LCD) && pPort->old_output & OUTPUT_LCD)
+    {
+        /* If the video of LCD becomes off, we also turn off LCD layer. */
+        if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
+        {
+            PixmapPtr pPixmap = _getPixmap (pPort->d.pDraw);
+            SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPixmap);
+
+            secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
+            if (pPixmap->devPrivate.ptr && privPixmap->size > 0)
+                memset (pPixmap->devPrivate.ptr, 0, privPixmap->size);
+            secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
+
+            DamageDamageRegion (pPort->d.pDraw, pPort->d.clip_boxes);
+        }
+        else
+        {
+            _secVideoCloseConverter (pPort);
+            _secVideoCloseOutBuffer (pPort, TRUE);
+        }
+    }
+
+    if (pPort->d.id == FOURCC_SR32 &&
+        pPort->in_crop.width == pPort->out_crop.width &&
+        pPort->in_crop.height == pPort->out_crop.height &&
+        pPort->hw_rotate == 0)
+        pPort->inbuf_is_fb = TRUE;
+    else
+        pPort->inbuf_is_fb = FALSE;
+
+    inbuf = _secVideoGetInbuf (pPort);
+    if (!inbuf)
+        return BadRequest;
+
+    /* punch here not only LCD but also HDMI. */
+    if (pPort->drawing == ON_FB)
+        _secVideoPunchDrawable (pPort);
+
+    /* HDMI */
+    if (output & OUTPUT_EXT)
+        tvout = _secVideoPutImageTvout (pPort, output, inbuf);
+    else
+    {
+        _secVideoUngrabTvout (pPort);
+
+        SECWb *wb = secWbGet ();
+        if (wb)
+            secWbSetSecure (wb, pPort->secure);
+    }
+
+    /* LCD */
+    if (output & OUTPUT_LCD)
+    {
+        SECPtr pSec = SECPTR (pScrn);
+
+        if (pSec->isLcdOff)
+            XDBG_TRACE (MVDO, "port(%d) put image after dpms off.\n", pPort->index);
+        else if (pPort->inbuf_is_fb)
+            lcdout = _secVideoPutImageInbuf (pPort, inbuf);
+        else
+            lcdout = _secVideoPutImageInternal (pPort, inbuf);
+    }
+
+    if (lcdout || tvout)
+    {
+        ret = Success;
+    }
+    else
+    {
+        if (IS_ZEROCOPY (pPort->d.id))
+        {
+            int i;
+
+            for (i = 0; i < INBUF_NUM; i++)
+                if (pPort->inbuf[i] == inbuf)
+                {
+                    pPort->inbuf[i] = NULL;
+                    secUtilRemoveFreeVideoBufferFunc (inbuf, _secVideoFreeInbuf, pPort);
+                    break;
+                }
+            XDBG_WARNING_IF_FAIL (inbuf->ref_cnt == 1);
+        }
+        else
+            XDBG_WARNING_IF_FAIL (inbuf->ref_cnt == 2);
+
+        ret = BadRequest;
+    }
+
+    /* decrease ref_cnt here to pass ownership of inbuf to converter or tvout.
+     * in case of zero-copy, it will be really freed
+     * when converting is finished or tvout is finished.
+     */
+    secUtilVideoBufferUnref (inbuf);
+
+    pPort->old_d = pPort->d;
+    pPort->old_output = output;
+
+    XDBG_TRACE (MVDO, "=======================================.. \n");
+
+    return ret;
+}
+
+static int
+SECVideoDDPutImage (ClientPtr client,
+               DrawablePtr pDraw,
+               XvPortPtr pPort,
+               GCPtr pGC,
+               INT16 src_x, INT16 src_y,
+               CARD16 src_w, CARD16 src_h,
+               INT16 drw_x, INT16 drw_y,
+               CARD16 drw_w, CARD16 drw_h,
+               XvImagePtr format,
+               unsigned char *data, Bool sync, CARD16 width, CARD16 height)
+{
+    SECVideoPortInfo *info = _port_info (pDraw);
+    int ret;
+
+    if (info)
+    {
+        info->client = client;
+        info->pp = pPort;
+    }
+
+    ret = ddPutImage (client, pDraw, pPort, pGC,
+                      src_x, src_y, src_w, src_h,
+                      drw_x, drw_y, drw_w, drw_h,
+                      format, data, sync, width, height);
+
+    return ret;
+}
+
+static void
+SECVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+
+    if (!exit)
+        return;
+
+    XDBG_DEBUG (MVDO, "exit (%d) \n", exit);
+
+    _secVideoStreamOff (pPort);
+
+    pPort->preemption = 0;
+    pPort->rotate = 0;
+    pPort->hflip = 0;
+    pPort->vflip = 0;
+    pPort->punched = FALSE;
+}
+
+/**
+ * Set up all our internal structures.
+ */
+static XF86VideoAdaptorPtr
+secVideoSetupImageVideo (ScreenPtr pScreen)
+{
+    XF86VideoAdaptorPtr pAdaptor;
+    SECPortPrivPtr pPort;
+    int i;
+
+    pAdaptor = calloc (1, sizeof (XF86VideoAdaptorRec) +
+                       (sizeof (DevUnion) + sizeof (SECPortPriv)) * SEC_MAX_PORT);
+    if (!pAdaptor)
+        return NULL;
+
+    dummy_encoding[0].width = pScreen->width;
+    dummy_encoding[0].height = pScreen->height;
+
+    pAdaptor->type = XvWindowMask | XvPixmapMask | XvInputMask | XvImageMask;
+    pAdaptor->flags = VIDEO_OVERLAID_IMAGES;
+    pAdaptor->name = "SEC supporting Software Video Conversions";
+    pAdaptor->nEncodings = sizeof (dummy_encoding) / sizeof (XF86VideoEncodingRec);
+    pAdaptor->pEncodings = dummy_encoding;
+    pAdaptor->nFormats = NUM_FORMATS;
+    pAdaptor->pFormats = formats;
+    pAdaptor->nPorts = SEC_MAX_PORT;
+    pAdaptor->pPortPrivates = (DevUnion*)(&pAdaptor[1]);
+
+    pPort =
+        (SECPortPrivPtr) (&pAdaptor->pPortPrivates[SEC_MAX_PORT]);
+
+    for (i = 0; i < SEC_MAX_PORT; i++)
+    {
+        pAdaptor->pPortPrivates[i].ptr = &pPort[i];
+        pPort[i].index = i;
+        pPort[i].usr_output = OUTPUT_LCD|OUTPUT_EXT;
+        pPort[i].outbuf_cvting = -1;
+    }
+
+    pAdaptor->nAttributes = NUM_ATTRIBUTES;
+    pAdaptor->pAttributes = attributes;
+    pAdaptor->nImages = NUM_IMAGES;
+    pAdaptor->pImages = images;
+
+    pAdaptor->GetPortAttribute     = SECVideoGetPortAttribute;
+    pAdaptor->SetPortAttribute     = SECVideoSetPortAttribute;
+    pAdaptor->QueryBestSize        = SECVideoQueryBestSize;
+    pAdaptor->QueryImageAttributes = SECVideoQueryImageAttributes;
+    pAdaptor->PutImage             = SECVideoPutImage;
+    pAdaptor->StopVideo            = SECVideoStop;
+
+    if (!_secVideoRegisterEventResourceTypes ())
+    {
+        ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "Failed to register EventResourceTypes. \n");
+        return FALSE;
+    }
+
+    return pAdaptor;
+}
+
+static void
+SECVideoReplacePutImageFunc (ScreenPtr pScreen)
+{
+    int i;
+
+    XvScreenPtr xvsp = dixLookupPrivate (&pScreen->devPrivates,
+                                         XvGetScreenKey());
+    if (!xvsp)
+        return;
+
+    for (i = 0; i < xvsp->nAdaptors; i++)
+    {
+        XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
+        if (pAdapt->ddPutImage)
+        {
+            ddPutImage = pAdapt->ddPutImage;
+            pAdapt->ddPutImage = SECVideoDDPutImage;
+            break;
+        }
+    }
+
+    if (!dixRegisterPrivateKey (VideoPortKey, PRIVATE_WINDOW, sizeof (SECVideoPortInfo)))
+        return;
+    if (!dixRegisterPrivateKey (VideoPortKey, PRIVATE_PIXMAP, sizeof (SECVideoPortInfo)))
+        return;
+}
+
+#ifdef XV
+/**
+ * Set up everything we need for Xv.
+ */
+Bool secVideoInit (ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = (SECPtr) pScrn->driverPrivate;
+    SECVideoPrivPtr pVideo;
+
+    pVideo = (SECVideoPrivPtr)calloc (sizeof (SECVideoPriv), 1);
+    if (!pVideo)
+        return FALSE;
+
+    pVideo->pAdaptor[0] = secVideoSetupImageVideo (pScreen);
+    if (!pVideo->pAdaptor[0])
+    {
+        free (pVideo);
+        return FALSE;
+    }
+
+    pVideo->pAdaptor[1] = secVideoSetupVirtualVideo (pScreen);
+    if (!pVideo->pAdaptor[1])
+    {
+        free (pVideo->pAdaptor[0]);
+        free (pVideo);
+        return FALSE;
+    }
+
+    pVideo->pAdaptor[2] = secVideoSetupDisplayVideo (pScreen);
+    if (!pVideo->pAdaptor[2])
+    {
+        free (pVideo->pAdaptor[1]);
+        free (pVideo->pAdaptor[0]);
+        free (pVideo);
+        return FALSE;
+    }
+
+    xf86XVScreenInit (pScreen, pVideo->pAdaptor, ADAPTOR_NUM);
+
+    SECVideoReplacePutImageFunc (pScreen);
+    secVirtualVideoReplacePutStillFunc (pScreen);
+
+    if(registered_handler == FALSE)
+    {
+        RegisterBlockAndWakeupHandlers(_secVideoBlockHandler,
+                                       (WakeupHandlerProcPtr)NoopDDA, pScrn);
+        registered_handler = TRUE;
+    }
+
+    pSec->pVideoPriv = pVideo;
+    xorg_list_init (&layer_owners);
+
+    return TRUE;
+}
+
+/**
+ * Shut down Xv, used on regeneration.
+ */
+void secVideoFini (ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    SECPtr pSec = (SECPtr) pScrn->driverPrivate;
+    SECVideoPrivPtr pVideo = pSec->pVideoPriv;
+    SECPortPrivPtr pCur = NULL, pNext = NULL;
+    int i;
+
+    xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
+    {
+        if (pCur->tv)
+        {
+            secVideoTvDisconnect (pCur->tv);
+            pCur->tv = NULL;
+        }
+
+        if (pCur->d.clip_boxes)
+        {
+            RegionDestroy (pCur->d.clip_boxes);
+            pCur->d.clip_boxes = NULL;
+        }
+    }
+
+    for (i = 0; i < ADAPTOR_NUM; i++)
+        if (pVideo->pAdaptor[i])
+            free (pVideo->pAdaptor[i]);
+
+    free (pVideo);
+    pSec->pVideoPriv= NULL;
+}
+
+#endif
+
+void
+secVideoDpms (ScrnInfoPtr pScrn, Bool on)
+{
+    if (!on)
+    {
+        SECPtr pSec = (SECPtr) pScrn->driverPrivate;
+        XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0];
+        int i;
+
+        for (i = 0; i < SEC_MAX_PORT; i++)
+        {
+            SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
+            if (pPort->stream_cnt == 0)
+                continue;
+            XDBG_TRACE (MVDO, "port(%d) cvt stop.\n", pPort->index);
+            _secVideoCloseConverter (pPort);
+            _secVideoCloseInBuffer (pPort);
+        }
+    }
+}
+
+void
+secVideoScreenRotate (ScrnInfoPtr pScrn, int degree)
+{
+    SECPtr pSec = SECPTR(pScrn);
+    SECVideoPrivPtr pVideo = pSec->pVideoPriv;
+    int old_degree;
+
+    if (pVideo->screen_rotate_degree == degree)
+        return;
+
+    old_degree = pVideo->screen_rotate_degree;
+    pVideo->screen_rotate_degree = degree;
+    XDBG_DEBUG (MVDO, "screen rotate degree: %d\n", degree);
+
+    if (pSec->isLcdOff)
+        return;
+
+    SECPortPrivPtr pCur = NULL, pNext = NULL;
+    xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
+    {
+        SECModePtr pSecMode = pSec->pSecMode;
+        SECVideoBuf *old_vbuf, *rot_vbuf;
+        xRectangle rot_rect, dst_rect;
+        int rot_width, rot_height;
+        int scn_width, scn_height;
+        int degree_diff = degree - old_degree;
+
+        if (!pCur->layer)
+            continue;
+
+        old_vbuf = secLayerGetBuffer (pCur->layer);
+        XDBG_RETURN_IF_FAIL (old_vbuf != NULL);
+
+        rot_width = old_vbuf->width;
+        rot_height = old_vbuf->height;
+        rot_rect = old_vbuf->crop;
+        secUtilRotateArea (&rot_width, &rot_height, &rot_rect, degree_diff);
+
+        rot_vbuf = secUtilAllocVideoBuffer (pScrn, FOURCC_RGB32, rot_width, rot_height,
+                                         (pSec->scanout)?TRUE:FALSE, FALSE, pCur->secure);
+        XDBG_RETURN_IF_FAIL (rot_vbuf != NULL);
+        rot_vbuf->crop = rot_rect;
+
+        secUtilConvertBos (pScrn,
+                           old_vbuf->bo[0], old_vbuf->width, old_vbuf->height, &old_vbuf->crop, old_vbuf->width*4,
+                           rot_vbuf->bo[0], rot_vbuf->width, rot_vbuf->height, &rot_vbuf->crop, rot_vbuf->width*4,
+                           FALSE, degree_diff);
+
+        tbm_bo_map (rot_vbuf->bo[0], TBM_DEVICE_2D, TBM_OPTION_READ);
+        tbm_bo_unmap (rot_vbuf->bo[0]);
+
+        secLayerGetRect (pCur->layer, NULL, &dst_rect);
+
+        scn_width = (old_degree % 180)?pSecMode->main_lcd_mode.vdisplay:pSecMode->main_lcd_mode.hdisplay;
+        scn_height = (old_degree % 180)?pSecMode->main_lcd_mode.hdisplay:pSecMode->main_lcd_mode.vdisplay;
+
+        secUtilRotateRect (scn_width, scn_height, &dst_rect, degree_diff);
+
+        secLayerFreezeUpdate (pCur->layer, TRUE);
+        secLayerSetRect (pCur->layer, &rot_vbuf->crop, &dst_rect);
+        secLayerFreezeUpdate (pCur->layer, FALSE);
+        secLayerSetBuffer (pCur->layer, rot_vbuf);
+
+        secUtilVideoBufferUnref (rot_vbuf);
+
+        _secVideoCloseConverter (pCur);
+    }
+}
+
+void
+secVideoSwapLayers (ScreenPtr pScreen)
+{
+    SECPortPrivPtr pCur = NULL, pNext = NULL;
+    SECPortPrivPtr pPort1 = NULL, pPort2 = NULL;
+
+    xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
+    {
+        if (!pPort1)
+            pPort1 = pCur;
+        else if (!pPort2)
+            pPort2 = pCur;
+    }
+
+    if (pPort1 && pPort2)
+    {
+        secLayerSwapPos (pPort1->layer, pPort2->layer);
+        XDBG_TRACE (MVDO, "%p : %p \n", pPort1->layer, pPort2->layer);
+    }
+}
+
+Bool
+secVideoIsSecureMode (ScrnInfoPtr pScrn)
+{
+    SECPtr pSec = (SECPtr) pScrn->driverPrivate;
+    XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0];
+    int i;
+
+    for (i = 0; i < SEC_MAX_PORT; i++)
+    {
+        SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
+        if (pPort->secure)
+        {
+            XDBG_TRACE (MVDO, "pPort(%d) is secure.\n", pPort->index);
+            return TRUE;
+        }
+    }
+
+    XDBG_TRACE (MVDO, "no secure port.\n");
+
+    return FALSE;
+}
diff --git a/src/xv/sec_video.h b/src/xv/sec_video.h
new file mode 100644 (file)
index 0000000..54888bc
--- /dev/null
@@ -0,0 +1,86 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+#ifndef SEC_VIDEO_H
+#define SEC_VIDEO_H
+
+#define ADAPTOR_NUM  3
+
+enum
+{
+    OUTPUT_MODE_DEFAULT,
+    OUTPUT_MODE_TVOUT,
+    OUTPUT_MODE_EXT_ONLY,
+};
+
+typedef struct
+{
+#ifdef XV
+    XF86VideoAdaptorPtr pAdaptor[ADAPTOR_NUM];
+#endif
+
+    int video_punch;
+    int video_fps;
+    int video_sync;
+    int video_fimc;
+    int video_output;
+
+    int video_offset_x;
+    int video_offset_y;
+
+    /* extension */
+    int tvout_in_use;
+
+    Bool no_retbuf;
+
+    int screen_rotate_degree;
+
+    /* for configure notify */
+    RestackWindowProcPtr       RestackWindow;
+
+} SECVideoPriv, *SECVideoPrivPtr;
+
+Bool secVideoInit (ScreenPtr pScreen);
+void secVideoFini (ScreenPtr pScreen);
+
+void secVideoDpms (ScrnInfoPtr pScrn, Bool on);
+void secVideoScreenRotate (ScrnInfoPtr pScrn, int degree);
+void secVideoSwapLayers (ScreenPtr pScreen);
+
+int  secVideoQueryImageAttrs (ScrnInfoPtr  pScrn,
+                              int          id,
+                              int         *w,
+                              int         *h,
+                              int         *pitches,
+                              int         *offsets,
+                              int         *lengths);
+
+Bool secVideoIsSecureMode (ScrnInfoPtr pScrn);
+
+#endif // SEC_VIDEO_H
diff --git a/src/xv/sec_video_display.c b/src/xv/sec_video_display.c
new file mode 100644 (file)
index 0000000..e1f50c8
--- /dev/null
@@ -0,0 +1,618 @@
+/*
+ * xserver-xorg-video-exynos
+ *
+ * Copyright 2004 Keith Packard
+ * Copyright 2005 Eric Anholt
+ * Copyright 2006 Nokia Corporation
+ * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+ *
+ * Contact: Boram Park <boram1288.park@samsung.com>
+ *
+ * Permission to use, copy, modify, distribute and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of the authors and/or copyright holders
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  The authors and
+ * copyright holders make no representations about the suitability of this
+ * software for any purpose.  It is provided "as is" without any express
+ * or implied warranty.
+ *
+ * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#include <pixman.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvproto.h>
+#include <fourcc.h>
+
+#include <xf86xv.h>
+
+#include "sec.h"
+#include "sec_util.h"
+#include "sec_video_display.h"
+#include "sec_video_fourcc.h"
+#include "sec_layer.h"
+
+#include "fimg2d.h"
+
+#define SEC_MAX_PORT        1
+#define LAYER_BUF_CNT       3
+
+static XF86VideoEncodingRec dummy_encoding[] =
+{
+    { 0, "XV_IMAGE", -1, -1, { 1, 1 } },
+    { 1, "XV_IMAGE", 4224, 4224, { 1, 1 } },
+};
+
+static XF86VideoFormatRec formats[] =
+{
+    { 16, TrueColor },
+    { 24, TrueColor },
+    { 32, TrueColor },
+};
+
+static XF86AttributeRec attributes[] =
+{
+    { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_OVERLAY" },
+};
+
+typedef enum
+{
+    PAA_MIN,
+    PAA_OVERLAY,
+    PAA_MAX
+} SECPortAttrAtom;
+
+static struct
+{
+    SECPortAttrAtom  paa;
+    const char      *name;
+    Atom             atom;
+} atoms[] =
+{
+    { PAA_OVERLAY, "_USER_WM_PORT_ATTRIBUTE_OVERLAY", None },
+};
+
+typedef struct _GetData
+{
+    int width;
+    int height;
+    xRectangle   src;
+    xRectangle   dst;
+    DrawablePtr  pDraw;
+} GetData;
+
+/* SEC port information structure */
+typedef struct
+{
+    int index;
+
+    /* attributes */
+    Bool overlay;
+
+    ScrnInfoPtr pScrn;
+    GetData d;
+    GetData old_d;
+
+    /* layer */
+    SECLayer *layer;
+    SECVideoBuf *outbuf[LAYER_BUF_CNT];
+
+    int    stream_cnt;
+    struct xorg_list link;
+} SECPortPriv, *SECPortPrivPtr;
+
+static RESTYPE event_drawable_type;
+
+typedef struct _SECDisplayVideoResource
+{
+    XID id;
+    RESTYPE type;
+
+    SECPortPrivPtr pPort;
+    ScrnInfoPtr pScrn;
+} SECDisplayVideoResource;
+
+static void _secDisplayVideoCloseBuffers (SECPortPrivPtr pPort);
+static void SECDisplayVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit);
+
+#define NUM_FORMATS       (sizeof(formats) / sizeof(formats[0]))
+#define NUM_ATTRIBUTES    (sizeof(attributes) / sizeof(attributes[0]))
+#define NUM_ATOMS         (sizeof(atoms) / sizeof(atoms[0]))
+
+static PixmapPtr
+_getPixmap (DrawablePtr pDraw)
+{
+    if (pDraw->type == DRAWABLE_WINDOW)
+        return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw);
+    else
+        return (PixmapPtr) pDraw;
+}
+
+static Atom
+_portAtom (SECPortAttrAtom paa)
+{
+    int i;
+
+    XDBG_RETURN_VAL_IF_FAIL (paa > PAA_MIN && paa < PAA_MAX, None);
+
+    for (i = 0; i < NUM_ATOMS; i++)
+    {
+        if (paa == atoms[i].paa)
+        {
+            if (atoms[i].atom == None)
+                atoms[i].atom = MakeAtom (atoms[i].name,
+                                          strlen (atoms[i].name), TRUE);
+
+            return atoms[i].atom;
+        }
+    }
+
+    XDBG_ERROR (MDA, "Error: Unknown Port Attribute Name!\n");
+
+    return None;
+}
+
+static void
+_copyBuffer (DrawablePtr pDraw, SECVideoBuf *vbuf)
+{
+    PixmapPtr pPixmap = (PixmapPtr)_getPixmap (pDraw);
+    SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPixmap);
+    Bool need_finish = FALSE;
+    tbm_bo_handle bo_handle_src, bo_handle_dst;
+    G2dImage *src_image = NULL, *dst_image = NULL;
+
+    if (!privPixmap->bo)
+    {
+        need_finish = TRUE;
+        secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
+        XDBG_GOTO_IF_FAIL (privPixmap->bo != NULL, done_copy_buf);
+    }
+
+    bo_handle_src = tbm_bo_get_handle (privPixmap->bo, TBM_DEVICE_DEFAULT);
+    XDBG_GOTO_IF_FAIL (bo_handle_src.u32 > 0, done_copy_buf);
+
+    bo_handle_dst = tbm_bo_get_handle (vbuf->bo[0], TBM_DEVICE_DEFAULT);
+    XDBG_GOTO_IF_FAIL (bo_handle_dst.u32 > 0, done_copy_buf);
+
+    src_image = g2d_image_create_bo2 (G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB,
+                                      (unsigned int)pDraw->width,
+                                      (unsigned int)pDraw->height,
+                                      (unsigned int)bo_handle_src.u32,
+                                      (unsigned int)0,
+                                      (unsigned int)pDraw->width * 4);
+    XDBG_GOTO_IF_FAIL (src_image != NULL, done_copy_buf);
+
+    dst_image = g2d_image_create_bo2 (G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB,
+                                      (unsigned int)vbuf->width,
+                                      (unsigned int)vbuf->height,
+                                      (unsigned int)vbuf->handles[0],
+                                      (unsigned int)vbuf->handles[1],
+                                      (unsigned int)vbuf->pitches[0]);
+    XDBG_GOTO_IF_FAIL (dst_image != NULL, done_copy_buf);
+
+    tbm_bo_map (privPixmap->bo, TBM_DEVICE_MM, TBM_OPTION_READ);
+    tbm_bo_map (vbuf->bo[0], TBM_DEVICE_MM, TBM_OPTION_READ);
+
+    util_g2d_blend_with_scale (G2D_OP_SRC, src_image, dst_image,
+                               (int)vbuf->crop.x, (int)vbuf->crop.y,
+                               (unsigned int)vbuf->crop.width,
+                               (unsigned int)vbuf->crop.height,
+                               (int)vbuf->crop.x, (int)vbuf->crop.y,
+                               (unsigned int)vbuf->crop.width,
+                               (unsigned int)vbuf->crop.height,
+                               FALSE);
+    g2d_exec();
+
+    tbm_bo_unmap (privPixmap->bo);
+    tbm_bo_unmap (vbuf->bo[0]);
+
+done_copy_buf:
+    if (src_image)
+        g2d_image_free (src_image);
+    if (dst_image)
+        g2d_image_free (dst_image);
+    if (need_finish)
+        secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
+}
+
+static Bool
+_secDisplayVideoShowLayer (SECPortPrivPtr pPort, SECVideoBuf *vbuf,
+                           SECLayerOutput output, SECLayerPos lpos)
+{
+    xRectangle src_rect, dst_rect;
+
+    if (!pPort->layer)
+    {
+        SECModePtr pSecMode = (SECModePtr) SECPTR (pPort->pScrn)->pSecMode;
+
+        if (!secUtilEnsureExternalCrtc (pPort->pScrn))
+        {
+            XDBG_ERROR (MDA, "failed : pPort(%d) connect external crtc\n", pPort->index);
+            return FALSE;
+        }
+
+        pPort->layer = secLayerCreate (pPort->pScrn, output, lpos);
+        XDBG_RETURN_VAL_IF_FAIL (pPort->layer != NULL, FALSE);
+
+        if (output == LAYER_OUTPUT_EXT && pSecMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL)
+            secLayerEnableVBlank (pPort->layer, TRUE);
+    }
+
+    secLayerGetRect (pPort->layer, &src_rect, &dst_rect);
+
+    if (memcmp (&pPort->d.src, &src_rect, sizeof (xRectangle)) ||
+        memcmp (&pPort->d.dst, &dst_rect, sizeof (xRectangle)))
+    {
+        secLayerFreezeUpdate (pPort->layer, TRUE);
+        secLayerSetRect (pPort->layer, &pPort->d.src, &pPort->d.dst);
+        secLayerFreezeUpdate (pPort->layer, FALSE);
+    }
+
+    secLayerSetBuffer (pPort->layer, vbuf);
+    if (!secLayerIsVisible (pPort->layer))
+        secLayerShow (pPort->layer);
+
+    XDBG_DEBUG (MDA, "pDraw(0x%lx), fb_id(%d), (%d,%d %dx%d) (%d,%d %dx%d)\n",
+                pPort->d.pDraw->id, vbuf->fb_id,
+                pPort->d.src.x, pPort->d.src.y, pPort->d.src.width, pPort->d.src.height,
+                pPort->d.dst.x, pPort->d.dst.y, pPort->d.dst.width, pPort->d.dst.height);
+
+    return TRUE;
+}
+
+static void
+_secDisplayVideoHideLayer (SECPortPrivPtr pPort)
+{
+    if (!pPort->layer)
+        return;
+
+    secLayerUnref (pPort->layer);
+    pPort->layer = NULL;
+}
+
+static SECVideoBuf*
+_secDisplayVideoGetBuffer (SECPortPrivPtr pPort)
+{
+    int i;
+
+    for (i = 0; i < LAYER_BUF_CNT; i++)
+    {
+        if (!pPort->outbuf[i])
+        {
+            SECPtr pSec = SECPTR (pPort->pScrn);
+
+            pPort->outbuf[i] = secUtilAllocVideoBuffer (pPort->pScrn, FOURCC_RGB32,
+                                                        pPort->d.pDraw->width,
+                                                        pPort->d.pDraw->height,
+                                                        (pSec->scanout)?TRUE:FALSE,
+                                                        FALSE, FALSE);
+            XDBG_GOTO_IF_FAIL (pPort->outbuf[i] != NULL, fail_get_buf);
+            break;
+        }
+        else if (!pPort->outbuf[i]->showing)
+            break;
+    }
+
+    if (i == LAYER_BUF_CNT)
+    {
+        XDBG_ERROR (MDA, "now all outbufs in use!\n");
+        return NULL;
+    }
+
+    XDBG_DEBUG (MDA, "outbuf: stamp(%ld) index(%d) h(%d,%d,%d)\n",
+                pPort->outbuf[i]->stamp, i,
+                pPort->outbuf[i]->handles[0],
+                pPort->outbuf[i]->handles[1],
+                pPort->outbuf[i]->handles[2]);
+
+    pPort->outbuf[i]->crop = pPort->d.src;
+
+    _copyBuffer (pPort->d.pDraw, pPort->outbuf[i]);
+
+    return pPort->outbuf[i];
+
+fail_get_buf:
+    _secDisplayVideoCloseBuffers (pPort);
+    return NULL;
+}
+
+static void
+_secDisplayVideoCloseBuffers (SECPortPrivPtr pPort)
+{
+    int i;
+
+    for (i = 0; i < LAYER_BUF_CNT; i++)
+        if (pPort->outbuf[i])
+        {
+            secUtilVideoBufferUnref (pPort->outbuf[i]);
+            pPort->outbuf[i] = NULL;
+        }
+}
+
+static void
+_secDisplayVideoStreamOff (SECPortPrivPtr pPort)
+{
+    _secDisplayVideoHideLayer (pPort);
+    _secDisplayVideoCloseBuffers (pPort);
+
+    memset (&pPort->old_d, 0, sizeof (GetData));
+    memset (&pPort->d, 0, sizeof (GetData));
+
+    if (pPort->stream_cnt > 0)
+    {
+        pPort->stream_cnt = 0;
+        XDBG_SECURE (MDA, "pPort(%d) stream off. \n", pPort->index);
+    }
+
+    XDBG_TRACE (MDA, "done. \n");
+}
+
+static Bool
+_secDisplayVideoAddDrawableEvent (SECPortPrivPtr pPort)
+{
+    SECDisplayVideoResource *resource;
+    void *ptr=NULL;
+    int ret;
+
+    ret = dixLookupResourceByType (&ptr, pPort->d.pDraw->id,
+                                   event_drawable_type, NULL, DixWriteAccess);
+    if (ret == Success)
+    {
+        return TRUE;
+    }
+
+    resource = malloc (sizeof (SECDisplayVideoResource));
+    if (resource == NULL)
+        return FALSE;
+
+    if (!AddResource (pPort->d.pDraw->id, event_drawable_type, resource))
+    {
+        free (resource);
+        return FALSE;
+    }
+
+    XDBG_TRACE (MDA, "id(0x%08lx). \n", pPort->d.pDraw->id);
+
+    resource->id = pPort->d.pDraw->id;
+    resource->type = event_drawable_type;
+    resource->pPort = pPort;
+    resource->pScrn = pPort->pScrn;
+
+    return TRUE;
+}
+
+static int
+_secDisplayVideoRegisterEventDrawableGone (void *data, XID id)
+{
+    SECDisplayVideoResource *resource = (SECDisplayVideoResource*)data;
+
+    XDBG_TRACE (MDA, "id(0x%08lx). \n", id);
+
+    if (!resource)
+        return Success;
+
+    if (!resource->pPort || !resource->pScrn)
+        return Success;
+
+    SECDisplayVideoStop (resource->pScrn, (pointer)resource->pPort, 1);
+
+    free(resource);
+
+    return Success;
+}
+
+static Bool
+_secDisplayVideoRegisterEventResourceTypes (void)
+{
+    event_drawable_type = CreateNewResourceType (_secDisplayVideoRegisterEventDrawableGone, "Sec Video Drawable");
+
+    if (!event_drawable_type)
+        return FALSE;
+
+    return TRUE;
+}
+
+static int
+SECDisplayVideoGetPortAttribute (ScrnInfoPtr pScrn,
+                                 Atom        attribute,
+                                 INT32      *value,
+                                 pointer     data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+
+    if (attribute == _portAtom (PAA_OVERLAY))
+    {
+        *value = pPort->overlay;
+        return Success;
+    }
+
+    return BadMatch;
+}
+
+static int
+SECDisplayVideoSetPortAttribute (ScrnInfoPtr pScrn,
+                                 Atom        attribute,
+                                 INT32       value,
+                                 pointer     data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+
+    if (attribute == _portAtom (PAA_OVERLAY))
+    {
+        pPort->overlay = value;
+        XDBG_DEBUG (MDA, "overlay(%d) \n", value);
+        return Success;
+    }
+
+    return BadMatch;
+}
+
+static int
+SECDisplayVideoGetStill (ScrnInfoPtr pScrn,
+                         short vid_x, short vid_y, short drw_x, short drw_y,
+                         short vid_w, short vid_h, short drw_w, short drw_h,
+                         RegionPtr clipBoxes, pointer data,
+                         DrawablePtr pDraw)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+    SECVideoBuf *vbuf;
+    SECLayerOutput output;
+    SECLayerPos lpos;
+
+    XDBG_RETURN_VAL_IF_FAIL (pDraw->type == DRAWABLE_PIXMAP, BadRequest);
+
+    pPort->pScrn = pScrn;
+
+    pPort->d.width = pDraw->width;
+    pPort->d.height = pDraw->height;
+    pPort->d.src.x = drw_x;
+    pPort->d.src.y = drw_y;
+    pPort->d.src.width = drw_w;
+    pPort->d.src.height = drw_h;
+    pPort->d.dst.x = vid_x;
+    pPort->d.dst.y = vid_y;
+    pPort->d.dst.width = drw_w;
+    pPort->d.dst.height = drw_h;
+    pPort->d.pDraw = pDraw;
+
+    if (pPort->old_d.width != pPort->d.width ||
+        pPort->old_d.height != pPort->d.height)
+    {
+        _secDisplayVideoHideLayer (pPort);
+        _secDisplayVideoCloseBuffers (pPort);
+    }
+
+    if (!_secDisplayVideoAddDrawableEvent (pPort))
+        return BadRequest;
+
+    if (pPort->stream_cnt == 0)
+    {
+        pPort->stream_cnt++;
+
+        XDBG_SECURE (MDA, "pPort(%d) sz(%dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d)\n",
+                     pPort->index, pDraw->width, pDraw->height,
+                     drw_x, drw_y, drw_w, drw_h, vid_x, vid_y, vid_w, vid_h);
+    }
+
+    vbuf = _secDisplayVideoGetBuffer (pPort);
+    XDBG_RETURN_VAL_IF_FAIL (vbuf != NULL, BadRequest);
+
+    if (pPort->overlay)
+    {
+        output = LAYER_OUTPUT_EXT;
+        lpos = LAYER_UPPER;
+    }
+    else
+    {
+        XDBG_ERROR (MDA, "pPort(%d) implemented for only overlay\n", pPort->index);
+        return BadRequest;
+    }
+
+    if (!_secDisplayVideoShowLayer (pPort, vbuf, output, lpos))
+        return BadRequest;
+
+    pPort->old_d = pPort->d;
+
+    return Success;
+}
+
+static void
+SECDisplayVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+
+    XDBG_TRACE (MDA, "exit (%d) \n", exit);
+
+    if (!exit)
+        return;
+
+    _secDisplayVideoStreamOff (pPort);
+
+    pPort->overlay = FALSE;
+}
+
+static void
+SECDisplayVideoQueryBestSize (ScrnInfoPtr pScrn,
+                              Bool motion,
+                              short vid_w, short vid_h,
+                              short dst_w, short dst_h,
+                              unsigned int *p_w, unsigned int *p_h,
+                              pointer data)
+{
+    if (p_w)
+        *p_w = (unsigned int)dst_w & ~1;
+    if (p_h)
+        *p_h = (unsigned int)dst_h;
+}
+
+XF86VideoAdaptorPtr
+secVideoSetupDisplayVideo (ScreenPtr pScreen)
+{
+    XF86VideoAdaptorPtr pAdaptor;
+    SECPortPrivPtr pPort;
+    int i;
+
+    pAdaptor = calloc (1, sizeof (XF86VideoAdaptorRec) +
+                       (sizeof (DevUnion) + sizeof (SECPortPriv)) * SEC_MAX_PORT);
+    if (!pAdaptor)
+        return NULL;
+
+    dummy_encoding[0].width = pScreen->width;
+    dummy_encoding[0].height = pScreen->height;
+
+    pAdaptor->type = XvPixmapMask | XvOutputMask | XvStillMask;
+    pAdaptor->flags = VIDEO_OVERLAID_IMAGES;
+    pAdaptor->name = "SEC External Overlay Video";
+    pAdaptor->nEncodings = sizeof (dummy_encoding) / sizeof (XF86VideoEncodingRec);
+    pAdaptor->pEncodings = dummy_encoding;
+    pAdaptor->nFormats = NUM_FORMATS;
+    pAdaptor->pFormats = formats;
+    pAdaptor->nPorts = SEC_MAX_PORT;
+    pAdaptor->pPortPrivates = (DevUnion*)(&pAdaptor[1]);
+
+    pPort = (SECPortPrivPtr) (&pAdaptor->pPortPrivates[SEC_MAX_PORT]);
+
+    for (i = 0; i < SEC_MAX_PORT; i++)
+    {
+        pAdaptor->pPortPrivates[i].ptr = &pPort[i];
+        pPort[i].index = i;
+    }
+
+    pAdaptor->nAttributes = NUM_ATTRIBUTES;
+    pAdaptor->pAttributes = attributes;
+
+    pAdaptor->GetPortAttribute     = SECDisplayVideoGetPortAttribute;
+    pAdaptor->SetPortAttribute     = SECDisplayVideoSetPortAttribute;
+    pAdaptor->GetStill             = SECDisplayVideoGetStill;
+    pAdaptor->StopVideo            = SECDisplayVideoStop;
+    pAdaptor->QueryBestSize        = SECDisplayVideoQueryBestSize;
+
+    if (!_secDisplayVideoRegisterEventResourceTypes ())
+    {
+        ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "Failed to register EventResourceTypes. \n");
+        return FALSE;
+    }
+
+    return pAdaptor;
+}
diff --git a/src/xv/sec_video_display.h b/src/xv/sec_video_display.h
new file mode 100644 (file)
index 0000000..96bb952
--- /dev/null
@@ -0,0 +1,36 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+#ifndef __SEC_VIDEO_DISPLAY_H__
+#define __SEC_VIDEO_DISPLAY_H__
+
+/* setup display adaptor */
+XF86VideoAdaptorPtr secVideoSetupDisplayVideo (ScreenPtr pScreen);
+
+#endif
\ No newline at end of file
diff --git a/src/xv/sec_video_fourcc.h b/src/xv/sec_video_fourcc.h
new file mode 100644 (file)
index 0000000..2023e49
--- /dev/null
@@ -0,0 +1,326 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_VIDEO_FOURCC_H__
+#define __SEC_VIDEO_FOURCC_H__
+
+#include <fourcc.h>
+#include <drm_fourcc.h>
+
+#define C(b,m)              (((b) >> (m)) & 0xFF)
+#define B(c,s)              ((((unsigned int)(c)) & 0xff) << (s))
+#define FOURCC(a,b,c,d)     (B(d,24) | B(c,16) | B(b,8) | B(a,0))
+#define FOURCC_STR(id)      C(id,0), C(id,8), C(id,16), C(id,24)
+#define FOURCC_ID(str)      FOURCC(((char*)str)[0],((char*)str)[1],((char*)str)[2],((char*)str)[3])
+#define IS_ZEROCOPY(id)     ((C(id,0) == 'S') || id == FOURCC_ITLV)
+#define IS_RGB(id)           (id == FOURCC_RGB565 || id == FOURCC_RGB32 || \
+                              id == FOURCC_SR16 || id == FOURCC_SR32)
+
+/* Specific format for S.LSI
+ * 2x2 subsampled Cr:Cb plane 64x32 macroblocks
+ */
+#define DRM_FORMAT_NV12MT       fourcc_code('T', 'M', '1', '2')
+
+/* http://www.fourcc.org/yuv.php
+ * http://en.wikipedia.org/wiki/YUV
+ */
+#define FOURCC_RGB565   FOURCC('R','G','B','P')
+#define XVIMAGE_RGB565 \
+   { \
+    FOURCC_RGB565, \
+    XvRGB, \
+    LSBFirst, \
+    {'R','G','B','P', \
+        0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    16, \
+    XvPacked, \
+    1, \
+    16, 0x0000F800, 0x000007E0, 0x0000001F, \
+    0, 0, 0, 0, 0, 0, 0, 0, 0, \
+    {'R','G','B',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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_SR16   FOURCC('S','R','1','6')
+#define XVIMAGE_SR16 \
+   { \
+    FOURCC_SR16, \
+    XvRGB, \
+    LSBFirst, \
+    {'S','R','1','6', \
+        0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    16, \
+    XvPacked, \
+    1, \
+    16, 0x0000F800, 0x000007E0, 0x0000001F, \
+    0, 0, 0, 0, 0, 0, 0, 0, 0, \
+    {'R','G','B',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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_RGB24    FOURCC('R','G','B','3')
+#define XVIMAGE_RGB24 \
+   { \
+    FOURCC_RGB24, \
+    XvRGB, \
+    LSBFirst, \
+    {'R','G','B','3', \
+        0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    24, \
+    XvPacked, \
+    1, \
+    24, 0x00FF0000, 0x0000FF00, 0x000000FF, \
+    0, 0, 0, 0, 0, 0, 0, 0, 0, \
+    {'R','G','B',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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_RGB32    FOURCC('R','G','B','4')
+#define XVIMAGE_RGB32 \
+   { \
+    FOURCC_RGB32, \
+    XvRGB, \
+    LSBFirst, \
+    {'R','G','B','4', \
+        0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    32, \
+    XvPacked, \
+    1, \
+    24, 0x00FF0000, 0x0000FF00, 0x000000FF, \
+    0, 0, 0, 0, 0, 0, 0, 0, 0, \
+    {'X','R','G','B', \
+        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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_SR32    FOURCC('S','R','3','2')
+#define XVIMAGE_SR32 \
+   { \
+    FOURCC_SR32, \
+    XvRGB, \
+    LSBFirst, \
+    {'S','R','3','2', \
+        0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    32, \
+    XvPacked, \
+    1, \
+    24, 0x00FF0000, 0x0000FF00, 0x000000FF, \
+    0, 0, 0, 0, 0, 0, 0, 0, 0, \
+    {'X','R','G','B', \
+        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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_ST12     FOURCC('S','T','1','2')
+#define XVIMAGE_ST12 \
+   { \
+    FOURCC_ST12, \
+    XvYUV, \
+    LSBFirst, \
+    {'S','T','1','2', \
+      0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    12, \
+    XvPlanar, \
+    2, \
+    0, 0, 0, 0, \
+    8, 8, 8, \
+    1, 2, 2, \
+    1, 2, 2, \
+    {'Y','U','V', \
+      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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_SN12     FOURCC('S','N','1','2')
+#define XVIMAGE_SN12 \
+   { \
+    FOURCC_SN12, \
+    XvYUV, \
+    LSBFirst, \
+    {'S','N','1','2', \
+      0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    12, \
+    XvPlanar, \
+    2, \
+    0, 0, 0, 0, \
+    8, 8, 8, \
+    1, 2, 2, \
+    1, 2, 2, \
+    {'Y','U','V', \
+      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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_NV12     FOURCC('N','V','1','2')
+#define XVIMAGE_NV12 \
+   { \
+    FOURCC_NV12, \
+    XvYUV, \
+    LSBFirst, \
+    {'N','V','1','2', \
+      0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    12, \
+    XvPlanar, \
+    2, \
+    0, 0, 0, 0, \
+    8, 8, 8, \
+    1, 2, 2, \
+    1, 2, 2, \
+    {'Y','U','V', \
+      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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_SN21     FOURCC('S','N','2','1')
+#define XVIMAGE_SN21 \
+   { \
+    FOURCC_SN21, \
+    XvYUV, \
+    LSBFirst, \
+    {'S','N','2','1', \
+      0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    12, \
+    XvPlanar, \
+    2, \
+    0, 0, 0, 0, \
+    8, 8, 8, \
+    1, 2, 2, \
+    1, 2, 2, \
+    {'Y','V','U', \
+      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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_NV21     FOURCC('N','V','2','1')
+#define XVIMAGE_NV21 \
+   { \
+    FOURCC_NV21, \
+    XvYUV, \
+    LSBFirst, \
+    {'N','V','2','1', \
+      0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    12, \
+    XvPlanar, \
+    2, \
+    0, 0, 0, 0, \
+    8, 8, 8, \
+    1, 2, 2, \
+    1, 2, 2, \
+    {'Y','V','U', \
+      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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_S420     FOURCC('S','4','2','0')
+#define XVIMAGE_S420 \
+   { \
+    FOURCC_S420, \
+        XvYUV, \
+    LSBFirst, \
+    {'S','4','2','0', \
+      0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    12, \
+    XvPlanar, \
+    3, \
+    0, 0, 0, 0, \
+    8, 8, 8, \
+    1, 2, 2, \
+    1, 2, 2, \
+    {'Y','U','V', \
+      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}, \
+    XvTopToBottom \
+   }
+#define FOURCC_SUYV     FOURCC('S','U','Y','V')
+#define XVIMAGE_SUYV \
+   { \
+    FOURCC_SUYV, \
+        XvYUV, \
+    LSBFirst, \
+    {'S','U','Y','V', \
+      0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    16, \
+    XvPacked, \
+    1, \
+    0, 0, 0, 0, \
+    8, 8, 8, \
+    1, 2, 2, \
+    1, 1, 1, \
+    {'Y','U','Y','V', \
+      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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_SYVY   FOURCC('S','Y','V','Y')
+#define XVIMAGE_SYVY \
+   { \
+    FOURCC_SYVY, \
+        XvYUV, \
+    LSBFirst, \
+    {'S','Y','V','Y', \
+      0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    16, \
+    XvPacked, \
+    1, \
+    0, 0, 0, 0, \
+    8, 8, 8, \
+    1, 2, 2, \
+    1, 1, 1, \
+    {'U','Y','V','Y', \
+      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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_ITLV   FOURCC('I','T','L','V')
+#define XVIMAGE_ITLV \
+   { \
+    FOURCC_ITLV, \
+        XvYUV, \
+    LSBFirst, \
+    {'I','T','L','V', \
+      0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
+    16, \
+    XvPacked, \
+    1, \
+    0, 0, 0, 0, \
+    8, 8, 8, \
+    1, 2, 2, \
+    1, 1, 1, \
+    {'U','Y','V','Y', \
+      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}, \
+    XvTopToBottom \
+   }
+
+#define FOURCC_Y444  FOURCC('Y','4','4','4')
+
+
+#endif // __SEC_VIDEO_FOURCC_H__
diff --git a/src/xv/sec_video_tvout.c b/src/xv/sec_video_tvout.c
new file mode 100644 (file)
index 0000000..20492ce
--- /dev/null
@@ -0,0 +1,529 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#include "sec.h"
+#include "sec_display.h"
+#include "sec_crtc.h"
+#include "sec_output.h"
+#include "sec_accel.h"
+#include "sec_util.h"
+#include "sec_converter.h"
+#include "sec_video_tvout.h"
+#include "sec_video_virtual.h"
+#include "sec_video_fourcc.h"
+#include "sec_drm_ipp.h"
+#include "sec_layer.h"
+#include "sec_prop.h"
+
+#include <sys/ioctl.h>
+#include <exynos_drm.h>
+#include <drm_fourcc.h>
+
+#define TVBUF_NUM  3
+
+/* HW restriction (VP) */
+#define MIN_WIDTH  32
+#define MIN_HEIGHT 4
+#define MAX_WIDTH  1920
+#define MAX_HEIGHT 1080
+#define MIN_SCALE  0.25
+#define MAX_SCALE  16.0
+
+/* private structure */
+struct _SECVideoTv
+{
+    ScrnInfoPtr pScrn;
+
+    SECLayer *layer;
+    SECLayerPos lpos;
+
+    /* used if id is not supported in case of lpos == LAYER_LOWER1. */
+    SECCvt      *cvt;
+    SECVideoBuf **outbuf;
+    int          outbuf_index;
+    int          outbuf_num;
+
+    int          tv_width;
+    int          tv_height;
+
+    xRectangle   tv_rect;
+
+    unsigned int convert_id;
+};
+
+static Bool
+_secVieoTvCalSize (SECVideoTv* tv, int src_w, int src_h, int dst_w, int dst_h)
+{
+    float r;
+
+    if (src_w < MIN_WIDTH || src_h < MIN_HEIGHT)
+    {
+        XDBG_WARNING (MTVO, "size(%dx%d) must be more than (%dx%d).\n",
+                      src_w, src_h, MIN_WIDTH, MAX_WIDTH);
+    }
+
+    r = (float)dst_w / src_w;
+    if (r < MIN_SCALE || r > MAX_SCALE)
+    {
+        XDBG_WARNING (MTVO, "ratio_w(%f) is out of range(%f~%f).\n",
+                      r, MIN_SCALE, MAX_SCALE);
+    }
+
+    r = (float)dst_h / src_h;
+    if (r < MIN_SCALE || r > MAX_SCALE)
+    {
+        XDBG_WARNING (MTVO, "ratio_h(%d) is out of range(%f~%f).\n",
+                      r, MIN_SCALE, MAX_SCALE);
+    }
+
+    return TRUE;
+}
+
+static SECVideoBuf*
+_secVideoTvGetOutBuffer (SECVideoTv* tv, int width, int height, Bool secure)
+{
+    int i = tv->outbuf_index, j;
+
+    if (!tv->outbuf)
+    {
+        tv->outbuf = (SECVideoBuf**)calloc (tv->outbuf_num, sizeof (SECVideoBuf*));
+        XDBG_RETURN_VAL_IF_FAIL (tv->outbuf != NULL, NULL);
+    }
+
+    i++;
+    if (i >= tv->outbuf_num)
+        i = 0;
+
+    for (j = 0; j < tv->outbuf_num; j++)
+    {
+        if (tv->outbuf[i])
+        {
+            XDBG_DEBUG (MTVO, "outbuf(%p) converting(%d) showing(%d)\n",
+                        tv->outbuf[i], VBUF_IS_CONVERTING (tv->outbuf[i]), tv->outbuf[i]->showing);
+
+            if (tv->outbuf[i] && !VBUF_IS_CONVERTING (tv->outbuf[i]) && !tv->outbuf[i]->showing)
+            {
+                tv->outbuf_index = i;
+                return tv->outbuf[i];
+            }
+        }
+        else
+        {
+            SECPtr pSec = SECPTR (tv->pScrn);
+
+            tv->outbuf[i] = secUtilAllocVideoBuffer (tv->pScrn, tv->convert_id, width, height,
+                                                     (pSec->scanout)?TRUE:FALSE, TRUE, secure);
+            XDBG_RETURN_VAL_IF_FAIL (tv->outbuf[i] != NULL, NULL);
+
+            XDBG_DEBUG (MTVO, "outbuf(%p, %c%c%c%c)\n", tv->outbuf[i], FOURCC_STR (tv->convert_id));
+
+            tv->outbuf_index = i;
+            return tv->outbuf[i];
+        }
+
+        i++;
+        if (i >= tv->outbuf_num)
+            i = 0;
+    }
+
+#if 0
+    char buffers[1024];
+    CLEAR (buffers);
+    for (j = 0; j < tv->outbuf_num; j++)
+    {
+        if (tv->outbuf[j])
+            snprintf (buffers, 1024, "%s %d(%d,%d) ", buffers, tv->outbuf[j]->keys[0],
+            VBUF_IS_CONVERTING (tv->outbuf[j]), tv->outbuf[j]->showing);
+    }
+
+    XDBG_ERROR (MTVO, "now all outbufs in use! %s\n", buffers);
+#else
+    XDBG_ERROR (MTVO, "now all outbufs in use!\n");
+#endif
+
+    return NULL;
+}
+
+static Bool
+_secVideoTvLayerEnsure (SECVideoTv* tv)
+{
+    SECLayer *layer;
+
+    if (tv->layer)
+        return TRUE;
+
+    XDBG_RETURN_VAL_IF_FAIL (tv->lpos != LAYER_NONE, FALSE);
+
+    layer = secLayerCreate (tv->pScrn, LAYER_OUTPUT_EXT, tv->lpos);
+    XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
+
+    tv->layer = layer;
+
+    return TRUE;
+}
+
+static void
+_secVideoTvLayerDestroy (SECVideoTv* tv)
+{
+    if (tv->layer)
+    {
+        secLayerUnref (tv->layer);
+        tv->layer = NULL;
+    }
+}
+
+static int
+_secVideoTvPutImageInternal (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *rect)
+{
+    int ret = 0;
+
+    XDBG_DEBUG (MTVO, "rect (%d,%d %dx%d) \n",
+                rect->x, rect->y, rect->width, rect->height);
+
+    secLayerSetRect (tv->layer, &vbuf->crop, rect);
+
+    if (tv->lpos == LAYER_LOWER1)
+        if (!_secVieoTvCalSize (tv, vbuf->width, vbuf->height,
+                                rect->width, rect->height))
+            return 0;
+
+    ret = secLayerSetBuffer (tv->layer, vbuf);
+
+    if (ret == 0)
+        return 0;
+
+    secLayerShow (tv->layer);
+
+    return ret;
+}
+
+static void
+_secVideoTvCvtCallback (SECCvt *cvt,
+                        SECVideoBuf *src,
+                        SECVideoBuf *dst,
+                        void *cvt_data,
+                        Bool error)
+{
+    SECVideoTv *tv = (SECVideoTv*)cvt_data;
+    int i;
+
+    XDBG_RETURN_IF_FAIL (tv != NULL);
+    XDBG_RETURN_IF_FAIL (cvt != NULL);
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (dst));
+
+    XDBG_DEBUG (MTVO, "++++++++++++++++++++++++ \n");
+
+    for (i = 0; i < tv->outbuf_num; i++)
+        if (tv->outbuf[i] == dst)
+            break;
+    XDBG_RETURN_IF_FAIL (i < tv->outbuf_num);
+
+    _secVideoTvPutImageInternal (tv, dst, &tv->tv_rect);
+
+    XDBG_DEBUG (MTVO, "++++++++++++++++++++++++.. \n");
+}
+
+SECVideoTv*
+secVideoTvConnect (ScrnInfoPtr pScrn, unsigned int id, SECLayerPos lpos)
+{
+    SECVideoTv* tv = NULL;
+    SECModePtr pSecMode;
+
+    XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (lpos >= LAYER_LOWER1 && lpos <= LAYER_UPPER, NULL);
+    XDBG_RETURN_VAL_IF_FAIL (id > 0, NULL);
+
+    tv = calloc (sizeof (SECVideoTv), 1);
+    XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
+
+    pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
+
+    if (lpos == LAYER_LOWER1 && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+    {
+        /* In case of video-only(virtual), we always use converter. */
+        tv->cvt = secCvtCreate (pScrn, CVT_OP_M2M);
+        XDBG_GOTO_IF_FAIL (tv->cvt != NULL, fail_connect);
+
+        secCvtAddCallback (tv->cvt, _secVideoTvCvtCallback, tv);
+    }
+    else if (lpos == LAYER_LOWER1 && pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI)
+    {
+        if (!secLayerSupport (pScrn, LAYER_OUTPUT_EXT, lpos, id))
+        {
+            /* used if id is not supported in case of lpos == LAYER_LOWER1. */
+            tv->cvt = secCvtCreate (pScrn, CVT_OP_M2M);
+            XDBG_GOTO_IF_FAIL (tv->cvt != NULL, fail_connect);
+
+            secCvtAddCallback (tv->cvt, _secVideoTvCvtCallback, tv);
+        }
+    }
+
+    XDBG_DEBUG (MTVO, "id(%c%c%c%c), lpos(%d)!\n", FOURCC_STR (id), lpos);
+
+    tv->pScrn = pScrn;
+    tv->lpos = lpos;
+    tv->outbuf_index = -1;
+    tv->convert_id = FOURCC_RGB32;
+    tv->outbuf_num = TVBUF_NUM;
+
+    return tv;
+
+fail_connect:
+    if (tv)
+    {
+        if (tv->cvt)
+            secCvtDestroy (tv->cvt);
+        free (tv);
+    }
+    return NULL;
+}
+
+void
+secVideoTvDisconnect (SECVideoTv* tv)
+{
+    int i;
+
+    XDBG_RETURN_IF_FAIL (tv != NULL);
+
+    XDBG_DEBUG (MTVO, "!\n");
+
+    if (tv->cvt)
+        secCvtDestroy (tv->cvt);
+
+    _secVideoTvLayerDestroy (tv);
+
+    if (tv->outbuf)
+    {
+        for (i = 0; i < tv->outbuf_num; i++)
+            if (tv->outbuf[i])
+                secUtilVideoBufferUnref (tv->outbuf[i]);
+
+        free (tv->outbuf);
+    }
+
+    free (tv);
+}
+
+Bool
+secVideoTvSetBuffer (SECVideoTv* tv, SECVideoBuf **vbufs, int bufnum)
+{
+    int i;
+
+    XDBG_RETURN_VAL_IF_FAIL (tv != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (vbufs != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (bufnum >= TVBUF_NUM, FALSE);
+
+    if (tv->outbuf)
+    {
+        XDBG_ERROR (MTVO, "already has buffers.\n");
+        return FALSE;
+    }
+
+    tv->outbuf_num = bufnum;
+    tv->outbuf = (SECVideoBuf**)calloc (bufnum, sizeof (SECVideoBuf*));
+    XDBG_RETURN_VAL_IF_FAIL (tv->outbuf != NULL, FALSE);
+
+    for (i = 0; i < tv->outbuf_num; i++)
+    {
+        XDBG_GOTO_IF_FAIL (tv->convert_id == vbufs[i]->id, fail_set_buffer);
+        XDBG_GOTO_IF_FAIL (tv->tv_width == vbufs[i]->width, fail_set_buffer);
+        XDBG_GOTO_IF_FAIL (tv->tv_height == vbufs[i]->height, fail_set_buffer);
+
+        tv->outbuf[i] = secUtilVideoBufferRef (vbufs[i]);
+        XDBG_GOTO_IF_FAIL (tv->outbuf[i] != NULL, fail_set_buffer);
+
+        if (!tv->outbuf[i]->showing && tv->outbuf[i]->need_reset)
+            secUtilClearVideoBuffer (tv->outbuf[i]);
+        else
+            tv->outbuf[i]->need_reset = TRUE;
+    }
+
+    return TRUE;
+
+fail_set_buffer:
+    if (tv->outbuf)
+    {
+        for (i = 0; i < tv->outbuf_num; i++)
+        {
+            if (tv->outbuf[i])
+            {
+                secUtilVideoBufferUnref (tv->outbuf[i]);
+                tv->outbuf[i] = NULL;
+            }
+        }
+
+        free (tv->outbuf);
+        tv->outbuf = NULL;
+    }
+
+    return FALSE;
+}
+SECLayerPos
+secVideoTvGetPos (SECVideoTv *tv)
+{
+    XDBG_RETURN_VAL_IF_FAIL (tv != NULL, LAYER_NONE);
+
+    return tv->lpos;
+}
+
+SECLayer*
+secVideoTvGetLayer (SECVideoTv *tv)
+{
+    XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
+
+    _secVideoTvLayerEnsure (tv);
+
+    return tv->layer;
+}
+
+/* HDMI    : 'handles' is "gem handle"
+ * VIRTUAL : 'handles' is "physical address"
+ *           'data' is "raw data"
+ *           only one of 'handles' and 'data' has value.
+ */
+int
+secVideoTvPutImage (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *rect, int csc_range)
+{
+    XDBG_RETURN_VAL_IF_FAIL (tv != NULL, 0);
+    XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), 0);
+    XDBG_RETURN_VAL_IF_FAIL (vbuf->id > 0, 0);
+    XDBG_RETURN_VAL_IF_FAIL (rect != NULL, 0);
+
+    XDBG_RETURN_VAL_IF_FAIL (vbuf->handles[0] > 0, 0);
+    XDBG_RETURN_VAL_IF_FAIL (vbuf->pitches[0] > 0, 0);
+
+    _secVideoTvLayerEnsure (tv);
+    XDBG_RETURN_VAL_IF_FAIL (tv->layer != NULL, 0);
+
+    if (tv->cvt)
+    {
+        /* can't show buffer to HDMI at now. */
+        SECModePtr pSecMode = (SECModePtr) SECPTR (tv->pScrn)->pSecMode;
+        SECCvtProp src_prop = {0,}, dst_prop = {0,};
+        SECVideoBuf *outbuf;
+        int dst_width, dst_height;
+        xRectangle dst_crop;
+
+
+        /* CHECK */
+        if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
+        {
+            XDBG_RETURN_VAL_IF_FAIL (tv->tv_width > 0, 0);
+            XDBG_RETURN_VAL_IF_FAIL (tv->tv_height > 0, 0);
+            dst_width = tv->tv_width;
+            dst_height = tv->tv_height;
+            dst_crop = *rect;
+
+            tv->tv_rect.x = 0;
+            tv->tv_rect.y = 0;
+            tv->tv_rect.width = tv->tv_width;
+            tv->tv_rect.height = tv->tv_height;
+        }
+        else
+        {
+            dst_width = rect->width;
+            dst_height = rect->height;
+            dst_crop = *rect;
+            dst_crop.x = 0;
+            dst_crop.y = 0;
+
+            tv->tv_rect = *rect;
+        }
+
+        src_prop.id = vbuf->id;
+        src_prop.width = vbuf->width;
+        src_prop.height = vbuf->height;
+        src_prop.crop = vbuf->crop;
+
+        dst_prop.id = tv->convert_id;
+        dst_prop.width = dst_width;
+        dst_prop.height = dst_height;
+        dst_prop.crop = dst_crop;
+        dst_prop.secure = vbuf->secure;
+        dst_prop.csc_range = csc_range;
+
+        if (!secCvtEnsureSize (&src_prop, &dst_prop))
+            return 0;
+
+        outbuf = _secVideoTvGetOutBuffer (tv, dst_prop.width, dst_prop.height, vbuf->secure);
+        if (!outbuf)
+            return 0;
+        outbuf->crop = dst_prop.crop;
+
+        if (!secCvtSetProperpty (tv->cvt, &src_prop, &dst_prop))
+            return 0;
+
+        if (!secCvtConvert (tv->cvt, vbuf, outbuf))
+            return 0;
+
+        XDBG_TRACE (MTVO, "'%c%c%c%c' %dx%d (%d,%d %dx%d) => '%c%c%c%c' %dx%d (%d,%d %dx%d) convert. rect(%d,%d %dx%d)\n",
+                    FOURCC_STR (vbuf->id), vbuf->width, vbuf->height,
+                    vbuf->crop.x, vbuf->crop.y, vbuf->crop.width, vbuf->crop.height,
+                    FOURCC_STR (outbuf->id), outbuf->width, outbuf->height,
+                    outbuf->crop.x, outbuf->crop.y, outbuf->crop.width, outbuf->crop.height,
+                    rect->x, rect->y, rect->width, rect->height);
+
+        return 1;
+    }
+
+    /* can show buffer to HDMI at now. */
+
+    return _secVideoTvPutImageInternal (tv, vbuf, rect);
+}
+
+void
+secVideoTvSetSize (SECVideoTv *tv, int width, int height)
+{
+    XDBG_RETURN_IF_FAIL (tv != NULL);
+
+    tv->tv_width = width;
+    tv->tv_height = height;
+
+    XDBG_TRACE (MTVO, "size(%dx%d) \n", width, height);
+}
+
+SECCvt*
+secVideoTvGetConverter (SECVideoTv *tv)
+{
+    XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
+
+    return tv->cvt;
+}
+
+void
+secVideoTvSetConvertFormat (SECVideoTv *tv, unsigned int convert_id)
+{
+    XDBG_RETURN_IF_FAIL (tv != NULL);
+    XDBG_RETURN_IF_FAIL (convert_id > 0);
+
+    tv->convert_id = convert_id;
+
+    XDBG_TRACE (MTVO, "convert_id(%c%c%c%c) \n", FOURCC_STR (convert_id));
+}
diff --git a/src/xv/sec_video_tvout.h b/src/xv/sec_video_tvout.h
new file mode 100644 (file)
index 0000000..9c88dc4
--- /dev/null
@@ -0,0 +1,56 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_VIDEO_TVOUT_H__
+#define __SEC_VIDEO_TVOUT_H__
+
+#include <xf86str.h>
+#include <X11/Xdefs.h>
+#include "sec_layer.h"
+#include "sec_converter.h"
+#include "sec_video_types.h"
+
+typedef struct _SECVideoTv SECVideoTv;
+
+SECVideoTv* secVideoTvConnect     (ScrnInfoPtr pScrn, unsigned int id, SECLayerPos lpos);
+void        secVideoTvDisconnect  (SECVideoTv *tv);
+
+Bool        secVideoTvSetBuffer   (SECVideoTv* tv, SECVideoBuf **vbufs, int bufnum);
+
+SECLayerPos secVideoTvGetPos      (SECVideoTv *tv);
+SECLayer*   secVideoTvGetLayer    (SECVideoTv *tv);
+
+void        secVideoTvSetSize     (SECVideoTv *tv, int width, int height);
+int         secVideoTvPutImage    (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *dst, int csc_range);
+
+SECCvt*     secVideoTvGetConverter (SECVideoTv *tv);
+void        secVideoTvSetConvertFormat (SECVideoTv *tv, unsigned int convert_id);
+
+#endif /* __SEC_VIDEO_TVOUT_H__ */
diff --git a/src/xv/sec_video_types.h b/src/xv/sec_video_types.h
new file mode 100644 (file)
index 0000000..1afe0fb
--- /dev/null
@@ -0,0 +1,168 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef __SEC_V4L2_TYPES_H__
+#define __SEC_V4L2_TYPES_H__
+
+#include <sys/types.h>
+#include <fbdevhw.h>
+#include <X11/Xdefs.h>
+#include <tbm_bufmgr.h>
+#include <exynos_drm.h>
+
+/* securezone memory */
+#define TZMEM_IOC_GET_TZMEM 0xC00C5402
+struct tzmem_get_region
+{
+   const char   *key;
+   unsigned int size;
+   int          fd;
+};
+
+/************************************************************
+ * DEFINITION
+ ************************************************************/
+#ifndef CLEAR
+#define CLEAR(x) memset(&(x), 0, sizeof (x))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef SWAP
+#define SWAP(a, b)  ({int t; t = a; a = b; b = t;})
+#endif
+
+#ifndef ROUNDUP
+#define ROUNDUP(x)  (ceil (floor ((float)(height) / 4)))
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+enum fimc_overlay_mode {
+    FIMC_OVLY_NOT_FIXED = 0,
+    FIMC_OVLY_FIFO,
+    FIMC_OVLY_DMA_AUTO,
+    FIMC_OVLY_DMA_MANUAL,
+    FIMC_OVLY_NONE_SINGLE_BUF,
+    FIMC_OVLY_NONE_MULTI_BUF,
+};
+
+#define ALIGN_TO_16B(x)    ((((x) + (1 <<  4) - 1) >>  4) <<  4)
+#define ALIGN_TO_32B(x)    ((((x) + (1 <<  5) - 1) >>  5) <<  5)
+#define ALIGN_TO_128B(x)   ((((x) + (1 <<  7) - 1) >>  7) <<  7)
+#define ALIGN_TO_2KB(x)    ((((x) + (1 << 11) - 1) >> 11) << 11)
+#define ALIGN_TO_8KB(x)    ((((x) + (1 << 13) - 1) >> 13) << 13)
+#define ALIGN_TO_64KB(x)   ((((x) + (1 << 16) - 1) >> 16) << 16)
+
+#define PLANAR_CNT    EXYNOS_DRM_PLANAR_MAX
+
+/************************************************************
+ * TYPE DEFINITION
+ ************************************************************/
+
+#ifndef uchar
+typedef unsigned char uchar;
+#endif
+
+typedef enum
+{
+    TYPE_NONE,
+    TYPE_RGB,
+    TYPE_YUV444,
+    TYPE_YUV422,
+    TYPE_YUV420,
+} SECFormatType;
+
+typedef struct _SECFormatTable
+{
+    unsigned int  id;
+    unsigned int  drmfmt;
+    SECFormatType type;
+} SECFormatTable;
+
+typedef struct _ConvertInfo
+{
+    void *cvt;
+    struct xorg_list link;
+} ConvertInfo;
+
+typedef struct _SECVideoBuf
+{
+    ScrnInfoPtr pScrn;
+    int     id;
+
+    int     width;
+    int     height;
+    xRectangle crop;
+
+    int     pitches[PLANAR_CNT];
+    int     offsets[PLANAR_CNT];
+    int     lengths[PLANAR_CNT];
+    int     size;
+
+    tbm_bo   bo[PLANAR_CNT];
+    unsigned int keys[PLANAR_CNT];
+    unsigned int phy_addrs[PLANAR_CNT];
+    unsigned int handles[PLANAR_CNT];
+
+    struct xorg_list convert_info;
+    Bool    showing;         /* now showing or now waiting to show. */
+    Bool    dirty;
+    Bool    need_reset;
+
+    unsigned int fb_id;      /* fb_id of vbuf */
+
+    struct xorg_list free_funcs;
+
+    Bool    secure;
+    int     csc_range;
+
+    struct xorg_list valid_link;   /* to check valid */
+    CARD32 stamp;
+    unsigned int ref_cnt;
+    char   *func;
+    int     flags;
+    Bool    scanout;
+
+    CARD32 put_time;
+} SECVideoBuf;
+
+#endif
diff --git a/src/xv/sec_video_virtual.c b/src/xv/sec_video_virtual.c
new file mode 100644 (file)
index 0000000..2272f6b
--- /dev/null
@@ -0,0 +1,2059 @@
+/*
+ * xserver-xorg-video-exynos
+ *
+ * Copyright 2004 Keith Packard
+ * Copyright 2005 Eric Anholt
+ * Copyright 2006 Nokia Corporation
+ * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+ *
+ * Contact: Boram Park <boram1288.park@samsung.com>
+ *
+ * Permission to use, copy, modify, distribute and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of the authors and/or copyright holders
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  The authors and
+ * copyright holders make no representations about the suitability of this
+ * software for any purpose.  It is provided "as is" without any express
+ * or implied warranty.
+ *
+ * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pixman.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xv.h>
+
+#include "sec.h"
+#include "sec_util.h"
+#include "sec_wb.h"
+#include "sec_crtc.h"
+#include "sec_converter.h"
+#include "sec_output.h"
+#include "sec_video.h"
+#include "sec_video_fourcc.h"
+#include "sec_video_virtual.h"
+#include "sec_video_tvout.h"
+#include "sec_display.h"
+#include "sec_xberc.h"
+
+#include "xv_types.h"
+
+#define DEV_INDEX   2
+#define BUF_NUM_EXTERNAL 5
+#define BUF_NUM_STREAM  3
+
+enum
+{
+    CAPTURE_MODE_NONE,
+    CAPTURE_MODE_STILL,
+    CAPTURE_MODE_STREAM,
+    CAPTURE_MODE_MAX,
+};
+
+enum
+{
+    DISPLAY_LCD,
+    DISPLAY_EXTERNAL,
+};
+
+enum
+{
+    DATA_TYPE_UI,
+    DATA_TYPE_VIDEO,
+    DATA_TYPE_MAX,
+};
+
+static unsigned int support_formats[] =
+{
+    FOURCC_RGB32,
+    FOURCC_ST12,
+    FOURCC_SN12,
+};
+
+static XF86VideoEncodingRec dummy_encoding[] =
+{
+    { 0, "XV_IMAGE", -1, -1, { 1, 1 } },
+    { 1, "XV_IMAGE", 2560, 2560, { 1, 1 } },
+};
+
+static XF86ImageRec images[] =
+{
+    XVIMAGE_RGB32,
+    XVIMAGE_SN12,
+    XVIMAGE_ST12,
+};
+
+static XF86VideoFormatRec formats[] =
+{
+    { 16, TrueColor },
+    { 24, TrueColor },
+    { 32, TrueColor },
+};
+
+static XF86AttributeRec attributes[] =
+{
+    { 0, 0, 0x7fffffff, "_USER_WM_PORT_ATTRIBUTE_FORMAT" },
+    { 0, 0, CAPTURE_MODE_MAX, "_USER_WM_PORT_ATTRIBUTE_CAPTURE" },
+    { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_DISPLAY" },
+    { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_ROTATE_OFF" },
+    { 0, 0, DATA_TYPE_MAX, "_USER_WM_PORT_ATTRIBUTE_DATA_TYPE" },
+    { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_SECURE" },
+    { 0, 0, 0x7fffffff, "_USER_WM_PORT_ATTRIBUTE_RETURN_BUFFER" },
+};
+
+typedef enum
+{
+    PAA_MIN,
+    PAA_FORMAT,
+    PAA_CAPTURE,
+    PAA_DISPLAY,
+    PAA_ROTATE_OFF,
+    PAA_DATA_TYPE,
+    PAA_SECURE,
+    PAA_RETBUF,
+    PAA_MAX
+} SECPortAttrAtom;
+
+static struct
+{
+    SECPortAttrAtom  paa;
+    const char      *name;
+    Atom             atom;
+} atoms[] =
+{
+    { PAA_FORMAT, "_USER_WM_PORT_ATTRIBUTE_FORMAT", None },
+    { PAA_CAPTURE, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", None },
+    { PAA_DISPLAY, "_USER_WM_PORT_ATTRIBUTE_DISPLAY", None },
+    { PAA_ROTATE_OFF, "_USER_WM_PORT_ATTRIBUTE_ROTATE_OFF", None },
+    { PAA_DATA_TYPE, "_USER_WM_PORT_ATTRIBUTE_DATA_TYPE", None },
+    { PAA_SECURE, "_USER_WM_PORT_ATTRIBUTE_SECURE", None },
+    { PAA_RETBUF, "_USER_WM_PORT_ATTRIBUTE_RETURN_BUFFER", None },
+};
+
+typedef struct _RetBufInfo
+{
+    SECVideoBuf *vbuf;
+    int type;
+    struct xorg_list link;
+} RetBufInfo;
+
+/* SEC port information structure */
+typedef struct
+{
+    /* index */
+    int     index;
+
+    /* port attribute */
+    int     id;
+    int     capture;
+    int     display;
+    Bool    secure;
+    Bool    data_type;
+    Bool    rotate_off;
+
+    /* information from outside */
+    ScrnInfoPtr pScrn;
+    DrawablePtr pDraw;
+    RegionPtr   clipBoxes;
+
+    /* writeback */
+    SECWb *wb;
+
+    /* video */
+    SECCvt     *cvt;
+
+    SECVideoBuf *dstbuf;
+    SECVideoBuf **outbuf;
+    int          outbuf_num;
+    int          outbuf_index;
+
+    struct xorg_list retbuf_info;
+    Bool         need_damage;
+
+    OsTimerPtr retire_timer;
+    Bool putstill_on;
+
+    unsigned int status;
+    CARD32       retire_time;
+    CARD32       prev_time;
+
+    struct xorg_list link;
+} SECPortPriv, *SECPortPrivPtr;
+
+static RESTYPE event_drawable_type;
+
+typedef struct _SECVideoResource
+{
+    XID            id;
+    RESTYPE        type;
+    SECPortPrivPtr pPort;
+    ScrnInfoPtr    pScrn;
+} SECVideoResource;
+
+#define SEC_MAX_PORT        1
+
+#define NUM_IMAGES        (sizeof(images) / sizeof(images[0]))
+#define NUM_FORMATS       (sizeof(formats) / sizeof(formats[0]))
+#define NUM_ATTRIBUTES    (sizeof(attributes) / sizeof(attributes[0]))
+#define NUM_ATOMS         (sizeof(atoms) / sizeof(atoms[0]))
+
+static DevPrivateKeyRec video_virtual_port_key;
+#define VideoVirtualPortKey (&video_virtual_port_key)
+#define GetPortInfo(pDraw) ((SECVideoPortInfo*)dixLookupPrivate(&(pDraw)->devPrivates, VideoVirtualPortKey))
+
+typedef struct _SECVideoPortInfo
+{
+    ClientPtr client;
+    XvPortPtr pp;
+} SECVideoPortInfo;
+
+static int (*ddPutStill) (ClientPtr, DrawablePtr, struct _XvPortRec *, GCPtr,
+                          INT16, INT16, CARD16, CARD16,
+                          INT16, INT16, CARD16, CARD16);
+
+static void SECVirtualVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit);
+static void _secVirtualVideoCloseOutBuffer (SECPortPrivPtr pPort);
+static void _secVirtualVideoLayerNotifyFunc (SECLayer *layer, int type, void *type_data, void *data);
+static void _secVirtualVideoWbDumpFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data);
+static void _secVirtualVideoWbStopFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data);
+static SECVideoBuf* _secVirtualVideoGetBlackBuffer (SECPortPrivPtr pPort);
+static Bool _secVirtualVideoEnsureOutBuffers (ScrnInfoPtr pScrn, SECPortPrivPtr pPort, int id, int width, int height);
+static void _secVirtualVideoWbCloseFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data);
+
+static SECVideoPortInfo*
+_port_info (DrawablePtr pDraw)
+{
+    if (!pDraw)
+        return NULL;
+
+    if (pDraw->type == DRAWABLE_WINDOW)
+        return GetPortInfo ((WindowPtr)pDraw);
+    else
+       return GetPortInfo ((PixmapPtr)pDraw);
+}
+
+static Atom
+_secVideoGetPortAtom (SECPortAttrAtom paa)
+{
+    int i;
+
+    XDBG_RETURN_VAL_IF_FAIL (paa > PAA_MIN && paa < PAA_MAX, None);
+
+    for (i = 0; i < NUM_ATOMS; i++)
+    {
+        if (paa == atoms[i].paa)
+        {
+            if (atoms[i].atom == None)
+                atoms[i].atom = MakeAtom (atoms[i].name,
+                                          strlen (atoms[i].name), TRUE);
+
+            return atoms[i].atom;
+        }
+    }
+
+    XDBG_ERROR (MVA, "Error: Unknown Port Attribute Name!\n");
+
+    return None;
+}
+
+static void
+_secVirtualVideoSetSecure (SECPortPrivPtr pPort, Bool secure)
+{
+    SECVideoPortInfo *info;
+
+    secure = (secure > 0) ? TRUE : FALSE;
+
+    if (pPort->secure == secure)
+        return;
+
+    pPort->secure = secure;
+
+    XDBG_TRACE (MVA, "secure(%d) \n", secure);
+
+    info = _port_info (pPort->pDraw);
+    if (!info || !info->pp)
+        return;
+
+    XvdiSendPortNotify (info->pp, _secVideoGetPortAtom (PAA_SECURE), secure);
+}
+
+static PixmapPtr
+_secVirtualVideoGetPixmap (DrawablePtr pDraw)
+{
+    if (pDraw->type == DRAWABLE_WINDOW)
+        return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw);
+    else
+        return (PixmapPtr) pDraw;
+}
+
+static Bool
+_secVirtualVideoIsSupport (unsigned int id)
+{
+    int i;
+
+    for (i = 0; i < sizeof (support_formats) / sizeof (unsigned int); i++)
+        if (support_formats[i] == id)
+            return TRUE;
+
+    return FALSE;
+}
+
+#if 0
+static char buffers[1024];
+
+static void
+_buffers (SECPortPrivPtr pPort)
+{
+    RetBufInfo *cur = NULL, *next = NULL;
+
+    CLEAR (buffers);
+    xorg_list_for_each_entry_safe (cur, next, &pPort->retbuf_info, link)
+    {
+        if (cur->vbuf)
+            snprintf (buffers, 1024, "%s %d", buffers, cur->vbuf->keys[0]);
+    }
+}
+#endif
+
+static RetBufInfo*
+_secVirtualVideoFindReturnBuf (SECPortPrivPtr pPort, unsigned int key)
+{
+    RetBufInfo *cur = NULL, *next = NULL;
+
+    XDBG_RETURN_VAL_IF_FAIL (pPort->capture != CAPTURE_MODE_STILL, NULL);
+
+    xorg_list_for_each_entry_safe (cur, next, &pPort->retbuf_info, link)
+    {
+        if (cur->vbuf && cur->vbuf->keys[0] == key)
+            return cur;
+    }
+
+    return NULL;
+}
+
+static Bool
+_secVirtualVideoAddReturnBuf (SECPortPrivPtr pPort, SECVideoBuf *vbuf)
+{
+    RetBufInfo *info;
+
+    XDBG_RETURN_VAL_IF_FAIL (pPort->capture != CAPTURE_MODE_STILL, FALSE);
+
+    info = _secVirtualVideoFindReturnBuf (pPort, vbuf->keys[0]);
+    XDBG_RETURN_VAL_IF_FAIL (info == NULL, FALSE);
+
+    info = calloc (1, sizeof (RetBufInfo));
+    XDBG_RETURN_VAL_IF_FAIL (info != NULL, FALSE);
+
+    info->vbuf = secUtilVideoBufferRef (vbuf);
+    info->vbuf->showing = TRUE;
+
+    XDBG_DEBUG (MVA, "retbuf (%ld,%d,%d,%d) added.\n", vbuf->stamp,
+                vbuf->keys[0], vbuf->keys[1], vbuf->keys[2]);
+
+    xorg_list_add (&info->link, &pPort->retbuf_info);
+
+    return TRUE;
+}
+
+static void
+_secVirtualVideoRemoveReturnBuf (SECPortPrivPtr pPort, RetBufInfo *info)
+{
+    XDBG_RETURN_IF_FAIL (pPort->capture != CAPTURE_MODE_STILL);
+    XDBG_RETURN_IF_FAIL (info != NULL);
+    XDBG_RETURN_IF_FAIL (info->vbuf != NULL);
+
+    info->vbuf->showing = FALSE;
+
+    XDBG_DEBUG (MVA, "retbuf (%ld,%d,%d,%d) removed.\n", info->vbuf->stamp,
+                info->vbuf->keys[0], info->vbuf->keys[1], info->vbuf->keys[2]);
+
+    if (pPort->wb)
+        secWbQueueBuffer (pPort->wb, info->vbuf);
+
+    secUtilVideoBufferUnref (info->vbuf);
+    xorg_list_del (&info->link);
+    free (info);
+}
+
+static void
+_secVirtualVideoRemoveReturnBufAll (SECPortPrivPtr pPort)
+{
+    RetBufInfo *cur = NULL, *next = NULL;
+
+    XDBG_RETURN_IF_FAIL (pPort->capture != CAPTURE_MODE_STILL);
+
+    xorg_list_for_each_entry_safe (cur, next, &pPort->retbuf_info, link)
+    {
+        _secVirtualVideoRemoveReturnBuf (pPort, cur);
+    }
+}
+
+static void
+_secVirtualVideoDraw (SECPortPrivPtr pPort, SECVideoBuf *buf)
+{
+    if (pPort->retire_timer)
+    {
+        TimerFree (pPort->retire_timer);
+        pPort->retire_timer = NULL;
+    }
+
+    if (!pPort->pDraw)
+    {
+        XDBG_TRACE (MVA, "drawable gone!\n");
+        return;
+    }
+
+    XDBG_RETURN_IF_FAIL (pPort->need_damage == TRUE);
+    XDBG_GOTO_IF_FAIL (VBUF_IS_VALID (buf), draw_done);
+
+    XDBG_TRACE (MVA, "%c%c%c%c, %dx%d. \n",
+                FOURCC_STR (buf->id), buf->width, buf->height);
+
+    if (pPort->id == FOURCC_RGB32)
+    {
+        PixmapPtr pPixmap = _secVirtualVideoGetPixmap (pPort->pDraw);
+        tbm_bo_handle bo_handle;
+
+        XDBG_GOTO_IF_FAIL (buf->secure == FALSE, draw_done);
+
+        if (pPort->pDraw->width != buf->width || pPort->pDraw->height != buf->height)
+        {
+            XDBG_ERROR (MVA, "not matched. (%dx%d != %dx%d) \n",
+                        pPort->pDraw->width, pPort->pDraw->height,
+                        buf->width, buf->height);
+            goto draw_done;
+        }
+
+        bo_handle = tbm_bo_map (buf->bo[0], TBM_DEVICE_CPU, TBM_OPTION_READ);
+        XDBG_GOTO_IF_FAIL (bo_handle.ptr != NULL, draw_done);
+        XDBG_GOTO_IF_FAIL (buf->size > 0, draw_done);
+
+        secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
+
+        if (pPixmap->devPrivate.ptr)
+        {
+            XDBG_DEBUG (MVA, "vir(%p) size(%d) => pixmap(%p)\n",
+                        bo_handle.ptr, buf->size, pPixmap->devPrivate.ptr);
+
+            memcpy (pPixmap->devPrivate.ptr, bo_handle.ptr, buf->size);
+        }
+
+        secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
+
+        tbm_bo_unmap (buf->bo[0]);
+    }
+    else /* FOURCC_ST12 */
+    {
+        PixmapPtr pPixmap = _secVirtualVideoGetPixmap (pPort->pDraw);
+        XV_DATA xv_data = {0,};
+
+        _secVirtualVideoSetSecure (pPort, buf->secure);
+
+        XV_INIT_DATA (&xv_data);
+
+        if (buf->phy_addrs[0] > 0)
+        {
+            xv_data.YBuf = buf->phy_addrs[0];
+            xv_data.CbBuf = buf->phy_addrs[1];
+            xv_data.CrBuf = buf->phy_addrs[2];
+
+            xv_data.BufType = XV_BUF_TYPE_LEGACY;
+        }
+        else
+        {
+            xv_data.YBuf = buf->keys[0];
+            xv_data.CbBuf = buf->keys[1];
+            xv_data.CrBuf = buf->keys[2];
+
+            xv_data.BufType = XV_BUF_TYPE_DMABUF;
+        }
+
+#if 0
+        _buffers (pPort);
+        ErrorF ("[Xorg] send : %d (%s)\n", xv_data.YBuf, buffers);
+#endif
+
+        XDBG_DEBUG (MVA, "still_data(%d,%d,%d) type(%d) \n",
+                    xv_data.YBuf, xv_data.CbBuf, xv_data.CrBuf,
+                    xv_data.BufType);
+
+        secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
+
+        if (pPixmap->devPrivate.ptr)
+            memcpy (pPixmap->devPrivate.ptr, &xv_data, sizeof (XV_DATA));
+
+        secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
+
+        _secVirtualVideoAddReturnBuf (pPort, buf);
+    }
+
+draw_done:
+    DamageDamageRegion (pPort->pDraw, pPort->clipBoxes);
+    pPort->need_damage = FALSE;
+
+    SECPtr pSec = SECPTR (pPort->pScrn);
+    if ((pSec->dump_mode & XBERC_DUMP_MODE_CA) && pSec->dump_info)
+    {
+        char file[128];
+        static int i;
+        snprintf (file, sizeof(file), "capout_stream_%c%c%c%c_%dx%d_%03d.%s",
+                  FOURCC_STR(buf->id), buf->width, buf->height, i++,
+                  IS_RGB (buf->id)?"bmp":"yuv");
+        secUtilDoDumpVBuf (pSec->dump_info, buf, file);
+    }
+
+    if (pSec->xvperf_mode & XBERC_XVPERF_MODE_CA)
+    {
+        CARD32 cur, sub;
+        cur = GetTimeInMillis ();
+        sub = cur - pPort->prev_time;
+        ErrorF ("damage send           : %6ld ms\n", sub);
+    }
+}
+
+static void
+_secVirtualVideoWbDumpFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)user_data;
+    SECVideoBuf *vbuf = (SECVideoBuf*)noti_data;
+
+    XDBG_RETURN_IF_FAIL (pPort != NULL);
+    XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (vbuf));
+    XDBG_RETURN_IF_FAIL (vbuf->showing == FALSE);
+
+    XDBG_TRACE (MVA, "dump (%ld,%d,%d,%d)\n", vbuf->stamp,
+                vbuf->keys[0], vbuf->keys[1], vbuf->keys[2]);
+
+    if (pPort->need_damage)
+    {
+        _secVirtualVideoDraw (pPort, vbuf);
+    }
+
+    return;
+}
+
+static void
+_secVirtualVideoWbDumpDoneFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)user_data;
+
+    if (!pPort)
+        return;
+
+    XDBG_DEBUG (MVA, "close wb after ipp event done\n");
+
+    XDBG_RETURN_IF_FAIL (pPort->wb != NULL);
+
+    secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbStopFunc);
+    secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbDumpFunc);
+    secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbDumpDoneFunc);
+    secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbCloseFunc);
+
+    secWbClose (pPort->wb);
+    pPort->wb = NULL;
+}
+
+static void
+_secVirtualVideoWbStopFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)user_data;
+
+    if (!pPort)
+        return;
+
+    if (pPort->need_damage)
+    {
+        SECVideoBuf *black = _secVirtualVideoGetBlackBuffer (pPort);
+        XDBG_TRACE (MVA, "black buffer(%d) return: wb stop\n", (black)?black->keys[0]:0);
+        _secVirtualVideoDraw (pPort, black);
+    }
+}
+
+static void
+_secVirtualVideoWbCloseFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)user_data;
+
+    if (!pPort)
+        return;
+
+    pPort->wb = NULL;
+}
+
+static void
+_secVirtualVideoStreamOff (SECPortPrivPtr pPort)
+{
+    SECLayer *layer;
+
+    XDBG_TRACE (MVA, "STREAM_OFF!\n");
+
+    if (pPort->retire_timer)
+    {
+        TimerFree (pPort->retire_timer);
+        pPort->retire_timer = NULL;
+    }
+
+    if (pPort->wb)
+    {
+        secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbStopFunc);
+        secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbDumpFunc);
+        secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbDumpDoneFunc);
+        secWbRemoveNotifyFunc (pPort->wb, _secVirtualVideoWbCloseFunc);
+
+        secWbClose (pPort->wb);
+        pPort->wb = NULL;
+    }
+
+    if (pPort->id != FOURCC_RGB32)
+        _secVirtualVideoRemoveReturnBufAll (pPort);
+
+    layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_LOWER1);
+    if (layer)
+        secLayerRemoveNotifyFunc (layer, _secVirtualVideoLayerNotifyFunc);
+
+    if (pPort->need_damage)
+    {
+        /* all callbacks has been removed from wb/layer. We can't expect
+         * any event. So we send black image at the end.
+         */
+        SECVideoBuf *black = _secVirtualVideoGetBlackBuffer (pPort);
+        XDBG_TRACE (MVA, "black buffer(%d) return: stream off\n", (black)?black->keys[0]:0);
+        _secVirtualVideoDraw (pPort, black);
+    }
+
+    _secVirtualVideoCloseOutBuffer (pPort);
+
+    if (pPort->clipBoxes)
+    {
+        RegionDestroy (pPort->clipBoxes);
+        pPort->clipBoxes = NULL;
+    }
+
+    pPort->pDraw = NULL;
+    pPort->capture = CAPTURE_MODE_NONE;
+    pPort->id = FOURCC_RGB32;
+    pPort->secure = FALSE;
+    pPort->data_type = DATA_TYPE_UI;
+    pPort->need_damage = FALSE;
+
+    if (pPort->putstill_on)
+    {
+        pPort->putstill_on = FALSE;
+        XDBG_SECURE (MVA, "pPort(%d) putstill off. \n", pPort->index);
+    }
+}
+
+static int
+_secVirtualVideoAddDrawableEvent (SECPortPrivPtr pPort)
+{
+    SECVideoResource *resource;
+    void *ptr;
+    int ret = 0;
+
+    XDBG_RETURN_VAL_IF_FAIL (pPort->pScrn != NULL, BadImplementation);
+    XDBG_RETURN_VAL_IF_FAIL (pPort->pDraw != NULL, BadImplementation);
+
+    ptr = NULL;
+    ret = dixLookupResourceByType (&ptr, pPort->pDraw->id,
+                             event_drawable_type, NULL, DixWriteAccess);
+    if (ret == Success)
+        return Success;
+
+    resource = malloc (sizeof (SECVideoResource));
+    if (resource == NULL)
+        return BadAlloc;
+
+    if (!AddResource (pPort->pDraw->id, event_drawable_type, resource))
+    {
+        free (resource);
+        return BadAlloc;
+    }
+
+    XDBG_TRACE (MVA, "id(0x%08lx). \n", pPort->pDraw->id);
+
+    resource->id = pPort->pDraw->id;
+    resource->type = event_drawable_type;
+    resource->pPort = pPort;
+    resource->pScrn = pPort->pScrn;
+
+    return Success;
+}
+
+static int
+_secVirtualVideoRegisterEventDrawableGone (void *data, XID id)
+{
+    SECVideoResource *resource = (SECVideoResource*)data;
+
+    XDBG_TRACE (MVA, "id(0x%08lx). \n", id);
+
+    if (!resource)
+        return Success;
+
+    if (!resource->pPort || !resource->pScrn)
+        return Success;
+
+    resource->pPort->pDraw = NULL;
+
+    SECVirtualVideoStop (resource->pScrn, (pointer)resource->pPort, 1);
+
+    free(resource);
+
+    return Success;
+}
+
+static Bool
+_secVirtualVideoRegisterEventResourceTypes (void)
+{
+    event_drawable_type = CreateNewResourceType (_secVirtualVideoRegisterEventDrawableGone,
+                                                 "Sec Virtual Video Drawable");
+
+    if (!event_drawable_type)
+        return FALSE;
+
+    return TRUE;
+}
+
+static tbm_bo
+_secVirtualVideoGetFrontBo (SECPortPrivPtr pPort, int connector_type)
+{
+    xf86CrtcConfigPtr pCrtcConfig;
+    int i;
+
+    pCrtcConfig = XF86_CRTC_CONFIG_PTR (pPort->pScrn);
+    XDBG_RETURN_VAL_IF_FAIL (pCrtcConfig != NULL, NULL);
+
+    for (i = 0; i < pCrtcConfig->num_output; i++)
+    {
+        xf86OutputPtr pOutput = pCrtcConfig->output[i];
+        SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
+
+        if (pOutputPriv->mode_output->connector_type == connector_type)
+        {
+            if (pOutput->crtc)
+            {
+                SECCrtcPrivPtr pCrtcPriv = pOutput->crtc->driver_private;
+                return pCrtcPriv->front_bo;
+            }
+            else
+                XDBG_ERROR (MVA, "no crtc.\n");
+        }
+    }
+
+    return NULL;
+}
+
+static SECVideoBuf*
+_secVirtualVideoGetBlackBuffer (SECPortPrivPtr pPort)
+{
+    int i;
+
+    if (!pPort->outbuf[0])
+    {
+        XDBG_RETURN_VAL_IF_FAIL (pPort->pDraw != NULL, NULL);
+        _secVirtualVideoEnsureOutBuffers (pPort->pScrn, pPort, pPort->id,
+                                          pPort->pDraw->width, pPort->pDraw->height);
+    }
+
+    for (i = 0; i < pPort->outbuf_num; i++)
+    {
+        if (pPort->outbuf[i] && !pPort->outbuf[i]->showing)
+        {
+            if (pPort->outbuf[i]->dirty)
+                secUtilClearVideoBuffer (pPort->outbuf[i]);
+
+            return pPort->outbuf[i];
+        }
+    }
+
+    XDBG_ERROR (MVA, "now all buffers are in showing\n");
+
+    return NULL;
+}
+
+static Bool
+_secVirtualVideoEnsureOutBuffers (ScrnInfoPtr pScrn, SECPortPrivPtr pPort, int id, int width, int height)
+{
+    SECPtr pSec = SECPTR (pScrn);
+    int i;
+
+    if (pPort->display == DISPLAY_EXTERNAL)
+        pPort->outbuf_num = BUF_NUM_EXTERNAL;
+    else
+        pPort->outbuf_num = BUF_NUM_STREAM;
+
+    if (!pPort->outbuf)
+    {
+        pPort->outbuf = (SECVideoBuf**)calloc(pPort->outbuf_num, sizeof (SECVideoBuf*));
+        XDBG_RETURN_VAL_IF_FAIL (pPort->outbuf != NULL, FALSE);
+    }
+
+    for (i = 0; i < pPort->outbuf_num; i++)
+    {
+        int scanout;
+
+        if (pPort->outbuf[i])
+            continue;
+
+        XDBG_RETURN_VAL_IF_FAIL (width > 0, FALSE);
+        XDBG_RETURN_VAL_IF_FAIL (height > 0, FALSE);
+
+        if (pPort->display == DISPLAY_LCD)
+            scanout = FALSE;
+        else
+            scanout = pSec->scanout;
+
+        /* pPort->pScrn can be NULL if XvPutStill isn't called. */
+        pPort->outbuf[i] = secUtilAllocVideoBuffer (pScrn, id,
+                                                    width, height,
+                                                    scanout, TRUE, pPort->secure);
+
+        XDBG_GOTO_IF_FAIL (pPort->outbuf[i] != NULL, ensure_buffer_fail);
+    }
+
+    return TRUE;
+
+ensure_buffer_fail:
+    _secVirtualVideoCloseOutBuffer (pPort);
+
+    return FALSE;
+}
+
+static Bool
+_secVirtualVideoEnsureDstBuffer (SECPortPrivPtr pPort)
+{
+    if (pPort->dstbuf)
+    {
+        secUtilClearVideoBuffer (pPort->dstbuf);
+        return TRUE;
+    }
+
+    pPort->dstbuf = secUtilAllocVideoBuffer (pPort->pScrn, FOURCC_RGB32,
+                                                pPort->pDraw->width,
+                                                pPort->pDraw->height,
+                                                FALSE, FALSE, pPort->secure);
+    XDBG_RETURN_VAL_IF_FAIL (pPort->dstbuf != NULL, FALSE);
+
+    return TRUE;
+}
+
+static SECVideoBuf*
+_secVirtualVideoGetUIBuffer (SECPortPrivPtr pPort, int connector_type)
+{
+    SECVideoBuf *uibuf = NULL;
+    tbm_bo bo[PLANAR_CNT] = {0,};
+    SECFbBoDataPtr bo_data = NULL;
+    tbm_bo_handle bo_handle;
+
+    bo[0] = _secVirtualVideoGetFrontBo (pPort, connector_type);
+    XDBG_RETURN_VAL_IF_FAIL (bo[0] != NULL, NULL);
+
+    tbm_bo_get_user_data (bo[0], TBM_BO_DATA_FB, (void**)&bo_data);
+    XDBG_RETURN_VAL_IF_FAIL (bo_data != NULL, NULL);
+
+    uibuf = secUtilCreateVideoBuffer (pPort->pScrn, FOURCC_RGB32,
+                                      bo_data->pos.x2 - bo_data->pos.x1,
+                                      bo_data->pos.y2 - bo_data->pos.y1,
+                                      FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (uibuf != NULL, NULL);
+
+    uibuf->bo[0] = tbm_bo_ref (bo[0]);
+    XDBG_GOTO_IF_FAIL (uibuf->bo[0] != NULL, fail_get);
+
+    bo_handle = tbm_bo_get_handle (bo[0], TBM_DEVICE_DEFAULT);
+    uibuf->handles[0] = bo_handle.u32;
+
+    XDBG_GOTO_IF_FAIL (uibuf->handles[0] > 0, fail_get);
+
+    return uibuf;
+
+fail_get:
+    if (uibuf)
+        secUtilVideoBufferUnref (uibuf);
+
+    return NULL;
+}
+
+static SECVideoBuf*
+_secVirtualVideoGetDrawableBuffer (SECPortPrivPtr pPort)
+{
+    SECVideoBuf *vbuf = NULL;
+    PixmapPtr pPixmap = NULL;
+    tbm_bo_handle bo_handle;
+    SECPixmapPriv *privPixmap;
+    Bool need_finish = FALSE;
+
+    XDBG_GOTO_IF_FAIL (pPort->secure == FALSE, fail_get);
+    XDBG_GOTO_IF_FAIL (pPort->pDraw != NULL, fail_get);
+
+    pPixmap = _secVirtualVideoGetPixmap (pPort->pDraw);
+    XDBG_GOTO_IF_FAIL (pPixmap != NULL, fail_get);
+
+    privPixmap = exaGetPixmapDriverPrivate (pPixmap);
+    XDBG_GOTO_IF_FAIL (privPixmap != NULL, fail_get);
+
+    if (!privPixmap->bo)
+    {
+        need_finish = TRUE;
+        secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
+        XDBG_GOTO_IF_FAIL (privPixmap->bo != NULL, fail_get);
+    }
+
+    vbuf = secUtilCreateVideoBuffer (pPort->pScrn, FOURCC_RGB32,
+                                     pPort->pDraw->width,
+                                     pPort->pDraw->height,
+                                     FALSE);
+    XDBG_GOTO_IF_FAIL (vbuf != NULL, fail_get);
+
+    vbuf->bo[0] = tbm_bo_ref (privPixmap->bo);
+    bo_handle = tbm_bo_get_handle (privPixmap->bo, TBM_DEVICE_DEFAULT);
+    vbuf->handles[0] = bo_handle.u32;
+
+    XDBG_GOTO_IF_FAIL (vbuf->handles[0] > 0, fail_get);
+
+    return vbuf;
+
+fail_get:
+    if (pPixmap && need_finish)
+        secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
+
+    if (vbuf)
+        secUtilVideoBufferUnref (vbuf);
+
+    return NULL;
+}
+
+static void
+_secVirtualVideoCloseOutBuffer (SECPortPrivPtr pPort)
+{
+    int i;
+
+    if (pPort->outbuf)
+    {
+        for (i = 0; i < pPort->outbuf_num; i++)
+        {
+            if (pPort->outbuf[i])
+                secUtilVideoBufferUnref (pPort->outbuf[i]);
+            pPort->outbuf[i] = NULL;
+        }
+
+        free (pPort->outbuf);
+        pPort->outbuf = NULL;
+    }
+
+    if (pPort->dstbuf)
+    {
+        secUtilVideoBufferUnref (pPort->dstbuf);
+        pPort->dstbuf = NULL;
+    }
+
+    pPort->outbuf_index = -1;
+}
+
+static int
+_secVirtualVideoDataType (SECPortPrivPtr pPort)
+{
+    SECLayer *video_layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_LOWER1);
+
+    return (video_layer) ? DATA_TYPE_VIDEO : DATA_TYPE_UI;
+}
+
+static int
+_secVirtualVideoPreProcess (ScrnInfoPtr pScrn, SECPortPrivPtr pPort,
+                            RegionPtr clipBoxes, DrawablePtr pDraw)
+{
+    if (pPort->pScrn == pScrn && pPort->pDraw == pDraw &&
+        pPort->clipBoxes && clipBoxes && RegionEqual (pPort->clipBoxes, clipBoxes))
+        return Success;
+
+    pPort->pScrn = pScrn;
+    pPort->pDraw = pDraw;
+
+    if (clipBoxes)
+    {
+        if (!pPort->clipBoxes)
+            pPort->clipBoxes = RegionCreate (NULL, 1);
+
+        XDBG_RETURN_VAL_IF_FAIL (pPort->clipBoxes != NULL, BadAlloc);
+
+        RegionCopy (pPort->clipBoxes, clipBoxes);
+    }
+
+    XDBG_TRACE (MVA, "pDraw(0x%x, %dx%d). \n", pDraw->id, pDraw->width, pDraw->height);
+
+    return Success;
+}
+
+static int
+_secVirtualVideoGetOutBufferIndex (SECPortPrivPtr pPort)
+{
+    if (!pPort->outbuf)
+        return -1;
+
+    pPort->outbuf_index++;
+    if (pPort->outbuf_index >= pPort->outbuf_num)
+        pPort->outbuf_index = 0;
+
+    return pPort->outbuf_index;
+}
+
+static int
+_secVirtualVideoSendPortNotify (SECPortPrivPtr pPort, SECPortAttrAtom paa, INT32 value)
+{
+    SECVideoPortInfo *info;
+    Atom atom = None;
+
+    XDBG_RETURN_VAL_IF_FAIL (pPort->pDraw != NULL, BadValue);
+
+    info = _port_info (pPort->pDraw);
+    XDBG_RETURN_VAL_IF_FAIL (info != NULL, BadValue);
+    XDBG_RETURN_VAL_IF_FAIL (info->pp != NULL, BadValue);
+
+    atom = _secVideoGetPortAtom (paa);
+    XDBG_RETURN_VAL_IF_FAIL (atom != None, BadValue);
+
+    XDBG_TRACE (MVA, "paa(%d), value(%d)\n", paa, value);
+
+    return XvdiSendPortNotify (info->pp, atom, value);
+}
+
+static Bool
+_secVirtualVideoComposite (SECVideoBuf *src, SECVideoBuf *dst,
+                           int src_x, int src_y, int src_w, int src_h,
+                           int dst_x, int dst_y, int dst_w, int dst_h,
+                           Bool composite, int rotate)
+{
+    xRectangle src_rect = {0,}, dst_rect = {0,};
+
+    XDBG_RETURN_VAL_IF_FAIL (src != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (dst != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (src->bo[0] != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (dst->bo[0] != NULL, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (src->pitches[0] > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (dst->pitches[0] > 0, FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (IS_RGB (src->id), FALSE);
+    XDBG_RETURN_VAL_IF_FAIL (IS_RGB (dst->id), FALSE);
+
+    XDBG_DEBUG (MVA, "comp(%d) src : %ld %c%c%c%c  %dx%d (%d,%d %dx%d) => dst : %ld %c%c%c%c  %dx%d (%d,%d %dx%d)\n",
+                composite, src->stamp, FOURCC_STR (src->id), src->width, src->height,
+                src_x, src_y, src_w, src_h,
+                dst->stamp, FOURCC_STR (dst->id), dst->width, dst->height,
+                dst_x, dst_y, dst_w, dst_h);
+
+    src_rect.x = src_x;
+    src_rect.y = src_y;
+    src_rect.width = src_w;
+    src_rect.height = src_h;
+    dst_rect.x = dst_x;
+    dst_rect.y = dst_y;
+    dst_rect.width = dst_w;
+    dst_rect.height = dst_h;
+
+    secUtilConvertBos (src->pScrn,
+                       src->bo[0], src->width, src->height, &src_rect, src->pitches[0],
+                       dst->bo[0], dst->width, dst->height, &dst_rect, dst->pitches[0],
+                       composite, rotate);
+
+    return TRUE;
+}
+
+static int
+_secVirtualVideoCompositeExtLayers (SECPortPrivPtr pPort)
+{
+    SECVideoBuf *dst_buf = NULL;
+    SECLayer    *lower_layer = NULL;
+    SECLayer    *upper_layer = NULL;
+    SECVideoBuf *ui_buf = NULL;
+    xRectangle   rect = {0,};
+    int index;
+    Bool comp = FALSE;
+
+    index = _secVirtualVideoGetOutBufferIndex (pPort);
+    if (index < 0)
+    {
+        XDBG_WARNING (MVA, "all out buffers are in use.\n");
+        return FALSE;
+    }
+
+    lower_layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_LOWER1);
+    if (lower_layer)
+    {
+        SECVideoBuf *lower_buf = secLayerGetBuffer (lower_layer);
+
+        if (!lower_buf->secure && lower_buf && VBUF_IS_VALID (lower_buf))
+        {
+            /* In case of virtual, lower layer already has full-size. */
+            dst_buf = lower_buf;
+            comp = TRUE;
+        }
+    }
+
+    if (!dst_buf)
+    {
+        if (!_secVirtualVideoEnsureDstBuffer (pPort))
+            return FALSE;
+
+        dst_buf = pPort->dstbuf;
+    }
+
+    /* before compositing, flush all */
+    secUtilCacheFlush (pPort->pScrn);
+
+    ui_buf = _secVirtualVideoGetUIBuffer (pPort, DRM_MODE_CONNECTOR_VIRTUAL);
+    if (ui_buf)
+    {
+        XDBG_DEBUG (MVA, "ui : %c%c%c%c  %dx%d (%d,%d %dx%d) => dst : %c%c%c%c  %dx%d (%d,%d %dx%d)\n",
+                    FOURCC_STR (ui_buf->id),
+                    ui_buf->width, ui_buf->height,
+                    ui_buf->crop.x, ui_buf->crop.y,
+                    ui_buf->crop.width, ui_buf->crop.height,
+                    FOURCC_STR (dst_buf->id),
+                    dst_buf->width, dst_buf->height,
+                    0, 0,
+                    dst_buf->width, dst_buf->height);
+
+        if (!_secVirtualVideoComposite (ui_buf, dst_buf,
+                                        ui_buf->crop.x, ui_buf->crop.y,
+                                        ui_buf->crop.width, ui_buf->crop.height,
+                                        0, 0,
+                                        dst_buf->width, dst_buf->height,
+                                        comp, 0))
+        {
+            secUtilVideoBufferUnref (ui_buf);
+            return FALSE;
+        }
+
+        comp = TRUE;
+    }
+
+    upper_layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_UPPER);
+    if (upper_layer)
+    {
+        SECVideoBuf *upper_buf = secLayerGetBuffer (upper_layer);
+
+        if (upper_buf && VBUF_IS_VALID (upper_buf))
+        {
+            secLayerGetRect (upper_layer, &upper_buf->crop, &rect);
+
+            XDBG_DEBUG (MVA, "upper : %c%c%c%c  %dx%d (%d,%d %dx%d) => dst : %c%c%c%c  %dx%d (%d,%d %dx%d)\n",
+                        FOURCC_STR (upper_buf->id),
+                        upper_buf->width, upper_buf->height,
+                        upper_buf->crop.x, upper_buf->crop.y,
+                        upper_buf->crop.width, upper_buf->crop.height,
+                        FOURCC_STR (dst_buf->id),
+                        dst_buf->width, dst_buf->height,
+                        rect.x, rect.y, rect.width, rect.height);
+
+            _secVirtualVideoComposite (upper_buf, dst_buf,
+                                       upper_buf->crop.x, upper_buf->crop.y,
+                                       upper_buf->crop.width, upper_buf->crop.height,
+                                       rect.x, rect.y, rect.width, rect.height,
+                                       comp, 0);
+        }
+    }
+
+    dst_buf->crop.x = 0;
+    dst_buf->crop.y = 0;
+    dst_buf->crop.width = dst_buf->width;
+    dst_buf->crop.height = dst_buf->height;
+
+    XDBG_RETURN_VAL_IF_FAIL (pPort->outbuf[index] != NULL, FALSE);
+
+    pPort->outbuf[index]->crop.x = 0;
+    pPort->outbuf[index]->crop.y = 0;
+    pPort->outbuf[index]->crop.width = pPort->outbuf[index]->width;
+    pPort->outbuf[index]->crop.height = pPort->outbuf[index]->height;
+    _secVirtualVideoComposite (dst_buf, pPort->outbuf[index],
+                               0, 0, dst_buf->width, dst_buf->height,
+                               0, 0, pPort->outbuf[index]->width, pPort->outbuf[index]->height,
+                               FALSE, 0);
+
+    _secVirtualVideoDraw (pPort, pPort->outbuf[index]);
+
+    if (ui_buf)
+        secUtilVideoBufferUnref (ui_buf);
+
+    return TRUE;
+}
+
+static void
+_secVirtualVideoCompositeSubtitle (SECPortPrivPtr pPort, SECVideoBuf *vbuf)
+{
+    SECLayer    *subtitle_layer;
+    SECVideoBuf *subtitle_vbuf;
+    xRectangle   src_rect;
+    xRectangle   dst_rect;
+
+    subtitle_layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_UPPER);
+    if (!subtitle_layer)
+        return;
+
+    subtitle_vbuf = secLayerGetBuffer (subtitle_layer);
+    if (!subtitle_vbuf || !VBUF_IS_VALID (subtitle_vbuf))
+        return;
+
+    CLEAR (src_rect);
+    CLEAR (dst_rect);
+    secLayerGetRect (subtitle_layer, &src_rect, &dst_rect);
+
+    XDBG_DEBUG (MVA, "subtitle : %dx%d (%d,%d %dx%d) => %dx%d (%d,%d %dx%d)\n",
+                subtitle_vbuf->width, subtitle_vbuf->height,
+                src_rect.x, src_rect.y, src_rect.width, src_rect.height,
+                vbuf->width, vbuf->height,
+                dst_rect.x, dst_rect.y, dst_rect.width, dst_rect.height);
+
+    _secVirtualVideoComposite (subtitle_vbuf, vbuf,
+                               src_rect.x, src_rect.y, src_rect.width, src_rect.height,
+                               dst_rect.x, dst_rect.y, dst_rect.width, dst_rect.height,
+                               TRUE, 0);
+}
+
+static CARD32
+_secVirtualVideoRetireTimeout (OsTimerPtr timer, CARD32 now, pointer arg)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr) arg;
+    SECModePtr pSecMode;
+    int diff;
+
+    if (!pPort)
+        return 0;
+
+    pSecMode = (SECModePtr)SECPTR (pPort->pScrn)->pSecMode;
+
+    if (pPort->retire_timer)
+    {
+        TimerFree (pPort->retire_timer);
+        pPort->retire_timer = NULL;
+    }
+
+    XDBG_ERROR (MVA, "capture(%d) mode(%d) conn(%d) type(%d) status(%x). \n",
+                pPort->capture, pSecMode->set_mode, pSecMode->conn_mode,
+                pPort->data_type, pPort->status);
+
+    diff = GetTimeInMillis () - pPort->retire_time;
+    XDBG_ERROR (MVA, "failed : +++ Retire Timeout!! diff(%d)\n", diff);
+
+    return 0;
+}
+
+static void
+_secVirtualVideoLayerNotifyFunc (SECLayer *layer, int type, void *type_data, void *data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr)data;
+    SECVideoBuf *vbuf = (SECVideoBuf*)type_data;
+    SECVideoBuf *black;
+
+    secLayerRemoveNotifyFunc (layer, _secVirtualVideoLayerNotifyFunc);
+
+    if (type == LAYER_DESTROYED || type != LAYER_BUF_CHANGED || !vbuf)
+        goto fail_layer_noti;
+
+    XDBG_GOTO_IF_FAIL (VBUF_IS_VALID (vbuf), fail_layer_noti);
+    XDBG_GOTO_IF_FAIL (vbuf->showing == FALSE, fail_layer_noti);
+
+    XDBG_DEBUG (MVA, "------------------------------\n");
+
+    _secVirtualVideoCompositeSubtitle (pPort, vbuf);
+    _secVirtualVideoDraw (pPort, vbuf);
+    XDBG_DEBUG (MVA, "------------------------------...\n");
+
+    return;
+
+fail_layer_noti:
+    black = _secVirtualVideoGetBlackBuffer (pPort);
+    XDBG_TRACE (MVA, "black buffer(%d) return: layer noti. type(%d), vbuf(%p)\n",
+                (black)?black->keys[0]:0, type, vbuf);
+    _secVirtualVideoDraw (pPort, black);
+}
+
+static int
+_secVirtualVideoPutStill (SECPortPrivPtr pPort)
+{
+    SECModePtr pSecMode = (SECModePtr)SECPTR (pPort->pScrn)->pSecMode;
+    SECVideoBuf *pix_buf = NULL;
+    SECVideoBuf *ui_buf = NULL;
+    Bool comp;
+    int i;
+    CARD32 start = GetTimeInMillis ();
+
+    XDBG_GOTO_IF_FAIL (pPort->secure == FALSE, done_still);
+
+    if (pPort->retire_timer)
+    {
+        TimerFree (pPort->retire_timer);
+        pPort->retire_timer = NULL;
+    }
+
+    comp = FALSE;
+
+    pix_buf = _secVirtualVideoGetDrawableBuffer (pPort);
+    XDBG_GOTO_IF_FAIL (pix_buf != NULL, done_still);
+
+    ui_buf = _secVirtualVideoGetUIBuffer (pPort, DRM_MODE_CONNECTOR_LVDS);
+    XDBG_GOTO_IF_FAIL (ui_buf != NULL, done_still);
+
+    tbm_bo_map (pix_buf->bo[0], TBM_DEVICE_2D, TBM_OPTION_WRITE);
+
+    for (i = LAYER_LOWER2; i < LAYER_MAX; i++)
+    {
+        SECVideoBuf *upper = NULL;
+        xRectangle src_rect, dst_rect;
+        int vwidth = pSecMode->main_lcd_mode.hdisplay;
+        int vheight = pSecMode->main_lcd_mode.vdisplay;
+        int rotate;
+
+        if (i == LAYER_DEFAULT)
+        {
+            upper = secUtilVideoBufferRef (ui_buf);
+            tbm_bo_map (upper->bo[0], TBM_DEVICE_2D, TBM_OPTION_READ);
+
+            src_rect.x = src_rect.y = 0;
+            src_rect.width = ui_buf->width;
+            src_rect.height = ui_buf->height;
+
+            dst_rect.x = dst_rect.y = 0;
+            dst_rect.width = ui_buf->width;
+            dst_rect.height = ui_buf->height;
+
+            rotate = 0;
+        }
+        else
+        {
+            SECLayer *layer = secLayerFind (LAYER_OUTPUT_LCD, (SECLayerPos)i);
+            int off_x = 0, off_y = 0;
+            SECVideoPrivPtr pVideo = SECPTR(pPort->pScrn)->pVideoPriv;
+
+            if (!layer)
+                continue;
+
+            upper = secUtilVideoBufferRef (secLayerGetBuffer (layer));
+            if (!upper || !VBUF_IS_VALID (upper))
+                continue;
+
+            secLayerGetRect (layer, &src_rect, &dst_rect);
+            secLayerGetOffset (layer, &off_x, &off_y);
+            dst_rect.x += off_x;
+            dst_rect.y += off_y;
+
+            rotate = (360 - pVideo->screen_rotate_degree) % 360;
+
+            /* rotate upper_rect */
+            secUtilRotateArea (&vwidth, &vheight, &dst_rect, rotate);
+        }
+
+        /* scale upper_rect */
+        secUtilScaleRect (vwidth, vheight, pix_buf->width, pix_buf->height, &dst_rect);
+
+        XDBG_DEBUG (MVA, "%dx%d(%d,%d, %dx%d) => %dx%d(%d,%d, %dx%d) :comp(%d) r(%d)\n",
+                    upper->width, upper->height,
+                    src_rect.x, src_rect.y, src_rect.width, src_rect.height,
+                    pix_buf->width, pix_buf->height,
+                    dst_rect.x, dst_rect.y, dst_rect.width, dst_rect.height,
+                    comp, rotate);
+
+        if (!_secVirtualVideoComposite (upper, pix_buf,
+                                        src_rect.x, src_rect.y,
+                                        src_rect.width, src_rect.height,
+                                        dst_rect.x, dst_rect.y,
+                                        dst_rect.width, dst_rect.height,
+                                        comp, rotate))
+        {
+            if (i == LAYER_DEFAULT)
+                tbm_bo_unmap (upper->bo[0]);
+            tbm_bo_unmap (pix_buf->bo[0]);
+            goto done_still;
+        }
+
+        if (i == LAYER_DEFAULT)
+            tbm_bo_unmap (upper->bo[0]);
+
+        secUtilVideoBufferUnref (upper);
+
+        comp = TRUE;
+    }
+
+    XDBG_TRACE (MVA, "make still: %ldms\n", GetTimeInMillis() - start);
+
+    tbm_bo_unmap (pix_buf->bo[0]);
+
+done_still:
+
+    secUtilCacheFlush (pPort->pScrn);
+
+    if (pix_buf)
+        secUtilVideoBufferUnref (pix_buf);
+    if (ui_buf)
+        secUtilVideoBufferUnref (ui_buf);
+
+    DamageDamageRegion (pPort->pDraw, pPort->clipBoxes);
+    pPort->need_damage = FALSE;
+
+    SECPtr pSec = SECPTR (pPort->pScrn);
+    if ((pSec->dump_mode & XBERC_DUMP_MODE_CA) && pSec->dump_info)
+    {
+        PixmapPtr pPixmap = _secVirtualVideoGetPixmap (pPort->pDraw);
+        char file[128];
+        static int i;
+        snprintf (file, sizeof(file), "capout_still_%03d.bmp", i++);
+        secUtilDoDumpPixmaps (pSec->dump_info, pPixmap, file);
+    }
+
+    return Success;
+}
+
+static int
+_secVirtualVideoPutWB (SECPortPrivPtr pPort)
+{
+    SECPtr pSec = SECPTR (pPort->pScrn);
+
+    XDBG_RETURN_VAL_IF_FAIL (pPort->pScrn != NULL, BadImplementation);
+    XDBG_RETURN_VAL_IF_FAIL (pPort->pDraw != NULL, BadImplementation);
+
+    if (!_secVirtualVideoEnsureOutBuffers (pPort->pScrn, pPort, pPort->id, pPort->pDraw->width, pPort->pDraw->height))
+        return BadAlloc;
+
+    if (!pPort->wb)
+    {
+        int scanout;
+
+        if (secWbIsOpened ())
+        {
+            XDBG_ERROR (MVA, "Fail : wb open. \n");
+            return BadRequest;
+        }
+
+        if (pPort->display == DISPLAY_LCD)
+            scanout = FALSE;
+        else
+            scanout = pSec->scanout;
+
+        /* For capture mode, we don't need to create contiguous buffer.
+         * Rotation should be considered when wb begins.
+         */
+        pPort->wb = secWbOpen (pPort->pScrn, pPort->id,
+                               pPort->pDraw->width, pPort->pDraw->height,
+                               scanout, 60,
+                               (pPort->rotate_off)?FALSE:TRUE);
+        XDBG_RETURN_VAL_IF_FAIL (pPort->wb != NULL, BadAlloc);
+
+        secWbSetBuffer (pPort->wb, pPort->outbuf, pPort->outbuf_num);
+
+        XDBG_TRACE (MVA, "wb(%p) start. \n", pPort->wb);
+
+        if (!secWbStart (pPort->wb))
+        {
+            secWbClose (pPort->wb);
+            pPort->wb = NULL;
+            return BadAlloc;
+        }
+        secWbAddNotifyFunc (pPort->wb, WB_NOTI_STOP,
+                            _secVirtualVideoWbStopFunc, pPort);
+        secWbAddNotifyFunc (pPort->wb, WB_NOTI_IPP_EVENT,
+                            _secVirtualVideoWbDumpFunc, pPort);
+        if (pPort->capture == CAPTURE_MODE_STILL)
+            secWbAddNotifyFunc (pPort->wb, WB_NOTI_IPP_EVENT_DONE,
+                                _secVirtualVideoWbDumpDoneFunc, pPort);
+        secWbAddNotifyFunc (pPort->wb, WB_NOTI_CLOSED,
+                            _secVirtualVideoWbCloseFunc, pPort);
+    }
+
+    /* no available buffer, need to return buffer by client. */
+    if (!secWbIsRunning ())
+    {
+        XDBG_WARNING (MVA, "wb is stopped.\n");
+        return BadRequest;
+    }
+
+    /* no available buffer, need to return buffer by client. */
+    if (!secWbCanDequeueBuffer (pPort->wb))
+    {
+        XDBG_TRACE (MVA, "no available buffer\n");
+        return BadRequest;
+    }
+
+    XDBG_TRACE (MVA, "wb(%p), running(%d). \n", pPort->wb, secWbIsRunning ());
+
+    return Success;
+}
+
+static int
+_secVirtualVideoPutVideoOnly (SECPortPrivPtr pPort)
+{
+    SECLayer *layer;
+    SECVideoBuf *vbuf;
+    int i;
+
+    XDBG_RETURN_VAL_IF_FAIL (pPort->display == DISPLAY_EXTERNAL, BadRequest);
+    XDBG_RETURN_VAL_IF_FAIL (pPort->capture == CAPTURE_MODE_STREAM, BadRequest);
+
+    layer = secLayerFind (LAYER_OUTPUT_EXT, LAYER_LOWER1);
+    if (!layer)
+        return BadRequest;
+
+    for (i = 0; i < pPort->outbuf_num; i++)
+    {
+        if (!pPort->outbuf[i]->showing)
+            break;
+    }
+
+    if (i == pPort->outbuf_num)
+    {
+        XDBG_ERROR (MVA, "now all buffers are in showing\n");
+        return BadRequest;
+    }
+
+    vbuf = secLayerGetBuffer (layer);
+    /* if layer is just created, vbuf can't be null. */
+    if (!vbuf || !VBUF_IS_VALID (vbuf))
+    {
+        SECVideoBuf *black = _secVirtualVideoGetBlackBuffer (pPort);
+        XDBG_RETURN_VAL_IF_FAIL (black != NULL, BadRequest);
+
+        XDBG_TRACE (MVA, "black buffer(%d) return: vbuf invalid\n", black->keys[0]);
+        _secVirtualVideoDraw (pPort, black);
+        return Success;
+    }
+
+    /* Wait the next frame if it's same as previous one */
+    if (_secVirtualVideoFindReturnBuf (pPort, vbuf->keys[0]))
+    {
+        secLayerAddNotifyFunc (layer, _secVirtualVideoLayerNotifyFunc, pPort);
+        XDBG_DEBUG (MVA, "wait notify.\n");
+        return Success;
+    }
+
+    _secVirtualVideoCompositeSubtitle (pPort, vbuf);
+    _secVirtualVideoDraw (pPort, vbuf);
+
+    return Success;
+}
+
+static int
+_secVirtualVideoPutExt (SECPortPrivPtr pPort)
+{
+    if (_secVirtualVideoCompositeExtLayers (pPort))
+        return Success;
+
+    return BadRequest;
+}
+
+static int
+SECVirtualVideoGetPortAttribute (ScrnInfoPtr pScrn,
+                                 Atom        attribute,
+                                 INT32      *value,
+                                 pointer     data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+
+    if (attribute == _secVideoGetPortAtom (PAA_FORMAT))
+    {
+        *value = pPort->id;
+        return Success;
+    }
+    else if (attribute == _secVideoGetPortAtom (PAA_CAPTURE))
+    {
+        *value = pPort->capture;
+        return Success;
+    }
+    else if (attribute == _secVideoGetPortAtom (PAA_DISPLAY))
+    {
+        *value = pPort->display;
+        return Success;
+    }
+    else if (attribute == _secVideoGetPortAtom (PAA_ROTATE_OFF))
+    {
+        *value = pPort->rotate_off;
+        return Success;
+    }
+    else if (attribute == _secVideoGetPortAtom (PAA_DATA_TYPE))
+    {
+        *value = pPort->data_type;
+        return Success;
+    }
+    else if (attribute == _secVideoGetPortAtom (PAA_SECURE))
+    {
+        *value = pPort->secure;
+        return Success;
+    }
+    return BadMatch;
+}
+
+static int
+SECVirtualVideoSetPortAttribute (ScrnInfoPtr pScrn,
+                                 Atom        attribute,
+                                 INT32       value,
+                                 pointer     data)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+
+    if (attribute == _secVideoGetPortAtom (PAA_FORMAT))
+    {
+        if (!_secVirtualVideoIsSupport ((unsigned int)value))
+        {
+            XDBG_ERROR (MVA, "id(%c%c%c%c) not supported.\n", FOURCC_STR (value));
+            return BadRequest;
+        }
+
+        pPort->id = (unsigned int)value;
+        XDBG_DEBUG (MVA, "id(%d) \n", value);
+        return Success;
+    }
+    else if (attribute == _secVideoGetPortAtom (PAA_CAPTURE))
+    {
+        if (value < CAPTURE_MODE_NONE || value >= CAPTURE_MODE_MAX)
+        {
+            XDBG_ERROR (MVA, "capture value(%d) is out of range\n", value);
+            return BadRequest;
+        }
+
+        pPort->capture = value;
+        XDBG_DEBUG (MVA, "capture(%d) \n", pPort->capture);
+        return Success;
+    }
+    else if (attribute == _secVideoGetPortAtom (PAA_DISPLAY))
+    {
+        XDBG_DEBUG (MVA, "display: %d \n", pPort->display);
+        pPort->display = value;
+        return Success;
+    }
+    else if (attribute == _secVideoGetPortAtom (PAA_ROTATE_OFF))
+    {
+        XDBG_DEBUG (MVA, "ROTATE_OFF: %d! \n", pPort->rotate_off);
+        pPort->rotate_off = value;
+        return Success;
+    }
+    else if (attribute == _secVideoGetPortAtom (PAA_SECURE))
+    {
+        XDBG_TRACE (MVA, "not implemented 'secure' attr. (%d) \n", pPort->secure);
+//        pPort->secure = value;
+        return Success;
+    }
+    else if (attribute == _secVideoGetPortAtom (PAA_RETBUF))
+    {
+        RetBufInfo *info;
+
+        if (!pPort->pDraw)
+            return Success;
+
+        info = _secVirtualVideoFindReturnBuf (pPort, value);
+        if (!info)
+        {
+            XDBG_WARNING (MVA, "wrong gem name(%d) returned\n", value);
+            return Success;
+        }
+
+        if (info->vbuf && info->vbuf->need_reset)
+            secUtilClearVideoBuffer (info->vbuf);
+
+        _secVirtualVideoRemoveReturnBuf (pPort, info);
+#if 0
+        _buffers (pPort);
+        ErrorF ("[Xorg] retbuf : %ld (%s)\n", value, buffers);
+#endif
+
+        return Success;
+    }
+
+    return Success;
+}
+
+/* vid_w, vid_h : no meaning for us. not using.
+ * dst_w, dst_h : size to hope for PutStill.
+ * p_w, p_h     : real size for PutStill.
+ */
+static void
+SECVirtualVideoQueryBestSize (ScrnInfoPtr pScrn,
+                              Bool motion,
+                              short vid_w, short vid_h,
+                              short dst_w, short dst_h,
+                              unsigned int *p_w, unsigned int *p_h,
+                              pointer data)
+{
+    SECModePtr pSecMode = (SECModePtr)SECPTR (pScrn)->pSecMode;
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+
+    if (pPort->display == DISPLAY_EXTERNAL)
+    {
+        if (p_w)
+            *p_w = pSecMode->ext_connector_mode.hdisplay;
+        if (p_h)
+            *p_h = pSecMode->ext_connector_mode.vdisplay;
+    }
+    else
+    {
+        if (p_w)
+            *p_w = (unsigned int)dst_w;
+        if (p_h)
+            *p_h = (unsigned int)dst_h;
+    }
+}
+
+/* vid_x, vid_y, vid_w, vid_h : no meaning for us. not using.
+ * drw_x, drw_y, dst_w, dst_h : no meaning for us. not using.
+ * Only pDraw's size is used.
+ */
+static int
+SECVirtualVideoPutStill (ScrnInfoPtr pScrn,
+                         short vid_x, short vid_y, short drw_x, short drw_y,
+                         short vid_w, short vid_h, short drw_w, short drw_h,
+                         RegionPtr clipBoxes, pointer data, DrawablePtr pDraw )
+{
+    SECPtr pSec = SECPTR (pScrn);
+    SECModePtr pSecMode = (SECModePtr)SECPTR (pScrn)->pSecMode;
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+    int ret = BadRequest;
+
+    XDBG_GOTO_IF_FAIL (pPort->need_damage == FALSE, put_still_fail);
+
+    if (pPort->capture == CAPTURE_MODE_STILL && pPort->display == DISPLAY_EXTERNAL)
+    {
+        XDBG_ERROR (MVA, "not implemented to capture still of external display. \n");
+        return BadImplementation;
+    }
+
+    if (pPort->display == DISPLAY_EXTERNAL && pSecMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL)
+    {
+        XDBG_ERROR (MVA, "virtual display not connected!. \n");
+        return BadRequest;
+    }
+
+#if 0
+    ErrorF ("[Xorg] PutStill\n");
+#endif
+
+    XDBG_DEBUG (MVA, "*************************************** \n");
+
+    if (pSec->xvperf_mode & XBERC_XVPERF_MODE_CA)
+    {
+        CARD32 cur, sub;
+        cur = GetTimeInMillis ();
+        sub = cur - pPort->prev_time;
+        pPort->prev_time = cur;
+        ErrorF ("getstill interval     : %6ld ms\n", sub);
+    }
+
+    if (pPort->retire_timer)
+    {
+        TimerFree (pPort->retire_timer);
+        pPort->retire_timer = NULL;
+    }
+
+    if (pSec->pVideoPriv->no_retbuf)
+        _secVirtualVideoRemoveReturnBufAll (pPort);
+
+    pPort->retire_timer = TimerSet (pPort->retire_timer, 0, 4000,
+                                    _secVirtualVideoRetireTimeout,
+                                    pPort);
+    XDBG_GOTO_IF_FAIL (pPort->id > 0, put_still_fail);
+
+    pPort->status = 0;
+    pPort->retire_time = GetTimeInMillis ();
+
+    ret = _secVirtualVideoPreProcess (pScrn, pPort, clipBoxes, pDraw);
+    XDBG_GOTO_IF_FAIL (ret == Success, put_still_fail);
+
+    ret = _secVirtualVideoAddDrawableEvent (pPort);
+    XDBG_GOTO_IF_FAIL (ret == Success, put_still_fail);
+
+    /* check drawable */
+    XDBG_RETURN_VAL_IF_FAIL (pDraw->type == DRAWABLE_PIXMAP, BadPixmap);
+
+    if (!pPort->putstill_on)
+    {
+        pPort->putstill_on = TRUE;
+        XDBG_SECURE (MVA, "pPort(%d) putstill on. secure(%d), capture(%d), format(%c%c%c%c)\n",
+                     pPort->index, pPort->secure, pPort->capture, FOURCC_STR (pPort->id), 60);
+    }
+
+    pPort->need_damage = TRUE;
+
+    if (pPort->capture == CAPTURE_MODE_STILL && pPort->display == DISPLAY_LCD)
+    {
+        XDBG_DEBUG (MVA, "still mode.\n");
+
+        if (1)
+            ret = _secVirtualVideoPutStill (pPort);
+        else
+            /* camera buffer can't be mapped. we should use WB to capture screen */
+            ret = _secVirtualVideoPutWB (pPort);
+
+        XDBG_GOTO_IF_FAIL (ret == Success, put_still_fail);
+    }
+    else if (pPort->capture == CAPTURE_MODE_STREAM && pPort->display == DISPLAY_LCD)
+    {
+        XDBG_DEBUG (MVA, "stream mode.\n");
+        if (SECPTR (pScrn)->isLcdOff)
+        {
+            XDBG_TRACE (MVA, "DPMS status: off. \n");
+            ret = BadRequest;
+            goto put_still_fail;
+        }
+
+        ret = _secVirtualVideoPutWB (pPort);
+        if (ret != Success)
+            goto put_still_fail;
+    }
+    else if (pPort->capture == CAPTURE_MODE_STREAM && pPort->display == DISPLAY_EXTERNAL)
+    {
+        int old_data_type = pPort->data_type;
+        SECVideoBuf *black;
+
+        switch (pSecMode->set_mode)
+        {
+        case DISPLAY_SET_MODE_OFF:
+            XDBG_DEBUG (MVA, "display mode is off. \n");
+            black = _secVirtualVideoGetBlackBuffer (pPort);
+            XDBG_RETURN_VAL_IF_FAIL (black != NULL, BadRequest);
+            XDBG_DEBUG (MVA, "black buffer(%d) return: lcd off\n", black->keys[0]);
+            _secVirtualVideoDraw (pPort, black);
+            ret = Success;
+            goto put_still_fail;
+
+        case DISPLAY_SET_MODE_CLONE:
+            pPort->data_type = _secVirtualVideoDataType (pPort);
+
+            if (pPort->data_type != old_data_type)
+                _secVirtualVideoSendPortNotify (pPort, PAA_DATA_TYPE, pPort->data_type);
+
+            if (pPort->data_type == DATA_TYPE_UI)
+            {
+                XDBG_DEBUG (MVA, "clone mode.\n");
+
+                ret = _secVirtualVideoPutWB (pPort);
+                if (ret != Success)
+                    goto put_still_fail;
+            }
+            else
+            {
+                XDBG_DEBUG (MVA, "video only mode.\n");
+                ret = _secVirtualVideoPutVideoOnly (pPort);
+                if (ret != Success)
+                    goto put_still_fail;
+            }
+            break;
+
+        case DISPLAY_SET_MODE_EXT:
+            XDBG_DEBUG (MVA, "desktop mode.\n");
+
+            if (pSecMode->ext_connector_mode.hdisplay != pDraw->width ||
+                pSecMode->ext_connector_mode.vdisplay != pDraw->height)
+            {
+                XDBG_ERROR (MVA, "drawble should have %dx%d size. mode(%d), conn(%d)\n",
+                            pSecMode->ext_connector_mode.hdisplay,
+                            pSecMode->ext_connector_mode.vdisplay,
+                            pSecMode->set_mode, pSecMode->conn_mode);
+                ret = BadRequest;
+                goto put_still_fail;
+            }
+
+            ret = _secVirtualVideoPutExt (pPort);
+            if (ret != Success)
+                goto put_still_fail;
+            break;
+
+        default:
+            break;
+        }
+    }
+    else
+    {
+        XDBG_NEVER_GET_HERE (MVA);
+        ret = BadRequest;
+        goto put_still_fail;
+    }
+
+    XDBG_DEBUG (MVA, "***************************************.. \n");
+    return Success;
+
+put_still_fail:
+    pPort->need_damage = FALSE;
+
+    if (pPort->retire_timer)
+    {
+        TimerFree (pPort->retire_timer);
+        pPort->retire_timer = NULL;
+    }
+
+    XDBG_DEBUG (MVA, "***************************************.. \n");
+
+    return ret;
+}
+
+static void
+SECVirtualVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit)
+{
+    SECPortPrivPtr pPort = (SECPortPrivPtr) data;
+
+    _secVirtualVideoStreamOff (pPort);
+}
+
+static int
+SECVirtualVideoDDPutStill (ClientPtr client,
+                           DrawablePtr pDraw,
+                           XvPortPtr pPort,
+                           GCPtr pGC,
+                           INT16 vid_x, INT16 vid_y,
+                           CARD16 vid_w, CARD16 vid_h,
+                           INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
+{
+    SECVideoPortInfo *info = _port_info (pDraw);
+    int ret;
+
+    if (info)
+    {
+        info->client = client;
+        info->pp = pPort;
+    }
+
+    ret = ddPutStill (client, pDraw, pPort, pGC,
+                      vid_x, vid_y, vid_w, vid_h,
+                      drw_x, drw_y, drw_w, drw_h);
+
+    return ret;
+}
+
+XF86VideoAdaptorPtr
+secVideoSetupVirtualVideo (ScreenPtr pScreen)
+{
+    XF86VideoAdaptorPtr pAdaptor;
+    SECPortPrivPtr pPort;
+    int i;
+
+    pAdaptor = calloc (1, sizeof (XF86VideoAdaptorRec) +
+                       (sizeof (DevUnion) + sizeof (SECPortPriv)) * SEC_MAX_PORT);
+    if (!pAdaptor)
+        return NULL;
+
+    dummy_encoding[0].width = pScreen->width;
+    dummy_encoding[0].height = pScreen->height;
+
+    pAdaptor->type = XvWindowMask | XvPixmapMask | XvInputMask | XvStillMask;
+    pAdaptor->flags = 0;
+    pAdaptor->name = "SEC Virtual Video";
+    pAdaptor->nEncodings = sizeof (dummy_encoding) / sizeof (XF86VideoEncodingRec);
+    pAdaptor->pEncodings = dummy_encoding;
+    pAdaptor->nFormats = NUM_FORMATS;
+    pAdaptor->pFormats = formats;
+    pAdaptor->nPorts = SEC_MAX_PORT;
+    pAdaptor->pPortPrivates = (DevUnion*)(&pAdaptor[1]);
+
+    pPort = (SECPortPrivPtr) (&pAdaptor->pPortPrivates[SEC_MAX_PORT]);
+
+    for (i = 0; i < SEC_MAX_PORT; i++)
+    {
+        pAdaptor->pPortPrivates[i].ptr = &pPort[i];
+        pPort[i].index = i;
+        pPort[i].id = FOURCC_RGB32;
+        pPort[i].outbuf_index = -1;
+
+        xorg_list_init (&pPort[i].retbuf_info);
+    }
+
+    pAdaptor->nAttributes = NUM_ATTRIBUTES;
+    pAdaptor->pAttributes = attributes;
+    pAdaptor->nImages = NUM_IMAGES;
+    pAdaptor->pImages = images;
+
+    pAdaptor->GetPortAttribute     = SECVirtualVideoGetPortAttribute;
+    pAdaptor->SetPortAttribute     = SECVirtualVideoSetPortAttribute;
+    pAdaptor->QueryBestSize        = SECVirtualVideoQueryBestSize;
+    pAdaptor->PutStill             = SECVirtualVideoPutStill;
+    pAdaptor->StopVideo            = SECVirtualVideoStop;
+
+    if (!_secVirtualVideoRegisterEventResourceTypes ())
+    {
+        ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+        xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "Failed to register EventResourceTypes. \n");
+        return NULL;
+    }
+
+    return pAdaptor;
+}
+
+void
+secVirtualVideoDpms (ScrnInfoPtr pScrn, Bool on)
+{
+    SECPtr pSec = (SECPtr) pScrn->driverPrivate;
+    XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[1];
+    int i;
+
+    if (on)
+        return;
+
+    for (i = 0; i < SEC_MAX_PORT; i++)
+    {
+        SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
+
+        if (pPort->wb)
+        {
+            secWbClose (pPort->wb);
+            pPort->wb = NULL;
+        }
+    }
+}
+
+void
+secVirtualVideoReplacePutStillFunc (ScreenPtr pScreen)
+{
+    int i;
+
+    XvScreenPtr xvsp = dixLookupPrivate (&pScreen->devPrivates,
+                                         XvGetScreenKey());
+    if (!xvsp)
+        return;
+
+    for (i = 1; i < xvsp->nAdaptors; i++)
+    {
+        XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
+        if (pAdapt->ddPutStill)
+        {
+            ddPutStill = pAdapt->ddPutStill;
+            pAdapt->ddPutStill = SECVirtualVideoDDPutStill;
+            break;
+        }
+    }
+
+    if (!dixRegisterPrivateKey (VideoVirtualPortKey, PRIVATE_WINDOW, sizeof (SECVideoPortInfo)))
+        return;
+    if (!dixRegisterPrivateKey (VideoVirtualPortKey, PRIVATE_PIXMAP, sizeof (SECVideoPortInfo)))
+        return;
+}
+
+void
+secVirtualVideoGetBuffers (ScrnInfoPtr pScrn, int id, int width, int height, SECVideoBuf ***vbufs, int *bufnum)
+{
+    SECPtr pSec = (SECPtr) pScrn->driverPrivate;
+    XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[1];
+    int i;
+
+    for (i = 0; i < SEC_MAX_PORT; i++)
+    {
+        SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
+
+        if (pPort->pDraw)
+        {
+            XDBG_RETURN_IF_FAIL (pPort->id == id);
+            XDBG_RETURN_IF_FAIL (pPort->pDraw->width == width);
+            XDBG_RETURN_IF_FAIL (pPort->pDraw->height == height);
+        }
+
+        if (!_secVirtualVideoEnsureOutBuffers (pScrn, pPort, id, width, height))
+            return;
+
+        *vbufs = pPort->outbuf;
+        *bufnum = pPort->outbuf_num;
+    }
+}
diff --git a/src/xv/sec_video_virtual.h b/src/xv/sec_video_virtual.h
new file mode 100644 (file)
index 0000000..a3400b4
--- /dev/null
@@ -0,0 +1,40 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+#ifndef __SEC_VIDEO_VIRTUAL_H__
+#define __SEC_VIDEO_VIRTUAL_H__
+
+/* setup virtual adaptor */
+XF86VideoAdaptorPtr secVideoSetupVirtualVideo (ScreenPtr pScreen);
+void secVirtualVideoReplacePutStillFunc (ScreenPtr pScreen);
+
+void secVirtualVideoDpms (ScrnInfoPtr pScrn, Bool on);
+void secVirtualVideoGetBuffers (ScrnInfoPtr pScrn, int id, int width, int height, SECVideoBuf ***vbufs, int *bufnum);
+
+#endif // __SEC_VIDEO_VIRTUAL_H__
diff --git a/src/xv/xv_types.h b/src/xv/xv_types.h
new file mode 100644 (file)
index 0000000..e82b4e4
--- /dev/null
@@ -0,0 +1,88 @@
+/**************************************************************************
+
+xserver-xorg-video-exynos
+
+Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Boram Park <boram1288.park@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*                                                              */
+/* File name : xv_types.h                                       */
+/* Author : Boram Park (boram1288.park@samsung.com)             */
+/* Protocol Version : 1.0.1 (Dec 16th 2009)                       */
+/* This file is for describing Xv APIs' buffer encoding method. */
+/*                                                              */
+
+#ifndef __XV_TYPE_H__
+#define __XV_TYPE_H__
+
+#define XV_DATA_HEADER 0xDEADCD01
+#define XV_DATA_VERSION        0x00010001
+
+/* Return Values */
+#define XV_OK 0
+#define XV_HEADER_ERROR -1
+#define XV_VERSION_MISMATCH -2
+
+#define XV_BUF_TYPE_DMABUF  0
+#define XV_BUF_TYPE_LEGACY  1
+
+/* Data structure for XvPutImage / XvShmPutImage */
+typedef struct
+{
+    unsigned int _header; /* for internal use only */
+    unsigned int _version; /* for internal use only */
+
+    unsigned int YBuf;
+    unsigned int CbBuf;
+    unsigned int CrBuf;
+
+    unsigned int BufType;
+} XV_DATA, * XV_DATA_PTR;
+
+static void
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+XV_INIT_DATA (XV_DATA_PTR data)
+{
+    data->_header = XV_DATA_HEADER;
+    data->_version = XV_DATA_VERSION;
+}
+
+static int
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+XV_VALIDATE_DATA (XV_DATA_PTR data)
+{
+    if (data->_header != XV_DATA_HEADER)
+        return XV_HEADER_ERROR;
+    if (data->_version != XV_DATA_VERSION)
+        return XV_VERSION_MISMATCH;
+    return XV_OK;
+}
+
+#endif