summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjk7744.park <jk7744.park@samsung.com>2015-09-08 21:31:07 +0900
committerjk7744.park <jk7744.park@samsung.com>2015-09-08 21:31:07 +0900
commitcb41fec8f453fd5dc9fb1d4a92a6d49f043578fc (patch)
tree5bc62f2394f8b418b20ea103b5afdac3d1427b0b /src
parentdd7d4f2aa2cf93ded1e89c1cb1770654e5f9c1e6 (diff)
downloadxserver-xorg-video-exynos-tizen_2.3.1.tar.gz
xserver-xorg-video-exynos-tizen_2.3.1.tar.bz2
xserver-xorg-video-exynos-tizen_2.3.1.zip
Diffstat (limited to 'src')
-rwxr-xr-xsrc/Makefile.am71
-rwxr-xr-xsrc/accel/sec_accel.h155
-rwxr-xr-xsrc/accel/sec_dri2.c1991
-rwxr-xr-xsrc/accel/sec_exa.c664
-rwxr-xr-xsrc/accel/sec_exa_g2d.c1726
-rwxr-xr-xsrc/accel/sec_exa_sw.c1266
-rwxr-xr-xsrc/crtcconfig/sec_crtc.c2768
-rwxr-xr-xsrc/crtcconfig/sec_crtc.h170
-rwxr-xr-xsrc/crtcconfig/sec_display.c1681
-rwxr-xr-xsrc/crtcconfig/sec_display.h183
-rwxr-xr-xsrc/crtcconfig/sec_layer.c1146
-rw-r--r--src/crtcconfig/sec_layer.h105
-rwxr-xr-xsrc/crtcconfig/sec_output.c881
-rw-r--r--src/crtcconfig/sec_output.h65
-rw-r--r--src/crtcconfig/sec_plane.c1334
-rw-r--r--src/crtcconfig/sec_plane.h84
-rwxr-xr-xsrc/crtcconfig/sec_prop.c713
-rw-r--r--src/crtcconfig/sec_prop.h50
-rwxr-xr-xsrc/crtcconfig/sec_xberc.c1276
-rw-r--r--src/crtcconfig/sec_xberc.h51
-rw-r--r--src/debug/sec_drmmode_dump.c422
-rw-r--r--src/debug/sec_drmmode_dump.h36
-rw-r--r--src/g2d/fimg2d.c670
-rwxr-xr-xsrc/g2d/fimg2d.h670
-rwxr-xr-xsrc/g2d/fimg2d_reg.h120
-rw-r--r--src/g2d/util_g2d.c889
-rw-r--r--src/ipp/sec_converter.c1021
-rw-r--r--src/ipp/sec_converter.h90
-rw-r--r--src/ipp/sec_drm_ipp.c165
-rw-r--r--src/ipp/sec_drm_ipp.h44
-rw-r--r--src/ipp/sec_wb.c1338
-rw-r--r--src/ipp/sec_wb.h95
-rw-r--r--src/memory/sec_memory_flush.c141
-rw-r--r--src/memory/sec_memory_flush.h85
-rw-r--r--src/neon/copy_area.c535
-rw-r--r--src/neon/memcpy_neon.s1889
-rw-r--r--src/neon/neonmem.h49
-rwxr-xr-xsrc/sec.c1777
-rwxr-xr-xsrc/sec.h230
-rwxr-xr-xsrc/util/sec_util.c2351
-rwxr-xr-xsrc/util/sec_util.h193
-rw-r--r--src/xv/sec_video.c3095
-rw-r--r--src/xv/sec_video.h86
-rw-r--r--src/xv/sec_video_display.c618
-rw-r--r--src/xv/sec_video_display.h36
-rw-r--r--src/xv/sec_video_fourcc.h326
-rw-r--r--src/xv/sec_video_tvout.c529
-rw-r--r--src/xv/sec_video_tvout.h56
-rw-r--r--src/xv/sec_video_types.h168
-rw-r--r--src/xv/sec_video_virtual.c2066
-rw-r--r--src/xv/sec_video_virtual.h40
-rw-r--r--src/xv/xv_types.h88
52 files changed, 36298 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100755
index 0000000..e293a9a
--- /dev/null
+++ b/src/Makefile.am
@@ -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 100755
index 0000000..f9808a3
--- /dev/null
+++ b/src/accel/sec_accel.h
@@ -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 100755
index 0000000..1808979
--- /dev/null
+++ b/src/accel/sec_dri2.c
@@ -0,0 +1,1991 @@
+/**************************************************************************
+
+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*));
+ }
+
+ XDBG_RETURN_VAL_IF_FAIL ((pBackBufPriv->pBackPixmaps != NULL), NULL);
+
+ 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);
+
+ XDBG_RETURN_IF_FAIL (dev != NULL);
+
+ 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 100755
index 0000000..c62ede5
--- /dev/null
+++ b/src/accel/sec_exa.c
@@ -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 100755
index 0000000..c0e4858
--- /dev/null
+++ b/src/accel/sec_exa_g2d.c
@@ -0,0 +1,1726 @@
+/**************************************************************************
+
+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));
+ XDBG_RETURN_VAL_IF_FAIL ((rgn != NULL), NULL);
+
+ 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 = NULL, *b2 = NULL;
+ 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 = NULL;
+
+ xorg_list_for_each_entry (b, l, link)
+ {
+ secUtilBoxMove (&b->box, tx, ty);
+ }
+}
+
+void _g2dBoxRemoveAll (struct xorg_list* l)
+{
+ ExaBox *ref = NULL, *next = NULL;
+
+ 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 = NULL;
+
+ 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 = NULL;
+ 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 = NULL;
+ 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));
+ XDBG_RETURN_IF_FAIL (dest != NULL);
+
+ 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 100755
index 0000000..d8c3537
--- /dev/null
+++ b/src/accel/sec_exa_sw.c
@@ -0,0 +1,1266 @@
+/**************************************************************************
+
+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));
+ XDBG_RETURN_VAL_IF_FAIL ((rgn != NULL), NULL);
+
+ 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 = NULL, *b2 = NULL;
+ 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 = NULL;
+
+ xorg_list_for_each_entry (b, l, link)
+ {
+ secUtilBoxMove (&b->box, tx, ty);
+ }
+}
+
+void _swBoxRemoveAll (struct xorg_list* l)
+{
+ ExaBox *ref = NULL, *next = NULL;
+
+ 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 = NULL;
+
+ 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 = NULL;
+ 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));
+ XDBG_RETURN_IF_FAIL (dest != NULL);
+
+ 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 100755
index 0000000..a69cc7b
--- /dev/null
+++ b/src/crtcconfig/sec_crtc.c
@@ -0,0 +1,2768 @@
+/**************************************************************************
+
+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);
+ XDBG_RETURN_IF_FAIL (pSec->ovl_damage);
+ 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;
+
+ XDBG_RETURN_IF_FAIL (pCrtc != NULL);
+
+ /* 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*));
+ XDBG_RETURN_IF_FAIL (pCrtcPriv->flip_backpixs.pix_free != NULL);
+ 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 = NULL, pNext = NULL;
+
+ 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 (!srcImg || !dstImg)
+ {
+ XDBG_ERROR (MDISP, "Accessibility : Fail to create g2d_image\n");
+ tbm_bo_unmap(src_bo);
+ tbm_bo_unmap(dst_bo);
+
+ if (srcImg)
+ g2d_image_free (srcImg);
+
+ if (dstImg)
+ g2d_image_free (dstImg);
+
+ return FALSE;
+ }
+
+ 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 100755
index 0000000..64d4a44
--- /dev/null
+++ b/src/crtcconfig/sec_crtc.h
@@ -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 100755
index 0000000..051903e
--- /dev/null
+++ b/src/crtcconfig/sec_display.c
@@ -0,0 +1,1681 @@
+/*
+ * 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 = NULL, output_next = NULL;
+ xorg_list_for_each_entry_safe (output_ref, output_next, &pSecMode->outputs, link)
+ {
+ pOutput = output_ref->pOutput;
+ xf86OutputDestroy (pOutput);
+ }
+
+ SECPlanePrivPtr plane_ref = NULL, plane_next = NULL;
+ 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!
+ */
+ if (drmModePageFlip (pSec->drm_fd, secCrtcID(pCrtcPriv), fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, pPageFlip))
+ {
+ 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 100755
index 0000000..e45cc05
--- /dev/null
+++ b/src/crtcconfig/sec_display.h
@@ -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 100755
index 0000000..d91f950
--- /dev/null
+++ b/src/crtcconfig/sec_layer.c
@@ -0,0 +1,1146 @@
+/**************************************************************************
+
+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);
+ XDBG_RETURN_VAL_IF_FAIL(layer->pending_vbuf, 0)
+ 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);
+ XDBG_RETURN_VAL_IF_FAIL ((layer->wait_vbuf != NULL), 0);
+ 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
index 0000000..e3f0685
--- /dev/null
+++ b/src/crtcconfig/sec_layer.h
@@ -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 100755
index 0000000..448c5c8
--- /dev/null
+++ b/src/crtcconfig/sec_output.c
@@ -0,0 +1,881 @@
+/**************************************************************************
+
+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);
+ }
+ }
+
+ if (p->atoms)
+ free (p->atoms);
+ }
+}
+
+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);
+ XDBG_RETURN_VAL_IF_FAIL ((name != NULL), FALSE);
+
+ /* 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 pCur = NULL, pNext = NULL, pOutputPriv = NULL;
+ 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 = NULL, pNext = NULL;
+
+ 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
index 0000000..7b9b107
--- /dev/null
+++ b/src/crtcconfig/sec_output.h
@@ -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
index 0000000..41384a6
--- /dev/null
+++ b/src/crtcconfig/sec_plane.c
@@ -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
index 0000000..5ce2fd1
--- /dev/null
+++ b/src/crtcconfig/sec_plane.h
@@ -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 100755
index 0000000..9cf1904
--- /dev/null
+++ b/src/crtcconfig/sec_prop.c
@@ -0,0 +1,713 @@
+/**************************************************************************
+
+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);
+ XDBG_RETURN_VAL_IF_FAIL ((pCrtc != NULL), FALSE);
+ 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
index 0000000..79a2135
--- /dev/null
+++ b/src/crtcconfig/sec_prop.h
@@ -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 100755
index 0000000..3b0936f
--- /dev/null
+++ b/src/crtcconfig/sec_xberc.c
@@ -0,0 +1,1276 @@
+/**************************************************************************
+
+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], ",");
+ if (!c)
+ {
+ _secXbercSetReturnProperty (value, "[Xorg] fail: read option");
+ return TRUE;
+ }
+
+ 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], ",");
+ if (!c)
+ {
+ _secXbercSetReturnProperty (value, "[Xorg] fail: read option\n");
+ return TRUE;
+ }
+
+ 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
index 0000000..bf9beaa
--- /dev/null
+++ b/src/crtcconfig/sec_xberc.h
@@ -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
index 0000000..f53ebd8
--- /dev/null
+++ b/src/debug/sec_drmmode_dump.c
@@ -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
index 0000000..b1493a9
--- /dev/null
+++ b/src/debug/sec_drmmode_dump.h
@@ -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
index 0000000..a68347b
--- /dev/null
+++ b/src/g2d/fimg2d.c
@@ -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 100755
index 0000000..ada1c2f
--- /dev/null
+++ b/src/g2d/fimg2d.h
@@ -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 100755
index 0000000..97813c8
--- /dev/null
+++ b/src/g2d/fimg2d_reg.h
@@ -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
index 0000000..7c5f2d7
--- /dev/null
+++ b/src/g2d/util_g2d.c
@@ -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
index 0000000..8b4f9bc
--- /dev/null
+++ b/src/ipp/sec_converter.c
@@ -0,0 +1,1021 @@
+/**************************************************************************
+
+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);
+ XDBG_GOTO_IF_FAIL (src_cbuf->vbuf != NULL, fail_to_convert);
+ 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
index 0000000..b1b147d
--- /dev/null
+++ b/src/ipp/sec_converter.h
@@ -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
index 0000000..cb50826
--- /dev/null
+++ b/src/ipp/sec_drm_ipp.c
@@ -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
index 0000000..e344c4f
--- /dev/null
+++ b/src/ipp/sec_drm_ipp.h
@@ -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
index 0000000..b1f708e
--- /dev/null
+++ b/src/ipp/sec_wb.c
@@ -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
index 0000000..38b9752
--- /dev/null
+++ b/src/ipp/sec_wb.h
@@ -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
index 0000000..ad7d631
--- /dev/null
+++ b/src/memory/sec_memory_flush.c
@@ -0,0 +1,141 @@
+/**************************************************************************
+
+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 <malloc.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <malloc.h>
+
+#include "sec.h"
+#include "xace.h"
+#include "xacestr.h"
+
+#include <X11/extensions/dpmsconst.h>
+#include "sec_util.h"
+#include "sec_dpms.h"
+#include "sec_memory_flush.h"
+
+extern CallbackListPtr DPMSCallback;
+
+static void
+_secMemoryDPMS (CallbackListPtr *list, pointer closure, pointer calldata)
+{
+ SecDPMSPtr pDPMSInfo = (SecDPMSPtr) calldata;
+ ScrnInfoPtr pScrn;
+ //int mode = pDPMSInfo->mode;
+ //int flags = pDPMSInfo->flags;
+
+ if (!pDPMSInfo || !(pScrn = pDPMSInfo->pScrn))
+ {
+ XDBG_ERROR (MMEM, "[X11][%s] DPMS info or screen info is invalid !\n", __FUNCTION__);
+ return;
+ }
+
+ SECPtr pSec = SECPTR (pScrn);
+
+ switch (DPMSPowerLevel)
+ {
+ case DPMSModeOn:
+ case DPMSModeSuspend:
+ break;
+
+ case DPMSModeStandby://LCD on
+ if (pSec->isLcdOff == FALSE) break;
+ break;
+
+ case DPMSModeOff://LCD off
+ if (pSec->isLcdOff == TRUE) break;
+
+ //stack and heap memory trim
+ secMemoryStackTrim();
+ malloc_trim (0);
+
+ XDBG_DEBUG (MMEM, "[X11][%s] Memory flush done !\n", __FUNCTION__);
+ break;
+
+ default:
+ return;
+ }
+}
+
+static void
+_secMemoryClientStateEvent (CallbackListPtr *list, pointer closure, pointer calldata)
+{
+ static int chance = 0;
+ NewClientInfoRec *clientinfo = (NewClientInfoRec*)calldata;
+ ClientPtr pClient = clientinfo->client;
+
+ if (ClientStateGone == pClient->clientState)
+ {
+ int flush;
+
+ //memory flush will be done for every third client gone
+ chance++;
+ flush = !(chance = chance % 3);
+
+ if ( flush )
+ {
+ //stack and heap memory trim
+ secMemoryStackTrim();
+ malloc_trim (0);
+
+ XDBG_DEBUG (MMEM, "[X11][%s] Memory flush done !\n", __FUNCTION__);
+ }
+ }
+}
+
+Bool
+secMemoryInstallHooks (void)
+{
+ int ret = TRUE;
+ ret &= AddCallback (&ClientStateCallback, _secMemoryClientStateEvent, NULL);
+ ret &= AddCallback (&DPMSCallback, _secMemoryDPMS, NULL);
+
+ if (!ret)
+ {
+ XDBG_ERROR (MMEM, "secMemoryInstallHooks: Failed to register one or more callbacks\n");
+ return BadAlloc;
+ }
+
+ return Success;
+}
+
+
+Bool
+secMemoryUninstallHooks (void)
+{
+ DeleteCallback (&ClientStateCallback, _secMemoryClientStateEvent, NULL);
+ DeleteCallback (&DPMSCallback, _secMemoryDPMS, NULL);
+
+ return Success;
+}
diff --git a/src/memory/sec_memory_flush.h b/src/memory/sec_memory_flush.h
new file mode 100644
index 0000000..d9c1062
--- /dev/null
+++ b/src/memory/sec_memory_flush.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+
+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_MEMORY_H
+#define SEC_MEMORY_H
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <X11/Xdefs.h> /* for Bool */
+
+#define GETSP() ({ unsigned int sp; asm volatile ("mov %0,sp " : "=r"(sp)); sp;})
+#define BUF_SIZE 256
+#define _PAGE_SIZE (1 << 12)
+#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
+#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))
+#define PAGE_ALIGN(addr) _ALIGN_DOWN(addr, _PAGE_SIZE)
+
+static inline void secMemoryStackTrim (void)
+{
+ unsigned int sp;
+ char buf[BUF_SIZE];
+ FILE* file;
+ unsigned int stacktop;
+ int found = 0;
+
+ sp = GETSP();
+
+ snprintf (buf, BUF_SIZE, "/proc/%d/maps", getpid());
+ file = fopen (buf,"r");
+
+ if (!file)
+ return;
+
+ while (fgets (buf, BUF_SIZE, file) != NULL)
+ {
+ if (strstr (buf, "[stack]"))
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ fclose (file);
+
+ if (found)
+ {
+ sscanf (buf,"%x-",&stacktop);
+ if (madvise ((void*)PAGE_ALIGN (stacktop), PAGE_ALIGN (sp)-stacktop, MADV_DONTNEED) < 0)
+ perror ("stack madvise fail");
+ }
+}
+
+Bool secMemoryInstallHooks (void);
+Bool secMemoryUninstallHooks (void);
+
+#endif/* SEC_MEMORY_H */
diff --git a/src/neon/copy_area.c b/src/neon/copy_area.c
new file mode 100644
index 0000000..9bd2c71
--- /dev/null
+++ b/src/neon/copy_area.c
@@ -0,0 +1,535 @@
+/**************************************************************************
+
+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 "neonmem.h"
+
+//#define _USE_LIBC
+//#define _X86_SSE2 // may not work on linux platform
+#define _ARM_NEON
+
+#ifdef _USE_LIBC
+#include <string.h>
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+// General C implementation of copy functions
+//////////////////////////////////////////////////////////////////////////
+static inline void memcpy32 (unsigned long *dst, unsigned long *src, int size)
+{
+ while ( size > 0 )
+ {
+ *dst++ = *src++;
+ size--;
+ }
+}
+
+static inline void memcpy_forward_32 (unsigned long *dst, unsigned long *src, int size)
+{
+ while ( size > 0 )
+ {
+ *dst++ = *src++;
+ size--;
+ }
+}
+
+static inline void memcpy_backward_32 (unsigned long *dst, unsigned long *src, int size)
+{
+ dst = dst + size;
+ src = src + size;
+
+ while ( size > 0 )
+ {
+ *(--dst) = *(--src);
+ size--;
+ }
+}
+
+static inline void memcpy_forward_16 (unsigned short *dst, unsigned short *src, int size)
+{
+ while ( size > 0 )
+ {
+ *dst++ = *src++;
+ size--;
+ }
+}
+
+static inline void memcpy_backward_16 (unsigned short *dst, unsigned short *src, int size)
+{
+ dst = dst + size;
+ src = src + size;
+
+ while ( size > 0 )
+ {
+ *(--dst) = *(--src);
+ size--;
+ }
+}
+
+static inline void memcpy_forward (unsigned char *dst, unsigned char *src, int size)
+{
+ while ( size > 0 && ((unsigned long) dst & 3))
+ {
+ *(unsigned short*)dst = *(unsigned short*)src;
+ dst += 2;
+ src += 2;
+ size -= 2;
+ }
+
+ while ( size >= 4 )
+ {
+ *(unsigned long*)dst = *(unsigned long*)src;
+ dst += 4;
+ src += 4;
+ size -= 4;
+ }
+
+ while ( size > 0 )
+ {
+ *dst++ = *src++;
+ size--;
+ }
+}
+
+static inline void memcpy_backward (unsigned char *dst, unsigned char *src, int size)
+{
+ dst = dst + size;
+ src = src + size;
+
+ while ( size > 0 && ((unsigned long) dst & 3))
+ {
+ *(--dst) = *(--src);
+ size--;
+ }
+
+ while ( size >= 4 )
+ {
+ dst -= 4;
+ src -= 4;
+ size -= 4;
+ *(unsigned long*)dst = *(unsigned long*)src;
+ }
+
+ while ( size > 0 )
+ {
+ *(--dst) = *(--src);
+ size--;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// ARM assembly implementation of copy functions
+//////////////////////////////////////////////////////////////////////////
+#ifdef _ARM_ASM
+static inline void memcpy_forward (unsigned char *dst, unsigned char *src, int size)
+{
+
+}
+
+static inline void memcpy_backward (unsigned char *dst, unsigned char *src, int size)
+{
+
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+// ARM NEON implementation of copy functions
+//////////////////////////////////////////////////////////////////////////
+#ifdef _ARM_NEON
+extern void memcpy_forward_32_neon (unsigned long *dst, unsigned long *src, int size);
+extern void memcpy_backward_32_neon (unsigned long *dst, unsigned long *src, int size);
+extern void memcpy_forward_16_neon (unsigned short *dst, unsigned short *src, int size);
+extern void memcpy_backward_16_neon (unsigned short *dst, unsigned short *src, int size);
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+// X86 SSE2 copy functions
+//////////////////////////////////////////////////////////////////////////
+#ifdef _X86_SSE2
+#include <emmintrin.h>
+
+static inline void memcpy_forward_sse2 (unsigned char *dst, unsigned char *src, int size)
+{
+ while ( size > 0 && ((unsigned long) dst & 1))
+ {
+ *dst++ = *src++;
+ size--;
+ }
+
+ while ( size > 0 && ((unsigned long) dst & 3))
+ {
+ *(unsigned short*)dst = *(unsigned short*)src;
+ dst += 2;
+ src += 2;
+ size -= 2;
+ }
+
+ while ( size > 0 && ((unsigned long) dst & 63))
+ {
+ *(unsigned long*)dst = *(unsigned long*)src;
+ dst += 4;
+ src += 4;
+ size -= 4;
+ }
+
+ if ((reinterpret_cast<unsigned long> (src) & 15) == 0 )
+ {
+ while ( size >= 64 )
+ {
+ __m128 xmm0, xmm1, xmm2, xmm3;
+
+ //_mm_prefetch((const char*)(src+320), _MM_HINT_NTA);
+
+ xmm0 = _mm_load_ps ((float*)(src));
+ xmm1 = _mm_load_ps ((float*)(src + 16));
+ xmm2 = _mm_load_ps ((float*)(src + 32));
+ xmm3 = _mm_load_ps ((float*)(src + 48));
+
+ _mm_stream_ps ((float*)(dst), xmm0);
+ _mm_stream_ps ((float*)(dst + 16), xmm1);
+ _mm_stream_ps ((float*)(dst + 32), xmm2);
+ _mm_stream_ps ((float*)(dst + 48), xmm3);
+
+ src += 64;
+ dst += 64;
+ size -= 64;
+ }
+
+ while ( size >= 16 )
+ {
+ _mm_stream_ps ((float*)dst, _mm_load_ps ((float*)src));
+ dst += 16;
+ src += 16;
+ size -= 16;
+ }
+ }
+ else
+ {
+ while ( size >= 64 )
+ {
+ __m128 xmm0, xmm1, xmm2, xmm3;
+
+ //_mm_prefetch((const char*)(src+320), _MM_HINT_NTA);
+
+ xmm0 = _mm_loadu_ps ((float*)(src));
+ xmm1 = _mm_loadu_ps ((float*)(src + 16));
+ xmm2 = _mm_loadu_ps ((float*)(src + 32));
+ xmm3 = _mm_loadu_ps ((float*)(src + 48));
+
+ _mm_stream_ps ((float*)(dst), xmm0);
+ _mm_stream_ps ((float*)(dst + 16), xmm1);
+ _mm_stream_ps ((float*)(dst + 32), xmm2);
+ _mm_stream_ps ((float*)(dst + 48), xmm3);
+
+ src += 64;
+ dst += 64;
+ size -= 64;
+ }
+
+ while ( size >= 16 )
+ {
+ _mm_stream_ps ((float*)dst, _mm_loadu_ps ((float*)src));
+ dst += 16;
+ src += 16;
+ size -= 16;
+ }
+ }
+
+ while ( size >= 4 )
+ {
+ *(unsigned long*)dst = *(unsigned long*)src;
+ dst += 4;
+ src += 4;
+ size -= 4;
+ }
+
+ while ( size > 0 )
+ {
+ *dst++ = *src++;
+ size--;
+ }
+}
+
+static inline void memcpy_backward_sse2 (unsigned char *dst, unsigned char *src, int size)
+{
+ dst = dst + size;
+ src = src + size;
+
+ while ( size > 0 && ((unsigned long) dst & 1))
+ {
+ dst--;
+ src--;
+ size--;
+ *dst = *src;
+ }
+
+ while ( size > 0 && ((unsigned long) dst & 3))
+ {
+ dst -= 2;
+ src -= 2;
+ size -= 2;
+ *(unsigned short*)dst = *(unsigned short*)src;
+ }
+
+ while ( size > 0 && ((unsigned long) dst & 63))
+ {
+ dst -= 4;
+ src -= 4;
+ size -= 4;
+ *(unsigned long*)dst = *(unsigned long*)src;
+ }
+
+ if ((reinterpret_cast<unsigned long> (src) & 15) == 0 )
+ {
+ while ( size >= 64 )
+ {
+ __m128 xmm0, xmm1, xmm2, xmm3;
+
+ src -= 64;
+ dst -= 64;
+ size -= 64;
+
+ //_mm_prefetch((const char*)(src+16), _MM_HINT_NTA);
+
+ xmm0 = _mm_load_ps ((float*)(src));
+ xmm1 = _mm_load_ps ((float*)(src + 16));
+ xmm2 = _mm_load_ps ((float*)(src + 32));
+ xmm3 = _mm_load_ps ((float*)(src + 48));
+
+ _mm_stream_ps ((float*)(dst), xmm0);
+ _mm_stream_ps ((float*)(dst + 16), xmm1);
+ _mm_stream_ps ((float*)(dst + 32), xmm2);
+ _mm_stream_ps ((float*)(dst + 48), xmm3);
+ }
+
+ while ( size >= 16 )
+ {
+ dst -= 16;
+ src -= 16;
+ size -= 16;
+ _mm_stream_ps ((float*)dst, _mm_load_ps ((float*)src));
+ }
+ }
+ else
+ {
+ while ( size >= 64 )
+ {
+ __m128 xmm0, xmm1, xmm2, xmm3;
+
+ src -= 64;
+ dst -= 64;
+ size -= 64;
+
+ //_mm_prefetch((const char*)(src+16), _MM_HINT_NTA);
+
+ xmm0 = _mm_loadu_ps ((float*)(src));
+ xmm1 = _mm_loadu_ps ((float*)(src + 16));
+ xmm2 = _mm_loadu_ps ((float*)(src + 32));
+ xmm3 = _mm_loadu_ps ((float*)(src + 48));
+
+ _mm_stream_ps ((float*)(dst), xmm0);
+ _mm_stream_ps ((float*)(dst + 16), xmm1);
+ _mm_stream_ps ((float*)(dst + 32), xmm2);
+ _mm_stream_ps ((float*)(dst + 48), xmm3);
+ }
+
+ while ( size >= 16 )
+ {
+ dst -= 16;
+ src -= 16;
+ size -= 16;
+ _mm_stream_ps ((float*)dst, _mm_loadu_ps ((float*)src));
+ }
+ }
+
+ while ( size >= 4 )
+ {
+ dst -= 4;
+ src -= 4;
+ size -= 4;
+ *(unsigned long*)dst = *(unsigned long*)src;
+ }
+
+ while ( size > 0 )
+ {
+ dst--;
+ src--;
+ size--;
+ *dst = *src;
+ }
+}
+#endif
+
+static inline void move_memory_32 (unsigned long *dst, unsigned long *src, int size)
+{
+#ifdef _USE_LIBC
+ memmove (dst, src, size*4);
+#elif defined(_ARM_NEON)
+ if ( dst > src && dst < src + size )
+ memcpy_backward_32_neon (dst, src, size);
+ else
+ memcpy_forward_32_neon (dst, src, size);
+#else
+ if ( dst > src && dst < src + size )
+ memcpy_backward_32 (dst, src, size);
+ else
+ memcpy_forward_32 (dst, src, size);
+#endif
+}
+
+static inline void move_memory_16 (unsigned short *dst, unsigned short *src, int size)
+{
+#ifdef _USE_LIBC
+ memmove (dst, src, size*2);
+#elif defined(_ARM_NEON)
+ if ( dst > src && dst < src + size )
+ memcpy_backward_16_neon (dst, src, size);
+ else
+ memcpy_forward_16_neon (dst, src, size);
+#else
+ if ( dst > src && dst < src + size )
+ memcpy_backward_16 (dst, src, size);
+ else
+ memcpy_forward_16 (dst, src, size);
+#endif
+}
+
+/**
+ * @brief Pixel block move function within one image buffer
+ *
+ * @param bits buffer address of top-left corner
+ * @param bpp bits per pixel, must be one of 16 and 32
+ * @param stride number of bytes to go next row (can be negative)
+ * @param img_width entire image width
+ * @param img_height entire image height
+ * @param sx top-left x position of source area
+ * @param sy top-left y position of source area
+ * @param dx top-left x position of destination area
+ * @param dy top-left y position of destination area
+ * @param w width of area to copy
+ * @param h height of area to copy
+ *
+ * @remark This function supports overlapping in source and destination area.
+ * Any source or destination area which is outside given image will be cropped.
+ * Support negative stride.
+ * bits must be word aligned if bpp == 32 and half-word aligned if bpp == 16.
+ */
+int move_pixels (void *bits, int bpp, int stride, int img_width, int img_height,
+ int sx, int sy, int dx, int dy, int w, int h)
+{
+ int bytes_per_pixel;
+ unsigned char *src_row;
+ unsigned char *dst_row;
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // check validity of arguments
+ //////////////////////////////////////////////////////////////////////////
+ if ( !bits || img_width < 0 || img_height < 0 || w < 0 || h < 0 )
+ return 0;
+
+ if ( bpp == 32 )
+ bytes_per_pixel = 4;
+ else if ( bpp == 16 )
+ bytes_per_pixel = 2;
+ else // unsupported bpp
+ return 0;
+
+ if ( bytes_per_pixel*img_width < stride ) // invalid image
+ return 0;
+
+ // Wow thanks, we have nothing to do
+ if ( sx == dx && sy == dy )
+ return 1;
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Bounds check and cropping
+ //////////////////////////////////////////////////////////////////////////
+ while ( sx < 0 || dx < 0 )
+ {
+ sx++;
+ dx++;
+ w--;
+ }
+
+ while ( sy < 0 || dy < 0 )
+ {
+ sy++;
+ dy++;
+ h--;
+ }
+
+ while ( sx + w > img_width || dx + w > img_width )
+ w--;
+
+ while ( sy + h > img_height || dy + h > img_height )
+ h--;
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Check overlap and do copy
+ //////////////////////////////////////////////////////////////////////////
+
+ // No remaining area to copy
+ if ( w <= 0 || h <= 0 )
+ return 1;
+
+ src_row = (unsigned char*)bits + sy*stride + sx*bytes_per_pixel;
+ dst_row = (unsigned char*)bits + dy*stride + dx*bytes_per_pixel;
+
+ // Check if we need to reverse y order
+ if ( dy > sy && dy < sy + h )
+ {
+ src_row += (h - 1) *stride;
+ dst_row += (h - 1) *stride;
+ stride = -stride;
+ }
+
+ if ( bpp == 32 )
+ {
+ while ( h-- )
+ {
+ move_memory_32 ((unsigned long*)dst_row, (unsigned long*)src_row, w);
+ dst_row += stride;
+ src_row += stride;
+ }
+ }
+ else if ( bpp == 16 )
+ {
+ while ( h-- )
+ {
+ move_memory_16 ((unsigned short*)dst_row, (unsigned short*)src_row, w);
+ dst_row += stride;
+ src_row += stride;
+ }
+ }
+
+ return 1;
+}
diff --git a/src/neon/memcpy_neon.s b/src/neon/memcpy_neon.s
new file mode 100644
index 0000000..eb3e3b1
--- /dev/null
+++ b/src/neon/memcpy_neon.s
@@ -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 바이???하??경우?
+ 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가 4-byte align ???닌 경우
+ LSLS r3,r2,#29
+ BCC COPY_UNDER_15B_UNALIGN_4B
+ @ neon ??가?
+ 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
index 0000000..626abec
--- /dev/null
+++ b/src/neon/neonmem.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+
+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 _NEON_MEMCPY_HEADER_
+#define _NEON_MEMCPY_HEADER_
+
+#include <stddef.h>
+
+#ifdef memcpy
+#undef memcpy
+#endif
+
+#define memcpy memcpy_neon
+
+void *
+memcpy_neon (void *dst, const void *src, size_t count);
+
+int
+move_pixels (void *bits, int bpp, int stride, int img_width, int img_height,
+ int sx, int sy, int dx, int dy, int w, int h);
+#endif /* _NEON_MEMCPY_HEADER_ */
+
diff --git a/src/sec.c b/src/sec.c
new file mode 100755
index 0000000..256f029
--- /dev/null
+++ b/src/sec.c
@@ -0,0 +1,1777 @@
+/**************************************************************************
+
+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)
+ {
+ free (ppDevSections);
+ 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));
+ XDBG_GOTO_IF_FAIL (bo_data != NULL, fail);
+ 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));
+ XDBG_RETURN_VAL_IF_FAIL (item != NULL, NULL);
+ 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 100755
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 100755
index 0000000..6f6f747
--- /dev/null
+++ b/src/util/sec_util.c
@@ -0,0 +1,2351 @@
+/**************************************************************************
+
+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;
+ int list_flag;
+
+ XDBG_RETURN_VAL_IF_FAIL (key != NULL, NULL);
+
+ if (!list)
+ {
+ list = calloc (sizeof (struct xorg_list), 1);
+ XDBG_RETURN_VAL_IF_FAIL (list != NULL, NULL);
+ xorg_list_init ((struct xorg_list*)list);
+ list_flag = 1;
+ }
+
+ if (_secUtilListGet (list, key))
+ return list;
+
+ data = malloc (sizeof (ListData));
+ XDBG_GOTO_IF_FAIL (data != NULL, fail);
+ data->key = key;
+ data->data = user_data;
+
+ xorg_list_add (&data->link, (struct xorg_list*)list);
+
+ return list;
+
+fail:
+ if (list_flag && list)
+ free (list);
+
+ return NULL;
+}
+
+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 100755
index 0000000..0b0cb8f
--- /dev/null
+++ b/src/util/sec_util.h
@@ -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
index 0000000..9eb7d01
--- /dev/null
+++ b/src/xv/sec_video.c
@@ -0,0 +1,3095 @@
+/*
+ * 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);
+ XDBG_RETURN_VAL_IF_FAIL (image_info != NULL, NULL);
+ 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_RETURN_VAL_IF_FAIL (inbuf != NULL, NULL);
+ XDBG_TRACE (MVDO, "keys: %d,%d,%d. stamp(%ld)\n", keys[0], keys[1], keys[2], inbuf->stamp);
+ }
+ else
+ inbuf = _secVideoGetInbufRAW (pPort);
+
+ XDBG_RETURN_VAL_IF_FAIL (inbuf != NULL, NULL);
+
+ 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
index 0000000..54888bc
--- /dev/null
+++ b/src/xv/sec_video.h
@@ -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
index 0000000..e1f50c8
--- /dev/null
+++ b/src/xv/sec_video_display.c
@@ -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
index 0000000..96bb952
--- /dev/null
+++ b/src/xv/sec_video_display.h
@@ -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
index 0000000..2023e49
--- /dev/null
+++ b/src/xv/sec_video_fourcc.h
@@ -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
index 0000000..20492ce
--- /dev/null
+++ b/src/xv/sec_video_tvout.c
@@ -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
index 0000000..9c88dc4
--- /dev/null
+++ b/src/xv/sec_video_tvout.h
@@ -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
index 0000000..1afe0fb
--- /dev/null
+++ b/src/xv/sec_video_types.h
@@ -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
index 0000000..fac74b8
--- /dev/null
+++ b/src/xv/sec_video_virtual.c
@@ -0,0 +1,2066 @@
+/*
+ * 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);
+ XDBG_GOTO_IF_FAIL (info->vbuf != NULL, fail);
+ 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;
+
+fail :
+ if (info)
+ free (info);
+
+ return FALSE;
+}
+
+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 && !lower_buf->secure && 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
index 0000000..a3400b4
--- /dev/null
+++ b/src/xv/sec_video_virtual.h
@@ -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
index 0000000..e82b4e4
--- /dev/null
+++ b/src/xv/xv_types.h
@@ -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