Fix flickering resized video frame.
[platform/adaptation/samsung_exynos/xf86-video-exynos.git] / src / xv / sec_video_tvout.c
1 /**************************************************************************
2
3 xserver-xorg-video-exynos
4
5 Copyright 2010 - 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 #include "sec.h"
32 #include "sec_display.h"
33 #include "sec_crtc.h"
34 #include "sec_output.h"
35 #include "sec_accel.h"
36 #include "sec_util.h"
37 #include "sec_converter.h"
38 #include "sec_video_tvout.h"
39 #include "sec_video_virtual.h"
40 #include "sec_video_fourcc.h"
41 #include "sec_drm_ipp.h"
42 #include "sec_layer.h"
43 #include "sec_prop.h"
44
45 #include <sys/ioctl.h>
46 #include "common.h"
47 #include <drm_fourcc.h>
48
49 #define TVBUF_NUM  3
50
51 /* HW restriction (VP) */
52 #define MIN_WIDTH  32
53 #define MIN_HEIGHT 4
54 #define MAX_WIDTH  1920
55 #define MAX_HEIGHT 1080
56 #define MIN_SCALE  0.25
57 #define MAX_SCALE  16.0
58
59 /* private structure */
60 struct _SECVideoTv
61 {
62     ScrnInfoPtr pScrn;
63
64     SECLayer *layer;
65     SECLayerPos lpos;
66
67     /* used if id is not supported in case of lpos == LAYER_LOWER1. */
68     SECCvt      *cvt;
69     SECVideoBuf **outbuf;
70     int          outbuf_index;
71     int          outbuf_num;
72
73     int          tv_width;
74     int          tv_height;
75
76     xRectangle   tv_rect;
77     int          is_resized;
78     unsigned int convert_id;
79     unsigned int src_id;
80     SECLayerOutput output;
81
82 };
83 #if 0
84 static Bool
85 _secVideoTvCalSize (SECVideoTv* tv, int src_w, int src_h, int dst_w, int dst_h)
86 {
87     float r;
88
89     if (src_w < MIN_WIDTH || src_h < MIN_HEIGHT)
90     {
91         XDBG_WARNING (MTVO, "size(%dx%d) must be more than (%dx%d).\n",
92                       src_w, src_h, MIN_WIDTH, MAX_WIDTH);
93     }
94
95     r = (float)dst_w / src_w;
96     if (r < MIN_SCALE || r > MAX_SCALE)
97     {
98         XDBG_WARNING (MTVO, "ratio_w(%f) is out of range(%f~%f).\n",
99                       r, MIN_SCALE, MAX_SCALE);
100     }
101
102     r = (float)dst_h / src_h;
103     if (r < MIN_SCALE || r > MAX_SCALE)
104     {
105         XDBG_WARNING (MTVO, "ratio_h(%d) is out of range(%f~%f).\n",
106                       r, MIN_SCALE, MAX_SCALE);
107     }
108
109     return TRUE;
110 }
111 #endif
112 static SECVideoBuf*
113 _secVideoTvGetOutBuffer (SECVideoTv* tv, int width, int height, Bool secure)
114 {
115     int i = tv->outbuf_index, j;
116
117     if (!tv->outbuf)
118     {
119         tv->outbuf = (SECVideoBuf**)calloc (tv->outbuf_num, sizeof (SECVideoBuf*));
120         XDBG_RETURN_VAL_IF_FAIL (tv->outbuf != NULL, NULL);
121     }
122
123     i++;
124     if (i >= tv->outbuf_num)
125         i = 0;
126
127     for (j = 0; j < tv->outbuf_num; j++)
128     {
129         if (tv->outbuf[i])
130         {
131             XDBG_DEBUG (MTVO, "outbuf(%p) converting(%d) showing(%d)\n",
132                         tv->outbuf[i], VBUF_IS_CONVERTING (tv->outbuf[i]), tv->outbuf[i]->showing);
133
134             if (tv->outbuf[i] && !VBUF_IS_CONVERTING (tv->outbuf[i]) && !tv->outbuf[i]->showing)
135             {
136                 if (tv->outbuf[i]->width == width &&
137                     tv->outbuf[i]->id == tv->convert_id &&
138                     tv->outbuf[i]->height == height)
139                 {
140                     tv->outbuf_index = i;
141                     return tv->outbuf[i];
142                 }
143                 else
144                 {
145                     secUtilVideoBufferUnref (tv->outbuf[i]);
146                     SECPtr pSec = SECPTR (tv->pScrn);
147                     tv->outbuf[i] = secUtilAllocVideoBuffer (tv->pScrn, tv->convert_id, width, height,
148                                                              (pSec->scanout)?TRUE:FALSE, TRUE, secure);
149                     XDBG_RETURN_VAL_IF_FAIL (tv->outbuf[i] != NULL, NULL);
150
151                     XDBG_DEBUG (MTVO, "outbuf(%p, %c%c%c%c)\n", tv->outbuf[i], FOURCC_STR (tv->convert_id));
152
153                     tv->outbuf_index = i;
154                     return tv->outbuf[i];
155                 }
156             }
157         }
158         else
159         {
160             SECPtr pSec = SECPTR (tv->pScrn);
161             tv->outbuf[i] = secUtilAllocVideoBuffer (tv->pScrn, tv->convert_id, width, height,
162                                                      (pSec->scanout)?TRUE:FALSE, TRUE, secure);
163             XDBG_RETURN_VAL_IF_FAIL (tv->outbuf[i] != NULL, NULL);
164
165             XDBG_DEBUG (MTVO, "outbuf(%p, %c%c%c%c)\n", tv->outbuf[i], FOURCC_STR (tv->convert_id));
166
167             tv->outbuf_index = i;
168             return tv->outbuf[i];
169         }
170
171         i++;
172         if (i >= tv->outbuf_num)
173             i = 0;
174     }
175
176 #if 0
177     char buffers[1024];
178     CLEAR (buffers);
179     for (j = 0; j < tv->outbuf_num; j++)
180     {
181         if (tv->outbuf[j])
182             snprintf (buffers, 1024, "%s %d(%d,%d) ", buffers, tv->outbuf[j]->keys[0],
183             VBUF_IS_CONVERTING (tv->outbuf[j]), tv->outbuf[j]->showing);
184     }
185
186     XDBG_ERROR (MTVO, "now all outbufs in use! %s\n", buffers);
187 #else
188     XDBG_ERROR (MTVO, "now all outbufs in use!\n");
189 #endif
190
191     return NULL;
192 }
193
194 static Bool
195 _secVideoTvLayerEnsure (SECVideoTv* tv)
196 {
197     SECLayer *layer;
198
199     if (tv->layer)
200         return TRUE;
201
202     XDBG_RETURN_VAL_IF_FAIL (tv->lpos != LAYER_NONE, FALSE);
203
204     layer = secLayerCreate (tv->pScrn, LAYER_OUTPUT_EXT, tv->lpos);
205     XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
206
207     tv->layer = layer;
208
209     return TRUE;
210 }
211
212 static void
213 _secVideoTvLayerDestroy (SECVideoTv* tv)
214 {
215     if (tv->layer)
216     {
217         secLayerUnref (tv->layer);
218         tv->layer = NULL;
219     }
220 }
221
222 static int
223 _secVideoTvPutImageInternal (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *rect)
224 {
225     int ret = 0;
226
227     XDBG_DEBUG (MTVO, "rect (%d,%d %dx%d) \n",
228                 rect->x, rect->y, rect->width, rect->height);
229
230 #if 0
231     if (tv->lpos == LAYER_LOWER1)
232         if (!_secVideoTvCalSize (tv, vbuf->width, vbuf->height,
233                                 rect->width, rect->height))
234         {
235             return 0;
236         }
237 #endif
238     xRectangle src_rect, dst_rect;
239     secLayerGetRect (tv->layer, &src_rect, &dst_rect);
240
241     if (tv->is_resized == 1)
242     {
243         secLayerFreezeUpdate (tv->layer, FALSE);
244 //        secLayerHide (tv->layer);
245         tv->is_resized = 0;
246     }
247
248     if (memcmp (&vbuf->crop, &src_rect, sizeof (xRectangle)) ||
249         memcmp (rect, &dst_rect, sizeof (xRectangle)))
250     {
251         secLayerFreezeUpdate (tv->layer, TRUE);
252         secLayerSetRect (tv->layer, &vbuf->crop, rect);
253         secLayerFreezeUpdate (tv->layer, FALSE);
254     }
255
256     ret = secLayerSetBuffer (tv->layer, vbuf);
257
258     if (ret == 0)
259         return 0;
260     if (!secLayerIsVisible (tv->layer))
261     {
262         secLayerShow (tv->layer);
263     }
264     else
265     {
266         XDBG_DEBUG(MTVO,"tv->layer(%p) is not visible\n", tv->layer);
267     }
268     return ret;
269 }
270
271 static void
272 _secVideoTvCvtCallback (SECCvt *cvt,
273                         SECVideoBuf *src,
274                         SECVideoBuf *dst,
275                         void *cvt_data,
276                         Bool error)
277 {
278     SECVideoTv *tv = (SECVideoTv*)cvt_data;
279     int i;
280
281     XDBG_RETURN_IF_FAIL (tv != NULL);
282     XDBG_RETURN_IF_FAIL (cvt != NULL);
283     XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (dst));
284
285     XDBG_DEBUG (MTVO, "++++++++++++++++++++++++ \n");
286
287     for (i = 0; i < tv->outbuf_num; i++)
288         if (tv->outbuf[i] == dst)
289             break;
290     XDBG_RETURN_IF_FAIL (i < tv->outbuf_num);
291     _secVideoTvPutImageInternal (tv, dst, &tv->tv_rect);
292
293     XDBG_DEBUG (MTVO, "++++++++++++++++++++++++.. \n");
294 }
295
296 SECVideoTv*
297 secVideoTvConnect (ScrnInfoPtr pScrn, unsigned int id, SECLayerPos lpos)
298 {
299     SECVideoTv* tv = NULL;
300     SECModePtr pSecMode;
301     unsigned int convert_id = FOURCC_RGB32;
302     XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, NULL);
303     XDBG_RETURN_VAL_IF_FAIL (lpos >= LAYER_LOWER1 && lpos <= LAYER_UPPER, NULL);
304     XDBG_RETURN_VAL_IF_FAIL (id > 0, NULL);
305
306     tv = calloc (sizeof (SECVideoTv), 1);
307     XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
308
309     pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
310
311     if (lpos == LAYER_LOWER1 && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
312     {
313         /* In case of video-only(virtual), we always use converter. */
314         tv->cvt = secCvtCreate (pScrn, CVT_OP_M2M);
315         XDBG_GOTO_IF_FAIL (tv->cvt != NULL, fail_connect);
316
317         secCvtAddCallback (tv->cvt, _secVideoTvCvtCallback, tv);
318     }
319     else if (lpos == LAYER_LOWER1 && pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI)
320     {
321         if (!secLayerSupport (pScrn, LAYER_OUTPUT_EXT, lpos, id))
322         {
323             /* used if id is not supported in case of lpos == LAYER_LOWER1. */
324             convert_id = FOURCC_SN12;
325             tv->cvt = secCvtCreate (pScrn, CVT_OP_M2M);
326             XDBG_GOTO_IF_FAIL (tv->cvt != NULL, fail_connect);
327             secCvtAddCallback (tv->cvt, _secVideoTvCvtCallback, tv);
328         }
329         else
330         {
331             XDBG_DEBUG(MTVO, "Not need converting id(%c%c%c%c)\n", FOURCC_STR (id));
332             convert_id = id;
333         }
334     }
335
336     XDBG_DEBUG (MTVO, "id(%c%c%c%c), lpos(%d)!\n", FOURCC_STR (id), lpos);
337     tv->output = LAYER_OUTPUT_EXT;
338     tv->pScrn = pScrn;
339     tv->lpos = lpos;
340     tv->outbuf_index = -1;
341     tv->convert_id = convert_id;
342     tv->outbuf_num = TVBUF_NUM;
343     tv->src_id = id;
344
345     return tv;
346
347 fail_connect:
348     if (tv)
349     {
350         if (tv->cvt)
351             secCvtDestroy (tv->cvt);
352         free (tv);
353     }
354     return NULL;
355 }
356
357 Bool
358 secVideoTvResizeOutput (SECVideoTv* tv, xRectanglePtr src, xRectanglePtr dst)
359 {
360     if (tv == NULL)
361         return FALSE;
362
363     if (!secVideoCanDirectDrawing (tv, src->width, src->height,
364                                    dst->width, dst->height))
365     {
366         secVideoTvReCreateConverter(tv);
367     }
368     else
369     {
370         if (tv->cvt)
371         {
372            secCvtDestroy (tv->cvt);
373         }
374     }
375
376     if (tv->outbuf)
377     {
378         int i;
379         for (i = 0; i < tv->outbuf_num; i++)
380             if (tv->outbuf[i] && !VBUF_IS_CONVERTING(tv->outbuf[i]) && !tv->outbuf[i]->showing)
381             {
382                 secUtilVideoBufferUnref (tv->outbuf[i]);
383                 tv->outbuf[i] = NULL;
384             }
385         tv->outbuf_index = -1;
386     }
387
388     secLayerFreezeUpdate (tv->layer, TRUE);
389     tv->is_resized = 1;
390     return TRUE;
391 }
392
393 void
394 secVideoTvDisconnect (SECVideoTv* tv)
395 {
396     int i;
397
398     XDBG_RETURN_IF_FAIL (tv != NULL);
399
400     XDBG_DEBUG (MTVO, "!\n");
401
402     if (tv->cvt)
403         secCvtDestroy (tv->cvt);
404
405     _secVideoTvLayerDestroy (tv);
406
407     if (tv->outbuf)
408     {
409         for (i = 0; i < tv->outbuf_num; i++)
410             if (tv->outbuf[i])
411                 secUtilVideoBufferUnref (tv->outbuf[i]);
412
413         free (tv->outbuf);
414     }
415
416     free (tv);
417 }
418
419 Bool
420 secVideoTvSetBuffer (SECVideoTv* tv, SECVideoBuf **vbufs, int bufnum)
421 {
422     int i;
423
424     XDBG_RETURN_VAL_IF_FAIL (tv != NULL, FALSE);
425     XDBG_RETURN_VAL_IF_FAIL (vbufs != NULL, FALSE);
426     XDBG_RETURN_VAL_IF_FAIL (bufnum >= TVBUF_NUM, FALSE);
427
428     if (tv->outbuf)
429     {
430         XDBG_ERROR (MTVO, "already has buffers.\n");
431         return FALSE;
432     }
433
434     tv->outbuf_num = bufnum;
435     tv->outbuf = (SECVideoBuf**)calloc (bufnum, sizeof (SECVideoBuf*));
436     XDBG_RETURN_VAL_IF_FAIL (tv->outbuf != NULL, FALSE);
437
438     for (i = 0; i < tv->outbuf_num; i++)
439     {
440         XDBG_GOTO_IF_FAIL (tv->convert_id == vbufs[i]->id, fail_set_buffer);
441         XDBG_GOTO_IF_FAIL (tv->tv_width == vbufs[i]->width, fail_set_buffer);
442         XDBG_GOTO_IF_FAIL (tv->tv_height == vbufs[i]->height, fail_set_buffer);
443
444         tv->outbuf[i] = secUtilVideoBufferRef (vbufs[i]);
445         XDBG_GOTO_IF_FAIL (tv->outbuf[i] != NULL, fail_set_buffer);
446
447         if (!tv->outbuf[i]->showing && tv->outbuf[i]->need_reset)
448             secUtilClearVideoBuffer (tv->outbuf[i]);
449         else
450             tv->outbuf[i]->need_reset = TRUE;
451     }
452
453     return TRUE;
454
455 fail_set_buffer:
456     if (tv->outbuf)
457     {
458         for (i = 0; i < tv->outbuf_num; i++)
459         {
460             if (tv->outbuf[i])
461             {
462                 secUtilVideoBufferUnref (tv->outbuf[i]);
463                 tv->outbuf[i] = NULL;
464             }
465         }
466
467         free (tv->outbuf);
468         tv->outbuf = NULL;
469     }
470
471     return FALSE;
472 }
473 SECLayerPos
474 secVideoTvGetPos (SECVideoTv *tv)
475 {
476     XDBG_RETURN_VAL_IF_FAIL (tv != NULL, LAYER_NONE);
477
478     return tv->lpos;
479 }
480
481 SECLayer*
482 secVideoTvGetLayer (SECVideoTv *tv)
483 {
484     XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
485
486     _secVideoTvLayerEnsure (tv);
487
488     return tv->layer;
489 }
490
491 /* HDMI    : 'handles' is "gem handle"
492  * VIRTUAL : 'handles' is "physical address"
493  *           'data' is "raw data"
494  *           only one of 'handles' and 'data' has value.
495  */
496 int
497 secVideoTvPutImage (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *rect, int csc_range)
498 {
499     XDBG_RETURN_VAL_IF_FAIL (tv != NULL, 0);
500     XDBG_RETURN_VAL_IF_FAIL (VBUF_IS_VALID (vbuf), 0);
501     XDBG_RETURN_VAL_IF_FAIL (vbuf->id > 0, 0);
502     XDBG_RETURN_VAL_IF_FAIL (rect != NULL, 0);
503
504     XDBG_RETURN_VAL_IF_FAIL (vbuf->handles[0] > 0, 0);
505     XDBG_RETURN_VAL_IF_FAIL (vbuf->pitches[0] > 0, 0);
506     XDBG_RETURN_VAL_IF_FAIL (rect->width > 0, 0);
507     XDBG_RETURN_VAL_IF_FAIL (rect->height > 0, 0);
508     XDBG_RETURN_VAL_IF_FAIL (vbuf->width > 0, 0);
509     XDBG_RETURN_VAL_IF_FAIL (vbuf->height > 0, 0);
510     _secVideoTvLayerEnsure (tv);
511     XDBG_RETURN_VAL_IF_FAIL (tv->layer != NULL, 0);
512
513     if (tv->cvt)
514     {
515         /* can't show buffer to HDMI at now. */
516         SECModePtr pSecMode = (SECModePtr) SECPTR (tv->pScrn)->pSecMode;
517         SECCvtProp src_prop = {0,}, dst_prop = {0,};
518         SECVideoBuf *outbuf;
519         int dst_width, dst_height;
520         xRectangle dst_crop;
521
522
523         /* CHECK */
524         if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
525         {
526             XDBG_RETURN_VAL_IF_FAIL (tv->tv_width > 0, 0);
527             XDBG_RETURN_VAL_IF_FAIL (tv->tv_height > 0, 0);
528             dst_width = tv->tv_width;
529             dst_height = tv->tv_height;
530             dst_crop = *rect;
531
532             tv->tv_rect.x = 0;
533             tv->tv_rect.y = 0;
534             tv->tv_rect.width = tv->tv_width;
535             tv->tv_rect.height = tv->tv_height;
536         }
537         else
538         {
539             dst_width = rect->width;
540             dst_height = rect->height;
541             dst_crop = *rect;
542             dst_crop.x = 0;
543             dst_crop.y = 0;
544
545             tv->tv_rect = *rect;
546         }
547
548         src_prop.id = vbuf->id;
549         src_prop.width = vbuf->width;
550         src_prop.height = vbuf->height;
551         src_prop.crop = vbuf->crop;
552
553         dst_prop.id = tv->convert_id;
554         dst_prop.width = dst_width;
555         dst_prop.height = dst_height;
556         dst_prop.crop = dst_crop;
557         dst_prop.secure = vbuf->secure;
558         dst_prop.csc_range = csc_range;
559
560         if (!secCvtEnsureSize (&src_prop, &dst_prop))
561         {
562             XDBG_DEBUG(MTVO, "Can't ensure size\n");
563             return 0;
564         }
565
566         outbuf = _secVideoTvGetOutBuffer (tv, dst_prop.width, dst_prop.height, vbuf->secure);
567         if (!outbuf)
568         {
569             XDBG_DEBUG(MTVO, "Can't get outbuf\n");
570             return 0;
571         }
572         outbuf->crop = dst_prop.crop;
573
574         if (!secCvtSetProperpty (tv->cvt, &src_prop, &dst_prop))
575         {
576             XDBG_DEBUG(MTVO, "Can't set cvt property\n");
577             return 0;
578         }
579
580         if (!secCvtConvert (tv->cvt, vbuf, outbuf))
581         {
582             XDBG_DEBUG(MTVO, "Can't start cvt\n");
583             return 0;
584         }
585
586         XDBG_TRACE (MTVO, "'%c%c%c%c' %dx%d (%d,%d %dx%d) => '%c%c%c%c' %dx%d (%d,%d %dx%d) convert. rect(%d,%d %dx%d)\n",
587                     FOURCC_STR (vbuf->id), vbuf->width, vbuf->height,
588                     vbuf->crop.x, vbuf->crop.y, vbuf->crop.width, vbuf->crop.height,
589                     FOURCC_STR (outbuf->id), outbuf->width, outbuf->height,
590                     outbuf->crop.x, outbuf->crop.y, outbuf->crop.width, outbuf->crop.height,
591                     rect->x, rect->y, rect->width, rect->height);
592
593         return 1;
594     }
595     /* can show buffer to HDMI at now. */
596     return _secVideoTvPutImageInternal (tv, vbuf, rect);
597 }
598
599 void
600 secVideoTvSetSize (SECVideoTv *tv, int width, int height)
601 {
602     XDBG_RETURN_IF_FAIL (tv != NULL);
603
604     tv->tv_width = width;
605     tv->tv_height = height;
606
607     XDBG_TRACE (MTVO, "size(%dx%d) \n", width, height);
608 }
609
610 SECCvt*
611 secVideoTvGetConverter (SECVideoTv *tv)
612 {
613     XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
614
615     return tv->cvt;
616 }
617
618 void
619 secVideoTvSetConvertFormat (SECVideoTv *tv, unsigned int convert_id)
620 {
621     XDBG_RETURN_IF_FAIL (tv != NULL);
622     XDBG_RETURN_IF_FAIL (convert_id > 0);
623
624     tv->convert_id = convert_id;
625
626     XDBG_TRACE (MTVO, "convert_id(%c%c%c%c) \n", FOURCC_STR (convert_id));
627 }
628
629 Bool
630 secVideoCanDirectDrawing (SECVideoTv *tv, int src_w, int src_h, int dst_w, int dst_h)
631 {
632     XDBG_RETURN_VAL_IF_FAIL(src_w != 0, FALSE);
633     XDBG_RETURN_VAL_IF_FAIL(src_h != 0, FALSE);
634     XDBG_RETURN_VAL_IF_FAIL(dst_w != 0, FALSE);
635     XDBG_RETURN_VAL_IF_FAIL(dst_h != 0, FALSE);
636 #if 1
637     /* :TODO. Need Fix flickering in direct draw case */
638     return FALSE;
639 #endif
640     int ratio_w = 0;
641     int ratio_h = 0;
642     XDBG_DEBUG(MTVO, "tv(%p) src_w %d, src_h %d, dst_w %d, dst_h %d\n",
643                tv, src_w, src_h, dst_w, dst_h);
644     if (src_w >= dst_w)
645     {
646         ratio_w = src_w / dst_w;
647         if (ratio_w > 4)
648         {
649             XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (1/%d) < 1/4\n", ratio_w);
650             return FALSE;
651         }
652         XDBG_DEBUG(MTVO, "ratio_w = 1/%d\n", ratio_w);
653     }
654     else if (src_w < dst_w)
655     {
656         ratio_w = dst_w / src_w;
657         if (ratio_w > 16)
658         {
659             XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) > 16\n", ratio_w);
660             return FALSE;
661         }
662         XDBG_DEBUG(MTVO, "ratio_w = %d\n", ratio_w);
663     }
664
665     if (src_h >= dst_h)
666     {
667         ratio_h = src_h / dst_h;
668         if (ratio_h > 4)
669         {
670             XDBG_DEBUG(MTVO, "Can't direct draw ratio_h (1/%d) < 1/4\n", ratio_w);
671             return FALSE;
672         }
673         XDBG_DEBUG(MTVO, "ratio_h = 1/%d\n", ratio_h);
674     }
675     else if (src_h < dst_h)
676     {
677         ratio_h = dst_h / src_h;
678         if (ratio_h > 16)
679         {
680             XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) > 16\n", ratio_w);
681             return FALSE;
682         }
683         XDBG_DEBUG(MTVO, "ratio_h = %d\n", ratio_h);
684     }
685
686     if (ratio_w != ratio_h)
687     {
688         XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) != ratio_h (%d)\n", ratio_w, ratio_h);
689         return FALSE;
690     }
691
692     if (tv != NULL)
693     {
694         if (!secLayerSupport (tv->pScrn, tv->output, tv->lpos, tv->src_id))
695         {
696             XDBG_DEBUG(MTVO, "Can't direct draw. Layer not support. lpos(%d), src_id (%c%c%c%c)\n",
697             tv->lpos, FOURCC_STR(tv->src_id));
698             return FALSE;
699         }
700     }
701 #if 0
702     /* FIXME: Using IPP converter if we haven't native frame size */
703     if (ratio_w > 1 || ratio_h > 1)
704     {
705         XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) && ratio_h (%d) != 1\n", ratio_w, ratio_h);
706         return FALSE;
707     }
708 #endif
709     XDBG_DEBUG(MTVO, "Support direct drawing\n");
710     return TRUE;
711 }
712
713 Bool
714 secVideoTvReCreateConverter(SECVideoTv* tv)
715 {
716     if (tv == NULL)
717         return FALSE;
718     if (tv->cvt)
719     {
720          secCvtDestroy (tv->cvt);
721     }
722     tv->cvt = secCvtCreate (tv->pScrn, CVT_OP_M2M);
723     XDBG_RETURN_VAL_IF_FAIL (tv->cvt != NULL, FALSE);
724     secCvtAddCallback (tv->cvt, _secVideoTvCvtCallback, tv);
725     return TRUE;
726 }