correct wrong usage of _secVideoPunchDrawable.
[platform/adaptation/samsung_exynos/xf86-video-exynos.git] / src / xv / sec_video.c
1 /*
2  * xserver-xorg-video-exynos
3  *
4  * Copyright 2004 Keith Packard
5  * Copyright 2005 Eric Anholt
6  * Copyright 2006 Nokia Corporation
7  * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
8  *
9  * Contact: Boram Park <boram1288.park@samsung.com>
10  *
11  * Permission to use, copy, modify, distribute and sell this software and its
12  * documentation for any purpose is hereby granted without fee, provided that
13  * the above copyright notice appear in all copies and that both that
14  * copyright notice and this permission notice appear in supporting
15  * documentation, and that the names of the authors and/or copyright holders
16  * not be used in advertising or publicity pertaining to distribution of the
17  * software without specific, written prior permission.  The authors and
18  * copyright holders make no representations about the suitability of this
19  * software for any purpose.  It is provided "as is" without any express
20  * or implied warranty.
21  *
22  * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO
23  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
24  * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
25  * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
26  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
27  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
28  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29  *
30  */
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <string.h>
37 #include <errno.h>
38 #include <sys/time.h>
39 #include <sys/ioctl.h>
40
41 #include <pixman.h>
42 #include <X11/Xatom.h>
43 #include <X11/extensions/Xv.h>
44 #include <X11/extensions/Xvproto.h>
45 #include <fourcc.h>
46
47 #include <fb.h>
48 #include <fbdevhw.h>
49 #include <damage.h>
50
51 #include <xf86xv.h>
52
53 #include "sec.h"
54
55 #include "sec_accel.h"
56 #include "sec_display.h"
57 #include "sec_crtc.h"
58 #include "sec_output.h"
59 #include "sec_video.h"
60 #include "sec_prop.h"
61 #include "sec_util.h"
62 #include "sec_wb.h"
63 #include "sec_video_virtual.h"
64 #include "sec_video_display.h"
65 #include "sec_video_tvout.h"
66 #include "sec_video_fourcc.h"
67 #include "sec_converter.h"
68 #include "sec_plane.h"
69 #include "sec_xberc.h"
70
71 #include "xv_types.h"
72
73 #include "common.h"
74
75 #define DONT_FILL_ALPHA     -1
76 #define SEC_MAX_PORT        16
77
78 #define INBUF_NUM           6
79 #define OUTBUF_NUM          3
80 #define NUM_HW_LAYER        2
81
82 #define OUTPUT_LCD   (1 << 0)
83 #define OUTPUT_EXT   (1 << 1)
84 #define OUTPUT_FULL  (1 << 8)
85
86 static XF86VideoEncodingRec dummy_encoding[] =
87 {
88     { 0, "XV_IMAGE", -1, -1, { 1, 1 } },
89     { 1, "XV_IMAGE", 4224, 4224, { 1, 1 } },
90 };
91
92 static XF86ImageRec images[] =
93 {
94     XVIMAGE_YUY2,
95     XVIMAGE_SUYV,
96     XVIMAGE_UYVY,
97     XVIMAGE_SYVY,
98     XVIMAGE_ITLV,
99     XVIMAGE_YV12,
100     XVIMAGE_I420,
101     XVIMAGE_S420,
102     XVIMAGE_ST12,
103     XVIMAGE_NV12,
104     XVIMAGE_SN12,
105     XVIMAGE_NV21,
106     XVIMAGE_SN21,
107     XVIMAGE_RGB32,
108     XVIMAGE_SR32,
109     XVIMAGE_RGB565,
110     XVIMAGE_SR16,
111 };
112
113 static XF86VideoFormatRec formats[] =
114 {
115     { 16, TrueColor },
116     { 24, TrueColor },
117     { 32, TrueColor },
118 };
119
120 static XF86AttributeRec attributes[] =
121 {
122     { 0, 0, 270, "_USER_WM_PORT_ATTRIBUTE_ROTATION" },
123     { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_HFLIP" },
124     { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_VFLIP" },
125     { 0, -1, 1, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION" },
126     { 0, 0, OUTPUT_MODE_EXT_ONLY, "_USER_WM_PORT_ATTRIBUTE_OUTPUT" },
127     { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_SECURE" },
128     { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_CSC_RANGE" },
129 };
130
131 typedef enum
132 {
133     PAA_MIN,
134     PAA_ROTATION,
135     PAA_HFLIP,
136     PAA_VFLIP,
137     PAA_PREEMPTION,
138     PAA_OUTPUT,
139     PAA_SECURE,
140     PAA_CSC_RANGE,
141     PAA_MAX
142 } SECPortAttrAtom;
143
144 static struct
145 {
146     SECPortAttrAtom  paa;
147     const char      *name;
148     Atom             atom;
149 } atoms[] =
150 {
151     { PAA_ROTATION, "_USER_WM_PORT_ATTRIBUTE_ROTATION", None },
152     { PAA_HFLIP, "_USER_WM_PORT_ATTRIBUTE_HFLIP", None },
153     { PAA_VFLIP, "_USER_WM_PORT_ATTRIBUTE_VFLIP", None },
154     { PAA_PREEMPTION, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION", None },
155     { PAA_OUTPUT, "_USER_WM_PORT_ATTRIBUTE_OUTPUT", None },
156     { PAA_SECURE, "_USER_WM_PORT_ATTRIBUTE_SECURE", None },
157     { PAA_CSC_RANGE, "_USER_WM_PORT_ATTRIBUTE_CSC_RANGE", None },
158 };
159
160 enum
161 {
162     ON_NONE,
163     ON_FB,
164     ON_WINDOW,
165     ON_PIXMAP
166 };
167
168 static char *drawing_type[4] = {"NONE", "FB", "WIN", "PIX"};
169
170 typedef struct _PutData
171 {
172     unsigned int id;
173     int          width;
174     int          height;
175     xRectangle   src;
176     xRectangle   dst;
177     void        *buf;
178     Bool         sync;
179     RegionPtr    clip_boxes;
180     void        *data;
181     DrawablePtr  pDraw;
182 } PutData;
183
184 /* SEC port information structure */
185 typedef struct
186 {
187     CARD32 prev_time;
188     int index;
189
190     /* attributes */
191     int rotate;
192     int hflip;
193     int vflip;
194     int preemption;     /* 1:high, 0:default, -1:low */
195     Bool secure;
196     int csc_range;
197
198     ScrnInfoPtr pScrn;
199     PutData d;
200     PutData old_d;
201
202     /* draw inform */
203     int          drawing;
204     int          hw_rotate;
205
206     int           in_width;
207     int           in_height;
208     xRectangle    in_crop;
209     SECVideoBuf  *inbuf[INBUF_NUM];
210     Bool          inbuf_is_fb;
211
212     /* converter */
213     SECCvt       *cvt;
214
215     /* layer */
216     SECLayer     *layer;
217     int           out_width;
218     int           out_height;
219     xRectangle    out_crop;
220     SECVideoBuf  *outbuf[OUTBUF_NUM];
221     int           outbuf_cvting;
222     DrawablePtr   pDamageDrawable[OUTBUF_NUM];
223
224     /* tvout */
225     int usr_output;
226     int old_output;
227     int grab_tvout;
228     SECVideoTv *tv;
229     void       *gem_list;
230     Bool skip_tvout;
231     Bool need_start_wb;
232     SECVideoBuf  *wait_vbuf;
233     CARD32 tv_prev_time;
234
235     /* count */
236     unsigned int put_counts;
237     OsTimerPtr timer;
238     Bool punched;
239     int  stream_cnt;
240     struct xorg_list link;
241 } SECPortPriv, *SECPortPrivPtr;
242
243 static RESTYPE event_drawable_type;
244
245 typedef struct _SECVideoResource
246 {
247     XID id;
248     RESTYPE type;
249
250     SECPortPrivPtr pPort;
251     ScrnInfoPtr pScrn;
252 } SECVideoResource;
253
254 typedef struct _SECVideoPortInfo
255 {
256     ClientPtr client;
257     XvPortPtr pp;
258 } SECVideoPortInfo;
259
260 static int (*ddPutImage) (ClientPtr, DrawablePtr, struct _XvPortRec *, GCPtr,
261                           INT16, INT16, CARD16, CARD16,
262                           INT16, INT16, CARD16, CARD16,
263                           XvImagePtr, unsigned char *, Bool, CARD16, CARD16);
264
265 static void _secVideoSendReturnBufferMessage (SECPortPrivPtr pPort, SECVideoBuf *vbuf, unsigned int *keys);
266 static void SECVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit);
267 static void _secVideoCloseInBuffer (SECPortPrivPtr pPort);
268 static void _secVideoCloseOutBuffer (SECPortPrivPtr pPort, Bool close_layer);
269 static void _secVideoCloseConverter (SECPortPrivPtr pPort);
270 static Bool _secVideoSetOutputExternalProperty (DrawablePtr pDraw, Bool tvout);
271
272 static int streaming_ports;
273 static int registered_handler;
274 static struct xorg_list layer_owners;
275
276 static DevPrivateKeyRec video_port_key;
277 #define VideoPortKey (&video_port_key)
278 #define GetPortInfo(pDraw) ((SECVideoPortInfo*)dixLookupPrivate(&(pDraw)->devPrivates, VideoPortKey))
279
280 #define NUM_IMAGES        (sizeof(images) / sizeof(images[0]))
281 #define NUM_FORMATS       (sizeof(formats) / sizeof(formats[0]))
282 #define NUM_ATTRIBUTES    (sizeof(attributes) / sizeof(attributes[0]))
283 #define NUM_ATOMS         (sizeof(atoms) / sizeof(atoms[0]))
284
285 #define ENSURE_AREA(off, lng, max) (lng = ((off + lng) > max ? (max - off) : lng))
286
287 static CARD32
288 _countPrint (OsTimerPtr timer, CARD32 now, pointer arg)
289 {
290     SECPortPrivPtr pPort = (SECPortPrivPtr)arg;
291
292     if (pPort->timer)
293     {
294         TimerFree (pPort->timer);
295         pPort->timer = NULL;
296     }
297
298     ErrorF ("PutImage(%d) : %d fps. \n", pPort->index, pPort->put_counts);
299
300     pPort->put_counts = 0;
301
302     return 0;
303 }
304
305 static void
306 _countFps (SECPortPrivPtr pPort)
307 {
308     pPort->put_counts++;
309
310     if (pPort->timer)
311         return;
312
313     pPort->timer = TimerSet (NULL, 0, 1000, _countPrint, pPort);
314 }
315
316 static SECVideoPortInfo*
317 _port_info (DrawablePtr pDraw)
318 {
319     if (!pDraw)
320         return NULL;
321
322     if (pDraw->type == DRAWABLE_WINDOW)
323         return GetPortInfo ((WindowPtr)pDraw);
324     else
325        return GetPortInfo ((PixmapPtr)pDraw);
326 }
327
328 static PixmapPtr
329 _getPixmap (DrawablePtr pDraw)
330 {
331     if (pDraw->type == DRAWABLE_WINDOW)
332         return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw);
333     else
334         return (PixmapPtr) pDraw;
335 }
336
337 static XF86ImagePtr
338 _get_image_info (int id)
339 {
340     int i;
341
342     for (i = 0; i < NUM_IMAGES; i++)
343         if (images[i].id == id)
344             return &images[i];
345
346     return NULL;
347 }
348
349 static Atom
350 _portAtom (SECPortAttrAtom paa)
351 {
352     int i;
353
354     XDBG_RETURN_VAL_IF_FAIL (paa > PAA_MIN && paa < PAA_MAX, None);
355
356     for (i = 0; i < NUM_ATOMS; i++)
357     {
358         if (paa == atoms[i].paa)
359         {
360             if (atoms[i].atom == None)
361                 atoms[i].atom = MakeAtom (atoms[i].name,
362                                           strlen (atoms[i].name), TRUE);
363
364             return atoms[i].atom;
365         }
366     }
367
368     XDBG_ERROR (MVDO, "Error: Unknown Port Attribute Name!\n");
369
370     return None;
371 }
372
373 static void
374 _DestroyData (void *port, void *data)
375 {
376     SECPortPrivPtr pPort = (SECPortPrivPtr)port;
377     unsigned int handle = (unsigned int)data;
378
379     secUtilFreeHandle (pPort->pScrn, handle);
380 }
381
382 static Bool
383 _secVideoGrabTvout (SECPortPrivPtr pPort)
384 {
385     SECVideoPrivPtr pVideo = SECPTR(pPort->pScrn)->pVideoPriv;
386
387     if (pPort->grab_tvout)
388         return TRUE;
389
390     /* other port already grabbed */
391     if (pVideo->tvout_in_use)
392     {
393         XDBG_WARNING (MVDO, "*** pPort(%p) can't grab tvout. It's in use.\n", pPort);
394         return FALSE;
395     }
396
397     if (pPort->tv)
398     {
399         XDBG_ERROR (MVDO, "*** wrong handle if you reach here. %p \n", pPort->tv);
400         return FALSE;
401     }
402
403     pPort->grab_tvout = TRUE;
404     pVideo->tvout_in_use = TRUE;
405
406     XDBG_TRACE (MVDO, "pPort(%p) grabs tvout.\n", pPort);
407
408     return TRUE;
409 }
410
411 static void
412 _secVideoUngrabTvout (SECPortPrivPtr pPort)
413 {
414     if (pPort->tv)
415     {
416         secVideoTvDisconnect (pPort->tv);
417         pPort->tv = NULL;
418     }
419
420     /* This port didn't grab tvout */
421     if (!pPort->grab_tvout)
422         return;
423
424     _secVideoSetOutputExternalProperty (pPort->d.pDraw, FALSE);
425
426     if (pPort->need_start_wb)
427     {
428         SECWb *wb = secWbGet ();
429         if (wb)
430         {
431             secWbSetSecure (wb, pPort->secure);
432             secWbStart (wb);
433         }
434         pPort->need_start_wb = FALSE;
435     }
436
437     XDBG_TRACE (MVDO, "pPort(%p) ungrabs tvout.\n", pPort);
438
439     pPort->grab_tvout = FALSE;
440
441     if (pPort->pScrn)
442     {
443         SECVideoPrivPtr pVideo;
444         pVideo = SECPTR(pPort->pScrn)->pVideoPriv;
445         pVideo->tvout_in_use = FALSE;
446     }
447     pPort->wait_vbuf = NULL;
448 }
449
450 static int
451 _secVideoGetTvoutMode (SECPortPrivPtr pPort)
452 {
453     SECModePtr pSecMode = (SECModePtr) SECPTR (pPort->pScrn)->pSecMode;
454     SECVideoPrivPtr pVideo = SECPTR(pPort->pScrn)->pVideoPriv;
455     SECDisplaySetMode disp_mode = secDisplayGetDispSetMode (pPort->pScrn);
456     int output = OUTPUT_LCD;
457
458     if (disp_mode == DISPLAY_SET_MODE_CLONE)
459     {
460         if (pPort->preemption > -1)
461         {
462             if (pVideo->video_output > 0 && streaming_ports == 1)
463             {
464                 int video_output = pVideo->video_output - 1;
465
466                 if (video_output == OUTPUT_MODE_DEFAULT)
467                     output = OUTPUT_LCD;
468                 else if (video_output == OUTPUT_MODE_TVOUT)
469                     output = OUTPUT_LCD|OUTPUT_EXT|OUTPUT_FULL;
470                 else
471                     output = OUTPUT_EXT|OUTPUT_FULL;
472             }
473             else if (streaming_ports == 1)
474             {
475                 output = pPort->usr_output;
476                 if (!(output & OUTPUT_FULL))
477                     output &= ~(OUTPUT_EXT);
478             }
479             else if (streaming_ports > 1)
480                 output = OUTPUT_LCD;
481             else
482                 XDBG_NEVER_GET_HERE (MVDO);
483         }
484         else
485             output = OUTPUT_LCD;
486     }
487     else if (disp_mode == DISPLAY_SET_MODE_EXT)
488     {
489         if (pPort->drawing == ON_PIXMAP)
490             output = OUTPUT_LCD;
491         else
492         {
493             xf86CrtcPtr pCrtc = secCrtcGetAtGeometry (pPort->pScrn,
494                           (int)pPort->d.pDraw->x, (int)pPort->d.pDraw->y,
495                           (int)pPort->d.pDraw->width, (int)pPort->d.pDraw->height);
496             int c = secCrtcGetConnectType (pCrtc);
497
498             if (c == DRM_MODE_CONNECTOR_LVDS || c == DRM_MODE_CONNECTOR_Unknown)
499                 output = OUTPUT_LCD;
500             else if (c == DRM_MODE_CONNECTOR_HDMIA || c == DRM_MODE_CONNECTOR_HDMIB)
501                 output = OUTPUT_EXT;
502             else if (c == DRM_MODE_CONNECTOR_VIRTUAL)
503                 output = OUTPUT_EXT;
504             else
505                 XDBG_NEVER_GET_HERE (MVDO);
506         }
507     }
508     else /* DISPLAY_SET_MODE_OFF */
509     {
510         output = OUTPUT_LCD;
511     }
512
513     /* OUTPUT_LCD is default display. If default display is HDMI,
514      * we need to change OUTPUT_LCD to OUTPUT_HDMI
515      */
516     if (output == OUTPUT_LCD)
517     {
518         xf86CrtcPtr pCrtc = secCrtcGetAtGeometry (pPort->pScrn,
519                       (int)pPort->d.pDraw->x, (int)pPort->d.pDraw->y,
520                       (int)pPort->d.pDraw->width, (int)pPort->d.pDraw->height);
521         int c = secCrtcGetConnectType (pCrtc);
522
523         if (c == DRM_MODE_CONNECTOR_LVDS || c == DRM_MODE_CONNECTOR_Unknown)
524             output = OUTPUT_LCD;
525         else if (c == DRM_MODE_CONNECTOR_HDMIA || c == DRM_MODE_CONNECTOR_HDMIB)
526             output = OUTPUT_EXT;
527         else if (c == DRM_MODE_CONNECTOR_VIRTUAL)
528             output = OUTPUT_EXT;
529         else
530             XDBG_NEVER_GET_HERE (MVDO);
531     }
532
533     if (pPort->drawing == ON_PIXMAP)
534         output = OUTPUT_LCD;
535
536     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",
537                 pPort->drawing, disp_mode, pPort->preemption, streaming_ports, pSecMode->conn_mode,
538                 pPort->usr_output, pVideo->video_output, output, pPort->skip_tvout);
539
540     return output;
541 }
542
543 static int
544 _secVideodrawingOn (SECPortPrivPtr pPort)
545 {
546     if (pPort->old_d.pDraw != pPort->d.pDraw)
547         pPort->drawing = ON_NONE;
548
549     if (pPort->drawing != ON_NONE)
550         return pPort->drawing;
551
552     if (pPort->d.pDraw->type == DRAWABLE_PIXMAP)
553         return ON_PIXMAP;
554     else if (pPort->d.pDraw->type == DRAWABLE_WINDOW)
555     {
556         PropertyPtr prop = secUtilGetWindowProperty ((WindowPtr)pPort->d.pDraw,
557                                                      "XV_ON_DRAWABLE");
558         if (prop && *(int*)prop->data > 0)
559             return ON_WINDOW;
560     }
561
562     return ON_FB;
563 }
564
565 static void
566 _secVideoGetRotation (SECPortPrivPtr pPort, int *hw_rotate)
567 {
568     SECVideoPrivPtr pVideo = SECPTR(pPort->pScrn)->pVideoPriv;
569
570     /*
571      * RR_Rotate_90:  Target turns to 90. UI turns to 270.
572      * RR_Rotate_270: Target turns to 270. UI turns to 90.
573      *
574      *     [Target]            ----------
575      *                         |        |
576      *     Top (RR_Rotate_90)  |        |  Top (RR_Rotate_270)
577      *                         |        |
578      *                         ----------
579      *     [UI,FIMC]           ----------
580      *                         |        |
581      *      Top (degree: 270)  |        |  Top (degree: 90)
582      *                         |        |
583      *                         ----------
584      */
585
586     if (pPort->drawing == ON_FB)
587         *hw_rotate = (pPort->rotate + pVideo->screen_rotate_degree) % 360;
588     else
589         *hw_rotate = pPort->rotate % 360;
590 }
591
592 static int
593 _secVideoGetKeys (SECPortPrivPtr pPort, unsigned int *keys, unsigned int *type)
594 {
595     XV_DATA_PTR data = (XV_DATA_PTR) pPort->d.buf;
596     int valid = XV_VALIDATE_DATA (data);
597
598     if (valid == XV_HEADER_ERROR)
599     {
600         XDBG_ERROR (MVDO, "XV_HEADER_ERROR\n");
601         return valid;
602     }
603     else if (valid == XV_VERSION_MISMATCH)
604     {
605         XDBG_ERROR (MVDO, "XV_VERSION_MISMATCH\n");
606         return valid;
607     }
608
609     if (keys)
610     {
611         keys[0] = data->YBuf;
612         keys[1] = data->CbBuf;
613         keys[2] = data->CrBuf;
614     }
615
616     if (type)
617         *type = data->BufType;
618
619     return 0;
620 }
621
622 static void
623 _secVideoFreeInbuf (SECVideoBuf *vbuf, void *data)
624 {
625     SECPortPrivPtr pPort = (SECPortPrivPtr)data;
626     int i;
627
628     XDBG_RETURN_IF_FAIL (pPort->drawing != ON_NONE);
629
630     for (i = 0; i < INBUF_NUM; i++)
631         if (pPort->inbuf[i] == vbuf)
632         {
633             _secVideoSendReturnBufferMessage (pPort, vbuf, NULL);
634             pPort->inbuf[i] = NULL;
635             return;
636         }
637
638     XDBG_NEVER_GET_HERE (MVDO);
639 }
640
641 static void
642 _secVideoFreeOutbuf (SECVideoBuf *vbuf, void *data)
643 {
644     SECPortPrivPtr pPort = (SECPortPrivPtr)data;
645     int i;
646
647     XDBG_RETURN_IF_FAIL (pPort->drawing != ON_NONE);
648
649     for (i = 0; i < OUTBUF_NUM; i++)
650         if (pPort->outbuf[i] == vbuf)
651         {
652             pPort->pDamageDrawable[i] = NULL;
653             pPort->outbuf[i] = NULL;
654             return;
655         }
656
657     XDBG_NEVER_GET_HERE (MVDO);
658 }
659
660 static SECLayer*
661 _secVideoCreateLayer (SECPortPrivPtr pPort)
662 {
663     ScrnInfoPtr pScrn = pPort->pScrn;
664     SECVideoPrivPtr pVideo = SECPTR(pScrn)->pVideoPriv;
665     DrawablePtr pDraw = pPort->d.pDraw;
666     xf86CrtcConfigPtr pCrtcConfig;
667     xf86OutputPtr pOutput = NULL;
668     int i;
669     xf86CrtcPtr pCrtc;
670     SECLayer   *layer;
671     Bool full = TRUE;
672     xRectangle src, dst;
673
674     pCrtc = secCrtcGetAtGeometry (pScrn, pDraw->x, pDraw->y, pDraw->width, pDraw->height);
675     XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, NULL);
676
677     pCrtcConfig = XF86_CRTC_CONFIG_PTR (pCrtc->scrn);
678     XDBG_RETURN_VAL_IF_FAIL (pCrtcConfig != NULL, NULL);
679
680     for (i = 0; i < pCrtcConfig->num_output; i++)
681     {
682         xf86OutputPtr pTemp = pCrtcConfig->output[i];
683         if (pTemp->crtc == pCrtc)
684         {
685             pOutput = pTemp;
686             break;
687         }
688     }
689     XDBG_RETURN_VAL_IF_FAIL (pOutput != NULL, NULL);
690
691     SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
692     SECLayerOutput output = LAYER_OUTPUT_LCD;
693
694     if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS ||
695         pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown)
696     {
697         output = LAYER_OUTPUT_LCD;
698     }
699     else if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
700              pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB ||
701              pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)
702     {
703         output = LAYER_OUTPUT_EXT;
704     }
705     else
706         XDBG_NEVER_GET_HERE (MVDO);
707
708     if (!secLayerFind (output, LAYER_LOWER2) || !secLayerFind (output, LAYER_LOWER1))
709         full = FALSE;
710
711     if (full)
712         return NULL;
713
714     layer = secLayerCreate (pScrn, output, LAYER_NONE);
715     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL);
716
717     src = dst = pPort->out_crop;
718     dst.x = pPort->d.dst.x;
719     dst.y = pPort->d.dst.y;
720
721     secLayerSetRect (layer, &src, &dst);
722     secLayerEnableVBlank (layer, TRUE);
723
724     xorg_list_add (&pPort->link, &layer_owners);
725
726     secLayerSetOffset (layer, pVideo->video_offset_x, pVideo->video_offset_y);
727
728     return layer;
729 }
730
731 static SECVideoBuf*
732 _secVideoGetInbufZeroCopy (SECPortPrivPtr pPort, unsigned int *names, unsigned int buf_type)
733 {
734     SECVideoBuf *inbuf = NULL;
735     int i, empty;
736     tbm_bo_handle bo_handle;
737
738     for (empty = 0; empty < INBUF_NUM; empty++)
739         if (!pPort->inbuf[empty])
740             break;
741
742     if (empty == INBUF_NUM)
743     {
744         XDBG_ERROR (MVDO, "now all inbufs in use!\n");
745         return NULL;
746     }
747
748     /* make sure both widths are same.*/
749     XDBG_RETURN_VAL_IF_FAIL (pPort->d.width == pPort->in_width, NULL);
750     XDBG_RETURN_VAL_IF_FAIL (pPort->d.height == pPort->in_height, NULL);
751
752     inbuf = secUtilCreateVideoBuffer (pPort->pScrn, pPort->d.id,
753                                       pPort->in_width, pPort->in_height,
754                                       pPort->secure);
755     XDBG_RETURN_VAL_IF_FAIL (inbuf != NULL, NULL);
756
757     inbuf->crop = pPort->in_crop;
758
759     for (i = 0; i < PLANAR_CNT; i++)
760     {
761         if (names[i] > 0)
762         {
763             inbuf->keys[i] = names[i];
764
765             if (buf_type == XV_BUF_TYPE_LEGACY)
766             {
767                 void *data = secUtilListGetData (pPort->gem_list, (void*)names[i]);
768                 if (!data)
769                 {
770                     secUtilConvertPhyaddress (pPort->pScrn, names[i], inbuf->lengths[i], &inbuf->handles[i]);
771
772                     pPort->gem_list = secUtilListAdd (pPort->gem_list, (void*)names[i],
773                                                       (void*)inbuf->handles[i]);
774                 }
775                 else
776                     inbuf->handles[i] = (unsigned int)data;
777
778                 XDBG_DEBUG (MVDO, "%d, %p => %d \n", i, (void*)names[i], inbuf->handles[i]);
779             }
780             else
781             {
782                 XDBG_GOTO_IF_FAIL (inbuf->lengths[i] > 0, fail_dma);
783                 XDBG_GOTO_IF_FAIL (inbuf->bo[i] == NULL, fail_dma);
784
785                 inbuf->bo[i] = tbm_bo_import (SECPTR (pPort->pScrn)->tbm_bufmgr, inbuf->keys[i]);
786                 XDBG_GOTO_IF_FAIL (inbuf->bo[i] != NULL, fail_dma);
787
788                 bo_handle = tbm_bo_get_handle(inbuf->bo[i], TBM_DEVICE_DEFAULT);
789                 inbuf->handles[i] = bo_handle.u32;
790                 XDBG_GOTO_IF_FAIL (inbuf->handles[i] > 0, fail_dma);
791
792                 inbuf->offsets[i] = 0;
793
794                 XDBG_DEBUG (MVDO, "%d, key(%d) => bo(%p) handle(%d)\n",
795                             i, inbuf->keys[i], inbuf->bo[i], inbuf->handles[i]);
796             }
797         }
798     }
799
800     /* not increase ref_cnt to free inbuf when converting/showing is done. */
801     pPort->inbuf[empty] = inbuf;
802
803     secUtilAddFreeVideoBufferFunc (inbuf, _secVideoFreeInbuf, pPort);
804
805     return inbuf;
806
807 fail_dma:
808     if (inbuf)
809         secUtilFreeVideoBuffer (inbuf);
810
811     return NULL;
812 }
813
814 static SECVideoBuf*
815 _secVideoGetInbufRAW (SECPortPrivPtr pPort)
816 {
817     SECVideoBuf *inbuf = NULL;
818     void *vir_addr = NULL;
819     int i;
820     tbm_bo_handle bo_handle;
821
822     /* we can't access virtual pointer. */
823     XDBG_RETURN_VAL_IF_FAIL (pPort->secure == FALSE, NULL);
824
825     for (i = 0; i < INBUF_NUM; i++)
826     {
827         if (pPort->inbuf[i])
828             continue;
829
830         pPort->inbuf[i] = secUtilAllocVideoBuffer (pPort->pScrn, pPort->d.id,
831                                                    pPort->in_width, pPort->in_height,
832                                                    FALSE, FALSE, pPort->secure);
833         XDBG_GOTO_IF_FAIL (pPort->inbuf[i] != NULL, fail_raw_alloc);
834     }
835
836     for (i = 0; i < INBUF_NUM; i++)
837     {
838         XDBG_DEBUG (MVDO, "? inbuf(%d,%p) converting(%d) showing(%d)\n", i,
839                     pPort->inbuf[i], VBUF_IS_CONVERTING (pPort->inbuf[i]), pPort->inbuf[i]->showing);
840
841         if (pPort->inbuf[i] && !VBUF_IS_CONVERTING (pPort->inbuf[i]) && !pPort->inbuf[i]->showing)
842         {
843             /* increase ref_cnt to keep inbuf until stream_off. */
844             inbuf = secUtilVideoBufferRef (pPort->inbuf[i]);
845             break;
846         }
847     }
848
849     if (!inbuf)
850     {
851         XDBG_ERROR (MVDO, "now all inbufs in use!\n");
852         return NULL;
853     }
854
855     inbuf->crop = pPort->in_crop;
856
857     bo_handle = tbm_bo_map (inbuf->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
858     vir_addr = bo_handle.ptr;
859     XDBG_RETURN_VAL_IF_FAIL (vir_addr != NULL, NULL);
860     XDBG_RETURN_VAL_IF_FAIL (inbuf->size > 0, NULL);
861
862     if (pPort->d.width != pPort->in_width || pPort->d.height != pPort->in_height)
863     {
864         XF86ImagePtr image_info = _get_image_info (pPort->d.id);
865         int pitches[3] = {0,};
866         int offsets[3] = {0,};
867         int lengths[3] = {0,};
868         int width, height;
869
870         width = pPort->d.width;
871         height = pPort->d.height;
872
873         secVideoQueryImageAttrs (pPort->pScrn, pPort->d.id,
874                                  &width, &height,
875                                  pitches, offsets, lengths);
876
877         secUtilCopyImage (width, height,
878                           pPort->d.buf, width, height,
879                           pitches, offsets, lengths,
880                           vir_addr, inbuf->width, inbuf->height,
881                           inbuf->pitches, inbuf->offsets, inbuf->lengths,
882                           image_info->num_planes,
883                           image_info->horz_u_period,
884                           image_info->vert_u_period);
885     }
886     else
887         memcpy (vir_addr, pPort->d.buf, inbuf->size);
888
889     tbm_bo_unmap (inbuf->bo[0]);
890     secUtilCacheFlush (pPort->pScrn);
891     return inbuf;
892
893 fail_raw_alloc:
894     _secVideoCloseInBuffer (pPort);
895     return NULL;
896 }
897
898 static SECVideoBuf*
899 _secVideoGetInbuf (SECPortPrivPtr pPort)
900 {
901     unsigned int keys[PLANAR_CNT] = {0,};
902     unsigned int buf_type = 0;
903     SECVideoBuf *inbuf = NULL;
904     SECPtr pSec = SECPTR (pPort->pScrn);
905
906     if (IS_ZEROCOPY (pPort->d.id))
907     {
908         if (_secVideoGetKeys (pPort, keys, &buf_type))
909             return NULL;
910
911         XDBG_RETURN_VAL_IF_FAIL (keys[0] > 0, NULL);
912
913         if (pPort->d.id == FOURCC_SN12 || pPort->d.id == FOURCC_ST12)
914             XDBG_RETURN_VAL_IF_FAIL (keys[1] > 0, NULL);
915
916         inbuf = _secVideoGetInbufZeroCopy (pPort, keys, buf_type);
917
918         XDBG_TRACE (MVDO, "keys: %d,%d,%d. stamp(%ld)\n", keys[0], keys[1], keys[2], inbuf->stamp);
919     }
920     else
921         inbuf = _secVideoGetInbufRAW (pPort);
922
923     if ((pSec->dump_mode & XBERC_DUMP_MODE_IA) && pSec->dump_info)
924     {
925         char file[128];
926         static int i;
927         snprintf (file, sizeof(file), "xvin_%c%c%c%c_%dx%d_p%d_%03d.%s",
928                   FOURCC_STR(inbuf->id),
929                   inbuf->width, inbuf->height, pPort->index, i++,
930                   IS_RGB(inbuf->id)?"bmp":"yuv");
931         secUtilDoDumpVBuf (pSec->dump_info, inbuf, file);
932     }
933
934     if (pSec->xvperf_mode & XBERC_XVPERF_MODE_IA)
935         inbuf->put_time = GetTimeInMillis ();
936
937     return inbuf;
938 }
939
940 static SECVideoBuf*
941 _secVideoGetOutbufDrawable (SECPortPrivPtr pPort)
942 {
943     ScrnInfoPtr pScrn = pPort->pScrn;
944     DrawablePtr pDraw = pPort->d.pDraw;
945     PixmapPtr pPixmap = (PixmapPtr)_getPixmap (pDraw);
946     SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPixmap);
947     Bool need_finish = FALSE;
948     SECVideoBuf *outbuf = NULL;
949     int empty;
950     tbm_bo_handle bo_handle;
951
952     for (empty = 0; empty < OUTBUF_NUM; empty++)
953         if (!pPort->outbuf[empty])
954             break;
955
956     if (empty == OUTBUF_NUM)
957     {
958         XDBG_ERROR (MVDO, "now all outbufs in use!\n");
959         return NULL;
960     }
961
962     if ((pDraw->width % 16) && (pPixmap->usage_hint != CREATE_PIXMAP_USAGE_XVIDEO))
963     {
964         ScreenPtr pScreen = pScrn->pScreen;
965         SECFbBoDataPtr bo_data = NULL;
966
967         pPixmap->usage_hint = CREATE_PIXMAP_USAGE_XVIDEO;
968         pScreen->ModifyPixmapHeader (pPixmap,
969                                      pDraw->width, pDraw->height,
970                                      pDraw->depth,
971                                      pDraw->bitsPerPixel,
972                                      pPixmap->devKind, 0);
973         XDBG_RETURN_VAL_IF_FAIL (privPixmap->bo != NULL, NULL);
974
975         tbm_bo_get_user_data(privPixmap->bo, TBM_BO_DATA_FB, (void**)&bo_data);
976         XDBG_RETURN_VAL_IF_FAIL (bo_data != NULL, NULL);
977         XDBG_RETURN_VAL_IF_FAIL ((bo_data->pos.x2 - bo_data->pos.x1) == pPort->out_width, NULL);
978         XDBG_RETURN_VAL_IF_FAIL ((bo_data->pos.y2 - bo_data->pos.y1) == pPort->out_height, NULL);
979     }
980
981     if (!privPixmap->bo)
982     {
983         need_finish = TRUE;
984         secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
985         XDBG_GOTO_IF_FAIL (privPixmap->bo != NULL, fail_drawable);
986     }
987
988     outbuf = secUtilCreateVideoBuffer (pScrn, FOURCC_RGB32,
989                                        pPort->out_width,
990                                        pPort->out_height,
991                                        pPort->secure);
992     XDBG_GOTO_IF_FAIL (outbuf != NULL, fail_drawable);
993     outbuf->crop = pPort->out_crop;
994
995     XDBG_TRACE (MVDO, "outbuf(%p)(%dx%d) created. [%s]\n",
996                 outbuf, pPort->out_width, pPort->out_height,
997                 (pPort->drawing==ON_PIXMAP)?"PIX":"WIN");
998
999     outbuf->bo[0] = tbm_bo_ref (privPixmap->bo);
1000
1001     bo_handle = tbm_bo_get_handle (outbuf->bo[0], TBM_DEVICE_DEFAULT);
1002     outbuf->handles[0] = bo_handle.u32;
1003     XDBG_GOTO_IF_FAIL (outbuf->handles[0] > 0, fail_drawable);
1004
1005     if (need_finish)
1006         secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
1007
1008     pPort->pDamageDrawable[empty] = pPort->d.pDraw;
1009
1010 //    RegionTranslate (pPort->d.clip_boxes, -pPort->d.dst.x, -pPort->d.dst.y);
1011
1012     /* not increase ref_cnt to free outbuf when converting/showing is done. */
1013     pPort->outbuf[empty] = outbuf;
1014
1015     secUtilAddFreeVideoBufferFunc (outbuf, _secVideoFreeOutbuf, pPort);
1016
1017     return outbuf;
1018
1019 fail_drawable:
1020     if (outbuf)
1021         secUtilFreeVideoBuffer (outbuf);
1022
1023     return NULL;
1024 }
1025
1026 static SECVideoBuf*
1027 _secVideoGetOutbufFB (SECPortPrivPtr pPort)
1028 {
1029     ScrnInfoPtr pScrn = pPort->pScrn;
1030     SECVideoBuf *outbuf = NULL;
1031     int i, next;
1032
1033     if (!pPort->layer)
1034     {
1035         pPort->layer = _secVideoCreateLayer (pPort);
1036         XDBG_RETURN_VAL_IF_FAIL (pPort->layer != NULL, NULL);
1037     }
1038     else
1039     {
1040         SECVideoBuf *vbuf = secLayerGetBuffer (pPort->layer);
1041         if (vbuf && (vbuf->width == pPort->out_width && vbuf->height == pPort->out_height))
1042         {
1043             xRectangle src = {0,}, dst = {0,};
1044
1045             secLayerGetRect (pPort->layer, &src, &dst);
1046
1047             /* CHECK */
1048             if (pPort->d.dst.x != dst.x || pPort->d.dst.y != dst.y)
1049             {
1050                 /* x,y can be changed when window is moved. */
1051                 dst.x = pPort->d.dst.x;
1052                 dst.y = pPort->d.dst.y;
1053                 secLayerSetRect (pPort->layer, &src, &dst);
1054             }
1055         }
1056     }
1057
1058     for (i = 0; i < OUTBUF_NUM; i++)
1059     {
1060         SECPtr pSec = SECPTR (pPort->pScrn);
1061
1062         if (pPort->outbuf[i])
1063             continue;
1064
1065         pPort->outbuf[i] = secUtilAllocVideoBuffer (pScrn, FOURCC_RGB32,
1066                                                     pPort->out_width, pPort->out_height,
1067                                                     (pSec->scanout)?TRUE:FALSE,
1068                                                     FALSE, pPort->secure);
1069         XDBG_GOTO_IF_FAIL (pPort->outbuf[i] != NULL, fail_fb);
1070         pPort->outbuf[i]->crop = pPort->out_crop;
1071
1072         XDBG_TRACE (MVDO, "out bo(%p, %d, %dx%d) created. [FB]\n",
1073                     pPort->outbuf[i]->bo[0], pPort->outbuf[i]->handles[0],
1074                     pPort->out_width, pPort->out_height);
1075     }
1076
1077     next = ++pPort->outbuf_cvting;
1078     if (next >= OUTBUF_NUM)
1079         next = 0;
1080
1081     for (i = 0; i < OUTBUF_NUM; i++)
1082     {
1083         XDBG_DEBUG (MVDO, "? outbuf(%d,%p) converting(%d)\n", next,
1084                     pPort->outbuf[next], VBUF_IS_CONVERTING (pPort->outbuf[next]));
1085
1086         if (pPort->outbuf[next] && !VBUF_IS_CONVERTING (pPort->outbuf[next]))
1087         {
1088             /* increase ref_cnt to keep outbuf until stream_off. */
1089             outbuf = secUtilVideoBufferRef (pPort->outbuf[next]);
1090             break;
1091         }
1092
1093         next++;
1094         if (next >= OUTBUF_NUM)
1095             next = 0;
1096     }
1097
1098     if (!outbuf)
1099     {
1100         XDBG_ERROR (MVDO, "now all outbufs in use!\n");
1101         return NULL;
1102     }
1103
1104     pPort->outbuf_cvting = next;
1105
1106     return outbuf;
1107
1108 fail_fb:
1109     _secVideoCloseConverter (pPort);
1110     _secVideoCloseOutBuffer (pPort, TRUE);
1111
1112     return NULL;
1113 }
1114
1115 static SECVideoBuf*
1116 _secVideoGetOutbuf (SECPortPrivPtr pPort)
1117 {
1118     if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
1119         return _secVideoGetOutbufDrawable (pPort);
1120     else /* ON_FB */
1121         return _secVideoGetOutbufFB (pPort);
1122 }
1123
1124 static void
1125 _secVideoCloseInBuffer (SECPortPrivPtr pPort)
1126 {
1127     int i;
1128
1129     _secVideoUngrabTvout (pPort);
1130
1131     if (pPort->gem_list)
1132     {
1133         secUtilListDestroyData (pPort->gem_list, _DestroyData, pPort);
1134         secUtilListDestroy (pPort->gem_list);
1135         pPort->gem_list = NULL;
1136     }
1137
1138     if (!IS_ZEROCOPY (pPort->d.id))
1139         for (i = 0; i < INBUF_NUM; i++)
1140         {
1141             if (pPort->inbuf[i])
1142             {
1143                 secUtilVideoBufferUnref (pPort->inbuf[i]);
1144                 pPort->inbuf[i] = NULL;
1145             }
1146         }
1147
1148     pPort->in_width = 0;
1149     pPort->in_height = 0;
1150     memset (&pPort->in_crop, 0, sizeof (xRectangle));
1151
1152     XDBG_DEBUG (MVDO, "done\n");
1153 }
1154
1155 static void
1156 _secVideoCloseOutBuffer (SECPortPrivPtr pPort, Bool close_layer)
1157 {
1158     int i;
1159
1160     /* before close outbuf, layer/cvt should be finished. */
1161     if (close_layer && pPort->layer)
1162     {
1163         secLayerUnref (pPort->layer);
1164         pPort->layer = NULL;
1165         xorg_list_del (&pPort->link);
1166     }
1167
1168     for (i = 0; i < OUTBUF_NUM; i++)
1169     {
1170         if (pPort->outbuf[i])
1171         {
1172             if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
1173                 XDBG_NEVER_GET_HERE (MVDO);
1174
1175             secUtilVideoBufferUnref (pPort->outbuf[i]);
1176             pPort->outbuf[i] = NULL;
1177         }
1178     }
1179
1180     pPort->out_width = 0;
1181     pPort->out_height = 0;
1182     memset (&pPort->out_crop, 0, sizeof (xRectangle));
1183     pPort->outbuf_cvting = -1;
1184
1185     XDBG_DEBUG (MVDO, "done\n");
1186 }
1187
1188 static void
1189 _secVideoSendReturnBufferMessage (SECPortPrivPtr pPort, SECVideoBuf *vbuf, unsigned int *keys)
1190 {
1191     static Atom return_atom = None;
1192     SECVideoPortInfo *info = _port_info (pPort->d.pDraw);
1193
1194     if (return_atom == None)
1195         return_atom = MakeAtom ("XV_RETURN_BUFFER",
1196                                 strlen ("XV_RETURN_BUFFER"), TRUE);
1197
1198     if (!info)
1199         return;
1200
1201     xEvent event;
1202
1203     CLEAR (event);
1204     event.u.u.type = ClientMessage;
1205     event.u.u.detail = 32;
1206     event.u.clientMessage.u.l.type = return_atom;
1207     if (vbuf)
1208     {
1209         event.u.clientMessage.u.l.longs0 = (INT32)vbuf->keys[0];
1210         event.u.clientMessage.u.l.longs1 = (INT32)vbuf->keys[1];
1211         event.u.clientMessage.u.l.longs2 = (INT32)vbuf->keys[2];
1212
1213         XDBG_TRACE (MVDO, "%ld: %d,%d,%d out. diff(%ld)\n", vbuf->stamp,
1214                     vbuf->keys[0], vbuf->keys[1], vbuf->keys[2], GetTimeInMillis()-vbuf->stamp);
1215     }
1216     else if (keys)
1217     {
1218         event.u.clientMessage.u.l.longs0 = (INT32)keys[0];
1219         event.u.clientMessage.u.l.longs1 = (INT32)keys[1];
1220         event.u.clientMessage.u.l.longs2 = (INT32)keys[2];
1221
1222         XDBG_TRACE (MVDO, "%d,%d,%d out. \n",
1223                     keys[0], keys[1], keys[2]);
1224     }
1225     else
1226         XDBG_NEVER_GET_HERE (MVDO);
1227
1228     WriteEventsToClient(info->client, 1, (xEventPtr) &event);
1229
1230     SECPtr pSec = SECPTR (pPort->pScrn);
1231     if (pSec->xvperf_mode & XBERC_XVPERF_MODE_IA)
1232     {
1233         if (vbuf)
1234         {
1235             CARD32 cur, sub;
1236             cur = GetTimeInMillis ();
1237             sub = cur - vbuf->put_time;
1238             ErrorF ("vbuf(%d,%d,%d)         retbuf  : %6ld ms\n",
1239                     vbuf->keys[0], vbuf->keys[1], vbuf->keys[2], sub);
1240         }
1241         else if (keys)
1242             ErrorF ("vbuf(%d,%d,%d)         retbuf  : 0 ms\n",
1243                     keys[0], keys[1], keys[2]);
1244         else
1245             XDBG_NEVER_GET_HERE (MVDO);
1246     }
1247 }
1248
1249 static void
1250 _secVideoCvtCallback (SECCvt *cvt,
1251                       SECVideoBuf *src,
1252                       SECVideoBuf *dst,
1253                       void *cvt_data,
1254                       Bool error)
1255 {
1256     SECPortPrivPtr pPort = (SECPortPrivPtr)cvt_data;
1257     DrawablePtr pDamageDrawable = NULL;
1258     int out_index;
1259
1260     XDBG_RETURN_IF_FAIL (pPort != NULL);
1261     XDBG_RETURN_IF_FAIL (cvt != NULL);
1262     XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (src));
1263     XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (dst));
1264     XDBG_DEBUG (MVDO, "++++++++++++++++++++++++ \n");
1265     XDBG_DEBUG (MVDO, "cvt(%p) src(%p) dst(%p)\n", cvt, src, dst);
1266
1267     for (out_index = 0; out_index < OUTBUF_NUM; out_index++)
1268         if (pPort->outbuf[out_index] == dst)
1269             break;
1270     XDBG_RETURN_IF_FAIL (out_index < OUTBUF_NUM);
1271
1272     if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
1273         pDamageDrawable = pPort->pDamageDrawable[out_index];
1274     else
1275         pDamageDrawable = pPort->d.pDraw;
1276
1277     XDBG_RETURN_IF_FAIL (pDamageDrawable != NULL);
1278
1279     if (error)
1280     {
1281         DamageDamageRegion (pDamageDrawable, pPort->d.clip_boxes);
1282         return;
1283     }
1284
1285     SECPtr pSec = SECPTR (pPort->pScrn);
1286     if ((pSec->dump_mode & XBERC_DUMP_MODE_IA) && pSec->dump_info)
1287     {
1288         char file[128];
1289         static int i;
1290         snprintf (file, sizeof(file), "xvout_p%d_%03d.bmp", pPort->index, i++);
1291         secUtilDoDumpVBuf (pSec->dump_info, dst, file);
1292     }
1293
1294     if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
1295     {
1296         DamageDamageRegion (pDamageDrawable, pPort->d.clip_boxes);
1297     }
1298     else if (pPort->layer)
1299     {
1300         SECVideoBuf *vbuf = secLayerGetBuffer (pPort->layer);
1301         Bool reset_layer = FALSE;
1302         xRectangle src_rect, dst_rect;
1303
1304         if (vbuf)
1305             if (vbuf->width != pPort->out_width || vbuf->height != pPort->out_height)
1306                 reset_layer = TRUE;
1307
1308         secLayerGetRect (pPort->layer, &src_rect, &dst_rect);
1309         if (memcmp (&src_rect, &pPort->out_crop, sizeof(xRectangle)) ||
1310             dst_rect.x != pPort->d.dst.x ||
1311             dst_rect.y != pPort->d.dst.y ||
1312             dst_rect.width != pPort->out_crop.width ||
1313             dst_rect.height != pPort->out_crop.height)
1314             reset_layer = TRUE;
1315
1316         if (reset_layer)
1317         {
1318             secLayerFreezeUpdate (pPort->layer, TRUE);
1319
1320             src_rect = pPort->out_crop;
1321             dst_rect.x = pPort->d.dst.x;
1322             dst_rect.y = pPort->d.dst.y;
1323             dst_rect.width = pPort->out_crop.width;
1324             dst_rect.height = pPort->out_crop.height;
1325
1326             secLayerSetRect (pPort->layer, &src_rect, &dst_rect);
1327             secLayerFreezeUpdate (pPort->layer, FALSE);
1328             secLayerSetBuffer (pPort->layer, dst);
1329         }
1330         else
1331             secLayerSetBuffer (pPort->layer, dst);
1332
1333         if (!secLayerIsVisible (pPort->layer))
1334             secLayerShow (pPort->layer);
1335     }
1336
1337     XDBG_DEBUG (MVDO, "++++++++++++++++++++++++.. \n");
1338 }
1339
1340 static void
1341 _secVideoTvoutCvtCallback (SECCvt *cvt,
1342                            SECVideoBuf *src,
1343                            SECVideoBuf *dst,
1344                            void *cvt_data,
1345                            Bool error)
1346 {
1347     SECPortPrivPtr pPort = (SECPortPrivPtr)cvt_data;
1348
1349     XDBG_RETURN_IF_FAIL (pPort != NULL);
1350     XDBG_RETURN_IF_FAIL (cvt != NULL);
1351     XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (src));
1352     XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (dst));
1353
1354     XDBG_DEBUG (MVDO, "######################## \n");
1355     XDBG_DEBUG (MVDO, "cvt(%p) src(%p) dst(%p)\n", cvt, src, dst);
1356
1357     if (pPort->wait_vbuf != src)
1358         XDBG_WARNING (MVDO, "wait_vbuf(%p) != src(%p). \n",
1359                       pPort->wait_vbuf, src);
1360
1361     pPort->wait_vbuf = NULL;
1362
1363     XDBG_DEBUG (MVDO, "########################.. \n");
1364 }
1365
1366 static void
1367 _secVideoLayerNotifyFunc (SECLayer *layer, int type, void *type_data, void *data)
1368 {
1369     SECPortPrivPtr pPort = (SECPortPrivPtr)data;
1370     SECVideoBuf *vbuf = (SECVideoBuf*)type_data;
1371
1372     if (type != LAYER_VBLANK)
1373         return;
1374
1375     XDBG_RETURN_IF_FAIL (pPort != NULL);
1376     XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (vbuf));
1377
1378     if (pPort->wait_vbuf != vbuf)
1379         XDBG_WARNING (MVDO, "wait_vbuf(%p) != vbuf(%p). \n",
1380                       pPort->wait_vbuf, vbuf);
1381
1382     XDBG_DEBUG (MVBUF, "now_showing(%p). \n", vbuf);
1383
1384     pPort->wait_vbuf = NULL;
1385 }
1386
1387 static void
1388 _secVideoEnsureConverter (SECPortPrivPtr pPort)
1389 {
1390     if (pPort->cvt)
1391         return;
1392
1393     pPort->cvt = secCvtCreate (pPort->pScrn, CVT_OP_M2M);
1394     XDBG_RETURN_IF_FAIL (pPort->cvt != NULL);
1395
1396     secCvtAddCallback (pPort->cvt, _secVideoCvtCallback, pPort);
1397 }
1398
1399 static void
1400 _secVideoCloseConverter (SECPortPrivPtr pPort)
1401 {
1402     if (pPort->cvt)
1403     {
1404         secCvtDestroy (pPort->cvt);
1405         pPort->cvt = NULL;
1406     }
1407
1408     XDBG_TRACE (MVDO, "done. \n");
1409 }
1410
1411 static void
1412 _secVideoStreamOff (SECPortPrivPtr pPort)
1413 {
1414     _secVideoCloseConverter (pPort);
1415     _secVideoCloseInBuffer (pPort);
1416     _secVideoCloseOutBuffer (pPort, TRUE);
1417
1418     SECWb *wb = secWbGet ();
1419     if (wb)
1420     {
1421         if (pPort->need_start_wb)
1422         {
1423             secWbSetSecure (wb, FALSE);
1424             secWbStart (wb);
1425             pPort->need_start_wb = FALSE;
1426         }
1427         else
1428             secWbSetSecure (wb, FALSE);
1429     }
1430
1431     if (pPort->d.clip_boxes)
1432     {
1433         RegionDestroy (pPort->d.clip_boxes);
1434         pPort->d.clip_boxes = NULL;
1435     }
1436
1437     memset (&pPort->old_d, 0, sizeof (PutData));
1438     memset (&pPort->d, 0, sizeof (PutData));
1439
1440     pPort->need_start_wb = FALSE;
1441     pPort->skip_tvout = FALSE;
1442     pPort->usr_output = OUTPUT_LCD|OUTPUT_EXT;
1443     pPort->outbuf_cvting = -1;
1444     pPort->drawing = 0;
1445     pPort->tv_prev_time = 0;
1446     pPort->secure = FALSE;
1447     pPort->csc_range = 0;
1448     pPort->inbuf_is_fb = FALSE;
1449
1450     if (pPort->stream_cnt > 0)
1451     {
1452         pPort->stream_cnt = 0;
1453         XDBG_SECURE (MVDO, "pPort(%d) stream off. \n", pPort->index);
1454
1455         if (pPort->preemption > -1)
1456             streaming_ports--;
1457
1458         XDBG_WARNING_IF_FAIL (streaming_ports >= 0);
1459     }
1460
1461     XDBG_TRACE (MVDO, "done. \n");
1462 }
1463
1464 static Bool
1465 _secVideoCalculateSize (SECPortPrivPtr pPort)
1466 {
1467     SECCvtProp src_prop = {0,}, dst_prop = {0,};
1468
1469     src_prop.id = pPort->d.id;
1470     src_prop.width = pPort->d.width;
1471     src_prop.height = pPort->d.height;
1472     src_prop.crop = pPort->d.src;
1473
1474      dst_prop.id = FOURCC_RGB32;
1475     if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
1476     {
1477         dst_prop.width = pPort->d.pDraw->width;
1478         dst_prop.height = pPort->d.pDraw->height;
1479         dst_prop.crop = pPort->d.dst;
1480         dst_prop.crop.x -= pPort->d.pDraw->x;
1481         dst_prop.crop.y -= pPort->d.pDraw->y;
1482     }
1483     else
1484     {
1485         dst_prop.width = pPort->d.dst.width;
1486         dst_prop.height = pPort->d.dst.height;
1487         dst_prop.crop = pPort->d.dst;
1488         dst_prop.crop.x = 0;
1489         dst_prop.crop.y = 0;
1490     }
1491
1492     XDBG_DEBUG (MVDO, "(%dx%d : %d,%d %dx%d) => (%dx%d : %d,%d %dx%d)\n",
1493                 src_prop.width, src_prop.height,
1494                 src_prop.crop.x, src_prop.crop.y, src_prop.crop.width, src_prop.crop.height,
1495                 dst_prop.width, dst_prop.height,
1496                 dst_prop.crop.x, dst_prop.crop.y, dst_prop.crop.width, dst_prop.crop.height);
1497
1498     if (!secCvtEnsureSize (&src_prop, &dst_prop))
1499         return FALSE;
1500
1501     XDBG_DEBUG (MVDO, "(%dx%d : %d,%d %dx%d) => (%dx%d : %d,%d %dx%d)\n",
1502                 src_prop.width, src_prop.height,
1503                 src_prop.crop.x, src_prop.crop.y, src_prop.crop.width, src_prop.crop.height,
1504                 dst_prop.width, dst_prop.height,
1505                 dst_prop.crop.x, dst_prop.crop.y, dst_prop.crop.width, dst_prop.crop.height);
1506
1507     XDBG_RETURN_VAL_IF_FAIL (src_prop.width > 0, FALSE);
1508     XDBG_RETURN_VAL_IF_FAIL (src_prop.height > 0, FALSE);
1509     XDBG_RETURN_VAL_IF_FAIL (src_prop.crop.width > 0, FALSE);
1510     XDBG_RETURN_VAL_IF_FAIL (src_prop.crop.height > 0, FALSE);
1511     XDBG_RETURN_VAL_IF_FAIL (dst_prop.width > 0, FALSE);
1512     XDBG_RETURN_VAL_IF_FAIL (dst_prop.height > 0, FALSE);
1513     XDBG_RETURN_VAL_IF_FAIL (dst_prop.crop.width > 0, FALSE);
1514     XDBG_RETURN_VAL_IF_FAIL (dst_prop.crop.height > 0, FALSE);
1515
1516     pPort->in_width = src_prop.width;
1517     pPort->in_height = src_prop.height;
1518     pPort->in_crop = src_prop.crop;
1519
1520     pPort->out_width = dst_prop.width;
1521     pPort->out_height = dst_prop.height;
1522     pPort->out_crop = dst_prop.crop;
1523     return TRUE;
1524 }
1525
1526 static void
1527 _secVideoPunchDrawable (SECPortPrivPtr pPort)
1528 {
1529     PixmapPtr pPixmap = _getPixmap (pPort->d.pDraw);
1530     SECPtr pSec = SECPTR (pPort->pScrn);
1531
1532     if (pPort->drawing != ON_FB || !pSec->pVideoPriv->video_punch)
1533         return;
1534
1535     if (!pPort->punched)
1536     {
1537         secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
1538         if (pPixmap->devPrivate.ptr)
1539             memset (pPixmap->devPrivate.ptr, 0,
1540                     pPixmap->drawable.width * pPixmap->drawable.height * 4);
1541         secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
1542         XDBG_TRACE (MVDO, "Punched (%dx%d) %p. \n",
1543                     pPixmap->drawable.width, pPixmap->drawable.height,
1544                     pPixmap->devPrivate.ptr);
1545         pPort->punched = TRUE;
1546         DamageDamageRegion (pPort->d.pDraw, pPort->d.clip_boxes);
1547     }
1548 }
1549
1550 static Bool
1551 _secVideoSupportID (int id)
1552 {
1553     int i;
1554
1555     for (i = 0; i < NUM_IMAGES; i++)
1556         if (images[i].id == id)
1557             if (secCvtSupportFormat (CVT_OP_M2M, id))
1558                 return TRUE;
1559
1560     return FALSE;
1561 }
1562
1563 static Bool
1564 _secVideoInBranch (WindowPtr p, WindowPtr w)
1565 {
1566     for (; w; w = w->parent)
1567         if (w == p)
1568             return TRUE;
1569
1570     return FALSE;
1571 }
1572
1573 /* Return the child of 'p' which includes 'w'. */
1574 static WindowPtr
1575 _secVideoGetChild (WindowPtr p, WindowPtr w)
1576 {
1577     WindowPtr c;
1578
1579     for (c = w, w = w->parent; w; c = w, w = w->parent)
1580         if (w == p)
1581             return c;
1582
1583     return NULL;
1584 }
1585
1586 /* ancestor : Return the parent of 'a' and 'b'.
1587  * ancestor_a : Return the child of 'ancestor' which includes 'a'.
1588  * ancestor_b : Return the child of 'ancestor' which includes 'b'.
1589  */
1590 static Bool
1591 _secVideoGetAncestors (WindowPtr a, WindowPtr b,
1592                        WindowPtr *ancestor,
1593                        WindowPtr *ancestor_a,
1594                        WindowPtr *ancestor_b)
1595 {
1596     WindowPtr child_a, child_b;
1597
1598     if (!ancestor || !ancestor_a || !ancestor_b)
1599         return FALSE;
1600
1601     for (child_b = b, b = b->parent; b; child_b = b, b = b->parent)
1602     {
1603         child_a = _secVideoGetChild (b, a);
1604         if (child_a)
1605         {
1606             *ancestor   = b;
1607             *ancestor_a = child_a;
1608             *ancestor_b = child_b;
1609             return TRUE;
1610         }
1611     }
1612
1613     return FALSE;
1614 }
1615
1616 static int
1617 _secVideoCompareWindow (WindowPtr pWin1, WindowPtr pWin2)
1618 {
1619     WindowPtr a, a1, a2, c;
1620
1621     if (!pWin1 || !pWin2)
1622         return -2;
1623
1624     if (pWin1 == pWin2)
1625         return 0;
1626
1627     if (_secVideoGetChild (pWin1, pWin2))
1628         return -1;
1629
1630     if (_secVideoGetChild (pWin2, pWin1))
1631         return 1;
1632
1633     if (!_secVideoGetAncestors (pWin1, pWin2, &a, &a1, &a2))
1634         return -3;
1635
1636     for (c = a->firstChild; c; c = c->nextSib)
1637     {
1638         if (c == a1)
1639             return 1;
1640         else if (c == a2)
1641             return -1;
1642     }
1643
1644     return -4;
1645 }
1646
1647 static void
1648 _secVideoArrangeLayerPos (SECPortPrivPtr pPort, Bool by_notify)
1649 {
1650     SECPortPrivPtr pCur = NULL, pNext = NULL;
1651     SECPortPrivPtr pAnother = NULL;
1652     int i = 0;
1653
1654     xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
1655     {
1656         if (pCur == pPort)
1657             continue;
1658
1659         i++;
1660
1661         if (!pAnother)
1662             pAnother = pCur;
1663         else
1664             XDBG_WARNING (MVDO, "There are 3 more V4L2 ports. (%d) \n", i);
1665     }
1666
1667     if (!pAnother)
1668     {
1669         SECLayerPos lpos = secLayerGetPos (pPort->layer);
1670
1671         if (lpos == LAYER_NONE)
1672             secLayerSetPos (pPort->layer, LAYER_LOWER2);
1673     }
1674     else
1675     {
1676         SECLayerPos lpos1 = LAYER_NONE;
1677         SECLayerPos lpos2 = LAYER_NONE;
1678
1679         if (pAnother->layer)
1680             lpos1 = secLayerGetPos (pAnother->layer);
1681         if (pPort->layer)
1682             lpos2 = secLayerGetPos (pPort->layer);
1683
1684         if (lpos2 == LAYER_NONE)
1685         {
1686             int comp = _secVideoCompareWindow ((WindowPtr)pAnother->d.pDraw,
1687                                                (WindowPtr)pPort->d.pDraw);
1688
1689             XDBG_TRACE (MVDO, "0x%08x : 0x%08x => %d \n",
1690                         _XID(pAnother->d.pDraw), _XID(pPort->d.pDraw), comp);
1691
1692             if (comp == 1)
1693             {
1694                 if (lpos1 != LAYER_LOWER1)
1695                     secLayerSetPos (pAnother->layer, LAYER_LOWER1);
1696                 secLayerSetPos (pPort->layer, LAYER_LOWER2);
1697             }
1698             else if (comp == -1)
1699             {
1700                 if (lpos1 != LAYER_LOWER2)
1701                     secLayerSetPos (pAnother->layer, LAYER_LOWER2);
1702                 secLayerSetPos (pPort->layer, LAYER_LOWER1);
1703             }
1704             else
1705             {
1706                 if (lpos1 == LAYER_LOWER1)
1707                     secLayerSetPos (pPort->layer, LAYER_LOWER2);
1708                 else
1709                     secLayerSetPos (pPort->layer, LAYER_LOWER1);
1710             }
1711         }
1712         else
1713         {
1714             if (!by_notify)
1715                 return;
1716
1717             int comp = _secVideoCompareWindow ((WindowPtr)pAnother->d.pDraw,
1718                                                (WindowPtr)pPort->d.pDraw);
1719
1720             XDBG_TRACE (MVDO, "0x%08x : 0x%08x => %d \n",
1721                         _XID(pAnother->d.pDraw), _XID(pPort->d.pDraw), comp);
1722
1723             if ((comp == 1 && lpos1 != LAYER_LOWER1) ||
1724                 (comp == -1 && lpos2 != LAYER_LOWER1))
1725                 secLayerSwapPos (pAnother->layer, pPort->layer);
1726         }
1727     }
1728 }
1729
1730 static void
1731 _secVideoStopTvout (ScrnInfoPtr pScrn)
1732 {
1733     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
1734     XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0];
1735     int i;
1736
1737     for (i = 0; i < SEC_MAX_PORT; i++)
1738     {
1739         SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
1740
1741         if (pPort->grab_tvout)
1742         {
1743             _secVideoUngrabTvout (pPort);
1744             return;
1745         }
1746     }
1747 }
1748
1749 /* TRUE  : current frame will be shown on TV. free after vblank.
1750  * FALSE : current frame won't be shown on TV.
1751  */
1752 static Bool
1753 _secVideoPutImageTvout (SECPortPrivPtr pPort, int output, SECVideoBuf *inbuf)
1754 {
1755     ScrnInfoPtr pScrn = pPort->pScrn;
1756     SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
1757     xRectangle tv_rect = {0,};
1758     Bool first_put = FALSE;
1759
1760     if (!(output & OUTPUT_EXT))
1761     {
1762         XDBG_DEBUG(MTVO, "!(output (%d) & OUTPUT_EXT)\n", output);
1763         return FALSE;
1764     }
1765
1766     if (pPort->skip_tvout)
1767     {
1768         XDBG_DEBUG(MTVO, "pPort->skip_tvout (%d)\n", pPort->skip_tvout);
1769         return FALSE;
1770     }
1771
1772     if (!_secVideoGrabTvout(pPort))
1773         goto fail_to_put_tvout;
1774
1775     if (!pPort->tv)
1776     {
1777         SECCvt *tv_cvt;
1778         SECWb  *wb;
1779
1780         if (!secUtilEnsureExternalCrtc (pScrn))
1781         {
1782             XDBG_ERROR (MVDO, "failed : pPort(%d) connect external crtc\n", pPort->index);
1783             goto fail_to_put_tvout;
1784         }
1785
1786         pPort->tv = secVideoTvConnect (pScrn, pPort->d.id, LAYER_LOWER1);
1787         XDBG_GOTO_IF_FAIL (pPort->tv != NULL, fail_to_put_tvout);
1788
1789         wb = secWbGet ();
1790         if (wb)
1791         {
1792             pPort->need_start_wb = TRUE;
1793
1794             /* in case of VIRTUAL, wb's buffer is used by tvout. */
1795             if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
1796                 secWbStop (wb, FALSE);
1797             else
1798                 secWbStop (wb, TRUE);
1799         }
1800
1801         if (secWbIsRunning ())
1802         {
1803             XDBG_ERROR (MVDO, "failed: wb still running\n");
1804             goto fail_to_put_tvout;
1805         }
1806
1807         tv_cvt = secVideoTvGetConverter (pPort->tv);
1808
1809         if (tv_cvt == NULL)
1810         {
1811             if (!secVideoCanDirectDrawing (NULL, pPort->d.src.width, pPort->d.src.height,
1812                                            pPort->d.dst.width, pPort->d.dst.height))
1813             {
1814                 XDBG_GOTO_IF_FAIL (secVideoTvReCreateConverter (pPort->tv),
1815                                    fail_to_put_tvout);
1816             }
1817         }
1818         if (tv_cvt)
1819         {
1820             /* HDMI    : SN12
1821              * VIRTUAL : SN12 or RGB32
1822              */
1823             if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
1824             {
1825                 if (pSecMode->set_mode == DISPLAY_SET_MODE_CLONE)
1826                 {
1827                     SECVideoBuf **vbufs = NULL;
1828                     int bufnum = 0;
1829
1830                     secVideoTvSetConvertFormat (pPort->tv, FOURCC_SN12);
1831
1832                     /* In case of virtual, we draw video on full-size buffer
1833                      * for virtual-adaptor
1834                      */
1835                     secVideoTvSetSize (pPort->tv,
1836                                        pSecMode->ext_connector_mode.hdisplay,
1837                                        pSecMode->ext_connector_mode.vdisplay);
1838
1839                     secVirtualVideoGetBuffers (pPort->pScrn, FOURCC_SN12,
1840                                                pSecMode->ext_connector_mode.hdisplay,
1841                                                pSecMode->ext_connector_mode.vdisplay,
1842                                                &vbufs, &bufnum);
1843
1844                     XDBG_GOTO_IF_FAIL (vbufs != NULL, fail_to_put_tvout);
1845                     XDBG_GOTO_IF_FAIL (bufnum > 0, fail_to_put_tvout);
1846
1847                     secVideoTvSetBuffer (pPort->tv, vbufs, bufnum);
1848                 }
1849                 else /* desktop */
1850                     secVideoTvSetConvertFormat (pPort->tv, FOURCC_RGB32);
1851             }
1852             else
1853             {
1854 #if 0
1855                 secVideoTvSetConvertFormat (pPort->tv, FOURCC_SN12);
1856 #endif
1857             }
1858
1859             secCvtAddCallback (tv_cvt, _secVideoTvoutCvtCallback, pPort);
1860         }
1861         else
1862         {
1863             SECLayer *layer = secVideoTvGetLayer (pPort->tv);
1864             XDBG_GOTO_IF_FAIL (layer != NULL, fail_to_put_tvout);
1865
1866             secLayerEnableVBlank (layer, TRUE);
1867             secLayerAddNotifyFunc (layer, _secVideoLayerNotifyFunc, pPort);
1868         }
1869
1870         first_put = TRUE;
1871     }
1872
1873     SECPtr pSec = SECPTR (pPort->pScrn);
1874     if (pPort->wait_vbuf)
1875     {
1876         if (pSec->pVideoPriv->video_fps)
1877         {
1878             CARD32 cur, sub;
1879             cur = GetTimeInMillis ();
1880             sub = cur - pPort->tv_prev_time;
1881             pPort->tv_prev_time = cur;
1882
1883             XDBG_DEBUG (MVDO, "tvout skip : sub(%ld) vbuf(%ld:%d,%d,%d) \n",
1884                         sub, inbuf->stamp,
1885                         inbuf->keys[0], inbuf->keys[1], inbuf->keys[2]);
1886         }
1887         XDBG_DEBUG (MVDO, "pPort->wait_vbuf (%d) skip_frame\n", pPort->wait_vbuf);
1888         return FALSE;
1889     }
1890     else if (pSec->pVideoPriv->video_fps)
1891         pPort->tv_prev_time = GetTimeInMillis ();
1892
1893     if (!(output & OUTPUT_FULL))
1894     {
1895         SECDisplaySetMode disp_mode = secDisplayGetDispSetMode (pScrn);
1896         if (disp_mode == DISPLAY_SET_MODE_EXT)
1897             tv_rect.x = pPort->d.dst.x
1898                         - pSecMode->main_lcd_mode.hdisplay;
1899         else
1900             tv_rect.x = pPort->d.dst.x;
1901         tv_rect.y = pPort->d.dst.y;
1902         tv_rect.width = pPort->d.dst.width;
1903         tv_rect.height = pPort->d.dst.height;
1904     }
1905     else
1906     {
1907         secUtilAlignRect (pPort->d.src.width, pPort->d.src.height,
1908                           pSecMode->ext_connector_mode.hdisplay,
1909                           pSecMode->ext_connector_mode.vdisplay,
1910                           &tv_rect, TRUE);
1911     }
1912
1913     /* if secVideoTvPutImage returns FALSE, it means this frame won't show on TV. */
1914     if (!secVideoTvPutImage (pPort->tv, inbuf, &tv_rect, pPort->csc_range))
1915         return FALSE;
1916
1917     if (first_put && !(output & OUTPUT_LCD))
1918         _secVideoSetOutputExternalProperty (pPort->d.pDraw, TRUE);
1919
1920     pPort->wait_vbuf = inbuf;
1921
1922     return TRUE;
1923
1924 fail_to_put_tvout:
1925     _secVideoUngrabTvout (pPort);
1926
1927     pPort->skip_tvout = TRUE;
1928
1929     XDBG_TRACE (MVDO, "pPort(%d) skip tvout \n", pPort->index);
1930
1931     return FALSE;
1932 }
1933
1934 static Bool
1935 _secVideoPutImageInbuf (SECPortPrivPtr pPort, SECVideoBuf *inbuf)
1936 {
1937     if (!pPort->layer)
1938     {
1939         pPort->layer = _secVideoCreateLayer (pPort);
1940         XDBG_RETURN_VAL_IF_FAIL (pPort->layer != NULL, FALSE);
1941
1942         _secVideoArrangeLayerPos (pPort, FALSE);
1943     }
1944
1945     secLayerSetBuffer (pPort->layer, inbuf);
1946
1947     if (!secLayerIsVisible (pPort->layer))
1948         secLayerShow (pPort->layer);
1949
1950     return TRUE;
1951 }
1952
1953 static Bool
1954 _secVideoPutImageInternal (SECPortPrivPtr pPort, SECVideoBuf *inbuf)
1955 {
1956     SECPtr pSec = (SECPtr) pPort->pScrn->driverPrivate;
1957     SECCvtProp src_prop = {0,}, dst_prop = {0,};
1958     SECVideoBuf *outbuf = NULL;
1959
1960     outbuf = _secVideoGetOutbuf (pPort);
1961     if (!outbuf)
1962         return FALSE;
1963
1964     /* cacheflush here becasue dst buffer can be created in _secVideoGetOutbuf() */
1965     if (pPort->stream_cnt == 1)
1966         if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
1967             secUtilCacheFlush (pPort->pScrn);
1968
1969     XDBG_DEBUG (MVDO, "'%c%c%c%c' preem(%d) rot(%d) \n",
1970                 FOURCC_STR (pPort->d.id),
1971                 pPort->preemption, pPort->hw_rotate);
1972
1973     if (pPort->layer)
1974         _secVideoArrangeLayerPos (pPort, FALSE);
1975
1976     _secVideoEnsureConverter (pPort);
1977     XDBG_GOTO_IF_FAIL (pPort->cvt != NULL, fail_to_put);
1978
1979     src_prop.id = pPort->d.id;
1980     src_prop.width = pPort->in_width;
1981     src_prop.height = pPort->in_height;
1982     src_prop.crop = pPort->in_crop;
1983
1984     dst_prop.id = FOURCC_RGB32;
1985     dst_prop.width = pPort->out_width;
1986     dst_prop.height = pPort->out_height;
1987     dst_prop.crop = pPort->out_crop;
1988
1989     dst_prop.degree = pPort->hw_rotate;
1990     dst_prop.hflip = pPort->hflip;
1991     dst_prop.vflip = pPort->vflip;
1992     dst_prop.secure = pPort->secure;
1993     dst_prop.csc_range = pPort->csc_range;
1994
1995     if (!secCvtEnsureSize (&src_prop, &dst_prop))
1996         goto fail_to_put;
1997
1998     if (!secCvtSetProperpty (pPort->cvt, &src_prop, &dst_prop))
1999         goto fail_to_put;
2000
2001     if (!secCvtConvert (pPort->cvt, inbuf, outbuf))
2002         goto fail_to_put;
2003
2004     if (pSec->pVideoPriv->video_fps)
2005         _countFps (pPort);
2006
2007     secUtilVideoBufferUnref (outbuf);
2008
2009     return TRUE;
2010
2011 fail_to_put:
2012     if (outbuf)
2013         secUtilVideoBufferUnref (outbuf);
2014
2015     _secVideoCloseConverter (pPort);
2016     _secVideoCloseOutBuffer (pPort, TRUE);
2017
2018     return FALSE;
2019 }
2020
2021 static Bool
2022 _secVideoSetHWPortsProperty (ScreenPtr pScreen, int nums)
2023 {
2024     WindowPtr pWin = pScreen->root;
2025     Atom atom_hw_ports;
2026
2027     /* With "X_HW_PORTS", an application can know
2028      * how many fimc devices XV uses.
2029      */
2030     if (!pWin || !serverClient)
2031         return FALSE;
2032
2033     atom_hw_ports = MakeAtom ("XV_HW_PORTS", strlen ("XV_HW_PORTS"), TRUE);
2034
2035     dixChangeWindowProperty (serverClient,
2036                              pWin, atom_hw_ports, XA_CARDINAL, 32,
2037                              PropModeReplace, 1, (unsigned int*)&nums, FALSE);
2038
2039     return TRUE;
2040 }
2041
2042 static Bool
2043 _secVideoSetOutputExternalProperty (DrawablePtr pDraw, Bool video_only)
2044 {
2045     WindowPtr pWin;
2046     Atom atom_external;
2047
2048     XDBG_RETURN_VAL_IF_FAIL (pDraw != NULL, FALSE);
2049     XDBG_RETURN_VAL_IF_FAIL (pDraw->type == DRAWABLE_WINDOW, FALSE);
2050
2051     pWin = (WindowPtr)pDraw;
2052
2053     atom_external = MakeAtom ("XV_OUTPUT_EXTERNAL", strlen ("XV_OUTPUT_EXTERNAL"), TRUE);
2054
2055     dixChangeWindowProperty (clients[CLIENT_ID(pDraw->id)],
2056                              pWin, atom_external, XA_CARDINAL, 32,
2057                              PropModeReplace, 1, (unsigned int*)&video_only, TRUE);
2058
2059     XDBG_TRACE (MVDO, "pDraw(0x%08x) video-only(%s)\n",
2060                 pDraw->id, (video_only)?"ON":"OFF");
2061
2062     return TRUE;
2063 }
2064
2065 static void
2066 _secVideoRestackWindow (WindowPtr pWin, WindowPtr pOldNextSib)
2067 {
2068     ScreenPtr pScreen = ((DrawablePtr)pWin)->pScreen;
2069     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2070     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
2071     SECVideoPrivPtr pVideo = pSec->pVideoPriv;
2072
2073     if (pVideo->RestackWindow)
2074     {
2075         pScreen->RestackWindow = pVideo->RestackWindow;
2076
2077         if (pScreen->RestackWindow)
2078             (*pScreen->RestackWindow)(pWin, pOldNextSib);
2079
2080         pVideo->RestackWindow = pScreen->RestackWindow;
2081         pScreen->RestackWindow = _secVideoRestackWindow;
2082     }
2083
2084     if (!xorg_list_is_empty (&layer_owners))
2085     {
2086         SECPortPrivPtr pCur = NULL, pNext = NULL;
2087         xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
2088         {
2089             if (_secVideoInBranch (pWin, (WindowPtr)pCur->d.pDraw))
2090             {
2091                 XDBG_TRACE (MVDO, "Do re-arrange. 0x%08x(0x%08x) \n",
2092                             _XID(pWin), _XID(pCur->d.pDraw));
2093                 _secVideoArrangeLayerPos (pCur, TRUE);
2094                 break;
2095             }
2096         }
2097     }
2098 }
2099
2100 static void
2101 _secVideoBlockHandler (pointer data, OSTimePtr pTimeout, pointer pRead)
2102 {
2103     ScreenPtr pScreen = ((ScrnInfoPtr)data)->pScreen;
2104     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2105     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
2106     SECVideoPrivPtr pVideo = pSec->pVideoPriv;
2107
2108     pVideo->RestackWindow = pScreen->RestackWindow;
2109     pScreen->RestackWindow = _secVideoRestackWindow;
2110
2111     if(registered_handler && _secVideoSetHWPortsProperty (pScreen, NUM_HW_LAYER))
2112     {
2113         RemoveBlockAndWakeupHandlers(_secVideoBlockHandler,
2114                                      (WakeupHandlerProcPtr)NoopDDA, data);
2115         registered_handler = FALSE;
2116     }
2117 }
2118
2119 static Bool
2120 _secVideoAddDrawableEvent (SECPortPrivPtr pPort)
2121 {
2122     SECVideoResource *resource;
2123     void *ptr=NULL;
2124     int ret;
2125
2126     ret = dixLookupResourceByType (&ptr, pPort->d.pDraw->id,
2127                              event_drawable_type, NULL, DixWriteAccess);
2128     if (ret == Success)
2129     {
2130         return TRUE;
2131     }
2132
2133     resource = malloc (sizeof (SECVideoResource));
2134     if (resource == NULL)
2135         return FALSE;
2136
2137     if (!AddResource (pPort->d.pDraw->id, event_drawable_type, resource))
2138     {
2139         free (resource);
2140         return FALSE;
2141     }
2142
2143     XDBG_TRACE (MVDO, "id(0x%08lx). \n", pPort->d.pDraw->id);
2144
2145     resource->id = pPort->d.pDraw->id;
2146     resource->type = event_drawable_type;
2147     resource->pPort = pPort;
2148     resource->pScrn = pPort->pScrn;
2149
2150     return TRUE;
2151 }
2152
2153 static int
2154 _secVideoRegisterEventDrawableGone (void *data, XID id)
2155 {
2156     SECVideoResource *resource = (SECVideoResource*)data;
2157
2158     XDBG_TRACE (MVDO, "id(0x%08lx). \n", id);
2159
2160     if (!resource)
2161         return Success;
2162
2163     if (!resource->pPort || !resource->pScrn)
2164         return Success;
2165
2166     SECVideoStop (resource->pScrn, (pointer)resource->pPort, 1);
2167
2168     free(resource);
2169
2170     return Success;
2171 }
2172
2173 static Bool
2174 _secVideoRegisterEventResourceTypes (void)
2175 {
2176     event_drawable_type = CreateNewResourceType (_secVideoRegisterEventDrawableGone, "Sec Video Drawable");
2177
2178     if (!event_drawable_type)
2179         return FALSE;
2180
2181     return TRUE;
2182 }
2183
2184 int
2185 secVideoQueryImageAttrs (ScrnInfoPtr  pScrn,
2186                          int          id,
2187                          int         *w,
2188                          int         *h,
2189                          int         *pitches,
2190                          int         *offsets,
2191                          int         *lengths)
2192 {
2193     int size = 0, tmp = 0;
2194
2195     *w = (*w + 1) & ~1;
2196     if (offsets)
2197         offsets[0] = 0;
2198
2199     switch (id)
2200     {
2201     /* RGB565 */
2202     case FOURCC_SR16:
2203     case FOURCC_RGB565:
2204         size += (*w << 1);
2205         if (pitches)
2206             pitches[0] = size;
2207         size *= *h;
2208         if (lengths)
2209             lengths[0] = size;
2210         break;
2211     /* RGB32 */
2212     case FOURCC_SR32:
2213     case FOURCC_RGB32:
2214         size += (*w << 2);
2215         if (pitches)
2216             pitches[0] = size;
2217         size *= *h;
2218         if (lengths)
2219             lengths[0] = size;
2220         break;
2221     /* YUV420, 3 planar */
2222     case FOURCC_I420:
2223     case FOURCC_S420:
2224     case FOURCC_YV12:
2225         *h = (*h + 1) & ~1;
2226         size = (*w + 3) & ~3;
2227         if (pitches)
2228             pitches[0] = size;
2229
2230         size *= *h;
2231         if (offsets)
2232             offsets[1] = size;
2233         if (lengths)
2234             lengths[0] = size;
2235
2236         tmp = ((*w >> 1) + 3) & ~3;
2237         if (pitches)
2238             pitches[1] = pitches[2] = tmp;
2239
2240         tmp *= (*h >> 1);
2241         size += tmp;
2242         if (offsets)
2243             offsets[2] = size;
2244         if (lengths)
2245             lengths[1] = tmp;
2246
2247         size += tmp;
2248         if (lengths)
2249             lengths[2] = tmp;
2250
2251         break;
2252     /* YUV422, packed */
2253     case FOURCC_UYVY:
2254     case FOURCC_SYVY:
2255     case FOURCC_ITLV:
2256     case FOURCC_SUYV:
2257     case FOURCC_YUY2:
2258         size = *w << 1;
2259         if (pitches)
2260             pitches[0] = size;
2261
2262         size *= *h;
2263         if (lengths)
2264             lengths[0] = size;
2265         break;
2266
2267     /* YUV420, 2 planar */
2268     case FOURCC_SN12:
2269     case FOURCC_NV12:
2270     case FOURCC_SN21:
2271     case FOURCC_NV21:
2272         if (pitches)
2273             pitches[0] = *w;
2274
2275         size = (*w) * (*h);
2276         if (offsets)
2277             offsets[1] = size;
2278         if (lengths)
2279             lengths[0] = size;
2280
2281         if (pitches)
2282             pitches[1] = *w;
2283
2284         tmp = (*w) * (*h >> 1);
2285         size += tmp;
2286         if (lengths)
2287             lengths[1] = tmp;
2288         break;
2289
2290     /* YUV420, 2 planar, tiled */
2291     case FOURCC_ST12:
2292         if (pitches)
2293             pitches[0] = *w;
2294
2295         size = ALIGN_TO_8KB(ALIGN_TO_128B(*w) * ALIGN_TO_32B(*h));
2296         if (offsets)
2297             offsets[1] = size;
2298         if (lengths)
2299             lengths[0] = size;
2300
2301         if (pitches)
2302             pitches[1] = *w;
2303
2304         tmp = ALIGN_TO_8KB(ALIGN_TO_128B(*w) * ALIGN_TO_32B(*h >> 1));
2305         size += tmp;
2306         if (lengths)
2307             lengths[1] = tmp;
2308         break;
2309     default:
2310         return 0;
2311     }
2312
2313     return size;
2314 }
2315
2316 static int
2317 SECVideoGetPortAttribute (ScrnInfoPtr pScrn,
2318                           Atom        attribute,
2319                           INT32      *value,
2320                           pointer     data)
2321 {
2322     SECPortPrivPtr pPort = (SECPortPrivPtr) data;
2323
2324     if (attribute == _portAtom (PAA_ROTATION))
2325     {
2326         *value = pPort->rotate;
2327         return Success;
2328     }
2329     else if (attribute == _portAtom (PAA_HFLIP))
2330     {
2331         *value = pPort->hflip;
2332         return Success;
2333     }
2334     else if (attribute == _portAtom (PAA_VFLIP))
2335     {
2336         *value = pPort->vflip;
2337         return Success;
2338     }
2339     else if (attribute == _portAtom (PAA_PREEMPTION))
2340     {
2341         *value = pPort->preemption;
2342         return Success;
2343     }
2344     else if (attribute == _portAtom (PAA_OUTPUT))
2345     {
2346         *value = pPort->usr_output;
2347         return Success;
2348     }
2349     else if (attribute == _portAtom (PAA_SECURE))
2350     {
2351         *value = pPort->secure;
2352         return Success;
2353     }
2354     else if (attribute == _portAtom (PAA_CSC_RANGE))
2355     {
2356         *value = pPort->csc_range;
2357         return Success;
2358     }
2359
2360     return BadMatch;
2361 }
2362
2363 static int
2364 SECVideoSetPortAttribute (ScrnInfoPtr pScrn,
2365                           Atom        attribute,
2366                           INT32       value,
2367                           pointer     data)
2368 {
2369     SECPortPrivPtr pPort = (SECPortPrivPtr) data;
2370
2371     if (attribute == _portAtom (PAA_ROTATION))
2372     {
2373         pPort->rotate = value;
2374         XDBG_DEBUG (MVDO, "rotate(%d) \n", value);
2375         return Success;
2376     }
2377     else if (attribute == _portAtom (PAA_HFLIP))
2378     {
2379         pPort->hflip = value;
2380         XDBG_DEBUG (MVDO, "hflip(%d) \n", value);
2381         return Success;
2382     }
2383     else if (attribute == _portAtom (PAA_VFLIP))
2384     {
2385         pPort->vflip = value;
2386         XDBG_DEBUG (MVDO, "vflip(%d) \n", value);
2387         return Success;
2388     }
2389     else if (attribute == _portAtom (PAA_PREEMPTION))
2390     {
2391         pPort->preemption = value;
2392         XDBG_DEBUG (MVDO, "preemption(%d) \n", value);
2393         return Success;
2394     }
2395     else if (attribute == _portAtom (PAA_OUTPUT))
2396     {
2397         if (value == OUTPUT_MODE_TVOUT)
2398             pPort->usr_output = OUTPUT_LCD|OUTPUT_EXT|OUTPUT_FULL;
2399         else if (value == OUTPUT_MODE_EXT_ONLY)
2400             pPort->usr_output = OUTPUT_EXT|OUTPUT_FULL;
2401         else
2402             pPort->usr_output = OUTPUT_LCD|OUTPUT_EXT;
2403
2404         XDBG_DEBUG (MVDO, "output (%d) \n", value);
2405
2406         return Success;
2407     }
2408     else if (attribute == _portAtom (PAA_SECURE))
2409     {
2410         pPort->secure = value;
2411         XDBG_DEBUG (MVDO, "secure(%d) \n", value);
2412         return Success;
2413     }
2414     else if (attribute == _portAtom (PAA_CSC_RANGE))
2415     {
2416         pPort->csc_range = value;
2417         XDBG_DEBUG (MVDO, "csc_range(%d) \n", value);
2418         return Success;
2419     }
2420
2421     return Success;
2422 }
2423
2424 static void
2425 SECVideoQueryBestSize (ScrnInfoPtr pScrn,
2426                        Bool motion,
2427                        short vid_w, short vid_h,
2428                        short dst_w, short dst_h,
2429                        uint *p_w, uint *p_h,
2430                        pointer data)
2431 {
2432     SECCvtProp prop = {0,};
2433
2434     if (!p_w && !p_h)
2435         return;
2436
2437     prop.width = dst_w;
2438     prop.height = dst_h;
2439     prop.crop.width = dst_w;
2440     prop.crop.height = dst_h;
2441
2442     if (secCvtEnsureSize (NULL, &prop))
2443     {
2444         if (p_w)
2445             *p_w = prop.width;
2446         if (p_h)
2447             *p_h = prop.height;
2448     }
2449     else
2450     {
2451         if (p_w)
2452             *p_w = dst_w;
2453         if (p_h)
2454             *p_h = dst_h;
2455     }
2456 }
2457
2458 /**
2459  * Give image size and pitches.
2460  */
2461 static int
2462 SECVideoQueryImageAttributes (ScrnInfoPtr    pScrn,
2463                               int            id,
2464                               unsigned short *w,
2465                               unsigned short *h,
2466                               int            *pitches,
2467                               int            *offsets)
2468 {
2469     int width, height, size;
2470
2471     if (!w || !h)
2472         return 0;
2473
2474     width = (int)*w;
2475     height = (int)*h;
2476
2477     size = secVideoQueryImageAttrs (pScrn, id, &width, &height, pitches, offsets, NULL);
2478
2479     *w = (unsigned short)width;
2480     *h = (unsigned short)height;
2481
2482     return size;
2483 }
2484
2485 /* coordinates : HW, SCREEN, PORT
2486  * BadRequest : when video can't be shown or drawn.
2487  * Success    : A damage event(pixmap) and inbuf should be return.
2488  *              If can't return a damage event and inbuf, should be return
2489  *              BadRequest.
2490  */
2491 static int
2492 SECVideoPutImage (ScrnInfoPtr pScrn,
2493                   short src_x, short src_y, short dst_x, short dst_y,
2494                   short src_w, short src_h, short dst_w, short dst_h,
2495                   int id, uchar *buf, short width, short height,
2496                   Bool sync, RegionPtr clip_boxes, pointer data,
2497                   DrawablePtr pDraw)
2498 {
2499     SECPtr pSec = SECPTR (pScrn);
2500 #ifdef NO_CRTC_MODE
2501     if (pSec->isCrtcOn == FALSE)
2502     {
2503         XDBG_WARNING (MVDO, "XV PutImage Disabled (No active CRTCs)\n");
2504         return BadRequest;
2505     }
2506 #endif
2507     SECModePtr pSecMode = (SECModePtr)SECPTR (pScrn)->pSecMode;
2508     SECVideoPrivPtr pVideo = SECPTR (pScrn)->pVideoPriv;
2509     SECPortPrivPtr pPort = (SECPortPrivPtr) data;
2510     int output, ret;
2511     Bool tvout = FALSE, lcdout = FALSE;
2512     SECVideoBuf *inbuf = NULL;
2513     int old_drawing;
2514
2515     if (!_secVideoSupportID (id))
2516     {
2517         XDBG_ERROR (MVDO, "'%c%c%c%c' not supported.\n", FOURCC_STR (id));
2518         return BadRequest;
2519     }
2520
2521     XDBG_TRACE (MVDO, "======================================= \n");
2522     XDBG_DEBUG(MVDO, "src:(x%d,y%d w%d-h%d), dst:(x%d,y%d w%d-h%d)\n",
2523                src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
2524     XDBG_DEBUG(MVDO, "image size:(w%d-h%d) fourcc(%c%c%c%c)\n", width, height, FOURCC_STR(id));
2525     pPort->pScrn = pScrn;
2526     pPort->d.id = id;
2527     pPort->d.buf = buf;
2528
2529     if (pSec->xvperf_mode & XBERC_XVPERF_MODE_IA)
2530     {
2531         unsigned int keys[PLANAR_CNT] = {0,};
2532         CARD32 cur, sub;
2533         char temp[64];
2534         cur = GetTimeInMillis ();
2535         sub = cur - pPort->prev_time;
2536         pPort->prev_time = cur;
2537         temp[0] = '\0';
2538         if (IS_ZEROCOPY (id))
2539         {
2540             _secVideoGetKeys (pPort, keys, NULL);
2541             snprintf (temp, sizeof(temp), "%d,%d,%d", keys[0], keys[1], keys[2]);
2542         }
2543         ErrorF ("pPort(%p) put interval(%s) : %6ld ms\n", pPort, temp, sub);
2544     }
2545
2546     if (IS_ZEROCOPY (pPort->d.id))
2547     {
2548         unsigned int keys[PLANAR_CNT] = {0,};
2549         int i;
2550
2551         if (_secVideoGetKeys (pPort, keys, NULL))
2552             return BadRequest;
2553
2554         for (i = 0; i < INBUF_NUM; i++)
2555             if (pPort->inbuf[i] && pPort->inbuf[i]->keys[0] == keys[0])
2556             {
2557                 XDBG_WARNING (MVDO, "got flink_id(%d) twice!\n", keys[0]);
2558                 _secVideoSendReturnBufferMessage (pPort, NULL, keys);
2559                 return Success;
2560             }
2561     }
2562
2563     pPort->d.width = width;
2564     pPort->d.height = height;
2565     pPort->d.src.x = src_x;
2566     pPort->d.src.y = src_y;
2567     pPort->d.src.width = src_w;
2568     pPort->d.src.height = src_h;
2569     pPort->d.dst.x = dst_x;    /* included pDraw'x */
2570     pPort->d.dst.y = dst_y;    /* included pDraw'y */
2571     pPort->d.dst.width = dst_w;
2572     pPort->d.dst.height = dst_h;
2573     pPort->d.sync = FALSE;
2574     if (sync)
2575         XDBG_WARNING (MVDO, "not support sync.\n");
2576     pPort->d.data = data;
2577     pPort->d.pDraw = pDraw;
2578     if (clip_boxes)
2579     {
2580         if (!pPort->d.clip_boxes)
2581             pPort->d.clip_boxes = RegionCreate(NullBox, 0);
2582         RegionCopy (pPort->d.clip_boxes, clip_boxes);
2583     }
2584
2585     old_drawing = pPort->drawing;
2586     pPort->drawing = _secVideodrawingOn (pPort);
2587     if (pDraw)
2588     {
2589         XDBG_DEBUG(MVDO, "pixmap:(x%d,y%d w%d-h%d) on:%d\n",
2590                    pDraw->x, pDraw->y, pDraw->width, pDraw->height, pPort->drawing);
2591     }
2592     if (old_drawing != pPort->drawing)
2593     {
2594         _secVideoCloseConverter (pPort);
2595         _secVideoCloseOutBuffer (pPort, TRUE);
2596
2597     }
2598
2599     _secVideoGetRotation (pPort, &pPort->hw_rotate);
2600
2601     if (pPort->drawing == ON_FB && pVideo->screen_rotate_degree > 0)
2602         secUtilRotateRect (pSecMode->main_lcd_mode.hdisplay,
2603                            pSecMode->main_lcd_mode.vdisplay,
2604                            &pPort->d.dst,
2605                            pVideo->screen_rotate_degree);
2606
2607     if (pPort->secure)
2608         if (pPort->drawing != ON_FB)
2609         {
2610             XDBG_ERROR (MVDO, "secure video should drawn on FB.\n");
2611             return BadRequest;
2612         }
2613
2614     if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
2615         if (!_secVideoAddDrawableEvent (pPort))
2616             return BadRequest;
2617
2618     if (pPort->stream_cnt == 0)
2619     {
2620         pPort->stream_cnt++;
2621
2622         if (pPort->preemption > -1)
2623             streaming_ports++;
2624
2625         XDBG_SECURE (MVDO, "pPort(%d) streams(%d) rotate(%d) flip(%d,%d) secure(%d) range(%d) usr_output(%x) on(%s)\n",
2626                      pPort->index, streaming_ports,
2627                      pPort->rotate, pPort->hflip, pPort->vflip, pPort->secure, pPort->csc_range,
2628                      pPort->usr_output, drawing_type[pPort->drawing]);
2629         XDBG_SECURE (MVDO, "id(%c%c%c%c) sz(%dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d)\n",
2630                      FOURCC_STR (id), width, height,
2631                      src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
2632
2633         if (streaming_ports > 1)
2634             _secVideoStopTvout (pPort->pScrn);
2635     }
2636     else if (pPort->stream_cnt == 1)
2637         pPort->stream_cnt++;
2638
2639     if (pPort->cvt)
2640     {
2641         SECCvtProp dst_prop;
2642
2643         secCvtGetProperpty (pPort->cvt, NULL, &dst_prop);
2644
2645         if (pPort->d.id != pPort->old_d.id ||
2646             pPort->d.width != pPort->old_d.width ||
2647             pPort->d.height != pPort->old_d.height ||
2648             memcmp (&pPort->d.src, &pPort->old_d.src, sizeof (xRectangle)) ||
2649             dst_prop.degree != pPort->hw_rotate ||
2650             dst_prop.hflip != pPort->hflip ||
2651             dst_prop.vflip != pPort->vflip ||
2652             dst_prop.secure != pPort->secure ||
2653             dst_prop.csc_range != pPort->csc_range)
2654         {
2655             XDBG_DEBUG (MVDO, "pPort(%d) streams(%d) rotate(%d) flip(%d,%d) secure(%d) range(%d) usr_output(%x) on(%s)\n",
2656                         pPort->index, streaming_ports,
2657                         pPort->rotate, pPort->hflip, pPort->vflip, pPort->secure, pPort->csc_range,
2658                         pPort->usr_output, drawing_type[pPort->drawing]);
2659             XDBG_DEBUG (MVDO, "pPort(%d) old_src(%dx%d %d,%d %dx%d) : new_src(%dx%d %d,%d %dx%d)\n",
2660                         pPort->index, pPort->old_d.width, pPort->old_d.height,
2661                         pPort->old_d.src.x, pPort->old_d.src.y,
2662                         pPort->old_d.src.width, pPort->old_d.src.height,
2663                         pPort->d.width, pPort->d.height,
2664                         pPort->d.src.x, pPort->d.src.y,
2665                         pPort->d.src.width, pPort->d.src.height);
2666             _secVideoCloseConverter (pPort);
2667             _secVideoCloseInBuffer (pPort);
2668             pPort->inbuf_is_fb = FALSE;
2669         }
2670     }
2671
2672     if (memcmp (&pPort->d.dst, &pPort->old_d.dst, sizeof (xRectangle)))
2673     {
2674         XDBG_DEBUG (MVDO, "pPort(%d) old_dst(%d,%d %dx%d) : new_dst(%dx%d %dx%d)\n",
2675                     pPort->index,
2676                     pPort->old_d.dst.x, pPort->old_d.dst.y,
2677                     pPort->old_d.dst.width, pPort->old_d.dst.height,
2678                     pPort->d.dst.x, pPort->d.dst.y,
2679                     pPort->d.dst.width, pPort->d.dst.height);
2680         _secVideoCloseConverter (pPort);
2681         _secVideoCloseOutBuffer (pPort, FALSE);
2682         pPort->inbuf_is_fb = FALSE;
2683     }
2684
2685     if (pPort->tv)
2686     {
2687         SECCvt *tv_cvt = secVideoTvGetConverter (pPort->tv);
2688         if (pPort->d.id != pPort->old_d.id ||
2689             pPort->d.width != pPort->old_d.width ||
2690             pPort->d.height != pPort->old_d.height ||
2691             memcmp (&pPort->d.src, &pPort->old_d.src, sizeof (xRectangle)))
2692         {
2693             _secVideoCloseInBuffer (pPort);
2694             pPort->inbuf_is_fb = FALSE;
2695         }
2696         else if (tv_cvt != NULL)
2697         {
2698             SECCvtProp dst_prop;
2699             secCvtGetProperpty (tv_cvt, NULL, &dst_prop);
2700
2701             if (dst_prop.degree != pPort->hw_rotate ||
2702                 dst_prop.hflip != pPort->hflip ||
2703                 dst_prop.vflip != pPort->vflip ||
2704                 dst_prop.secure != pPort->secure ||
2705                 dst_prop.csc_range != pPort->csc_range)
2706             {
2707                 _secVideoCloseInBuffer (pPort);
2708                 pPort->inbuf_is_fb = FALSE;
2709             }
2710         }
2711
2712         if (pPort->tv && memcmp (&pPort->d.dst, &pPort->old_d.dst, sizeof (xRectangle)))
2713         {
2714             if (secVideoTvResizeOutput (pPort->tv, &pPort->d.src, &pPort->d.dst) == TRUE)
2715             {
2716                 SECCvt *tv_cvt = secVideoTvGetConverter (pPort->tv);
2717                 if (tv_cvt != NULL)
2718                 {
2719                     secCvtAddCallback (tv_cvt, _secVideoTvoutCvtCallback, pPort);
2720                 }
2721             }
2722             else
2723             {
2724                 secVideoTvDisconnect (pPort->tv);
2725                 pPort->tv = NULL;
2726             }
2727             pPort->punched = FALSE;
2728             pPort->wait_vbuf = NULL;
2729         }
2730     }
2731
2732     if (!_secVideoCalculateSize (pPort))
2733         return BadRequest;
2734
2735     output = _secVideoGetTvoutMode (pPort);
2736     if (!(output & OUTPUT_LCD) && pPort->old_output & OUTPUT_LCD)
2737     {
2738         /* If the video of LCD becomes off, we also turn off LCD layer. */
2739         if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
2740         {
2741             PixmapPtr pPixmap = _getPixmap (pPort->d.pDraw);
2742             SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPixmap);
2743
2744             secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
2745             if (pPixmap->devPrivate.ptr && privPixmap->size > 0)
2746                 memset (pPixmap->devPrivate.ptr, 0, privPixmap->size);
2747             secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
2748
2749             DamageDamageRegion (pPort->d.pDraw, pPort->d.clip_boxes);
2750         }
2751         else
2752         {
2753             _secVideoCloseConverter (pPort);
2754             _secVideoCloseOutBuffer (pPort, TRUE);
2755         }
2756     }
2757
2758     if (pPort->d.id == FOURCC_SR32 &&
2759         pPort->in_crop.width == pPort->out_crop.width &&
2760         pPort->in_crop.height == pPort->out_crop.height &&
2761         pPort->hw_rotate == 0)
2762         pPort->inbuf_is_fb = TRUE;
2763     else
2764         pPort->inbuf_is_fb = FALSE;
2765
2766     inbuf = _secVideoGetInbuf (pPort);
2767     if (!inbuf)
2768         return BadRequest;
2769
2770     /* punch here not only LCD but also HDMI. */
2771     if (pPort->drawing == ON_FB)
2772         _secVideoPunchDrawable (pPort);
2773
2774     /* HDMI */
2775     if (output & OUTPUT_EXT)
2776         tvout = _secVideoPutImageTvout (pPort, output, inbuf);
2777     else
2778     {
2779         _secVideoUngrabTvout (pPort);
2780
2781         SECWb *wb = secWbGet ();
2782         if (wb)
2783             secWbSetSecure (wb, pPort->secure);
2784     }
2785
2786     /* LCD */
2787     if (output & OUTPUT_LCD)
2788     {
2789         SECPtr pSec = SECPTR (pScrn);
2790
2791         if (pSec->isLcdOff)
2792             XDBG_TRACE (MVDO, "port(%d) put image after dpms off.\n", pPort->index);
2793         else if (pPort->inbuf_is_fb)
2794             lcdout = _secVideoPutImageInbuf (pPort, inbuf);
2795         else
2796             lcdout = _secVideoPutImageInternal (pPort, inbuf);
2797     }
2798
2799     if (lcdout || tvout)
2800     {
2801         ret = Success;
2802     }
2803     else
2804     {
2805         if (IS_ZEROCOPY (pPort->d.id))
2806         {
2807             int i;
2808
2809             for (i = 0; i < INBUF_NUM; i++)
2810                 if (pPort->inbuf[i] == inbuf)
2811                 {
2812                     pPort->inbuf[i] = NULL;
2813                     secUtilRemoveFreeVideoBufferFunc (inbuf, _secVideoFreeInbuf, pPort);
2814                     break;
2815                 }
2816             XDBG_WARNING_IF_FAIL (inbuf->ref_cnt == 1);
2817         }
2818         else
2819             XDBG_WARNING_IF_FAIL (inbuf->ref_cnt == 2);
2820
2821         ret = BadRequest;
2822     }
2823
2824     /* decrease ref_cnt here to pass ownership of inbuf to converter or tvout.
2825      * in case of zero-copy, it will be really freed
2826      * when converting is finished or tvout is finished.
2827      */
2828     secUtilVideoBufferUnref (inbuf);
2829
2830     pPort->old_d = pPort->d;
2831     pPort->old_output = output;
2832
2833     XDBG_TRACE (MVDO, "=======================================.. \n");
2834
2835     return ret;
2836 }
2837
2838 static int
2839 SECVideoDDPutImage (ClientPtr client,
2840                DrawablePtr pDraw,
2841                XvPortPtr pPort,
2842                GCPtr pGC,
2843                INT16 src_x, INT16 src_y,
2844                CARD16 src_w, CARD16 src_h,
2845                INT16 drw_x, INT16 drw_y,
2846                CARD16 drw_w, CARD16 drw_h,
2847                XvImagePtr format,
2848                unsigned char *data, Bool sync, CARD16 width, CARD16 height)
2849 {
2850     SECVideoPortInfo *info = _port_info (pDraw);
2851     int ret;
2852
2853     if (info)
2854     {
2855         info->client = client;
2856         info->pp = pPort;
2857     }
2858
2859     ret = ddPutImage (client, pDraw, pPort, pGC,
2860                       src_x, src_y, src_w, src_h,
2861                       drw_x, drw_y, drw_w, drw_h,
2862                       format, data, sync, width, height);
2863
2864     return ret;
2865 }
2866
2867 static void
2868 SECVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit)
2869 {
2870     SECPortPrivPtr pPort = (SECPortPrivPtr) data;
2871
2872     if (!exit)
2873         return;
2874
2875     XDBG_DEBUG (MVDO, "exit (%d) \n", exit);
2876
2877     _secVideoStreamOff (pPort);
2878
2879     pPort->preemption = 0;
2880     pPort->rotate = 0;
2881     pPort->hflip = 0;
2882     pPort->vflip = 0;
2883     pPort->punched = FALSE;
2884 }
2885
2886 /**
2887  * Set up all our internal structures.
2888  */
2889 static XF86VideoAdaptorPtr
2890 secVideoSetupImageVideo (ScreenPtr pScreen)
2891 {
2892     XF86VideoAdaptorPtr pAdaptor;
2893     SECPortPrivPtr pPort;
2894     int i;
2895
2896     pAdaptor = calloc (1, sizeof (XF86VideoAdaptorRec) +
2897                        (sizeof (DevUnion) + sizeof (SECPortPriv)) * SEC_MAX_PORT);
2898     if (!pAdaptor)
2899         return NULL;
2900
2901     dummy_encoding[0].width = pScreen->width;
2902     dummy_encoding[0].height = pScreen->height;
2903
2904     pAdaptor->type = XvWindowMask | XvPixmapMask | XvInputMask | XvImageMask;
2905     pAdaptor->flags = VIDEO_OVERLAID_IMAGES;
2906     pAdaptor->name = "SEC supporting Software Video Conversions";
2907     pAdaptor->nEncodings = sizeof (dummy_encoding) / sizeof (XF86VideoEncodingRec);
2908     pAdaptor->pEncodings = dummy_encoding;
2909     pAdaptor->nFormats = NUM_FORMATS;
2910     pAdaptor->pFormats = formats;
2911     pAdaptor->nPorts = SEC_MAX_PORT;
2912     pAdaptor->pPortPrivates = (DevUnion*)(&pAdaptor[1]);
2913
2914     pPort =
2915         (SECPortPrivPtr) (&pAdaptor->pPortPrivates[SEC_MAX_PORT]);
2916
2917     for (i = 0; i < SEC_MAX_PORT; i++)
2918     {
2919         pAdaptor->pPortPrivates[i].ptr = &pPort[i];
2920         pPort[i].index = i;
2921         pPort[i].usr_output = OUTPUT_LCD|OUTPUT_EXT;
2922         pPort[i].outbuf_cvting = -1;
2923     }
2924
2925     pAdaptor->nAttributes = NUM_ATTRIBUTES;
2926     pAdaptor->pAttributes = attributes;
2927     pAdaptor->nImages = NUM_IMAGES;
2928     pAdaptor->pImages = images;
2929
2930     pAdaptor->GetPortAttribute     = SECVideoGetPortAttribute;
2931     pAdaptor->SetPortAttribute     = SECVideoSetPortAttribute;
2932     pAdaptor->QueryBestSize        = SECVideoQueryBestSize;
2933     pAdaptor->QueryImageAttributes = SECVideoQueryImageAttributes;
2934     pAdaptor->PutImage             = SECVideoPutImage;
2935     pAdaptor->StopVideo            = SECVideoStop;
2936
2937     if (!_secVideoRegisterEventResourceTypes ())
2938     {
2939         ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2940         xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "Failed to register EventResourceTypes. \n");
2941         return FALSE;
2942     }
2943
2944     return pAdaptor;
2945 }
2946
2947 static void
2948 SECVideoReplacePutImageFunc (ScreenPtr pScreen)
2949 {
2950     int i;
2951
2952     XvScreenPtr xvsp = dixLookupPrivate (&pScreen->devPrivates,
2953                                          XvGetScreenKey());
2954     if (!xvsp)
2955         return;
2956
2957     for (i = 0; i < xvsp->nAdaptors; i++)
2958     {
2959         XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
2960         if (pAdapt->ddPutImage)
2961         {
2962             ddPutImage = pAdapt->ddPutImage;
2963             pAdapt->ddPutImage = SECVideoDDPutImage;
2964             break;
2965         }
2966     }
2967
2968     if (!dixRegisterPrivateKey (VideoPortKey, PRIVATE_WINDOW, sizeof (SECVideoPortInfo)))
2969         return;
2970     if (!dixRegisterPrivateKey (VideoPortKey, PRIVATE_PIXMAP, sizeof (SECVideoPortInfo)))
2971         return;
2972 }
2973
2974 #ifdef XV
2975 /**
2976  * Set up everything we need for Xv.
2977  */
2978 Bool secVideoInit (ScreenPtr pScreen)
2979 {
2980     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2981     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
2982     SECVideoPrivPtr pVideo;
2983
2984     pVideo = (SECVideoPrivPtr)calloc (sizeof (SECVideoPriv), 1);
2985     if (!pVideo)
2986         return FALSE;
2987
2988     pVideo->pAdaptor[0] = secVideoSetupImageVideo (pScreen);
2989     if (!pVideo->pAdaptor[0])
2990     {
2991         free (pVideo);
2992         return FALSE;
2993     }
2994
2995     pVideo->pAdaptor[1] = secVideoSetupVirtualVideo (pScreen);
2996     if (!pVideo->pAdaptor[1])
2997     {
2998         free (pVideo->pAdaptor[0]);
2999         free (pVideo);
3000         return FALSE;
3001     }
3002
3003     pVideo->pAdaptor[2] = secVideoSetupDisplayVideo (pScreen);
3004     if (!pVideo->pAdaptor[2])
3005     {
3006         free (pVideo->pAdaptor[1]);
3007         free (pVideo->pAdaptor[0]);
3008         free (pVideo);
3009         return FALSE;
3010     }
3011
3012     xf86XVScreenInit (pScreen, pVideo->pAdaptor, ADAPTOR_NUM);
3013
3014     SECVideoReplacePutImageFunc (pScreen);
3015     secVirtualVideoReplacePutStillFunc (pScreen);
3016
3017     if(registered_handler == FALSE)
3018     {
3019         RegisterBlockAndWakeupHandlers(_secVideoBlockHandler,
3020                                        (WakeupHandlerProcPtr)NoopDDA, pScrn);
3021         registered_handler = TRUE;
3022     }
3023
3024     pSec->pVideoPriv = pVideo;
3025     xorg_list_init (&layer_owners);
3026
3027     return TRUE;
3028 }
3029
3030 /**
3031  * Shut down Xv, used on regeneration.
3032  */
3033 void secVideoFini (ScreenPtr pScreen)
3034 {
3035     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
3036     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
3037     SECVideoPrivPtr pVideo = pSec->pVideoPriv;
3038     SECPortPrivPtr pCur = NULL, pNext = NULL;
3039     int i;
3040
3041     xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
3042     {
3043         if (pCur->tv)
3044         {
3045             secVideoTvDisconnect (pCur->tv);
3046             pCur->tv = NULL;
3047         }
3048
3049         if (pCur->d.clip_boxes)
3050         {
3051             RegionDestroy (pCur->d.clip_boxes);
3052             pCur->d.clip_boxes = NULL;
3053         }
3054     }
3055
3056     for (i = 0; i < ADAPTOR_NUM; i++)
3057         if (pVideo->pAdaptor[i])
3058             free (pVideo->pAdaptor[i]);
3059
3060     free (pVideo);
3061     pSec->pVideoPriv= NULL;
3062 }
3063
3064 #endif
3065
3066 void
3067 secVideoDpms (ScrnInfoPtr pScrn, Bool on)
3068 {
3069     if (!on)
3070     {
3071         SECPtr pSec = (SECPtr) pScrn->driverPrivate;
3072         XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0];
3073         int i;
3074
3075         for (i = 0; i < SEC_MAX_PORT; i++)
3076         {
3077             SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
3078             if (pPort->stream_cnt == 0)
3079                 continue;
3080             XDBG_TRACE (MVDO, "port(%d) cvt stop.\n", pPort->index);
3081             _secVideoCloseConverter (pPort);
3082             _secVideoCloseInBuffer (pPort);
3083         }
3084     }
3085 }
3086
3087 void
3088 secVideoScreenRotate (ScrnInfoPtr pScrn, int degree)
3089 {
3090     SECPtr pSec = SECPTR(pScrn);
3091     SECVideoPrivPtr pVideo = pSec->pVideoPriv;
3092     int old_degree;
3093
3094     if (pVideo->screen_rotate_degree == degree)
3095         return;
3096
3097     old_degree = pVideo->screen_rotate_degree;
3098     pVideo->screen_rotate_degree = degree;
3099     XDBG_DEBUG (MVDO, "screen rotate degree: %d\n", degree);
3100
3101     if (pSec->isLcdOff)
3102         return;
3103
3104     SECPortPrivPtr pCur = NULL, pNext = NULL;
3105     xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
3106     {
3107         SECModePtr pSecMode = pSec->pSecMode;
3108         SECVideoBuf *old_vbuf, *rot_vbuf;
3109         xRectangle rot_rect, dst_rect;
3110         int rot_width, rot_height;
3111         int scn_width, scn_height;
3112         int degree_diff = degree - old_degree;
3113
3114         if (!pCur->layer)
3115             continue;
3116
3117         old_vbuf = secLayerGetBuffer (pCur->layer);
3118         XDBG_RETURN_IF_FAIL (old_vbuf != NULL);
3119
3120         rot_width = old_vbuf->width;
3121         rot_height = old_vbuf->height;
3122         rot_rect = old_vbuf->crop;
3123         secUtilRotateArea (&rot_width, &rot_height, &rot_rect, degree_diff);
3124
3125         rot_vbuf = secUtilAllocVideoBuffer (pScrn, FOURCC_RGB32, rot_width, rot_height,
3126                                          (pSec->scanout)?TRUE:FALSE, FALSE, pCur->secure);
3127         XDBG_RETURN_IF_FAIL (rot_vbuf != NULL);
3128         rot_vbuf->crop = rot_rect;
3129
3130         secUtilConvertBos (pScrn, 0,
3131                            old_vbuf->bo[0], old_vbuf->width, old_vbuf->height, &old_vbuf->crop, old_vbuf->width*4,
3132                            rot_vbuf->bo[0], rot_vbuf->width, rot_vbuf->height, &rot_vbuf->crop, rot_vbuf->width*4,
3133                            FALSE, degree_diff);
3134
3135         tbm_bo_map (rot_vbuf->bo[0], TBM_DEVICE_2D, TBM_OPTION_READ);
3136         tbm_bo_unmap (rot_vbuf->bo[0]);
3137
3138         secLayerGetRect (pCur->layer, NULL, &dst_rect);
3139
3140         scn_width = (old_degree % 180)?pSecMode->main_lcd_mode.vdisplay:pSecMode->main_lcd_mode.hdisplay;
3141         scn_height = (old_degree % 180)?pSecMode->main_lcd_mode.hdisplay:pSecMode->main_lcd_mode.vdisplay;
3142
3143         secUtilRotateRect (scn_width, scn_height, &dst_rect, degree_diff);
3144
3145         secLayerFreezeUpdate (pCur->layer, TRUE);
3146         secLayerSetRect (pCur->layer, &rot_vbuf->crop, &dst_rect);
3147         secLayerFreezeUpdate (pCur->layer, FALSE);
3148         secLayerSetBuffer (pCur->layer, rot_vbuf);
3149
3150         secUtilVideoBufferUnref (rot_vbuf);
3151
3152         _secVideoCloseConverter (pCur);
3153     }
3154 }
3155
3156 void
3157 secVideoSwapLayers (ScreenPtr pScreen)
3158 {
3159     SECPortPrivPtr pCur = NULL, pNext = NULL;
3160     SECPortPrivPtr pPort1 = NULL, pPort2 = NULL;
3161
3162     xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
3163     {
3164         if (!pPort1)
3165             pPort1 = pCur;
3166         else if (!pPort2)
3167             pPort2 = pCur;
3168     }
3169
3170     if (pPort1 && pPort2)
3171     {
3172         secLayerSwapPos (pPort1->layer, pPort2->layer);
3173         XDBG_TRACE (MVDO, "%p : %p \n", pPort1->layer, pPort2->layer);
3174     }
3175 }
3176
3177 Bool
3178 secVideoIsSecureMode (ScrnInfoPtr pScrn)
3179 {
3180     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
3181     XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0];
3182     int i;
3183
3184     for (i = 0; i < SEC_MAX_PORT; i++)
3185     {
3186         SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
3187         if (pPort->secure)
3188         {
3189             XDBG_TRACE (MVDO, "pPort(%d) is secure.\n", pPort->index);
3190             return TRUE;
3191         }
3192     }
3193
3194     XDBG_TRACE (MVDO, "no secure port.\n");
3195
3196     return FALSE;
3197 }