884872d5807c7e44c0286979f18933c18277f519
[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)
1533     {
1534         XDBG_DEBUG (MVDO, "pPort->drawing (%d), pSec->pVideoPriv->video_punch (%d)\n",
1535                     pPort->drawing, pSec->pVideoPriv->video_punch);
1536         return;
1537     }
1538
1539     if (!pPort->punched)
1540     {
1541         DamageRegionAppend(pPort->d.pDraw, pPort->d.clip_boxes);
1542         secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
1543         if (pPixmap->devPrivate.ptr)
1544             memset (pPixmap->devPrivate.ptr, 0,
1545                     pPixmap->drawable.width * pPixmap->drawable.height * 4);
1546         secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
1547         DamageRegionProcessPending(pPort->d.pDraw);
1548         XDBG_TRACE (MVDO, "Punched (%dx%d) %p. \n",
1549                     pPixmap->drawable.width, pPixmap->drawable.height,
1550                     pPixmap->devPrivate.ptr);
1551         pPort->punched = TRUE;
1552 #if 0
1553         DamageDamageRegion (pPort->d.pDraw, pPort->d.clip_boxes);
1554 #endif
1555     }
1556 }
1557
1558 static Bool
1559 _secVideoSupportID (int id)
1560 {
1561     int i;
1562
1563     for (i = 0; i < NUM_IMAGES; i++)
1564         if (images[i].id == id)
1565             if (secCvtSupportFormat (CVT_OP_M2M, id))
1566                 return TRUE;
1567
1568     return FALSE;
1569 }
1570
1571 static Bool
1572 _secVideoInBranch (WindowPtr p, WindowPtr w)
1573 {
1574     for (; w; w = w->parent)
1575         if (w == p)
1576             return TRUE;
1577
1578     return FALSE;
1579 }
1580
1581 /* Return the child of 'p' which includes 'w'. */
1582 static WindowPtr
1583 _secVideoGetChild (WindowPtr p, WindowPtr w)
1584 {
1585     WindowPtr c;
1586
1587     for (c = w, w = w->parent; w; c = w, w = w->parent)
1588         if (w == p)
1589             return c;
1590
1591     return NULL;
1592 }
1593
1594 /* ancestor : Return the parent of 'a' and 'b'.
1595  * ancestor_a : Return the child of 'ancestor' which includes 'a'.
1596  * ancestor_b : Return the child of 'ancestor' which includes 'b'.
1597  */
1598 static Bool
1599 _secVideoGetAncestors (WindowPtr a, WindowPtr b,
1600                        WindowPtr *ancestor,
1601                        WindowPtr *ancestor_a,
1602                        WindowPtr *ancestor_b)
1603 {
1604     WindowPtr child_a, child_b;
1605
1606     if (!ancestor || !ancestor_a || !ancestor_b)
1607         return FALSE;
1608
1609     for (child_b = b, b = b->parent; b; child_b = b, b = b->parent)
1610     {
1611         child_a = _secVideoGetChild (b, a);
1612         if (child_a)
1613         {
1614             *ancestor   = b;
1615             *ancestor_a = child_a;
1616             *ancestor_b = child_b;
1617             return TRUE;
1618         }
1619     }
1620
1621     return FALSE;
1622 }
1623
1624 static int
1625 _secVideoCompareWindow (WindowPtr pWin1, WindowPtr pWin2)
1626 {
1627     WindowPtr a, a1, a2, c;
1628
1629     if (!pWin1 || !pWin2)
1630         return -2;
1631
1632     if (pWin1 == pWin2)
1633         return 0;
1634
1635     if (_secVideoGetChild (pWin1, pWin2))
1636         return -1;
1637
1638     if (_secVideoGetChild (pWin2, pWin1))
1639         return 1;
1640
1641     if (!_secVideoGetAncestors (pWin1, pWin2, &a, &a1, &a2))
1642         return -3;
1643
1644     for (c = a->firstChild; c; c = c->nextSib)
1645     {
1646         if (c == a1)
1647             return 1;
1648         else if (c == a2)
1649             return -1;
1650     }
1651
1652     return -4;
1653 }
1654
1655 static void
1656 _secVideoArrangeLayerPos (SECPortPrivPtr pPort, Bool by_notify)
1657 {
1658     SECPortPrivPtr pCur = NULL, pNext = NULL;
1659     SECPortPrivPtr pAnother = NULL;
1660     int i = 0;
1661
1662     xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
1663     {
1664         if (pCur == pPort)
1665             continue;
1666
1667         i++;
1668
1669         if (!pAnother)
1670             pAnother = pCur;
1671         else
1672             XDBG_WARNING (MVDO, "There are 3 more V4L2 ports. (%d) \n", i);
1673     }
1674
1675     if (!pAnother)
1676     {
1677         SECLayerPos lpos = secLayerGetPos (pPort->layer);
1678
1679         if (lpos == LAYER_NONE)
1680             secLayerSetPos (pPort->layer, LAYER_LOWER2);
1681     }
1682     else
1683     {
1684         SECLayerPos lpos1 = LAYER_NONE;
1685         SECLayerPos lpos2 = LAYER_NONE;
1686
1687         if (pAnother->layer)
1688             lpos1 = secLayerGetPos (pAnother->layer);
1689         if (pPort->layer)
1690             lpos2 = secLayerGetPos (pPort->layer);
1691
1692         if (lpos2 == LAYER_NONE)
1693         {
1694             int comp = _secVideoCompareWindow ((WindowPtr)pAnother->d.pDraw,
1695                                                (WindowPtr)pPort->d.pDraw);
1696
1697             XDBG_TRACE (MVDO, "0x%08x : 0x%08x => %d \n",
1698                         _XID(pAnother->d.pDraw), _XID(pPort->d.pDraw), comp);
1699
1700             if (comp == 1)
1701             {
1702                 if (lpos1 != LAYER_LOWER1)
1703                     secLayerSetPos (pAnother->layer, LAYER_LOWER1);
1704                 secLayerSetPos (pPort->layer, LAYER_LOWER2);
1705             }
1706             else if (comp == -1)
1707             {
1708                 if (lpos1 != LAYER_LOWER2)
1709                     secLayerSetPos (pAnother->layer, LAYER_LOWER2);
1710                 secLayerSetPos (pPort->layer, LAYER_LOWER1);
1711             }
1712             else
1713             {
1714                 if (lpos1 == LAYER_LOWER1)
1715                     secLayerSetPos (pPort->layer, LAYER_LOWER2);
1716                 else
1717                     secLayerSetPos (pPort->layer, LAYER_LOWER1);
1718             }
1719         }
1720         else
1721         {
1722             if (!by_notify)
1723                 return;
1724
1725             int comp = _secVideoCompareWindow ((WindowPtr)pAnother->d.pDraw,
1726                                                (WindowPtr)pPort->d.pDraw);
1727
1728             XDBG_TRACE (MVDO, "0x%08x : 0x%08x => %d \n",
1729                         _XID(pAnother->d.pDraw), _XID(pPort->d.pDraw), comp);
1730
1731             if ((comp == 1 && lpos1 != LAYER_LOWER1) ||
1732                 (comp == -1 && lpos2 != LAYER_LOWER1))
1733                 secLayerSwapPos (pAnother->layer, pPort->layer);
1734         }
1735     }
1736 }
1737
1738 static void
1739 _secVideoStopTvout (ScrnInfoPtr pScrn)
1740 {
1741     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
1742     XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0];
1743     int i;
1744
1745     for (i = 0; i < SEC_MAX_PORT; i++)
1746     {
1747         SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
1748
1749         if (pPort->grab_tvout)
1750         {
1751             _secVideoUngrabTvout (pPort);
1752             return;
1753         }
1754     }
1755 }
1756
1757 /* TRUE  : current frame will be shown on TV. free after vblank.
1758  * FALSE : current frame won't be shown on TV.
1759  */
1760 static Bool
1761 _secVideoPutImageTvout (SECPortPrivPtr pPort, int output, SECVideoBuf *inbuf)
1762 {
1763     ScrnInfoPtr pScrn = pPort->pScrn;
1764     SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
1765     xRectangle tv_rect = {0,};
1766     Bool first_put = FALSE;
1767
1768     if (!(output & OUTPUT_EXT))
1769     {
1770         XDBG_DEBUG(MTVO, "!(output (%d) & OUTPUT_EXT)\n", output);
1771         return FALSE;
1772     }
1773
1774     if (pPort->skip_tvout)
1775     {
1776         XDBG_DEBUG(MTVO, "pPort->skip_tvout (%d)\n", pPort->skip_tvout);
1777         return FALSE;
1778     }
1779
1780     if (!_secVideoGrabTvout(pPort))
1781         goto fail_to_put_tvout;
1782
1783     if (!pPort->tv)
1784     {
1785         SECCvt *tv_cvt;
1786         SECWb  *wb;
1787
1788         if (!secUtilEnsureExternalCrtc (pScrn))
1789         {
1790             XDBG_ERROR (MVDO, "failed : pPort(%d) connect external crtc\n", pPort->index);
1791             goto fail_to_put_tvout;
1792         }
1793
1794         pPort->tv = secVideoTvConnect (pScrn, pPort->d.id, LAYER_LOWER1);
1795         XDBG_GOTO_IF_FAIL (pPort->tv != NULL, fail_to_put_tvout);
1796
1797         wb = secWbGet ();
1798         if (wb)
1799         {
1800             pPort->need_start_wb = TRUE;
1801
1802             /* in case of VIRTUAL, wb's buffer is used by tvout. */
1803             if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
1804                 secWbStop (wb, FALSE);
1805             else
1806                 secWbStop (wb, TRUE);
1807         }
1808
1809         if (secWbIsRunning ())
1810         {
1811             XDBG_ERROR (MVDO, "failed: wb still running\n");
1812             goto fail_to_put_tvout;
1813         }
1814
1815         tv_cvt = secVideoTvGetConverter (pPort->tv);
1816
1817         if (tv_cvt == NULL)
1818         {
1819             if (!secVideoCanDirectDrawing (NULL, pPort->d.src.width, pPort->d.src.height,
1820                                            pPort->d.dst.width, pPort->d.dst.height))
1821             {
1822                 XDBG_GOTO_IF_FAIL (secVideoTvReCreateConverter (pPort->tv),
1823                                    fail_to_put_tvout);
1824             }
1825         }
1826         if (tv_cvt)
1827         {
1828             /* HDMI    : SN12
1829              * VIRTUAL : SN12 or RGB32
1830              */
1831             if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
1832             {
1833                 if (pSecMode->set_mode == DISPLAY_SET_MODE_CLONE)
1834                 {
1835                     SECVideoBuf **vbufs = NULL;
1836                     int bufnum = 0;
1837
1838                     secVideoTvSetConvertFormat (pPort->tv, FOURCC_SN12);
1839
1840                     /* In case of virtual, we draw video on full-size buffer
1841                      * for virtual-adaptor
1842                      */
1843                     secVideoTvSetSize (pPort->tv,
1844                                        pSecMode->ext_connector_mode.hdisplay,
1845                                        pSecMode->ext_connector_mode.vdisplay);
1846
1847                     secVirtualVideoGetBuffers (pPort->pScrn, FOURCC_SN12,
1848                                                pSecMode->ext_connector_mode.hdisplay,
1849                                                pSecMode->ext_connector_mode.vdisplay,
1850                                                &vbufs, &bufnum);
1851
1852                     XDBG_GOTO_IF_FAIL (vbufs != NULL, fail_to_put_tvout);
1853                     XDBG_GOTO_IF_FAIL (bufnum > 0, fail_to_put_tvout);
1854
1855                     secVideoTvSetBuffer (pPort->tv, vbufs, bufnum);
1856                 }
1857                 else /* desktop */
1858                     secVideoTvSetConvertFormat (pPort->tv, FOURCC_RGB32);
1859             }
1860             else
1861             {
1862 #if 0
1863                 secVideoTvSetConvertFormat (pPort->tv, FOURCC_SN12);
1864 #endif
1865             }
1866
1867             secCvtAddCallback (tv_cvt, _secVideoTvoutCvtCallback, pPort);
1868         }
1869         else
1870         {
1871             SECLayer *layer = secVideoTvGetLayer (pPort->tv);
1872             XDBG_GOTO_IF_FAIL (layer != NULL, fail_to_put_tvout);
1873
1874             secLayerEnableVBlank (layer, TRUE);
1875             secLayerAddNotifyFunc (layer, _secVideoLayerNotifyFunc, pPort);
1876         }
1877
1878         first_put = TRUE;
1879     }
1880
1881     SECPtr pSec = SECPTR (pPort->pScrn);
1882     if (pPort->wait_vbuf)
1883     {
1884         if (pSec->pVideoPriv->video_fps)
1885         {
1886             CARD32 cur, sub;
1887             cur = GetTimeInMillis ();
1888             sub = cur - pPort->tv_prev_time;
1889             pPort->tv_prev_time = cur;
1890
1891             XDBG_DEBUG (MVDO, "tvout skip : sub(%ld) vbuf(%ld:%d,%d,%d) \n",
1892                         sub, inbuf->stamp,
1893                         inbuf->keys[0], inbuf->keys[1], inbuf->keys[2]);
1894         }
1895         XDBG_DEBUG (MVDO, "pPort->wait_vbuf (%d) skip_frame\n", pPort->wait_vbuf);
1896         return FALSE;
1897     }
1898     else if (pSec->pVideoPriv->video_fps)
1899         pPort->tv_prev_time = GetTimeInMillis ();
1900
1901     if (!(output & OUTPUT_FULL))
1902     {
1903         SECDisplaySetMode disp_mode = secDisplayGetDispSetMode (pScrn);
1904         if (disp_mode == DISPLAY_SET_MODE_EXT)
1905             tv_rect.x = pPort->d.dst.x
1906                         - pSecMode->main_lcd_mode.hdisplay;
1907         else
1908             tv_rect.x = pPort->d.dst.x;
1909         tv_rect.y = pPort->d.dst.y;
1910         tv_rect.width = pPort->d.dst.width;
1911         tv_rect.height = pPort->d.dst.height;
1912     }
1913     else
1914     {
1915         secUtilAlignRect (pPort->d.src.width, pPort->d.src.height,
1916                           pSecMode->ext_connector_mode.hdisplay,
1917                           pSecMode->ext_connector_mode.vdisplay,
1918                           &tv_rect, TRUE);
1919     }
1920
1921     /* if secVideoTvPutImage returns FALSE, it means this frame won't show on TV. */
1922     if (!secVideoTvPutImage (pPort->tv, inbuf, &tv_rect, pPort->csc_range))
1923         return FALSE;
1924
1925     if (first_put && !(output & OUTPUT_LCD))
1926         _secVideoSetOutputExternalProperty (pPort->d.pDraw, TRUE);
1927
1928     pPort->wait_vbuf = inbuf;
1929
1930     return TRUE;
1931
1932 fail_to_put_tvout:
1933     _secVideoUngrabTvout (pPort);
1934
1935     pPort->skip_tvout = TRUE;
1936
1937     XDBG_TRACE (MVDO, "pPort(%d) skip tvout \n", pPort->index);
1938
1939     return FALSE;
1940 }
1941
1942 static Bool
1943 _secVideoPutImageInbuf (SECPortPrivPtr pPort, SECVideoBuf *inbuf)
1944 {
1945     if (!pPort->layer)
1946     {
1947         pPort->layer = _secVideoCreateLayer (pPort);
1948         XDBG_RETURN_VAL_IF_FAIL (pPort->layer != NULL, FALSE);
1949
1950         _secVideoArrangeLayerPos (pPort, FALSE);
1951     }
1952
1953     secLayerSetBuffer (pPort->layer, inbuf);
1954
1955     if (!secLayerIsVisible (pPort->layer))
1956         secLayerShow (pPort->layer);
1957
1958     return TRUE;
1959 }
1960
1961 static Bool
1962 _secVideoPutImageInternal (SECPortPrivPtr pPort, SECVideoBuf *inbuf)
1963 {
1964     SECPtr pSec = (SECPtr) pPort->pScrn->driverPrivate;
1965     SECCvtProp src_prop = {0,}, dst_prop = {0,};
1966     SECVideoBuf *outbuf = NULL;
1967
1968     outbuf = _secVideoGetOutbuf (pPort);
1969     if (!outbuf)
1970         return FALSE;
1971
1972     /* cacheflush here becasue dst buffer can be created in _secVideoGetOutbuf() */
1973     if (pPort->stream_cnt == 1)
1974         if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
1975             secUtilCacheFlush (pPort->pScrn);
1976
1977     XDBG_DEBUG (MVDO, "'%c%c%c%c' preem(%d) rot(%d) \n",
1978                 FOURCC_STR (pPort->d.id),
1979                 pPort->preemption, pPort->hw_rotate);
1980
1981     if (pPort->layer)
1982         _secVideoArrangeLayerPos (pPort, FALSE);
1983
1984     _secVideoEnsureConverter (pPort);
1985     XDBG_GOTO_IF_FAIL (pPort->cvt != NULL, fail_to_put);
1986
1987     src_prop.id = pPort->d.id;
1988     src_prop.width = pPort->in_width;
1989     src_prop.height = pPort->in_height;
1990     src_prop.crop = pPort->in_crop;
1991
1992     dst_prop.id = FOURCC_RGB32;
1993     dst_prop.width = pPort->out_width;
1994     dst_prop.height = pPort->out_height;
1995     dst_prop.crop = pPort->out_crop;
1996
1997     dst_prop.degree = pPort->hw_rotate;
1998     dst_prop.hflip = pPort->hflip;
1999     dst_prop.vflip = pPort->vflip;
2000     dst_prop.secure = pPort->secure;
2001     dst_prop.csc_range = pPort->csc_range;
2002
2003     if (!secCvtEnsureSize (&src_prop, &dst_prop))
2004         goto fail_to_put;
2005
2006     if (!secCvtSetProperpty (pPort->cvt, &src_prop, &dst_prop))
2007         goto fail_to_put;
2008
2009     if (!secCvtConvert (pPort->cvt, inbuf, outbuf))
2010         goto fail_to_put;
2011
2012     if (pSec->pVideoPriv->video_fps)
2013         _countFps (pPort);
2014
2015     secUtilVideoBufferUnref (outbuf);
2016
2017     return TRUE;
2018
2019 fail_to_put:
2020     if (outbuf)
2021         secUtilVideoBufferUnref (outbuf);
2022
2023     _secVideoCloseConverter (pPort);
2024     _secVideoCloseOutBuffer (pPort, TRUE);
2025
2026     return FALSE;
2027 }
2028
2029 static Bool
2030 _secVideoSetHWPortsProperty (ScreenPtr pScreen, int nums)
2031 {
2032     WindowPtr pWin = pScreen->root;
2033     Atom atom_hw_ports;
2034
2035     /* With "X_HW_PORTS", an application can know
2036      * how many fimc devices XV uses.
2037      */
2038     if (!pWin || !serverClient)
2039         return FALSE;
2040
2041     atom_hw_ports = MakeAtom ("XV_HW_PORTS", strlen ("XV_HW_PORTS"), TRUE);
2042
2043     dixChangeWindowProperty (serverClient,
2044                              pWin, atom_hw_ports, XA_CARDINAL, 32,
2045                              PropModeReplace, 1, (unsigned int*)&nums, FALSE);
2046
2047     return TRUE;
2048 }
2049
2050 static Bool
2051 _secVideoSetOutputExternalProperty (DrawablePtr pDraw, Bool video_only)
2052 {
2053     WindowPtr pWin;
2054     Atom atom_external;
2055
2056     XDBG_RETURN_VAL_IF_FAIL (pDraw != NULL, FALSE);
2057     XDBG_RETURN_VAL_IF_FAIL (pDraw->type == DRAWABLE_WINDOW, FALSE);
2058
2059     pWin = (WindowPtr)pDraw;
2060
2061     atom_external = MakeAtom ("XV_OUTPUT_EXTERNAL", strlen ("XV_OUTPUT_EXTERNAL"), TRUE);
2062
2063     dixChangeWindowProperty (clients[CLIENT_ID(pDraw->id)],
2064                              pWin, atom_external, XA_CARDINAL, 32,
2065                              PropModeReplace, 1, (unsigned int*)&video_only, TRUE);
2066
2067     XDBG_TRACE (MVDO, "pDraw(0x%08x) video-only(%s)\n",
2068                 pDraw->id, (video_only)?"ON":"OFF");
2069
2070     return TRUE;
2071 }
2072
2073 static void
2074 _secVideoRestackWindow (WindowPtr pWin, WindowPtr pOldNextSib)
2075 {
2076     ScreenPtr pScreen = ((DrawablePtr)pWin)->pScreen;
2077     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2078     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
2079     SECVideoPrivPtr pVideo = pSec->pVideoPriv;
2080
2081     if (pVideo->RestackWindow)
2082     {
2083         pScreen->RestackWindow = pVideo->RestackWindow;
2084
2085         if (pScreen->RestackWindow)
2086             (*pScreen->RestackWindow)(pWin, pOldNextSib);
2087
2088         pVideo->RestackWindow = pScreen->RestackWindow;
2089         pScreen->RestackWindow = _secVideoRestackWindow;
2090     }
2091
2092     if (!xorg_list_is_empty (&layer_owners))
2093     {
2094         SECPortPrivPtr pCur = NULL, pNext = NULL;
2095         xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
2096         {
2097             if (_secVideoInBranch (pWin, (WindowPtr)pCur->d.pDraw))
2098             {
2099                 XDBG_TRACE (MVDO, "Do re-arrange. 0x%08x(0x%08x) \n",
2100                             _XID(pWin), _XID(pCur->d.pDraw));
2101                 _secVideoArrangeLayerPos (pCur, TRUE);
2102                 break;
2103             }
2104         }
2105     }
2106 }
2107
2108 static void
2109 _secVideoBlockHandler (pointer data, OSTimePtr pTimeout, pointer pRead)
2110 {
2111     ScreenPtr pScreen = ((ScrnInfoPtr)data)->pScreen;
2112     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2113     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
2114     SECVideoPrivPtr pVideo = pSec->pVideoPriv;
2115
2116     pVideo->RestackWindow = pScreen->RestackWindow;
2117     pScreen->RestackWindow = _secVideoRestackWindow;
2118
2119     if(registered_handler && _secVideoSetHWPortsProperty (pScreen, NUM_HW_LAYER))
2120     {
2121         RemoveBlockAndWakeupHandlers(_secVideoBlockHandler,
2122                                      (WakeupHandlerProcPtr)NoopDDA, data);
2123         registered_handler = FALSE;
2124     }
2125 }
2126
2127 static Bool
2128 _secVideoAddDrawableEvent (SECPortPrivPtr pPort)
2129 {
2130     SECVideoResource *resource;
2131     void *ptr=NULL;
2132     int ret;
2133
2134     ret = dixLookupResourceByType (&ptr, pPort->d.pDraw->id,
2135                              event_drawable_type, NULL, DixWriteAccess);
2136     if (ret == Success)
2137     {
2138         return TRUE;
2139     }
2140
2141     resource = malloc (sizeof (SECVideoResource));
2142     if (resource == NULL)
2143         return FALSE;
2144
2145     if (!AddResource (pPort->d.pDraw->id, event_drawable_type, resource))
2146     {
2147         free (resource);
2148         return FALSE;
2149     }
2150
2151     XDBG_TRACE (MVDO, "id(0x%08lx). \n", pPort->d.pDraw->id);
2152
2153     resource->id = pPort->d.pDraw->id;
2154     resource->type = event_drawable_type;
2155     resource->pPort = pPort;
2156     resource->pScrn = pPort->pScrn;
2157
2158     return TRUE;
2159 }
2160
2161 static int
2162 _secVideoRegisterEventDrawableGone (void *data, XID id)
2163 {
2164     SECVideoResource *resource = (SECVideoResource*)data;
2165
2166     XDBG_TRACE (MVDO, "id(0x%08lx). \n", id);
2167
2168     if (!resource)
2169         return Success;
2170
2171     if (!resource->pPort || !resource->pScrn)
2172         return Success;
2173
2174     SECVideoStop (resource->pScrn, (pointer)resource->pPort, 1);
2175
2176     free(resource);
2177
2178     return Success;
2179 }
2180
2181 static Bool
2182 _secVideoRegisterEventResourceTypes (void)
2183 {
2184     event_drawable_type = CreateNewResourceType (_secVideoRegisterEventDrawableGone, "Sec Video Drawable");
2185
2186     if (!event_drawable_type)
2187         return FALSE;
2188
2189     return TRUE;
2190 }
2191
2192 int
2193 secVideoQueryImageAttrs (ScrnInfoPtr  pScrn,
2194                          int          id,
2195                          int         *w,
2196                          int         *h,
2197                          int         *pitches,
2198                          int         *offsets,
2199                          int         *lengths)
2200 {
2201     int size = 0, tmp = 0;
2202
2203     *w = (*w + 1) & ~1;
2204     if (offsets)
2205         offsets[0] = 0;
2206
2207     switch (id)
2208     {
2209     /* RGB565 */
2210     case FOURCC_SR16:
2211     case FOURCC_RGB565:
2212         size += (*w << 1);
2213         if (pitches)
2214             pitches[0] = size;
2215         size *= *h;
2216         if (lengths)
2217             lengths[0] = size;
2218         break;
2219     /* RGB32 */
2220     case FOURCC_SR32:
2221     case FOURCC_RGB32:
2222         size += (*w << 2);
2223         if (pitches)
2224             pitches[0] = size;
2225         size *= *h;
2226         if (lengths)
2227             lengths[0] = size;
2228         break;
2229     /* YUV420, 3 planar */
2230     case FOURCC_I420:
2231     case FOURCC_S420:
2232     case FOURCC_YV12:
2233         *h = (*h + 1) & ~1;
2234         size = (*w + 3) & ~3;
2235         if (pitches)
2236             pitches[0] = size;
2237
2238         size *= *h;
2239         if (offsets)
2240             offsets[1] = size;
2241         if (lengths)
2242             lengths[0] = size;
2243
2244         tmp = ((*w >> 1) + 3) & ~3;
2245         if (pitches)
2246             pitches[1] = pitches[2] = tmp;
2247
2248         tmp *= (*h >> 1);
2249         size += tmp;
2250         if (offsets)
2251             offsets[2] = size;
2252         if (lengths)
2253             lengths[1] = tmp;
2254
2255         size += tmp;
2256         if (lengths)
2257             lengths[2] = tmp;
2258
2259         break;
2260     /* YUV422, packed */
2261     case FOURCC_UYVY:
2262     case FOURCC_SYVY:
2263     case FOURCC_ITLV:
2264     case FOURCC_SUYV:
2265     case FOURCC_YUY2:
2266         size = *w << 1;
2267         if (pitches)
2268             pitches[0] = size;
2269
2270         size *= *h;
2271         if (lengths)
2272             lengths[0] = size;
2273         break;
2274
2275     /* YUV420, 2 planar */
2276     case FOURCC_SN12:
2277     case FOURCC_NV12:
2278     case FOURCC_SN21:
2279     case FOURCC_NV21:
2280         if (pitches)
2281             pitches[0] = *w;
2282
2283         size = (*w) * (*h);
2284         if (offsets)
2285             offsets[1] = size;
2286         if (lengths)
2287             lengths[0] = size;
2288
2289         if (pitches)
2290             pitches[1] = *w;
2291
2292         tmp = (*w) * (*h >> 1);
2293         size += tmp;
2294         if (lengths)
2295             lengths[1] = tmp;
2296         break;
2297
2298     /* YUV420, 2 planar, tiled */
2299     case FOURCC_ST12:
2300         if (pitches)
2301             pitches[0] = *w;
2302
2303         size = ALIGN_TO_8KB(ALIGN_TO_128B(*w) * ALIGN_TO_32B(*h));
2304         if (offsets)
2305             offsets[1] = size;
2306         if (lengths)
2307             lengths[0] = size;
2308
2309         if (pitches)
2310             pitches[1] = *w;
2311
2312         tmp = ALIGN_TO_8KB(ALIGN_TO_128B(*w) * ALIGN_TO_32B(*h >> 1));
2313         size += tmp;
2314         if (lengths)
2315             lengths[1] = tmp;
2316         break;
2317     default:
2318         return 0;
2319     }
2320
2321     return size;
2322 }
2323
2324 static int
2325 SECVideoGetPortAttribute (ScrnInfoPtr pScrn,
2326                           Atom        attribute,
2327                           INT32      *value,
2328                           pointer     data)
2329 {
2330     SECPortPrivPtr pPort = (SECPortPrivPtr) data;
2331
2332     if (attribute == _portAtom (PAA_ROTATION))
2333     {
2334         *value = pPort->rotate;
2335         return Success;
2336     }
2337     else if (attribute == _portAtom (PAA_HFLIP))
2338     {
2339         *value = pPort->hflip;
2340         return Success;
2341     }
2342     else if (attribute == _portAtom (PAA_VFLIP))
2343     {
2344         *value = pPort->vflip;
2345         return Success;
2346     }
2347     else if (attribute == _portAtom (PAA_PREEMPTION))
2348     {
2349         *value = pPort->preemption;
2350         return Success;
2351     }
2352     else if (attribute == _portAtom (PAA_OUTPUT))
2353     {
2354         *value = pPort->usr_output;
2355         return Success;
2356     }
2357     else if (attribute == _portAtom (PAA_SECURE))
2358     {
2359         *value = pPort->secure;
2360         return Success;
2361     }
2362     else if (attribute == _portAtom (PAA_CSC_RANGE))
2363     {
2364         *value = pPort->csc_range;
2365         return Success;
2366     }
2367
2368     return BadMatch;
2369 }
2370
2371 static int
2372 SECVideoSetPortAttribute (ScrnInfoPtr pScrn,
2373                           Atom        attribute,
2374                           INT32       value,
2375                           pointer     data)
2376 {
2377     SECPortPrivPtr pPort = (SECPortPrivPtr) data;
2378
2379     if (attribute == _portAtom (PAA_ROTATION))
2380     {
2381         pPort->rotate = value;
2382         XDBG_DEBUG (MVDO, "rotate(%d) \n", value);
2383         return Success;
2384     }
2385     else if (attribute == _portAtom (PAA_HFLIP))
2386     {
2387         pPort->hflip = value;
2388         XDBG_DEBUG (MVDO, "hflip(%d) \n", value);
2389         return Success;
2390     }
2391     else if (attribute == _portAtom (PAA_VFLIP))
2392     {
2393         pPort->vflip = value;
2394         XDBG_DEBUG (MVDO, "vflip(%d) \n", value);
2395         return Success;
2396     }
2397     else if (attribute == _portAtom (PAA_PREEMPTION))
2398     {
2399         pPort->preemption = value;
2400         XDBG_DEBUG (MVDO, "preemption(%d) \n", value);
2401         return Success;
2402     }
2403     else if (attribute == _portAtom (PAA_OUTPUT))
2404     {
2405         if (value == OUTPUT_MODE_TVOUT)
2406             pPort->usr_output = OUTPUT_LCD|OUTPUT_EXT|OUTPUT_FULL;
2407         else if (value == OUTPUT_MODE_EXT_ONLY)
2408             pPort->usr_output = OUTPUT_EXT|OUTPUT_FULL;
2409         else
2410             pPort->usr_output = OUTPUT_LCD|OUTPUT_EXT;
2411
2412         XDBG_DEBUG (MVDO, "output (%d) \n", value);
2413
2414         return Success;
2415     }
2416     else if (attribute == _portAtom (PAA_SECURE))
2417     {
2418         pPort->secure = value;
2419         XDBG_DEBUG (MVDO, "secure(%d) \n", value);
2420         return Success;
2421     }
2422     else if (attribute == _portAtom (PAA_CSC_RANGE))
2423     {
2424         pPort->csc_range = value;
2425         XDBG_DEBUG (MVDO, "csc_range(%d) \n", value);
2426         return Success;
2427     }
2428
2429     return Success;
2430 }
2431
2432 static void
2433 SECVideoQueryBestSize (ScrnInfoPtr pScrn,
2434                        Bool motion,
2435                        short vid_w, short vid_h,
2436                        short dst_w, short dst_h,
2437                        uint *p_w, uint *p_h,
2438                        pointer data)
2439 {
2440     SECCvtProp prop = {0,};
2441
2442     if (!p_w && !p_h)
2443         return;
2444
2445     prop.width = dst_w;
2446     prop.height = dst_h;
2447     prop.crop.width = dst_w;
2448     prop.crop.height = dst_h;
2449
2450     if (secCvtEnsureSize (NULL, &prop))
2451     {
2452         if (p_w)
2453             *p_w = prop.width;
2454         if (p_h)
2455             *p_h = prop.height;
2456     }
2457     else
2458     {
2459         if (p_w)
2460             *p_w = dst_w;
2461         if (p_h)
2462             *p_h = dst_h;
2463     }
2464 }
2465
2466 /**
2467  * Give image size and pitches.
2468  */
2469 static int
2470 SECVideoQueryImageAttributes (ScrnInfoPtr    pScrn,
2471                               int            id,
2472                               unsigned short *w,
2473                               unsigned short *h,
2474                               int            *pitches,
2475                               int            *offsets)
2476 {
2477     int width, height, size;
2478
2479     if (!w || !h)
2480         return 0;
2481
2482     width = (int)*w;
2483     height = (int)*h;
2484
2485     size = secVideoQueryImageAttrs (pScrn, id, &width, &height, pitches, offsets, NULL);
2486
2487     *w = (unsigned short)width;
2488     *h = (unsigned short)height;
2489
2490     return size;
2491 }
2492
2493 /* coordinates : HW, SCREEN, PORT
2494  * BadRequest : when video can't be shown or drawn.
2495  * Success    : A damage event(pixmap) and inbuf should be return.
2496  *              If can't return a damage event and inbuf, should be return
2497  *              BadRequest.
2498  */
2499 static int
2500 SECVideoPutImage (ScrnInfoPtr pScrn,
2501                   short src_x, short src_y, short dst_x, short dst_y,
2502                   short src_w, short src_h, short dst_w, short dst_h,
2503                   int id, uchar *buf, short width, short height,
2504                   Bool sync, RegionPtr clip_boxes, pointer data,
2505                   DrawablePtr pDraw)
2506 {
2507     SECPtr pSec = SECPTR (pScrn);
2508 #ifdef NO_CRTC_MODE
2509     if (pSec->isCrtcOn == FALSE)
2510     {
2511         XDBG_WARNING (MVDO, "XV PutImage Disabled (No active CRTCs)\n");
2512         return BadRequest;
2513     }
2514 #endif
2515     SECModePtr pSecMode = (SECModePtr)SECPTR (pScrn)->pSecMode;
2516     SECVideoPrivPtr pVideo = SECPTR (pScrn)->pVideoPriv;
2517     SECPortPrivPtr pPort = (SECPortPrivPtr) data;
2518     int output, ret;
2519     Bool tvout = FALSE, lcdout = FALSE;
2520     SECVideoBuf *inbuf = NULL;
2521     int old_drawing;
2522
2523     if (!_secVideoSupportID (id))
2524     {
2525         XDBG_ERROR (MVDO, "'%c%c%c%c' not supported.\n", FOURCC_STR (id));
2526         return BadRequest;
2527     }
2528
2529     XDBG_TRACE (MVDO, "======================================= \n");
2530     XDBG_DEBUG(MVDO, "src:(x%d,y%d w%d-h%d), dst:(x%d,y%d w%d-h%d)\n",
2531                src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
2532     XDBG_DEBUG(MVDO, "image size:(w%d-h%d) fourcc(%c%c%c%c)\n", width, height, FOURCC_STR(id));
2533     pPort->pScrn = pScrn;
2534     pPort->d.id = id;
2535     pPort->d.buf = buf;
2536
2537     if (pSec->xvperf_mode & XBERC_XVPERF_MODE_IA)
2538     {
2539         unsigned int keys[PLANAR_CNT] = {0,};
2540         CARD32 cur, sub;
2541         char temp[64];
2542         cur = GetTimeInMillis ();
2543         sub = cur - pPort->prev_time;
2544         pPort->prev_time = cur;
2545         temp[0] = '\0';
2546         if (IS_ZEROCOPY (id))
2547         {
2548             _secVideoGetKeys (pPort, keys, NULL);
2549             snprintf (temp, sizeof(temp), "%d,%d,%d", keys[0], keys[1], keys[2]);
2550         }
2551         ErrorF ("pPort(%p) put interval(%s) : %6ld ms\n", pPort, temp, sub);
2552     }
2553
2554     if (IS_ZEROCOPY (pPort->d.id))
2555     {
2556         unsigned int keys[PLANAR_CNT] = {0,};
2557         int i;
2558
2559         if (_secVideoGetKeys (pPort, keys, NULL))
2560             return BadRequest;
2561
2562         for (i = 0; i < INBUF_NUM; i++)
2563             if (pPort->inbuf[i] && pPort->inbuf[i]->keys[0] == keys[0])
2564             {
2565                 XDBG_WARNING (MVDO, "got flink_id(%d) twice!\n", keys[0]);
2566                 _secVideoSendReturnBufferMessage (pPort, NULL, keys);
2567                 return Success;
2568             }
2569     }
2570
2571     pPort->d.width = width;
2572     pPort->d.height = height;
2573     pPort->d.src.x = src_x;
2574     pPort->d.src.y = src_y;
2575     pPort->d.src.width = src_w;
2576     pPort->d.src.height = src_h;
2577     pPort->d.dst.x = dst_x;    /* included pDraw'x */
2578     pPort->d.dst.y = dst_y;    /* included pDraw'y */
2579     pPort->d.dst.width = dst_w;
2580     pPort->d.dst.height = dst_h;
2581     pPort->d.sync = FALSE;
2582     if (sync)
2583         XDBG_WARNING (MVDO, "not support sync.\n");
2584     pPort->d.data = data;
2585     pPort->d.pDraw = pDraw;
2586     if (clip_boxes)
2587     {
2588         if (!pPort->d.clip_boxes)
2589             pPort->d.clip_boxes = RegionCreate(NullBox, 0);
2590         RegionCopy (pPort->d.clip_boxes, clip_boxes);
2591     }
2592
2593     old_drawing = pPort->drawing;
2594     pPort->drawing = _secVideodrawingOn (pPort);
2595     if (pDraw)
2596     {
2597         XDBG_DEBUG(MVDO, "pixmap:(x%d,y%d w%d-h%d) on:%d\n",
2598                    pDraw->x, pDraw->y, pDraw->width, pDraw->height, pPort->drawing);
2599     }
2600     if (old_drawing != pPort->drawing)
2601     {
2602         _secVideoCloseConverter (pPort);
2603         _secVideoCloseOutBuffer (pPort, TRUE);
2604
2605     }
2606
2607     _secVideoGetRotation (pPort, &pPort->hw_rotate);
2608
2609     if (pPort->drawing == ON_FB && pVideo->screen_rotate_degree > 0)
2610         secUtilRotateRect (pSecMode->main_lcd_mode.hdisplay,
2611                            pSecMode->main_lcd_mode.vdisplay,
2612                            &pPort->d.dst,
2613                            pVideo->screen_rotate_degree);
2614
2615     if (pPort->secure)
2616         if (pPort->drawing != ON_FB)
2617         {
2618             XDBG_ERROR (MVDO, "secure video should drawn on FB.\n");
2619             return BadRequest;
2620         }
2621
2622     if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
2623         if (!_secVideoAddDrawableEvent (pPort))
2624             return BadRequest;
2625
2626     if (pPort->stream_cnt == 0)
2627     {
2628         pPort->stream_cnt++;
2629
2630         if (pPort->preemption > -1)
2631             streaming_ports++;
2632
2633         XDBG_SECURE (MVDO, "pPort(%d) streams(%d) rotate(%d) flip(%d,%d) secure(%d) range(%d) usr_output(%x) on(%s)\n",
2634                      pPort->index, streaming_ports,
2635                      pPort->rotate, pPort->hflip, pPort->vflip, pPort->secure, pPort->csc_range,
2636                      pPort->usr_output, drawing_type[pPort->drawing]);
2637         XDBG_SECURE (MVDO, "id(%c%c%c%c) sz(%dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d)\n",
2638                      FOURCC_STR (id), width, height,
2639                      src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h);
2640
2641         if (streaming_ports > 1)
2642             _secVideoStopTvout (pPort->pScrn);
2643     }
2644     else if (pPort->stream_cnt == 1)
2645         pPort->stream_cnt++;
2646
2647     if (pPort->cvt)
2648     {
2649         SECCvtProp dst_prop;
2650
2651         secCvtGetProperpty (pPort->cvt, NULL, &dst_prop);
2652
2653         if (pPort->d.id != pPort->old_d.id ||
2654             pPort->d.width != pPort->old_d.width ||
2655             pPort->d.height != pPort->old_d.height ||
2656             memcmp (&pPort->d.src, &pPort->old_d.src, sizeof (xRectangle)) ||
2657             dst_prop.degree != pPort->hw_rotate ||
2658             dst_prop.hflip != pPort->hflip ||
2659             dst_prop.vflip != pPort->vflip ||
2660             dst_prop.secure != pPort->secure ||
2661             dst_prop.csc_range != pPort->csc_range)
2662         {
2663             XDBG_DEBUG (MVDO, "pPort(%d) streams(%d) rotate(%d) flip(%d,%d) secure(%d) range(%d) usr_output(%x) on(%s)\n",
2664                         pPort->index, streaming_ports,
2665                         pPort->rotate, pPort->hflip, pPort->vflip, pPort->secure, pPort->csc_range,
2666                         pPort->usr_output, drawing_type[pPort->drawing]);
2667             XDBG_DEBUG (MVDO, "pPort(%d) old_src(%dx%d %d,%d %dx%d) : new_src(%dx%d %d,%d %dx%d)\n",
2668                         pPort->index, pPort->old_d.width, pPort->old_d.height,
2669                         pPort->old_d.src.x, pPort->old_d.src.y,
2670                         pPort->old_d.src.width, pPort->old_d.src.height,
2671                         pPort->d.width, pPort->d.height,
2672                         pPort->d.src.x, pPort->d.src.y,
2673                         pPort->d.src.width, pPort->d.src.height);
2674             _secVideoCloseConverter (pPort);
2675             _secVideoCloseInBuffer (pPort);
2676             pPort->inbuf_is_fb = FALSE;
2677         }
2678     }
2679
2680     if (memcmp (&pPort->d.dst, &pPort->old_d.dst, sizeof (xRectangle)))
2681     {
2682         XDBG_DEBUG (MVDO, "pPort(%d) old_dst(%d,%d %dx%d) : new_dst(%dx%d %dx%d)\n",
2683                     pPort->index,
2684                     pPort->old_d.dst.x, pPort->old_d.dst.y,
2685                     pPort->old_d.dst.width, pPort->old_d.dst.height,
2686                     pPort->d.dst.x, pPort->d.dst.y,
2687                     pPort->d.dst.width, pPort->d.dst.height);
2688         _secVideoCloseConverter (pPort);
2689         _secVideoCloseOutBuffer (pPort, FALSE);
2690         pPort->inbuf_is_fb = FALSE;
2691     }
2692
2693     if (pPort->tv)
2694     {
2695         SECCvt *tv_cvt = secVideoTvGetConverter (pPort->tv);
2696         if (pPort->d.id != pPort->old_d.id ||
2697             pPort->d.width != pPort->old_d.width ||
2698             pPort->d.height != pPort->old_d.height ||
2699             memcmp (&pPort->d.src, &pPort->old_d.src, sizeof (xRectangle)))
2700         {
2701             _secVideoCloseInBuffer (pPort);
2702             pPort->inbuf_is_fb = FALSE;
2703         }
2704         else if (tv_cvt != NULL)
2705         {
2706             SECCvtProp dst_prop;
2707             secCvtGetProperpty (tv_cvt, NULL, &dst_prop);
2708
2709             if (dst_prop.degree != pPort->hw_rotate ||
2710                 dst_prop.hflip != pPort->hflip ||
2711                 dst_prop.vflip != pPort->vflip ||
2712                 dst_prop.secure != pPort->secure ||
2713                 dst_prop.csc_range != pPort->csc_range)
2714             {
2715                 _secVideoCloseInBuffer (pPort);
2716                 pPort->inbuf_is_fb = FALSE;
2717             }
2718         }
2719
2720         if (pPort->tv && memcmp (&pPort->d.dst, &pPort->old_d.dst, sizeof (xRectangle)))
2721         {
2722             if (secVideoTvResizeOutput (pPort->tv, &pPort->d.src, &pPort->d.dst) == TRUE)
2723             {
2724                 SECCvt *tv_cvt = secVideoTvGetConverter (pPort->tv);
2725                 if (tv_cvt != NULL)
2726                 {
2727                     secCvtAddCallback (tv_cvt, _secVideoTvoutCvtCallback, pPort);
2728                 }
2729             }
2730             else
2731             {
2732                 secVideoTvDisconnect (pPort->tv);
2733                 pPort->tv = NULL;
2734             }
2735             pPort->punched = FALSE;
2736             pPort->wait_vbuf = NULL;
2737         }
2738     }
2739
2740     if (!_secVideoCalculateSize (pPort))
2741         return BadRequest;
2742
2743     output = _secVideoGetTvoutMode (pPort);
2744     if (!(output & OUTPUT_LCD) && pPort->old_output & OUTPUT_LCD)
2745     {
2746         /* If the video of LCD becomes off, we also turn off LCD layer. */
2747         if (pPort->drawing == ON_PIXMAP || pPort->drawing == ON_WINDOW)
2748         {
2749             PixmapPtr pPixmap = _getPixmap (pPort->d.pDraw);
2750             SECPixmapPriv *privPixmap = exaGetPixmapDriverPrivate (pPixmap);
2751
2752             secExaPrepareAccess (pPixmap, EXA_PREPARE_DEST);
2753             if (pPixmap->devPrivate.ptr && privPixmap->size > 0)
2754                 memset (pPixmap->devPrivate.ptr, 0, privPixmap->size);
2755             secExaFinishAccess (pPixmap, EXA_PREPARE_DEST);
2756
2757             DamageDamageRegion (pPort->d.pDraw, pPort->d.clip_boxes);
2758         }
2759         else
2760         {
2761             _secVideoCloseConverter (pPort);
2762             _secVideoCloseOutBuffer (pPort, TRUE);
2763         }
2764     }
2765
2766     if (pPort->d.id == FOURCC_SR32 &&
2767         pPort->in_crop.width == pPort->out_crop.width &&
2768         pPort->in_crop.height == pPort->out_crop.height &&
2769         pPort->hw_rotate == 0)
2770         pPort->inbuf_is_fb = TRUE;
2771     else
2772         pPort->inbuf_is_fb = FALSE;
2773
2774     inbuf = _secVideoGetInbuf (pPort);
2775     if (!inbuf)
2776         return BadRequest;
2777
2778     /* punch here not only LCD but also HDMI. */
2779     if (pPort->drawing == ON_FB)
2780         _secVideoPunchDrawable (pPort);
2781
2782     /* HDMI */
2783     if (output & OUTPUT_EXT)
2784         tvout = _secVideoPutImageTvout (pPort, output, inbuf);
2785     else
2786     {
2787         _secVideoUngrabTvout (pPort);
2788
2789         SECWb *wb = secWbGet ();
2790         if (wb)
2791             secWbSetSecure (wb, pPort->secure);
2792     }
2793
2794     /* LCD */
2795     if (output & OUTPUT_LCD)
2796     {
2797         SECPtr pSec = SECPTR (pScrn);
2798
2799         if (pSec->isLcdOff)
2800             XDBG_TRACE (MVDO, "port(%d) put image after dpms off.\n", pPort->index);
2801         else if (pPort->inbuf_is_fb)
2802             lcdout = _secVideoPutImageInbuf (pPort, inbuf);
2803         else
2804             lcdout = _secVideoPutImageInternal (pPort, inbuf);
2805     }
2806
2807     if (lcdout || tvout)
2808     {
2809         ret = Success;
2810     }
2811     else
2812     {
2813         if (IS_ZEROCOPY (pPort->d.id))
2814         {
2815             int i;
2816
2817             for (i = 0; i < INBUF_NUM; i++)
2818                 if (pPort->inbuf[i] == inbuf)
2819                 {
2820                     pPort->inbuf[i] = NULL;
2821                     secUtilRemoveFreeVideoBufferFunc (inbuf, _secVideoFreeInbuf, pPort);
2822                     break;
2823                 }
2824             XDBG_WARNING_IF_FAIL (inbuf->ref_cnt == 1);
2825         }
2826         else
2827             XDBG_WARNING_IF_FAIL (inbuf->ref_cnt == 2);
2828
2829         ret = BadRequest;
2830     }
2831
2832     /* decrease ref_cnt here to pass ownership of inbuf to converter or tvout.
2833      * in case of zero-copy, it will be really freed
2834      * when converting is finished or tvout is finished.
2835      */
2836     secUtilVideoBufferUnref (inbuf);
2837
2838     pPort->old_d = pPort->d;
2839     pPort->old_output = output;
2840
2841     XDBG_TRACE (MVDO, "=======================================.. \n");
2842
2843     return ret;
2844 }
2845
2846 static int
2847 SECVideoDDPutImage (ClientPtr client,
2848                DrawablePtr pDraw,
2849                XvPortPtr pPort,
2850                GCPtr pGC,
2851                INT16 src_x, INT16 src_y,
2852                CARD16 src_w, CARD16 src_h,
2853                INT16 drw_x, INT16 drw_y,
2854                CARD16 drw_w, CARD16 drw_h,
2855                XvImagePtr format,
2856                unsigned char *data, Bool sync, CARD16 width, CARD16 height)
2857 {
2858     SECVideoPortInfo *info = _port_info (pDraw);
2859     int ret;
2860
2861     if (info)
2862     {
2863         info->client = client;
2864         info->pp = pPort;
2865     }
2866
2867     ret = ddPutImage (client, pDraw, pPort, pGC,
2868                       src_x, src_y, src_w, src_h,
2869                       drw_x, drw_y, drw_w, drw_h,
2870                       format, data, sync, width, height);
2871
2872     return ret;
2873 }
2874
2875 static void
2876 SECVideoStop (ScrnInfoPtr pScrn, pointer data, Bool exit)
2877 {
2878     SECPortPrivPtr pPort = (SECPortPrivPtr) data;
2879
2880     if (!exit)
2881         return;
2882
2883     XDBG_DEBUG (MVDO, "exit (%d) \n", exit);
2884
2885     _secVideoStreamOff (pPort);
2886
2887     pPort->preemption = 0;
2888     pPort->rotate = 0;
2889     pPort->hflip = 0;
2890     pPort->vflip = 0;
2891     pPort->punched = FALSE;
2892 }
2893
2894 /**
2895  * Set up all our internal structures.
2896  */
2897 static XF86VideoAdaptorPtr
2898 secVideoSetupImageVideo (ScreenPtr pScreen)
2899 {
2900     XF86VideoAdaptorPtr pAdaptor;
2901     SECPortPrivPtr pPort;
2902     int i;
2903
2904     pAdaptor = calloc (1, sizeof (XF86VideoAdaptorRec) +
2905                        (sizeof (DevUnion) + sizeof (SECPortPriv)) * SEC_MAX_PORT);
2906     if (!pAdaptor)
2907         return NULL;
2908
2909     dummy_encoding[0].width = pScreen->width;
2910     dummy_encoding[0].height = pScreen->height;
2911
2912     pAdaptor->type = XvWindowMask | XvPixmapMask | XvInputMask | XvImageMask;
2913     pAdaptor->flags = VIDEO_OVERLAID_IMAGES;
2914     pAdaptor->name = "SEC supporting Software Video Conversions";
2915     pAdaptor->nEncodings = sizeof (dummy_encoding) / sizeof (XF86VideoEncodingRec);
2916     pAdaptor->pEncodings = dummy_encoding;
2917     pAdaptor->nFormats = NUM_FORMATS;
2918     pAdaptor->pFormats = formats;
2919     pAdaptor->nPorts = SEC_MAX_PORT;
2920     pAdaptor->pPortPrivates = (DevUnion*)(&pAdaptor[1]);
2921
2922     pPort =
2923         (SECPortPrivPtr) (&pAdaptor->pPortPrivates[SEC_MAX_PORT]);
2924
2925     for (i = 0; i < SEC_MAX_PORT; i++)
2926     {
2927         pAdaptor->pPortPrivates[i].ptr = &pPort[i];
2928         pPort[i].index = i;
2929         pPort[i].usr_output = OUTPUT_LCD|OUTPUT_EXT;
2930         pPort[i].outbuf_cvting = -1;
2931     }
2932
2933     pAdaptor->nAttributes = NUM_ATTRIBUTES;
2934     pAdaptor->pAttributes = attributes;
2935     pAdaptor->nImages = NUM_IMAGES;
2936     pAdaptor->pImages = images;
2937
2938     pAdaptor->GetPortAttribute     = SECVideoGetPortAttribute;
2939     pAdaptor->SetPortAttribute     = SECVideoSetPortAttribute;
2940     pAdaptor->QueryBestSize        = SECVideoQueryBestSize;
2941     pAdaptor->QueryImageAttributes = SECVideoQueryImageAttributes;
2942     pAdaptor->PutImage             = SECVideoPutImage;
2943     pAdaptor->StopVideo            = SECVideoStop;
2944
2945     if (!_secVideoRegisterEventResourceTypes ())
2946     {
2947         ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2948         xf86DrvMsg (pScrn->scrnIndex, X_ERROR, "Failed to register EventResourceTypes. \n");
2949         return FALSE;
2950     }
2951
2952     return pAdaptor;
2953 }
2954
2955 static void
2956 SECVideoReplacePutImageFunc (ScreenPtr pScreen)
2957 {
2958     int i;
2959
2960     XvScreenPtr xvsp = dixLookupPrivate (&pScreen->devPrivates,
2961                                          XvGetScreenKey());
2962     if (!xvsp)
2963         return;
2964
2965     for (i = 0; i < xvsp->nAdaptors; i++)
2966     {
2967         XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
2968         if (pAdapt->ddPutImage)
2969         {
2970             ddPutImage = pAdapt->ddPutImage;
2971             pAdapt->ddPutImage = SECVideoDDPutImage;
2972             break;
2973         }
2974     }
2975
2976     if (!dixRegisterPrivateKey (VideoPortKey, PRIVATE_WINDOW, sizeof (SECVideoPortInfo)))
2977         return;
2978     if (!dixRegisterPrivateKey (VideoPortKey, PRIVATE_PIXMAP, sizeof (SECVideoPortInfo)))
2979         return;
2980 }
2981
2982 #ifdef XV
2983 /**
2984  * Set up everything we need for Xv.
2985  */
2986 Bool secVideoInit (ScreenPtr pScreen)
2987 {
2988     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2989     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
2990     SECVideoPrivPtr pVideo;
2991
2992     pVideo = (SECVideoPrivPtr)calloc (sizeof (SECVideoPriv), 1);
2993     if (!pVideo)
2994         return FALSE;
2995
2996     pVideo->pAdaptor[0] = secVideoSetupImageVideo (pScreen);
2997     if (!pVideo->pAdaptor[0])
2998     {
2999         free (pVideo);
3000         return FALSE;
3001     }
3002
3003     pVideo->pAdaptor[1] = secVideoSetupVirtualVideo (pScreen);
3004     if (!pVideo->pAdaptor[1])
3005     {
3006         free (pVideo->pAdaptor[0]);
3007         free (pVideo);
3008         return FALSE;
3009     }
3010
3011     pVideo->pAdaptor[2] = secVideoSetupDisplayVideo (pScreen);
3012     if (!pVideo->pAdaptor[2])
3013     {
3014         free (pVideo->pAdaptor[1]);
3015         free (pVideo->pAdaptor[0]);
3016         free (pVideo);
3017         return FALSE;
3018     }
3019
3020     xf86XVScreenInit (pScreen, pVideo->pAdaptor, ADAPTOR_NUM);
3021
3022     SECVideoReplacePutImageFunc (pScreen);
3023     secVirtualVideoReplacePutStillFunc (pScreen);
3024
3025     if(registered_handler == FALSE)
3026     {
3027         RegisterBlockAndWakeupHandlers(_secVideoBlockHandler,
3028                                        (WakeupHandlerProcPtr)NoopDDA, pScrn);
3029         registered_handler = TRUE;
3030     }
3031
3032     pSec->pVideoPriv = pVideo;
3033     xorg_list_init (&layer_owners);
3034
3035     return TRUE;
3036 }
3037
3038 /**
3039  * Shut down Xv, used on regeneration.
3040  */
3041 void secVideoFini (ScreenPtr pScreen)
3042 {
3043     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
3044     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
3045     SECVideoPrivPtr pVideo = pSec->pVideoPriv;
3046     SECPortPrivPtr pCur = NULL, pNext = NULL;
3047     int i;
3048
3049     xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
3050     {
3051         if (pCur->tv)
3052         {
3053             secVideoTvDisconnect (pCur->tv);
3054             pCur->tv = NULL;
3055         }
3056
3057         if (pCur->d.clip_boxes)
3058         {
3059             RegionDestroy (pCur->d.clip_boxes);
3060             pCur->d.clip_boxes = NULL;
3061         }
3062     }
3063
3064     for (i = 0; i < ADAPTOR_NUM; i++)
3065         if (pVideo->pAdaptor[i])
3066             free (pVideo->pAdaptor[i]);
3067
3068     free (pVideo);
3069     pSec->pVideoPriv= NULL;
3070 }
3071
3072 #endif
3073
3074 void
3075 secVideoDpms (ScrnInfoPtr pScrn, Bool on)
3076 {
3077     if (!on)
3078     {
3079         SECPtr pSec = (SECPtr) pScrn->driverPrivate;
3080         XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0];
3081         int i;
3082
3083         for (i = 0; i < SEC_MAX_PORT; i++)
3084         {
3085             SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
3086             if (pPort->stream_cnt == 0)
3087                 continue;
3088             XDBG_TRACE (MVDO, "port(%d) cvt stop.\n", pPort->index);
3089             _secVideoCloseConverter (pPort);
3090             _secVideoCloseInBuffer (pPort);
3091         }
3092     }
3093 }
3094
3095 void
3096 secVideoScreenRotate (ScrnInfoPtr pScrn, int degree)
3097 {
3098     SECPtr pSec = SECPTR(pScrn);
3099     SECVideoPrivPtr pVideo = pSec->pVideoPriv;
3100     int old_degree;
3101
3102     if (pVideo->screen_rotate_degree == degree)
3103         return;
3104
3105     old_degree = pVideo->screen_rotate_degree;
3106     pVideo->screen_rotate_degree = degree;
3107     XDBG_DEBUG (MVDO, "screen rotate degree: %d\n", degree);
3108
3109     if (pSec->isLcdOff)
3110         return;
3111
3112     SECPortPrivPtr pCur = NULL, pNext = NULL;
3113     xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
3114     {
3115         SECModePtr pSecMode = pSec->pSecMode;
3116         SECVideoBuf *old_vbuf, *rot_vbuf;
3117         xRectangle rot_rect, dst_rect;
3118         int rot_width, rot_height;
3119         int scn_width, scn_height;
3120         int degree_diff = degree - old_degree;
3121
3122         if (!pCur->layer)
3123             continue;
3124
3125         old_vbuf = secLayerGetBuffer (pCur->layer);
3126         XDBG_RETURN_IF_FAIL (old_vbuf != NULL);
3127
3128         rot_width = old_vbuf->width;
3129         rot_height = old_vbuf->height;
3130         rot_rect = old_vbuf->crop;
3131         secUtilRotateArea (&rot_width, &rot_height, &rot_rect, degree_diff);
3132
3133         rot_vbuf = secUtilAllocVideoBuffer (pScrn, FOURCC_RGB32, rot_width, rot_height,
3134                                          (pSec->scanout)?TRUE:FALSE, FALSE, pCur->secure);
3135         XDBG_RETURN_IF_FAIL (rot_vbuf != NULL);
3136         rot_vbuf->crop = rot_rect;
3137
3138         secUtilConvertBos (pScrn, 0,
3139                            old_vbuf->bo[0], old_vbuf->width, old_vbuf->height, &old_vbuf->crop, old_vbuf->width*4,
3140                            rot_vbuf->bo[0], rot_vbuf->width, rot_vbuf->height, &rot_vbuf->crop, rot_vbuf->width*4,
3141                            FALSE, degree_diff);
3142
3143         tbm_bo_map (rot_vbuf->bo[0], TBM_DEVICE_2D, TBM_OPTION_READ);
3144         tbm_bo_unmap (rot_vbuf->bo[0]);
3145
3146         secLayerGetRect (pCur->layer, NULL, &dst_rect);
3147
3148         scn_width = (old_degree % 180)?pSecMode->main_lcd_mode.vdisplay:pSecMode->main_lcd_mode.hdisplay;
3149         scn_height = (old_degree % 180)?pSecMode->main_lcd_mode.hdisplay:pSecMode->main_lcd_mode.vdisplay;
3150
3151         secUtilRotateRect (scn_width, scn_height, &dst_rect, degree_diff);
3152
3153         secLayerFreezeUpdate (pCur->layer, TRUE);
3154         secLayerSetRect (pCur->layer, &rot_vbuf->crop, &dst_rect);
3155         secLayerFreezeUpdate (pCur->layer, FALSE);
3156         secLayerSetBuffer (pCur->layer, rot_vbuf);
3157
3158         secUtilVideoBufferUnref (rot_vbuf);
3159
3160         _secVideoCloseConverter (pCur);
3161     }
3162 }
3163
3164 void
3165 secVideoSwapLayers (ScreenPtr pScreen)
3166 {
3167     SECPortPrivPtr pCur = NULL, pNext = NULL;
3168     SECPortPrivPtr pPort1 = NULL, pPort2 = NULL;
3169
3170     xorg_list_for_each_entry_safe (pCur, pNext, &layer_owners, link)
3171     {
3172         if (!pPort1)
3173             pPort1 = pCur;
3174         else if (!pPort2)
3175             pPort2 = pCur;
3176     }
3177
3178     if (pPort1 && pPort2)
3179     {
3180         secLayerSwapPos (pPort1->layer, pPort2->layer);
3181         XDBG_TRACE (MVDO, "%p : %p \n", pPort1->layer, pPort2->layer);
3182     }
3183 }
3184
3185 Bool
3186 secVideoIsSecureMode (ScrnInfoPtr pScrn)
3187 {
3188     SECPtr pSec = (SECPtr) pScrn->driverPrivate;
3189     XF86VideoAdaptorPtr pAdaptor = pSec->pVideoPriv->pAdaptor[0];
3190     int i;
3191
3192     for (i = 0; i < SEC_MAX_PORT; i++)
3193     {
3194         SECPortPrivPtr pPort = (SECPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
3195         if (pPort->secure)
3196         {
3197             XDBG_TRACE (MVDO, "pPort(%d) is secure.\n", pPort->index);
3198             return TRUE;
3199         }
3200     }
3201
3202     XDBG_TRACE (MVDO, "no secure port.\n");
3203
3204     return FALSE;
3205 }