1 /**************************************************************************
3 xserver-xorg-video-exynos
5 Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: Boram Park <boram1288.park@samsung.com>
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:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
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.
29 **************************************************************************/
32 #include "sec_display.h"
34 #include "sec_output.h"
35 #include "sec_accel.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"
45 #include <sys/ioctl.h>
47 #include <drm_fourcc.h>
51 /* HW restriction (VP) */
54 #define MAX_WIDTH 1920
55 #define MAX_HEIGHT 1080
56 #define MIN_SCALE 0.25
57 #define MAX_SCALE 16.0
59 /* private structure */
67 /* used if id is not supported in case of lpos == LAYER_LOWER1. */
78 unsigned int convert_id;
80 SECLayerOutput output;
85 _secVideoTvCalSize (SECVideoTv* tv, int src_w, int src_h, int dst_w, int dst_h)
89 if (src_w < MIN_WIDTH || src_h < MIN_HEIGHT)
91 XDBG_WARNING (MTVO, "size(%dx%d) must be more than (%dx%d).\n",
92 src_w, src_h, MIN_WIDTH, MAX_WIDTH);
95 r = (float)dst_w / src_w;
96 if (r < MIN_SCALE || r > MAX_SCALE)
98 XDBG_WARNING (MTVO, "ratio_w(%f) is out of range(%f~%f).\n",
99 r, MIN_SCALE, MAX_SCALE);
102 r = (float)dst_h / src_h;
103 if (r < MIN_SCALE || r > MAX_SCALE)
105 XDBG_WARNING (MTVO, "ratio_h(%d) is out of range(%f~%f).\n",
106 r, MIN_SCALE, MAX_SCALE);
113 _secVideoTvGetOutBuffer (SECVideoTv* tv, int width, int height, Bool secure)
115 int i = tv->outbuf_index, j;
119 tv->outbuf = (SECVideoBuf**)calloc (tv->outbuf_num, sizeof (SECVideoBuf*));
120 XDBG_RETURN_VAL_IF_FAIL (tv->outbuf != NULL, NULL);
124 if (i >= tv->outbuf_num)
127 for (j = 0; j < tv->outbuf_num; j++)
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);
134 if (tv->outbuf[i] && !VBUF_IS_CONVERTING (tv->outbuf[i]) && !tv->outbuf[i]->showing)
136 if (tv->outbuf[i]->width == width &&
137 tv->outbuf[i]->id == tv->convert_id &&
138 tv->outbuf[i]->height == height)
140 tv->outbuf_index = i;
141 return tv->outbuf[i];
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);
151 XDBG_DEBUG (MTVO, "outbuf(%p, %c%c%c%c)\n", tv->outbuf[i], FOURCC_STR (tv->convert_id));
153 tv->outbuf_index = i;
154 return tv->outbuf[i];
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);
165 XDBG_DEBUG (MTVO, "outbuf(%p, %c%c%c%c)\n", tv->outbuf[i], FOURCC_STR (tv->convert_id));
167 tv->outbuf_index = i;
168 return tv->outbuf[i];
172 if (i >= tv->outbuf_num)
179 for (j = 0; j < tv->outbuf_num; 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);
186 XDBG_ERROR (MTVO, "now all outbufs in use! %s\n", buffers);
188 XDBG_ERROR (MTVO, "now all outbufs in use!\n");
195 _secVideoTvLayerEnsure (SECVideoTv* tv)
202 XDBG_RETURN_VAL_IF_FAIL (tv->lpos != LAYER_NONE, FALSE);
204 layer = secLayerCreate (tv->pScrn, LAYER_OUTPUT_EXT, tv->lpos);
205 XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
213 _secVideoTvLayerDestroy (SECVideoTv* tv)
217 secLayerUnref (tv->layer);
223 _secVideoTvPutImageInternal (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *rect)
227 XDBG_DEBUG (MTVO, "rect (%d,%d %dx%d) \n",
228 rect->x, rect->y, rect->width, rect->height);
231 if (tv->lpos == LAYER_LOWER1)
232 if (!_secVideoTvCalSize (tv, vbuf->width, vbuf->height,
233 rect->width, rect->height))
238 xRectangle src_rect, dst_rect;
239 secLayerGetRect (tv->layer, &src_rect, &dst_rect);
241 if (tv->is_resized == 1)
243 secLayerFreezeUpdate (tv->layer, FALSE);
244 // secLayerHide (tv->layer);
248 if (memcmp (&vbuf->crop, &src_rect, sizeof (xRectangle)) ||
249 memcmp (rect, &dst_rect, sizeof (xRectangle)))
251 secLayerFreezeUpdate (tv->layer, TRUE);
252 secLayerSetRect (tv->layer, &vbuf->crop, rect);
253 secLayerFreezeUpdate (tv->layer, FALSE);
256 ret = secLayerSetBuffer (tv->layer, vbuf);
260 if (!secLayerIsVisible (tv->layer))
262 secLayerShow (tv->layer);
266 XDBG_DEBUG(MTVO,"tv->layer(%p) is not visible\n", tv->layer);
272 _secVideoTvCvtCallback (SECCvt *cvt,
278 SECVideoTv *tv = (SECVideoTv*)cvt_data;
281 XDBG_RETURN_IF_FAIL (tv != NULL);
282 XDBG_RETURN_IF_FAIL (cvt != NULL);
283 XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (dst));
285 XDBG_DEBUG (MTVO, "++++++++++++++++++++++++ \n");
287 for (i = 0; i < tv->outbuf_num; i++)
288 if (tv->outbuf[i] == dst)
290 XDBG_RETURN_IF_FAIL (i < tv->outbuf_num);
291 _secVideoTvPutImageInternal (tv, dst, &tv->tv_rect);
293 XDBG_DEBUG (MTVO, "++++++++++++++++++++++++.. \n");
297 secVideoTvConnect (ScrnInfoPtr pScrn, unsigned int id, SECLayerPos lpos)
299 SECVideoTv* tv = NULL;
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);
306 tv = calloc (sizeof (SECVideoTv), 1);
307 XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
309 pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
311 if (lpos == LAYER_LOWER1 && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
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);
317 secCvtAddCallback (tv->cvt, _secVideoTvCvtCallback, tv);
319 else if (lpos == LAYER_LOWER1 && pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI)
321 if (!secLayerSupport (pScrn, LAYER_OUTPUT_EXT, lpos, id))
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);
331 XDBG_DEBUG(MTVO, "Not need converting id(%c%c%c%c)\n", FOURCC_STR (id));
336 XDBG_DEBUG (MTVO, "id(%c%c%c%c), lpos(%d)!\n", FOURCC_STR (id), lpos);
337 tv->output = LAYER_OUTPUT_EXT;
340 tv->outbuf_index = -1;
341 tv->convert_id = convert_id;
342 tv->outbuf_num = TVBUF_NUM;
351 secCvtDestroy (tv->cvt);
358 secVideoTvResizeOutput (SECVideoTv* tv, xRectanglePtr src, xRectanglePtr dst)
363 if (!secVideoCanDirectDrawing (tv, src->width, src->height,
364 dst->width, dst->height))
366 secVideoTvReCreateConverter(tv);
372 secCvtDestroy (tv->cvt);
379 for (i = 0; i < tv->outbuf_num; i++)
380 if (tv->outbuf[i] && !VBUF_IS_CONVERTING(tv->outbuf[i]) && !tv->outbuf[i]->showing)
382 secUtilVideoBufferUnref (tv->outbuf[i]);
383 tv->outbuf[i] = NULL;
385 tv->outbuf_index = -1;
388 secLayerFreezeUpdate (tv->layer, TRUE);
394 secVideoTvDisconnect (SECVideoTv* tv)
398 XDBG_RETURN_IF_FAIL (tv != NULL);
400 XDBG_DEBUG (MTVO, "!\n");
403 secCvtDestroy (tv->cvt);
405 _secVideoTvLayerDestroy (tv);
409 for (i = 0; i < tv->outbuf_num; i++)
411 secUtilVideoBufferUnref (tv->outbuf[i]);
420 secVideoTvSetBuffer (SECVideoTv* tv, SECVideoBuf **vbufs, int bufnum)
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);
430 XDBG_ERROR (MTVO, "already has buffers.\n");
434 tv->outbuf_num = bufnum;
435 tv->outbuf = (SECVideoBuf**)calloc (bufnum, sizeof (SECVideoBuf*));
436 XDBG_RETURN_VAL_IF_FAIL (tv->outbuf != NULL, FALSE);
438 for (i = 0; i < tv->outbuf_num; i++)
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);
444 tv->outbuf[i] = secUtilVideoBufferRef (vbufs[i]);
445 XDBG_GOTO_IF_FAIL (tv->outbuf[i] != NULL, fail_set_buffer);
447 if (!tv->outbuf[i]->showing && tv->outbuf[i]->need_reset)
448 secUtilClearVideoBuffer (tv->outbuf[i]);
450 tv->outbuf[i]->need_reset = TRUE;
458 for (i = 0; i < tv->outbuf_num; i++)
462 secUtilVideoBufferUnref (tv->outbuf[i]);
463 tv->outbuf[i] = NULL;
474 secVideoTvGetPos (SECVideoTv *tv)
476 XDBG_RETURN_VAL_IF_FAIL (tv != NULL, LAYER_NONE);
482 secVideoTvGetLayer (SECVideoTv *tv)
484 XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
486 _secVideoTvLayerEnsure (tv);
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.
497 secVideoTvPutImage (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *rect, int csc_range)
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);
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);
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,};
519 int dst_width, dst_height;
524 if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
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;
534 tv->tv_rect.width = tv->tv_width;
535 tv->tv_rect.height = tv->tv_height;
539 dst_width = rect->width;
540 dst_height = rect->height;
548 src_prop.id = vbuf->id;
549 src_prop.width = vbuf->width;
550 src_prop.height = vbuf->height;
551 src_prop.crop = vbuf->crop;
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;
560 if (!secCvtEnsureSize (&src_prop, &dst_prop))
562 XDBG_DEBUG(MTVO, "Can't ensure size\n");
566 outbuf = _secVideoTvGetOutBuffer (tv, dst_prop.width, dst_prop.height, vbuf->secure);
569 XDBG_DEBUG(MTVO, "Can't get outbuf\n");
572 outbuf->crop = dst_prop.crop;
574 if (!secCvtSetProperpty (tv->cvt, &src_prop, &dst_prop))
576 XDBG_DEBUG(MTVO, "Can't set cvt property\n");
580 if (!secCvtConvert (tv->cvt, vbuf, outbuf))
582 XDBG_DEBUG(MTVO, "Can't start cvt\n");
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);
595 /* can show buffer to HDMI at now. */
596 return _secVideoTvPutImageInternal (tv, vbuf, rect);
600 secVideoTvSetSize (SECVideoTv *tv, int width, int height)
602 XDBG_RETURN_IF_FAIL (tv != NULL);
604 tv->tv_width = width;
605 tv->tv_height = height;
607 XDBG_TRACE (MTVO, "size(%dx%d) \n", width, height);
611 secVideoTvGetConverter (SECVideoTv *tv)
613 XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
619 secVideoTvSetConvertFormat (SECVideoTv *tv, unsigned int convert_id)
621 XDBG_RETURN_IF_FAIL (tv != NULL);
622 XDBG_RETURN_IF_FAIL (convert_id > 0);
624 tv->convert_id = convert_id;
626 XDBG_TRACE (MTVO, "convert_id(%c%c%c%c) \n", FOURCC_STR (convert_id));
630 secVideoCanDirectDrawing (SECVideoTv *tv, int src_w, int src_h, int dst_w, int dst_h)
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);
637 /* :TODO. Need Fix flickering in direct draw case */
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);
646 ratio_w = src_w / dst_w;
649 XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (1/%d) < 1/4\n", ratio_w);
652 XDBG_DEBUG(MTVO, "ratio_w = 1/%d\n", ratio_w);
654 else if (src_w < dst_w)
656 ratio_w = dst_w / src_w;
659 XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) > 16\n", ratio_w);
662 XDBG_DEBUG(MTVO, "ratio_w = %d\n", ratio_w);
667 ratio_h = src_h / dst_h;
670 XDBG_DEBUG(MTVO, "Can't direct draw ratio_h (1/%d) < 1/4\n", ratio_w);
673 XDBG_DEBUG(MTVO, "ratio_h = 1/%d\n", ratio_h);
675 else if (src_h < dst_h)
677 ratio_h = dst_h / src_h;
680 XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) > 16\n", ratio_w);
683 XDBG_DEBUG(MTVO, "ratio_h = %d\n", ratio_h);
686 if (ratio_w != ratio_h)
688 XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) != ratio_h (%d)\n", ratio_w, ratio_h);
694 if (!secLayerSupport (tv->pScrn, tv->output, tv->lpos, tv->src_id))
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));
702 /* FIXME: Using IPP converter if we haven't native frame size */
703 if (ratio_w > 1 || ratio_h > 1)
705 XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) && ratio_h (%d) != 1\n", ratio_w, ratio_h);
709 XDBG_DEBUG(MTVO, "Support direct drawing\n");
714 secVideoTvReCreateConverter(SECVideoTv* tv)
720 secCvtDestroy (tv->cvt);
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);