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