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