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 _secVideoTvGetOutBuffer (SECVideoTv* tv, int width, int height, Bool secure)
87 int i = tv->outbuf_index, j;
91 tv->outbuf = (SECVideoBuf**)calloc (tv->outbuf_num, sizeof (SECVideoBuf*));
92 XDBG_RETURN_VAL_IF_FAIL (tv->outbuf != NULL, NULL);
96 if (i >= tv->outbuf_num)
99 for (j = 0; j < tv->outbuf_num; j++)
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);
106 if (tv->outbuf[i] && !VBUF_IS_CONVERTING (tv->outbuf[i]) && !tv->outbuf[i]->showing)
108 if (tv->outbuf[i]->width == width &&
109 tv->outbuf[i]->id == tv->convert_id &&
110 tv->outbuf[i]->height == height)
112 tv->outbuf_index = i;
113 return tv->outbuf[i];
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);
123 XDBG_DEBUG (MTVO, "outbuf(%p, %c%c%c%c)\n", tv->outbuf[i], FOURCC_STR (tv->convert_id));
125 tv->outbuf_index = i;
126 return tv->outbuf[i];
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);
137 XDBG_DEBUG (MTVO, "outbuf(%p, %c%c%c%c)\n", tv->outbuf[i], FOURCC_STR (tv->convert_id));
139 tv->outbuf_index = i;
140 return tv->outbuf[i];
144 if (i >= tv->outbuf_num)
151 for (j = 0; j < tv->outbuf_num; 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);
158 XDBG_ERROR (MTVO, "now all outbufs in use! %s\n", buffers);
160 XDBG_ERROR (MTVO, "now all outbufs in use!\n");
167 _secVideoTvLayerEnsure (SECVideoTv* tv)
174 XDBG_RETURN_VAL_IF_FAIL (tv->lpos != LAYER_NONE, FALSE);
176 layer = secLayerCreate (tv->pScrn, LAYER_OUTPUT_EXT, tv->lpos);
177 XDBG_RETURN_VAL_IF_FAIL (layer != NULL, FALSE);
185 _secVideoTvLayerDestroy (SECVideoTv* tv)
189 secLayerUnref (tv->layer);
195 _secVideoTvPutImageInternal (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *rect)
199 XDBG_DEBUG (MTVO, "rect (%d,%d %dx%d) \n",
200 rect->x, rect->y, rect->width, rect->height);
202 xRectangle src_rect, dst_rect;
203 secLayerGetRect (tv->layer, &src_rect, &dst_rect);
205 if (tv->is_resized == 1)
207 secLayerFreezeUpdate (tv->layer, FALSE);
211 if (memcmp (&vbuf->crop, &src_rect, sizeof (xRectangle)) ||
212 memcmp (rect, &dst_rect, sizeof (xRectangle)))
214 secLayerFreezeUpdate (tv->layer, TRUE);
215 secLayerSetRect (tv->layer, &vbuf->crop, rect);
216 secLayerFreezeUpdate (tv->layer, FALSE);
219 ret = secLayerSetBuffer (tv->layer, vbuf);
224 secLayerShow (tv->layer);
230 _secVideoTvCvtCallback (SECCvt *cvt,
236 SECVideoTv *tv = (SECVideoTv*)cvt_data;
239 XDBG_RETURN_IF_FAIL (tv != NULL);
240 XDBG_RETURN_IF_FAIL (cvt != NULL);
241 XDBG_RETURN_IF_FAIL (VBUF_IS_VALID (dst));
243 XDBG_DEBUG (MTVO, "++++++++++++++++++++++++ \n");
245 for (i = 0; i < tv->outbuf_num; i++)
246 if (tv->outbuf[i] == dst)
248 XDBG_RETURN_IF_FAIL (i < tv->outbuf_num);
249 _secVideoTvPutImageInternal (tv, dst, &tv->tv_rect);
251 XDBG_DEBUG (MTVO, "++++++++++++++++++++++++.. \n");
255 secVideoTvConnect (ScrnInfoPtr pScrn, unsigned int id, SECLayerPos lpos)
257 SECVideoTv* tv = NULL;
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);
264 tv = calloc (sizeof (SECVideoTv), 1);
265 XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
267 pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
269 if (lpos == LAYER_LOWER1 && pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
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);
275 secCvtAddCallback (tv->cvt, _secVideoTvCvtCallback, tv);
277 else if (lpos == LAYER_LOWER1 && pSecMode->conn_mode == DISPLAY_CONN_MODE_HDMI)
279 if (!secLayerSupport (pScrn, LAYER_OUTPUT_EXT, lpos, id))
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);
289 XDBG_DEBUG(MTVO, "Not need converting id(%c%c%c%c)\n", FOURCC_STR (id));
294 XDBG_DEBUG (MTVO, "id(%c%c%c%c), lpos(%d)!\n", FOURCC_STR (id), lpos);
295 tv->output = LAYER_OUTPUT_EXT;
298 tv->outbuf_index = -1;
299 tv->convert_id = convert_id;
300 tv->outbuf_num = TVBUF_NUM;
309 secCvtDestroy (tv->cvt);
316 secVideoTvResizeOutput (SECVideoTv* tv, xRectanglePtr src, xRectanglePtr dst)
321 if (!secVideoCanDirectDrawing (tv, src->width, src->height,
322 dst->width, dst->height))
324 secVideoTvReCreateConverter(tv);
330 secCvtDestroy (tv->cvt);
337 for (i = 0; i < tv->outbuf_num; i++)
338 if (tv->outbuf[i] && !VBUF_IS_CONVERTING(tv->outbuf[i]) && !tv->outbuf[i]->showing)
340 secUtilVideoBufferUnref (tv->outbuf[i]);
341 tv->outbuf[i] = NULL;
343 tv->outbuf_index = -1;
346 secLayerFreezeUpdate (tv->layer, TRUE);
352 secVideoTvDisconnect (SECVideoTv* tv)
356 XDBG_RETURN_IF_FAIL (tv != NULL);
358 XDBG_DEBUG (MTVO, "!\n");
361 secCvtDestroy (tv->cvt);
363 _secVideoTvLayerDestroy (tv);
367 for (i = 0; i < tv->outbuf_num; i++)
369 secUtilVideoBufferUnref (tv->outbuf[i]);
378 secVideoTvSetBuffer (SECVideoTv* tv, SECVideoBuf **vbufs, int bufnum)
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);
388 XDBG_ERROR (MTVO, "already has buffers.\n");
392 tv->outbuf_num = bufnum;
393 tv->outbuf = (SECVideoBuf**)calloc (bufnum, sizeof (SECVideoBuf*));
394 XDBG_RETURN_VAL_IF_FAIL (tv->outbuf != NULL, FALSE);
396 for (i = 0; i < tv->outbuf_num; i++)
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);
402 tv->outbuf[i] = secUtilVideoBufferRef (vbufs[i]);
403 XDBG_GOTO_IF_FAIL (tv->outbuf[i] != NULL, fail_set_buffer);
405 if (!tv->outbuf[i]->showing && tv->outbuf[i]->need_reset)
406 secUtilClearVideoBuffer (tv->outbuf[i]);
408 tv->outbuf[i]->need_reset = TRUE;
416 for (i = 0; i < tv->outbuf_num; i++)
420 secUtilVideoBufferUnref (tv->outbuf[i]);
421 tv->outbuf[i] = NULL;
432 secVideoTvGetPos (SECVideoTv *tv)
434 XDBG_RETURN_VAL_IF_FAIL (tv != NULL, LAYER_NONE);
440 secVideoTvGetLayer (SECVideoTv *tv)
442 XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
444 _secVideoTvLayerEnsure (tv);
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.
455 secVideoTvPutImage (SECVideoTv *tv, SECVideoBuf *vbuf, xRectangle *rect, int csc_range)
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);
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);
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,};
477 int dst_width, dst_height;
482 if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
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;
492 tv->tv_rect.width = tv->tv_width;
493 tv->tv_rect.height = tv->tv_height;
497 dst_width = rect->width;
498 dst_height = rect->height;
506 src_prop.id = vbuf->id;
507 src_prop.width = vbuf->width;
508 src_prop.height = vbuf->height;
509 src_prop.crop = vbuf->crop;
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;
518 if (!secCvtEnsureSize (&src_prop, &dst_prop))
520 XDBG_ERROR(MTVO, "Can't ensure size\n");
524 outbuf = _secVideoTvGetOutBuffer (tv, dst_prop.width, dst_prop.height, vbuf->secure);
527 XDBG_ERROR(MTVO, "Can't get outbuf\n");
530 outbuf->crop = dst_prop.crop;
532 if (!secCvtSetProperpty (tv->cvt, &src_prop, &dst_prop))
534 XDBG_ERROR(MTVO, "Can't set cvt property\n");
538 if (!secCvtConvert (tv->cvt, vbuf, outbuf))
540 XDBG_ERROR(MTVO, "Can't start cvt\n");
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);
553 /* can show buffer to HDMI at now. */
554 return _secVideoTvPutImageInternal (tv, vbuf, rect);
558 secVideoTvSetSize (SECVideoTv *tv, int width, int height)
560 XDBG_RETURN_IF_FAIL (tv != NULL);
562 tv->tv_width = width;
563 tv->tv_height = height;
565 XDBG_TRACE (MTVO, "size(%dx%d) \n", width, height);
569 secVideoTvGetConverter (SECVideoTv *tv)
571 XDBG_RETURN_VAL_IF_FAIL (tv != NULL, NULL);
577 secVideoTvSetConvertFormat (SECVideoTv *tv, unsigned int convert_id)
579 XDBG_RETURN_IF_FAIL (tv != NULL);
580 XDBG_RETURN_IF_FAIL (convert_id > 0);
582 tv->convert_id = convert_id;
584 XDBG_TRACE (MTVO, "convert_id(%c%c%c%c) \n", FOURCC_STR (convert_id));
588 secVideoCanDirectDrawing (SECVideoTv *tv, int src_w, int src_h, int dst_w, int dst_h)
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);
595 /* :TODO. Need Fix flickering in direct draw case */
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);
604 ratio_w = src_w / dst_w;
607 XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (1/%d) < 1/4\n", ratio_w);
610 XDBG_DEBUG(MTVO, "ratio_w = 1/%d\n", ratio_w);
612 else if (src_w < dst_w)
614 ratio_w = dst_w / src_w;
617 XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) > 16\n", ratio_w);
620 XDBG_DEBUG(MTVO, "ratio_w = %d\n", ratio_w);
625 ratio_h = src_h / dst_h;
628 XDBG_DEBUG(MTVO, "Can't direct draw ratio_h (1/%d) < 1/4\n", ratio_w);
631 XDBG_DEBUG(MTVO, "ratio_h = 1/%d\n", ratio_h);
633 else if (src_h < dst_h)
635 ratio_h = dst_h / src_h;
638 XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) > 16\n", ratio_w);
641 XDBG_DEBUG(MTVO, "ratio_h = %d\n", ratio_h);
644 if (ratio_w != ratio_h)
646 XDBG_DEBUG(MTVO, "Can't direct draw ratio_w (%d) != ratio_h (%d)\n", ratio_w, ratio_h);
652 if (!secLayerSupport (tv->pScrn, tv->output, tv->lpos, tv->src_id))
654 XDBG_DEBUG(MTVO, "Can't direct draw. Layer not support. lpos(%d), src_id (%c%c%c%c)\n",
655 tv->lpos, FOURCC_STR(tv->src_id));
659 XDBG_DEBUG(MTVO, "Support direct drawing\n");
664 secVideoTvReCreateConverter(SECVideoTv* tv)
670 secCvtDestroy (tv->cvt);
672 tv->cvt = secCvtCreate (tv->pScrn, CVT_OP_M2M);
673 XDBG_RETURN_VAL_IF_FAIL (tv->cvt != NULL, FALSE);
674 secCvtAddCallback (tv->cvt, _secVideoTvCvtCallback, tv);