Fix flickering resized video frame.
[platform/adaptation/samsung_exynos/xf86-video-exynos.git] / src / crtcconfig / sec_layer.c
1 /**************************************************************************
2
3 xserver-xorg-video-exynos
4
5 Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: Boram Park <boram1288.park@samsung.com>
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <sys/ioctl.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <stdlib.h>
39
40 #include "sec.h"
41 #include "sec_util.h"
42 #include "sec_crtc.h"
43 #include "sec_output.h"
44 #include "sec_plane.h"
45 #include "sec_layer.h"
46 #include "sec_video_fourcc.h"
47 #include "sec_video_tvout.h"
48 #include "sec_video_virtual.h"
49
50 #include "common.h"
51
52 //#define DEBUG_REFCNT
53
54 #ifdef DEBUG_REFCNT
55 #define SEC_LAYER_PRINT_REFCNT(b) \
56             XDBG_TRACE(MLYR, "layer(%p) ref_cnt(%d) \n", b, b->ref_cnt)
57 #else
58 #define SEC_LAYER_PRINT_REFCNT(b)
59 #endif
60
61 typedef struct _NotifyFuncData
62 {
63     NotifyFunc  func;
64     void       *user_data;
65
66     struct xorg_list link;
67 } NotifyFuncData;
68
69 struct _SECLayer
70 {
71     ScrnInfoPtr    pScrn;
72
73     SECLayerOutput output;
74     SECLayerPos lpos;
75
76     int         plane_id;
77     int         crtc_id;
78
79     /* for buffer */
80     int         fb_id;
81
82     int         offset_x;
83     int         offset_y;
84
85     xRectangle *src;
86     xRectangle *dst;
87
88     SECVideoBuf *vbuf;
89     Bool         visible;
90
91     /* vblank */
92     Bool        enable_vblank;
93     Bool        wait_vblank;
94     SECVideoBuf *wait_vbuf;
95     SECVideoBuf *pending_vbuf;
96     SECVideoBuf *showing_vbuf;
97
98     struct xorg_list noti_data;
99     struct xorg_list link;
100
101     Bool onoff;
102     int ref_cnt;
103     Bool freeze_update;
104
105     /* count */
106     unsigned int put_counts;
107     OsTimerPtr timer;
108 };
109
110 static Bool crtc_layers_init;
111 static struct xorg_list crtc_layers;
112 static Bool wait_vblank[LAYER_OUTPUT_MAX];
113
114 #define LAYER_VBLANK_FLAG 0xFFFF
115
116 static CARD32
117 _countPrint (OsTimerPtr timer, CARD32 now, pointer arg)
118 {
119     SECLayer *layer = (SECLayer*)arg;
120
121     if (layer->timer)
122     {
123         TimerFree (layer->timer);
124         layer->timer = NULL;
125     }
126
127     XDBG_DEBUG (MEXA, "crtc(%d) pos(%d) : %d fps. \n",
128             layer->crtc_id, layer->lpos, layer->put_counts);
129
130     layer->put_counts = 0;
131
132     return 0;
133 }
134
135 static void
136 _countFps (SECLayer *layer)
137 {
138     layer->put_counts++;
139
140     if (layer->timer)
141         return;
142
143     layer->timer = TimerSet (NULL, 0, 1000, _countPrint, layer);
144 }
145
146 static void
147 _secLayerInitList (void)
148 {
149     if (!crtc_layers_init)
150     {
151         xorg_list_init (&crtc_layers);
152         crtc_layers_init = TRUE;
153     }
154 }
155
156 static void
157 _secLayerNotify (SECLayer *layer, int type, void *type_data)
158 {
159     NotifyFuncData *data = NULL, *data_next = NULL;
160
161     xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link)
162     {
163         if (data->func)
164             data->func (layer, type, type_data, data->user_data);
165     }
166 }
167
168 static int
169 _GetCrtcIdForOutput (ScrnInfoPtr pScrn, SECLayerOutput output)
170 {
171     SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
172     SECOutputPrivPtr pOutputPriv = NULL;
173     int crtc_id = 0;
174
175     switch (output)
176     {
177     case LAYER_OUTPUT_LCD:
178         pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_LVDS);
179         if (!pOutputPriv)
180             pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_Unknown);
181         if (pOutputPriv && pOutputPriv->mode_encoder)
182             crtc_id = pOutputPriv->mode_encoder->crtc_id;
183         break;
184     case LAYER_OUTPUT_EXT:
185         if (pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI)
186         {
187             pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_HDMIA);
188             if (!pOutputPriv)
189                 pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_HDMIB);
190             if (pOutputPriv && pOutputPriv->mode_encoder)
191                 crtc_id = pOutputPriv->mode_encoder->crtc_id;
192         }
193         else if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
194         {
195             pOutputPriv = secOutputGetPrivateForConnType (pScrn, DRM_MODE_CONNECTOR_VIRTUAL);
196             if (pOutputPriv && pOutputPriv->mode_encoder)
197                 crtc_id = pOutputPriv->mode_encoder->crtc_id;
198         }
199         break;
200     default:
201         break;
202     }
203
204     XDBG_DEBUG (MLYR, "crtc(%d) for output(%d) \n", crtc_id, output);
205
206     if (crtc_id == 0)
207         XDBG_ERROR (MLYR, "no crtc for output(%d) \n", output);
208
209     return crtc_id;
210 }
211
212 static int
213 _GetCrtcID (SECLayer *layer)
214 {
215     if (layer->crtc_id > 0)
216         return layer->crtc_id;
217
218     layer->crtc_id = _GetCrtcIdForOutput (layer->pScrn, layer->output);
219
220     XDBG_RETURN_VAL_IF_FAIL (layer->crtc_id > 0, 0);
221
222     return layer->crtc_id;
223 }
224
225 static int
226 _secLayerGetPlanePos (SECLayer *layer, SECLayerPos lpos)
227 {
228     if (layer->output == LAYER_OUTPUT_LCD)
229     {
230         XDBG_DEBUG (MLYR, "lpos(%d) => ppos(%d) (1)\n", lpos, PLANE_POS_3 + lpos);
231         return PLANE_POS_3 + lpos;
232     }
233     else if (layer->output == LAYER_OUTPUT_EXT)
234     {
235         if (lpos == -1)
236         {
237             XDBG_DEBUG (MLYR, "lpos(%d) => ppos(%d) (2)\n", lpos, PLANE_POS_2);
238             return PLANE_POS_2;
239         }
240         else
241         {
242             XDBG_DEBUG (MLYR, "lpos(%d) => ppos(%d) (3)\n", lpos, PLANE_POS_0 + lpos);
243             return PLANE_POS_0 + lpos;
244         }
245     }
246     else
247     {
248         XDBG_NEVER_GET_HERE (MLYR);
249     }
250
251     return -1;
252 }
253
254 static void
255 _secLayerDestroy (SECLayer *layer)
256 {
257     NotifyFuncData *data = NULL, *data_next = NULL;
258
259     XDBG_RETURN_IF_FAIL (layer != NULL);
260
261     xorg_list_del (&layer->link);
262
263     if (layer->src)
264         free (layer->src);
265     if (layer->dst)
266         free (layer->dst);
267
268     if (layer->wait_vbuf)
269         secUtilVideoBufferUnref (layer->wait_vbuf);
270     if (layer->pending_vbuf)
271         secUtilVideoBufferUnref (layer->pending_vbuf);
272     if (layer->showing_vbuf)
273         secUtilVideoBufferUnref (layer->showing_vbuf);
274     if (layer->vbuf)
275     {
276         secUtilVideoBufferUnref (layer->vbuf);
277         layer->vbuf = NULL;
278     }
279
280     XDBG_TRACE (MLYR, "layer(%p) destroyed. \n", layer);
281     SEC_LAYER_PRINT_REFCNT (layer);
282
283     _secLayerNotify (layer, LAYER_DESTROYED, NULL);
284
285     xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link)
286     {
287         xorg_list_del (&data->link);
288         free (data);
289     }
290
291     if (layer->plane_id > 0)
292         secPlaneFreeId (layer->plane_id);
293
294     free (layer);
295 }
296
297 static void
298 _secLayerWatchVblank (SECLayer *layer)
299 {
300     CARD64 ust, msc, target_msc;
301     int pipe, flip = 1;
302     SECPtr pSec = SECPTR (layer->pScrn);
303
304     /* if lcd is off, do not request vblank information */
305 #ifdef NO_CRTC_MODE
306     if (pSec->isCrtcOn == FALSE)
307         return;
308     else
309 #endif //NO_CRTC_MODE
310     if (pSec->isLcdOff)
311     {
312         XDBG_DEBUG(MLYR, "pSec->isLcdOff (%d)\n", pSec->isLcdOff);
313         return;
314     }
315
316     pipe = secDisplayCrtcPipe (layer->pScrn, _GetCrtcID (layer));
317
318     layer->wait_vblank = TRUE;
319
320     if (wait_vblank[pipe])
321         return;
322
323     wait_vblank[pipe] = TRUE;
324
325     if (!secDisplayGetCurMSC (layer->pScrn, pipe, &ust, &msc))
326         XDBG_WARNING (MLYR, "fail to get current_msc.\n");
327
328     target_msc = msc + 1;
329
330     XDBG_TRACE (MLYR, "layer(%p) wait vblank : cur(%lld) target(%lld). \n",
331                 layer, msc, target_msc);
332
333     if (!secDisplayVBlank (layer->pScrn, pipe, &target_msc, flip, VBLANK_INFO_PLANE, (void*)pipe))
334         XDBG_WARNING (MLYR, "fail to Vblank.\n");
335 }
336
337 static Bool
338 _secLayerShowInternal (SECLayer *layer, Bool need_update)
339 {
340     int crtc_id, plane_pos;
341
342     XDBG_RETURN_VAL_IF_FAIL (layer->fb_id > 0, FALSE);
343
344     crtc_id = _GetCrtcID (layer);
345     plane_pos = _secLayerGetPlanePos (layer, layer->lpos);
346
347     if (!secPlaneShow (layer->plane_id, crtc_id,
348                        layer->src->x, layer->src->y,
349                        layer->src->width, layer->src->height,
350                        layer->offset_x + layer->dst->x,
351                        layer->offset_y + layer->dst->y,
352                        layer->dst->width, layer->dst->height,
353                        plane_pos, need_update))
354         return FALSE;
355
356     return TRUE;
357 }
358
359 static void
360 _secLayerGetBufferID (SECLayer *layer, SECVideoBuf *vbuf)
361 {
362     SECModePtr pSecMode;
363     unsigned int drmfmt;
364     unsigned int handles[4] = {0,};
365     unsigned int pitches[4] = {0,};
366     unsigned int offsets[4] = {0,};
367     int i;
368
369     if (vbuf->fb_id > 0)
370         return;
371
372     pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
373     drmfmt = secUtilGetDrmFormat (vbuf->id);
374
375     for (i = 0 ; i < PLANAR_CNT; i++)
376     {
377         handles[i] = (unsigned int)vbuf->handles[i];
378         pitches[i] = (unsigned int)vbuf->pitches[i];
379         offsets[i] = (unsigned int)vbuf->offsets[i];
380     }
381
382     if (drmModeAddFB2 (pSecMode->fd, vbuf->width, vbuf->height, drmfmt,
383                        handles, pitches, offsets, &vbuf->fb_id, 0))
384     {
385         XDBG_ERRNO (MLYR, "drmModeAddFB2 failed. handles(%d %d %d) pitches(%d %d %d) offsets(%d %d %d) '%c%c%c%c'\n",
386                     handles[0], handles[1], handles[2],
387                     pitches[0], pitches[1], pitches[2],
388                     offsets[0], offsets[1], offsets[2],
389                     FOURCC_STR (drmfmt));
390     }
391
392     XDBG_DEBUG (MVBUF, "layer(%p) vbuf(%ld) fb_id(%d) added. \n", layer, vbuf->stamp, vbuf->fb_id);
393 }
394
395 Bool
396 secLayerSupport (ScrnInfoPtr pScrn, SECLayerOutput output, SECLayerPos lpos, unsigned int id)
397 {
398     SECModePtr pSecMode;
399
400     XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, FALSE);
401     XDBG_RETURN_VAL_IF_FAIL (output < LAYER_OUTPUT_MAX, FALSE);
402
403     pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
404
405     if (output == LAYER_OUTPUT_EXT && lpos == LAYER_LOWER1)
406     {
407         if (pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI)
408         {
409             if (id == FOURCC_SN12 || id == FOURCC_ST12)
410                 return TRUE;
411             else
412                 return FALSE;
413         }
414         else if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
415         {
416             if (id == FOURCC_SN12 || id == FOURCC_RGB32)
417                 return TRUE;
418             else
419                 return FALSE;
420         }
421     }
422
423     return (id == FOURCC_RGB32 || id == FOURCC_SR32) ? TRUE : FALSE;
424 }
425
426 SECLayer*
427 secLayerFind (SECLayerOutput output, SECLayerPos lpos)
428 {
429     SECLayer *layer = NULL, *layer_next = NULL;
430
431     XDBG_RETURN_VAL_IF_FAIL (output < LAYER_OUTPUT_MAX, NULL);
432
433     _secLayerInitList ();
434
435     xorg_list_for_each_entry_safe (layer, layer_next, &crtc_layers, link)
436     {
437         if (layer->output == output && layer->lpos == lpos)
438             return layer;
439     }
440
441     return NULL;
442 }
443
444 void
445 secLayerDestroyAll (void)
446 {
447     SECLayer *layer = NULL, *layer_next = NULL;
448
449     _secLayerInitList ();
450
451     xorg_list_for_each_entry_safe (layer, layer_next, &crtc_layers, link)
452     {
453         _secLayerDestroy (layer);
454     }
455 }
456
457 void
458 secLayerShowAll (ScrnInfoPtr pScrn, SECLayerOutput output)
459 {
460     int crtc_id = _GetCrtcIdForOutput (pScrn, output);
461
462     secPlaneShowAll (crtc_id);
463 }
464
465 SECLayer*
466 secLayerCreate (ScrnInfoPtr pScrn, SECLayerOutput output, SECLayerPos lpos)
467 {
468     SECLayer* layer;
469
470     XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL);
471     XDBG_RETURN_VAL_IF_FAIL (output < LAYER_OUTPUT_MAX, NULL);
472     XDBG_RETURN_VAL_IF_FAIL (lpos != LAYER_DEFAULT, NULL);
473
474     layer = secLayerFind (output, lpos);
475     if (layer)
476     {
477         XDBG_ERROR (MLYR, "layer(%p) already is at output(%d) lpos(%d). \n",
478                     layer, output, lpos);
479
480         return NULL;
481     }
482
483     layer = calloc (sizeof (SECLayer), 1);
484     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL);
485
486     layer->pScrn = pScrn;
487     layer->output = output;
488     layer->lpos = lpos;
489
490     layer->plane_id = secPlaneGetID ();
491     if (layer->plane_id < 0)
492     {
493         free (layer);
494         return NULL;
495     }
496
497     layer->ref_cnt = 1;
498     xorg_list_init (&layer->noti_data);
499
500     _secLayerInitList ();
501
502     xorg_list_add(&layer->link, &crtc_layers);
503
504     XDBG_TRACE (MLYR, "layer(%p) output(%d) lpos(%d) created. \n", layer, output, lpos);
505     SEC_LAYER_PRINT_REFCNT (layer);
506
507     return layer;
508 }
509
510 SECLayer*
511 secLayerRef (SECLayer* layer)
512 {
513     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL);
514
515     layer->ref_cnt++;
516
517     SEC_LAYER_PRINT_REFCNT (layer);
518
519     return layer;
520 }
521
522 void
523 secLayerUnref (SECLayer* layer)
524 {
525     XDBG_RETURN_IF_FAIL (layer != NULL);
526
527     layer->ref_cnt--;
528
529     SEC_LAYER_PRINT_REFCNT (layer);
530
531     if (layer->ref_cnt == 0)
532     {
533         secLayerHide (layer);
534         _secLayerDestroy (layer);
535     }
536 }
537
538 void
539 secLayerAddNotifyFunc (SECLayer* layer, NotifyFunc func, void *user_data)
540 {
541     NotifyFuncData *data = NULL, *data_next = NULL;
542
543     XDBG_RETURN_IF_FAIL (layer != NULL);
544     XDBG_RETURN_IF_FAIL (func != NULL);
545
546     xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link)
547     {
548         if (data->func == func && data->user_data == user_data)
549             return;
550     }
551
552     data = calloc (sizeof (NotifyFuncData), 1);
553     XDBG_RETURN_IF_FAIL (data != NULL);
554
555     data->func      = func;
556     data->user_data = user_data;
557
558     xorg_list_add (&data->link, &layer->noti_data);
559 }
560
561 void
562 secLayerRemoveNotifyFunc (SECLayer* layer, NotifyFunc func)
563 {
564     NotifyFuncData *data = NULL, *data_next = NULL;
565
566     XDBG_RETURN_IF_FAIL (layer != NULL);
567     XDBG_RETURN_IF_FAIL (func != NULL);
568
569     xorg_list_for_each_entry_safe (data, data_next, &layer->noti_data, link)
570     {
571         if (data->func == func)
572         {
573             xorg_list_del (&data->link);
574             free (data);
575         }
576     }
577 }
578
579 Bool
580 secLayerIsVisible (SECLayer *layer)
581 {
582     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
583
584     return layer->visible;
585 }
586
587 void
588 secLayerShow (SECLayer *layer)
589 {
590     SECModePtr pSecMode;
591
592     XDBG_RETURN_IF_FAIL (layer != NULL);
593     XDBG_RETURN_IF_FAIL (layer->fb_id > 0);
594
595     pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
596
597     if (layer->visible)
598         return;
599 #if 1
600     if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
601     {
602         layer->visible = TRUE;
603         XDBG_TRACE (MLYR, "layer(%p) shown. \n", layer);
604         return;
605     }
606 #endif
607     if (!_secLayerShowInternal (layer, FALSE))
608         return;
609
610     if (layer->enable_vblank)
611         _secLayerWatchVblank (layer);
612
613     layer->visible = TRUE;
614
615     XDBG_TRACE (MLYR, "layer(%p) shown. \n", layer);
616
617     _secLayerNotify (layer, LAYER_SHOWN, (void*)layer->fb_id);
618 }
619
620 void
621 secLayerHide (SECLayer *layer)
622 {
623     SECModePtr pSecMode;
624
625     XDBG_RETURN_IF_FAIL (layer != NULL);
626
627     pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
628 #if 1
629     if (!layer->visible || layer->ref_cnt > 1)
630         return;
631
632     if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
633     {
634         layer->visible = FALSE;
635         XDBG_TRACE (MLYR, "layer(%p) hidden. \n", layer);
636         return;
637     }
638 #endif
639     if (!secPlaneHide (layer->plane_id))
640         return;
641
642     if (layer->wait_vbuf && VBUF_IS_VALID (layer->wait_vbuf))
643     {
644         layer->wait_vbuf->showing = FALSE;
645         XDBG_DEBUG (MVBUF, "layer(%p) <-- %s (%ld,%d,%d) \n", layer,
646                     (layer->output==LAYER_OUTPUT_LCD)?"LCD":"TV",
647                     layer->wait_vbuf->stamp, VBUF_IS_CONVERTING (layer->wait_vbuf),
648                     layer->wait_vbuf->showing);
649         secUtilVideoBufferUnref (layer->wait_vbuf);
650     }
651
652     if (layer->pending_vbuf && VBUF_IS_VALID (layer->pending_vbuf))
653     {
654         layer->pending_vbuf->showing = FALSE;
655         secUtilVideoBufferUnref (layer->pending_vbuf);
656     }
657
658     if (layer->showing_vbuf && VBUF_IS_VALID (layer->showing_vbuf))
659     {
660         layer->showing_vbuf->showing = FALSE;
661         XDBG_DEBUG (MVBUF, "layer(%p) <-- %s (%ld,%d,%d) \n", layer,
662                     (layer->output==LAYER_OUTPUT_LCD)?"LCD":"TV",
663                     layer->showing_vbuf->stamp, VBUF_IS_CONVERTING (layer->showing_vbuf),
664                     layer->showing_vbuf->showing);
665         secUtilVideoBufferUnref (layer->showing_vbuf);
666     }
667
668     layer->showing_vbuf = NULL;
669     layer->pending_vbuf = NULL;
670     layer->wait_vbuf = NULL;
671     layer->wait_vblank = FALSE;
672     layer->visible = FALSE;
673     layer->crtc_id = 0;
674
675     XDBG_TRACE (MLYR, "layer(%p) hidden. \n", layer);
676
677     _secLayerNotify (layer, LAYER_HIDDEN, (void*)layer->fb_id);
678 }
679
680 void
681 secLayerFreezeUpdate (SECLayer *layer, Bool enable)
682 {
683     XDBG_RETURN_IF_FAIL (layer != NULL);
684
685     layer->freeze_update = enable;
686
687     XDBG_TRACE (MLYR, "layer(%p) freeze %d. \n", layer, enable);
688
689     if (layer->plane_id > 0)
690         secPlaneFreezeUpdate (layer->plane_id, enable);
691 }
692
693 void
694 secLayerUpdate (SECLayer *layer)
695 {
696     SECModePtr pSecMode;
697
698     XDBG_RETURN_IF_FAIL (layer != NULL);
699     XDBG_RETURN_IF_FAIL (layer->fb_id > 0);
700
701     pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
702
703     if (!layer->visible)
704         return;
705
706     xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (layer->pScrn);
707     SECCrtcPrivPtr pCrtcPriv = NULL;
708     int c;
709
710     for (c = 0; c < pCrtcConfig->num_crtc; c++)
711     {
712         xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c];
713         SECCrtcPrivPtr pTemp =  pCrtc->driver_private;
714         if (pTemp == NULL)
715             continue;
716         if (pTemp->mode_crtc && pTemp->mode_crtc->crtc_id == layer->crtc_id)
717         {
718             pCrtcPriv = pTemp;
719             break;
720         }
721     }
722
723     if (!pCrtcPriv || !pCrtcPriv->bAccessibility)
724         return;
725
726     if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
727         return;
728
729     if (!_secLayerShowInternal (layer, TRUE))
730         return;
731 }
732
733 void
734 secLayerTurn (SECLayer *layer, Bool onoff, Bool user)
735 {
736     XDBG_RETURN_IF_FAIL (layer != NULL);
737
738     secPlaneTrun (layer->plane_id, onoff, user);
739 }
740
741 Bool
742 secLayerTurnStatus (SECLayer *layer)
743 {
744     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
745
746     return secPlaneTrunStatus (layer->plane_id);
747 }
748
749 void
750 secLayerEnableVBlank (SECLayer *layer, Bool enable)
751 {
752     XDBG_RETURN_IF_FAIL (layer != NULL);
753
754     layer->enable_vblank = (enable) ? TRUE : FALSE;
755 }
756
757 Bool
758 secLayerSetOffset (SECLayer *layer, int x, int y)
759 {
760     SECModePtr pSecMode;
761
762     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
763
764     pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
765
766     if (layer->offset_x == x && layer->offset_y == y)
767         return TRUE;
768
769     /* display controller restriction. x+width=2's mutiple */
770     XDBG_TRACE (MLYR, "layer(%p) offset(%d,%d => %d,%d).\n",
771                 layer, x, y, x & (~0x1), y);
772     layer->offset_x = x & (~0x1);
773     layer->offset_y = y;
774
775     if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
776         return TRUE;
777
778     if (secLayerIsVisible (layer) && !layer->freeze_update)
779     {
780         int crtc_id = _GetCrtcID (layer);
781         int plane_pos = _secLayerGetPlanePos (layer, layer->lpos);
782
783         if (!secPlaneShow (layer->plane_id, crtc_id,
784                            layer->src->x, layer->src->y,
785                            layer->src->width, layer->src->height,
786                            layer->offset_x + layer->dst->x,
787                            layer->offset_y + layer->dst->y,
788                            layer->dst->width, layer->dst->height,
789                            plane_pos, FALSE))
790             return FALSE;
791     }
792
793     return TRUE;
794 }
795
796 void
797 secLayerGetOffset (SECLayer *layer, int *x, int *y)
798 {
799     XDBG_RETURN_IF_FAIL (layer != NULL);
800
801     if (x)
802         *x = layer->offset_x;
803     if (y)
804         *y = layer->offset_y;
805 }
806
807 Bool
808 secLayerSetPos (SECLayer *layer, SECLayerPos lpos)
809 {
810     SECModePtr pSecMode;
811     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
812     XDBG_RETURN_VAL_IF_FAIL (lpos >= LAYER_NONE && lpos < LAYER_MAX, FALSE);
813
814     pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
815
816     if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
817     {
818         layer->lpos = lpos;
819         return TRUE;
820     }
821
822
823     if (layer->lpos == lpos)
824         return TRUE;
825
826     if (secLayerFind (layer->output, lpos))
827         return FALSE;
828
829     if (secLayerIsVisible (layer) && !layer->freeze_update)
830     {
831         if (lpos == LAYER_NONE)
832         {
833             if (!secPlaneHide (layer->plane_id))
834                 return FALSE;
835
836             layer->visible = FALSE;
837             layer->crtc_id = 0;
838         }
839         else
840         {
841             int crtc_id = _GetCrtcID (layer);
842             int plane_pos = _secLayerGetPlanePos (layer, lpos);
843
844             if (!secPlaneShow (layer->plane_id, crtc_id,
845                                layer->src->x, layer->src->y,
846                                layer->src->width, layer->src->height,
847                                layer->offset_x + layer->dst->x,
848                                layer->offset_y + layer->dst->y,
849                                layer->dst->width, layer->dst->height,
850                                plane_pos, FALSE))
851                 return FALSE;
852         }
853     }
854
855     XDBG_TRACE (MLYR, "layer(%p) lpos(%d). \n", layer, lpos);
856
857     layer->lpos = lpos;
858
859     return TRUE;
860 }
861
862 Bool
863 secLayerSwapPos (SECLayer *layer1, SECLayer *layer2)
864 {
865     SECLayer *lower, *upper;
866     SECLayerPos upper_lpos, lower_lpos;
867
868     XDBG_RETURN_VAL_IF_FAIL (layer1 != NULL, FALSE);
869     XDBG_RETURN_VAL_IF_FAIL (layer2 != NULL, FALSE);
870
871     XDBG_TRACE (MLYR, "layer1(%p) layer2(%p). \n", layer1, layer2);
872
873     lower = (layer2->lpos < layer1->lpos) ? layer2 : layer1;
874     upper = (layer2->lpos < layer1->lpos) ? layer1 : layer2;
875
876     upper_lpos = upper->lpos;
877     lower_lpos = lower->lpos;
878
879     secLayerSetPos (upper, LAYER_NONE);
880     secLayerSetPos (lower, upper_lpos);
881     secLayerSetPos (upper, lower_lpos);
882
883     return TRUE;
884 }
885
886 SECLayerPos
887 secLayerGetPos (SECLayer *layer)
888 {
889     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, 0);
890
891     return layer->lpos;
892 }
893
894 Bool
895 secLayerSetRect (SECLayer *layer, xRectangle *src, xRectangle *dst)
896 {
897     SECModePtr pSecMode;
898
899     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
900     XDBG_RETURN_VAL_IF_FAIL (src != NULL, FALSE);
901     XDBG_RETURN_VAL_IF_FAIL (dst != NULL, FALSE);
902
903     pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
904
905     if (!layer->src)
906         layer->src = calloc (sizeof (xRectangle), 1);
907
908     XDBG_RETURN_VAL_IF_FAIL (layer->src != NULL, FALSE);
909
910     if (!layer->dst)
911         layer->dst = calloc (sizeof (xRectangle), 1);
912
913     XDBG_RETURN_VAL_IF_FAIL (layer->dst != NULL, FALSE);
914
915     if (!memcmp (layer->src, src, sizeof (xRectangle)) &&
916         !memcmp (layer->dst, dst, sizeof (xRectangle)))
917         return TRUE;
918
919     *layer->src = *src;
920     *layer->dst = *dst;
921
922     XDBG_TRACE (MLYR, "layer(%p) src(%d,%d %dx%d) dst(%d,%d %dx%d). \n",
923                 layer, src->x, src->y, src->width, src->height,
924                 dst->x, dst->y, dst->width, dst->height);
925     if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
926         return TRUE;
927
928     if (layer->pending_vbuf && VBUF_IS_VALID (layer->pending_vbuf))
929     {
930         layer->pending_vbuf->showing = FALSE;
931         secUtilVideoBufferUnref (layer->pending_vbuf);
932         layer->pending_vbuf = NULL;
933     }
934
935     if (secLayerIsVisible (layer) && !layer->freeze_update)
936     {
937         int plane_pos = _secLayerGetPlanePos (layer, layer->lpos);
938
939         if (!secPlaneShow (layer->plane_id, _GetCrtcID (layer),
940                            src->x, src->y, src->width, src->height,
941                            layer->offset_x + dst->x,
942                            layer->offset_y + dst->y,
943                            dst->width, dst->height,
944                            plane_pos, FALSE))
945             return FALSE;
946     }
947
948     return TRUE;
949 }
950
951 void
952 secLayerGetRect (SECLayer *layer, xRectangle *src, xRectangle *dst)
953 {
954     XDBG_RETURN_IF_FAIL (layer != NULL);
955
956     if (src && layer->src)
957         *src = *layer->src;
958
959     if (dst && layer->dst)
960         *dst = *layer->dst;
961 }
962
963 int
964 secLayerSetBuffer (SECLayer *layer, SECVideoBuf *vbuf)
965 {
966     SECModePtr pSecMode;
967     unsigned int fb_id;
968
969     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, 0);
970     XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), 0);
971
972     if (!secLayerSupport (layer->pScrn, layer->output, layer->lpos, vbuf->id))
973     {
974         XDBG_ERROR (MLYR, "fail : layer(%p) output(%d) lpos(%d) vbuf(%c%c%c%c)\n",
975                     layer, layer->output, layer->lpos, FOURCC_STR (vbuf->id));
976         return 0;
977     }
978
979     pSecMode = (SECModePtr) SECPTR (layer->pScrn)->pSecMode;
980
981     if (layer->output == LAYER_OUTPUT_EXT && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
982     {
983         XDBG_RETURN_VAL_IF_FAIL (layer->enable_vblank == FALSE, 0);
984
985         XDBG_TRACE (MLYR, "layer(%p) vbuf('%c%c%c%c', %dx%d, %d,%d %dx%d)\n",
986                     layer, FOURCC_STR(vbuf->id), vbuf->width, vbuf->height,
987                     vbuf->crop.x, vbuf->crop.y, vbuf->crop.width, vbuf->crop.height);
988
989         if (layer->vbuf)
990             secUtilVideoBufferUnref (layer->vbuf);
991
992         layer->vbuf = secUtilVideoBufferRef (vbuf);
993         layer->fb_id = 1;
994
995         _secLayerNotify (layer, LAYER_BUF_CHANGED, vbuf);
996
997         return layer->fb_id;
998     }
999
1000     if (layer->wait_vbuf && layer->pending_vbuf)
1001     {
1002         XDBG_TRACE (MLYR, "pending_vbuf(%ld) exists.\n", layer->pending_vbuf->stamp);
1003         return 0;
1004     }
1005
1006     _secLayerGetBufferID (layer, vbuf);
1007     XDBG_RETURN_VAL_IF_FAIL (vbuf->fb_id > 0, 0);
1008
1009     if (layer->wait_vbuf && !layer->pending_vbuf)
1010     {
1011         layer->pending_vbuf = secUtilVideoBufferRef (vbuf);
1012         layer->pending_vbuf->showing = TRUE;
1013         XDBG_TRACE (MLYR, "pending vbuf(%ld).\n", layer->pending_vbuf->stamp);
1014         return vbuf->fb_id;
1015     }
1016
1017     fb_id = secPlaneGetBuffer (layer->plane_id, NULL, vbuf);
1018     if (fb_id == 0)
1019     {
1020         fb_id = secPlaneAddBuffer (layer->plane_id, vbuf);
1021         XDBG_RETURN_VAL_IF_FAIL (fb_id > 0, 0);
1022
1023         layer->fb_id = vbuf->fb_id;
1024     }
1025
1026     if (vbuf->fb_id != fb_id)
1027         XDBG_WARNING (MLYR, "fb_id (%d != %d) \n", vbuf->fb_id, fb_id);
1028
1029     layer->fb_id = fb_id;
1030     if (!secPlaneAttach (layer->plane_id, fb_id))
1031         return 0;
1032
1033     if (secLayerIsVisible (layer) && !layer->freeze_update)
1034         if (!_secLayerShowInternal (layer, TRUE))
1035             return 0;
1036
1037     if (layer->enable_vblank)
1038     {
1039         XDBG_RETURN_VAL_IF_FAIL (layer->wait_vbuf == NULL, 0);
1040
1041         layer->wait_vbuf = secUtilVideoBufferRef (vbuf);
1042         layer->wait_vbuf->showing = TRUE;
1043         XDBG_DEBUG (MVBUF, "layer(%p) --> %s (%ld,%d,%d) \n", layer,
1044                     (layer->output==LAYER_OUTPUT_LCD)?"LCD":"TV",
1045                     layer->wait_vbuf->stamp,
1046                     VBUF_IS_CONVERTING (layer->wait_vbuf),
1047                     layer->wait_vbuf->showing);
1048
1049         if (secLayerIsVisible (layer))
1050         {
1051             XDBG_TRACE (MLYR, "layer(%p) fb_id(%d) attached. \n", layer, fb_id);
1052             _secLayerWatchVblank (layer);
1053         }
1054     }
1055
1056     if (layer->vbuf)
1057         secUtilVideoBufferUnref (layer->vbuf);
1058     layer->vbuf = secUtilVideoBufferRef (vbuf);
1059
1060     _secLayerNotify (layer, LAYER_BUF_CHANGED, vbuf);
1061
1062     return fb_id;
1063 }
1064
1065 SECVideoBuf*
1066 secLayerGetBuffer (SECLayer *layer)
1067 {
1068     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, NULL);
1069
1070     if (layer->showing_vbuf && layer->dst && layer->visible)
1071         return layer->showing_vbuf;
1072     else if (layer->vbuf)
1073         return layer->vbuf;
1074
1075     return NULL;
1076 }
1077
1078 void
1079 secLayerVBlankEventHandler (unsigned int frame, unsigned int tv_sec,
1080                             unsigned int tv_usec, void *event_data)
1081 {
1082     SECLayer *layer = NULL, *layer_next = NULL;
1083     int pipe = (int)event_data;
1084
1085     XDBG_RETURN_IF_FAIL (pipe < LAYER_OUTPUT_MAX);
1086
1087     _secLayerInitList ();
1088
1089     wait_vblank[pipe] = FALSE;
1090
1091     XDBG_DEBUG (MLYR, "frame(%d), tv_sec(%d), tv_usec(%d) \n", frame, tv_sec, tv_usec);
1092
1093     xorg_list_for_each_entry_safe (layer, layer_next, &crtc_layers, link)
1094     {
1095         int crtc_pipe = secDisplayCrtcPipe (layer->pScrn, _GetCrtcID (layer));
1096
1097         if (!layer->enable_vblank || !layer->wait_vblank)
1098             continue;
1099
1100         if (crtc_pipe != pipe)
1101             continue;
1102
1103         layer->wait_vblank = FALSE;
1104
1105         if (VBUF_IS_VALID (layer->wait_vbuf))
1106         {
1107             if (layer->showing_vbuf && VBUF_IS_VALID (layer->showing_vbuf))
1108             {
1109                 layer->showing_vbuf->showing = FALSE;
1110                 secUtilVideoBufferUnref (layer->showing_vbuf);
1111             }
1112
1113             layer->showing_vbuf = layer->wait_vbuf;
1114             layer->wait_vbuf = NULL;
1115
1116             if (layer->pending_vbuf && VBUF_IS_VALID (layer->pending_vbuf))
1117             {
1118                 int fb_id;
1119
1120                 layer->wait_vbuf = layer->pending_vbuf;
1121                 layer->pending_vbuf = NULL;
1122
1123                 fb_id = secPlaneGetBuffer (layer->plane_id, NULL, layer->wait_vbuf);
1124                 if (fb_id == 0)
1125                 {
1126                     fb_id = secPlaneAddBuffer (layer->plane_id, layer->wait_vbuf);
1127                     XDBG_RETURN_IF_FAIL (fb_id > 0);
1128
1129                     layer->fb_id = layer->wait_vbuf->fb_id;
1130                 }
1131
1132                 if (!secPlaneAttach (layer->plane_id, layer->wait_vbuf->fb_id))
1133                     continue;
1134
1135                 if (secLayerIsVisible (layer) && !layer->freeze_update)
1136                     _secLayerShowInternal (layer, TRUE);
1137
1138                 _secLayerWatchVblank (layer);
1139             }
1140
1141             SECPtr pSec = SECPTR (layer->pScrn);
1142             if (pSec->pVideoPriv->video_fps)
1143                 _countFps (layer);
1144
1145             XDBG_TRACE (MLYR, "layer(%p) fb_id(%d) now showing frame(%d) (%ld,%ld,%ld) => crtc(%d) pos(%d). \n",
1146                         layer, layer->fb_id, frame,
1147                         VSTMAP(layer->pending_vbuf), VSTMAP(layer->wait_vbuf), VSTMAP(layer->showing_vbuf),
1148                         _GetCrtcID (layer), layer->lpos);
1149
1150             _secLayerNotify (layer, LAYER_VBLANK, (void*)layer->showing_vbuf);
1151         }
1152     }
1153 }