1 /*
2 * Copyright (C) 2013 The Android Open Source Project
3 * Copyright@ Samsung Electronics Co. LTD
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /*!
19 * \file libscaler.cpp
20 * \brief source file for Scaler HAL
21 * \author Sunyoung Kang (sy0816.kang@samsung.com)
22 * \date 2013/02/01
23 *
24 * <b>Revision History: </b>
25 * - 2013.02.01 : Sunyoung Kang (sy0816.kang@samsung.com) \n
26 * Create
27 * - 2013.04.10 : Cho KyongHo (pullip.cho@samsung.com) \n
28 * Refactoring
29 *
30 */
31
32 #include <sys/types.h>
33 #include <sys/ioctl.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <system/graphics.h>
38
39 #include "exynos_scaler.h"
40
41 #include "libscaler-common.h"
42 #include "libscalerblend-v4l2.h"
43 #include "libscaler-v4l2.h"
44 #include "libscaler-m2m1shot.h"
45
hal_pixfmt_to_v4l2(int hal_pixel_format)46 int hal_pixfmt_to_v4l2(int hal_pixel_format)
47 {
48 int v4l2_pixel_format = -1;
49
50 switch (hal_pixel_format) {
51 case HAL_PIXEL_FORMAT_RGBA_8888:
52 case HAL_PIXEL_FORMAT_RGBX_8888:
53 v4l2_pixel_format = V4L2_PIX_FMT_RGB32;
54 break;
55
56 case HAL_PIXEL_FORMAT_RGB_888:
57 v4l2_pixel_format = V4L2_PIX_FMT_RGB24;
58 break;
59
60 case HAL_PIXEL_FORMAT_RGB_565:
61 v4l2_pixel_format = V4L2_PIX_FMT_RGB565;
62 break;
63
64 case HAL_PIXEL_FORMAT_BGRA_8888:
65 v4l2_pixel_format = V4L2_PIX_FMT_BGR32;
66 break;
67
68 case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
69 v4l2_pixel_format = V4L2_PIX_FMT_YVU420M;
70 break;
71
72 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
73 v4l2_pixel_format = V4L2_PIX_FMT_YUV420M;
74 break;
75
76 case HAL_PIXEL_FORMAT_YV12:
77 v4l2_pixel_format = V4L2_PIX_FMT_YVU420;
78 break;
79
80 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
81 v4l2_pixel_format = V4L2_PIX_FMT_YUV420;
82 break;
83
84 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN:
85 v4l2_pixel_format = V4L2_PIX_FMT_YUV420N;
86 break;
87
88 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
89 v4l2_pixel_format = V4L2_PIX_FMT_NV16;
90 break;
91
92 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP:
93 v4l2_pixel_format = V4L2_PIX_FMT_NV12;
94 break;
95
96 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
97 v4l2_pixel_format = V4L2_PIX_FMT_NV12N;
98 break;
99
100 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
101 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV:
102 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
103 v4l2_pixel_format = V4L2_PIX_FMT_NV12M;
104 break;
105
106 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B:
107 v4l2_pixel_format = V4L2_PIX_FMT_NV12N_10B;
108 break;
109
110 case HAL_PIXEL_FORMAT_YCbCr_422_I:
111 v4l2_pixel_format = V4L2_PIX_FMT_YUYV;
112 break;
113
114 case HAL_PIXEL_FORMAT_EXYNOS_CbYCrY_422_I:
115 v4l2_pixel_format = V4L2_PIX_FMT_UYVY;
116 break;
117
118 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_422_SP:
119 v4l2_pixel_format = V4L2_PIX_FMT_NV61;
120 break;
121
122 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
123 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL:
124 v4l2_pixel_format = V4L2_PIX_FMT_NV21M;
125 break;
126
127 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
128 v4l2_pixel_format = V4L2_PIX_FMT_NV21;
129 break;
130
131 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED:
132 #ifdef USES_FIMC
133 v4l2_pixel_format = V4L2_PIX_FMT_NV12MT;
134 #else
135 v4l2_pixel_format = V4L2_PIX_FMT_NV12MT_16X16;
136 #endif
137 break;
138
139 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_TILED:
140 v4l2_pixel_format = V4L2_PIX_FMT_NV12NT;
141 break;
142
143 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_422_I:
144 v4l2_pixel_format = V4L2_PIX_FMT_YVYU;
145 break;
146
147 case HAL_PIXEL_FORMAT_EXYNOS_CrYCbY_422_I:
148 v4l2_pixel_format = V4L2_PIX_FMT_VYUY;
149 break;
150
151 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M:
152 v4l2_pixel_format = V4L2_PIX_FMT_NV12M_P010;
153 break;
154
155 default:
156 ALOGE("%s::unmatched HAL_PIXEL_FORMAT color_space(0x%x)\n",
157 __func__, hal_pixel_format);
158 break;
159 }
160
161 return v4l2_pixel_format;
162 }
163
find_pixel(unsigned int sc_pxfmt,unsigned int __out * v4l2_pxfmt)164 static bool find_pixel(unsigned int sc_pxfmt, unsigned int __out *v4l2_pxfmt)
165 {
166 const static unsigned int sc_fmt_tbl[][2] = {
167 {EXYNOS_SC_FMT_RGB32, V4L2_PIX_FMT_RGB32},
168 {EXYNOS_SC_FMT_BGR32, V4L2_PIX_FMT_BGR32},
169 {EXYNOS_SC_FMT_RGB565, V4L2_PIX_FMT_RGB565},
170 {EXYNOS_SC_FMT_RGB555X, V4L2_PIX_FMT_RGB555X},
171 {EXYNOS_SC_FMT_RGB444, V4L2_PIX_FMT_RGB444},
172 };
173
174 for (size_t i = 0; i < ARRSIZE(sc_fmt_tbl); i++) {
175 if (sc_pxfmt == sc_fmt_tbl[i][0]) {
176 *v4l2_pxfmt = sc_fmt_tbl[i][1];
177 return true;
178 }
179 }
180
181 SC_LOGE("Unknown format value %d", sc_pxfmt);
182
183 return false;
184 }
185
exynos_sc_copy_pixels(exynos_sc_pxinfo * pxinfo,int dev_num)186 bool exynos_sc_copy_pixels(exynos_sc_pxinfo *pxinfo, int dev_num)
187 {
188 unsigned int srcfmt;
189 unsigned int dstfmt;
190
191 CScalerM2M1SHOT sc(dev_num);
192
193 if (!sc.Valid())
194 return false;
195
196 if (!find_pixel(pxinfo->src.pxfmt, &srcfmt))
197 return false;
198
199 if (!find_pixel(pxinfo->dst.pxfmt, &dstfmt))
200 return false;
201
202 if (!sc.SetSrcFormat(pxinfo->src.width, pxinfo->src.height, srcfmt))
203 return false;
204
205 if (!sc.SetDstFormat(pxinfo->dst.width, pxinfo->dst.height, dstfmt))
206 return false;
207
208 if (!sc.SetSrcCrop(pxinfo->src.crop_left, pxinfo->src.crop_top,
209 pxinfo->src.crop_width, pxinfo->src.crop_height))
210 return false;
211
212 if (!sc.SetDstCrop(pxinfo->dst.crop_left, pxinfo->dst.crop_top,
213 pxinfo->dst.crop_width, pxinfo->dst.crop_height))
214 return false;
215
216 if (!sc.SetRotate(pxinfo->rotate, pxinfo->hflip, pxinfo->vflip))
217 return false;
218
219 // the first argument ot CScalerM2M1SHOT.SetXXXAddr() must be void *[3]
220 // it is safe to pass void *[1] which is not an array actually
221 // because CScalerM2M1SHOT.SetAddr() just accesses the array elements
222 // that are used for the specified format and this function just specifies
223 // RGB formats with one planar.
224 void *addr[SC_NUM_OF_PLANES];
225 for (size_t i = 1; i < SC_NUM_OF_PLANES; i++)
226 addr[i] = NULL;
227
228 addr[0] = pxinfo->src.addr;
229 if (!sc.SetSrcAddr(addr, V4L2_MEMORY_USERPTR))
230 return false;
231
232 addr[0] = pxinfo->dst.addr;
233 if (!sc.SetDstAddr(addr, V4L2_MEMORY_USERPTR))
234 return false;
235
236 return sc.Run();
237 }
238
239 #ifdef SCALER_USE_M2M1SHOT
240 typedef CScalerM2M1SHOT CScalerNonStream;
241 #else
242 typedef CScalerV4L2 CScalerNonStream;
243 #endif
244
GetNonStreamScaler(void * handle)245 static CScalerNonStream *GetNonStreamScaler(void *handle)
246 {
247 if (handle == NULL) {
248 SC_LOGE("NULL Scaler handle");
249 return NULL;
250 }
251
252 CScalerNonStream *sc = reinterpret_cast<CScalerNonStream *>(handle);
253 if (!sc->Valid()) {
254 SC_LOGE("Invalid Scaler handle %p", handle);
255 return NULL;
256 }
257
258 return sc;
259 }
260
exynos_sc_create(int dev_num)261 void *exynos_sc_create(int dev_num)
262 {
263 CScalerNonStream *sc = new CScalerNonStream(dev_num);
264
265 if (!sc) {
266 SC_LOGE("Failed to allocate a Scaler handle for instance %d", dev_num);
267 return NULL;
268 }
269
270 if (!sc->Valid()) {
271 SC_LOGE("Failed to create a Scaler handle for instance %d", dev_num);
272 delete sc;
273 return NULL;
274 }
275
276 return reinterpret_cast<void *>(sc);
277 }
278
exynos_sc_destroy(void * handle)279 int exynos_sc_destroy(void *handle)
280 {
281 int ret = 0;
282
283 CScalerNonStream *sc = GetNonStreamScaler(handle);
284 if (!sc)
285 return -1;
286
287 if (!sc->Stop()) {
288 SC_LOGE("Failed to stop Scaler (handle %p)", handle);
289 ret = -1;
290 }
291
292 delete sc;
293
294 return ret;
295 }
296
exynos_sc_set_csc_property(void * handle,unsigned int csc_range,unsigned int v4l2_colorspace,unsigned int filter)297 int exynos_sc_set_csc_property(
298 void *handle,
299 unsigned int csc_range,
300 unsigned int v4l2_colorspace,
301 unsigned int filter)
302
303 {
304 CScalerNonStream *sc = GetNonStreamScaler(handle);
305 if (!sc)
306 return -1;
307
308 sc->SetCSCWide(csc_range);
309 sc->SetCSCEq(v4l2_colorspace);
310 sc->SetFilter(filter);
311
312 return 0;
313 }
314
exynos_sc_set_src_format(void * handle,unsigned int width,unsigned int height,unsigned int crop_left,unsigned int crop_top,unsigned int crop_width,unsigned int crop_height,unsigned int v4l2_colorformat,unsigned int cacheable,unsigned int mode_drm,unsigned int premultiplied)315 int exynos_sc_set_src_format(
316 void *handle,
317 unsigned int width,
318 unsigned int height,
319 unsigned int crop_left,
320 unsigned int crop_top,
321 unsigned int crop_width,
322 unsigned int crop_height,
323 unsigned int v4l2_colorformat,
324 unsigned int cacheable,
325 unsigned int mode_drm,
326 unsigned int premultiplied)
327 {
328 CScalerNonStream *sc = GetNonStreamScaler(handle);
329 if (!sc)
330 return -1;
331
332 sc->SetSrcPremultiplied(premultiplied != 0);
333 sc->SetSrcCacheable(cacheable != 0);
334 sc->SetDRM(mode_drm != 0);
335
336 if (!sc->SetSrcFormat(width, height, v4l2_colorformat))
337 return -1;
338
339 return sc->SetSrcCrop(crop_left, crop_top, crop_width, crop_height) ? 0 : -1;
340 }
341
exynos_sc_set_dst_format(void * handle,unsigned int width,unsigned int height,unsigned int crop_left,unsigned int crop_top,unsigned int crop_width,unsigned int crop_height,unsigned int v4l2_colorformat,unsigned int cacheable,unsigned int mode_drm,unsigned int premultiplied)342 int exynos_sc_set_dst_format(
343 void *handle,
344 unsigned int width,
345 unsigned int height,
346 unsigned int crop_left,
347 unsigned int crop_top,
348 unsigned int crop_width,
349 unsigned int crop_height,
350 unsigned int v4l2_colorformat,
351 unsigned int cacheable,
352 unsigned int mode_drm,
353 unsigned int premultiplied)
354 {
355 CScalerNonStream *sc = GetNonStreamScaler(handle);
356 if (!sc)
357 return -1;
358
359 sc->SetDstPremultiplied(premultiplied != 0);
360 sc->SetDstCacheable(cacheable != 0);
361 sc->SetDRM(mode_drm != 0);
362
363 if (!sc->SetDstFormat(width, height, v4l2_colorformat))
364 return -1;
365
366 if (!sc->SetDstCrop(crop_left, crop_top, crop_width, crop_height))
367 return -1;
368
369 return 0;
370 }
371
exynos_sc_set_rotation(void * handle,int rot,int flip_h,int flip_v)372 int exynos_sc_set_rotation(
373 void *handle,
374 int rot,
375 int flip_h,
376 int flip_v)
377 {
378 CScalerNonStream *sc = GetNonStreamScaler(handle);
379 if (!sc)
380 return -1;
381
382 return sc->SetRotate(rot, flip_h, flip_v) ? 0 : -1;
383 }
384
exynos_sc_set_framerate(void * handle,int framerate)385 void exynos_sc_set_framerate(
386 void *handle,
387 int framerate)
388 {
389 CScalerNonStream *sc = GetNonStreamScaler(handle);
390 if (!sc)
391 return;
392
393 sc->SetFrameRate(framerate);
394 }
395
exynos_sc_set_src_addr(void * handle,void * addr[SC_NUM_OF_PLANES],int mem_type,int __UNUSED__ acquireFenceFd)396 int exynos_sc_set_src_addr(
397 void *handle,
398 void *addr[SC_NUM_OF_PLANES],
399 int mem_type,
400 int __UNUSED__ acquireFenceFd)
401 {
402 CScalerNonStream *sc = GetNonStreamScaler(handle);
403 if (!sc)
404 return -1;
405
406 // acquireFenceFd is ignored by blocking mode
407 return sc->SetSrcAddr(addr, mem_type) ? 0 : -1;
408 }
409
exynos_sc_set_dst_addr(void * handle,void * addr[SC_NUM_OF_PLANES],int mem_type,int __UNUSED__ acquireFenceFd)410 int exynos_sc_set_dst_addr(
411 void *handle,
412 void *addr[SC_NUM_OF_PLANES],
413 int mem_type,
414 int __UNUSED__ acquireFenceFd)
415 {
416 CScalerNonStream *sc = GetNonStreamScaler(handle);
417 if (!sc)
418 return -1;
419
420 // acquireFenceFd is ignored by blocking mode
421 return sc->SetDstAddr(addr, mem_type) ? 0 : -1;
422 }
423
exynos_sc_convert(void * handle)424 int exynos_sc_convert(void *handle)
425 {
426 CScalerNonStream *sc = GetNonStreamScaler(handle);
427 if (!sc)
428 return -1;
429
430 return sc->Run() ? 0 : -1;
431 }
432
GetScalerBlend(void * handle)433 static CScalerBlendV4L2 *GetScalerBlend(void *handle)
434 {
435 if (handle == NULL) {
436 SC_LOGE("NULL Scaler handle");
437 return NULL;
438 }
439
440 CScalerBlendV4L2 *sc = reinterpret_cast<CScalerBlendV4L2 *>(handle);
441 if (!sc->Valid()) {
442 SC_LOGE("Invalid Scaler handle %p", handle);
443 return NULL;
444 }
445
446 return sc;
447 }
448
GetScaler(void * handle)449 static CScalerV4L2 *GetScaler(void *handle)
450 {
451 if (handle == NULL) {
452 SC_LOGE("NULL Scaler handle");
453 return NULL;
454 }
455
456 CScalerV4L2 *sc = reinterpret_cast<CScalerV4L2 *>(handle);
457 if (!sc->Valid()) {
458 SC_LOGE("Invalid Scaler handle %p", handle);
459 return NULL;
460 }
461
462 return sc;
463 }
464
exynos_sc_create_exclusive(int dev_num,int allow_drm)465 void *exynos_sc_create_exclusive(
466 int dev_num,
467 int allow_drm
468 )
469 {
470 CScalerV4L2 *sc;
471
472 sc = new CScalerV4L2(dev_num, allow_drm);
473 if (!sc) {
474 SC_LOGE("Failed to allocate a Scaler handle for instance %d", dev_num);
475 return NULL;
476 }
477
478 if (!sc->Valid()) {
479 SC_LOGE("Failed to create a Scaler handle for instance %d", dev_num);
480 delete sc;
481 return NULL;
482 }
483
484 SC_LOGD("Scaler %d is successfully created", dev_num);
485 return reinterpret_cast<void *>(sc);
486 }
487
exynos_sc_free_and_close(void * handle)488 int exynos_sc_free_and_close(void *handle)
489 {
490 CScalerV4L2 *sc = GetScaler(handle);
491 if (!sc)
492 return -1;
493
494 int ret = 0;
495 if (!sc->Stop()) {
496 SC_LOGE("Failed to stop Scaler (handle %p)", handle);
497 ret = -1;
498 }
499
500 delete sc;
501
502 return ret;
503 }
504
exynos_sc_stop_exclusive(void * handle)505 int exynos_sc_stop_exclusive(void *handle)
506 {
507 CScalerV4L2 *sc = GetScaler(handle);
508 if (!sc)
509 return -1;
510
511 if (!sc->Stop()) {
512 SC_LOGE("Failed to stop Scaler (handle %p)", handle);
513 return -1;
514 }
515
516 return 0;
517 }
518
exynos_sc_csc_exclusive(void * handle,unsigned int range_full,unsigned int v4l2_colorspace)519 int exynos_sc_csc_exclusive(void *handle,
520 unsigned int range_full,
521 unsigned int v4l2_colorspace)
522 {
523 CScalerV4L2 *sc = GetScaler(handle);
524 if (!sc)
525 return -1;
526
527 sc->SetCSCWide(range_full);
528 sc->SetCSCEq(v4l2_colorspace);
529
530 return 0;
531 }
532
exynos_sc_config_exclusive(void * handle,exynos_sc_img * src_img,exynos_sc_img * dst_img)533 int exynos_sc_config_exclusive(
534 void *handle,
535 exynos_sc_img *src_img,
536 exynos_sc_img *dst_img)
537 {
538 CScalerV4L2 *sc = GetScaler(handle);
539 if (!sc)
540 return -1;
541
542 if (src_img->drmMode && !sc->IsDRMAllowed()) {
543 SC_LOGE("Invalid DRM state request for Scaler%d (s=%d d=%d)",
544 sc->GetScalerID(), src_img->drmMode, dst_img->drmMode);
545 return -1;
546 }
547
548 unsigned int rot = 0;
549 unsigned int flip_h = 0;
550 unsigned int flip_v = 0;
551
552 if (dst_img->rot == HAL_TRANSFORM_ROT_270) {
553 rot = 270;
554 } else {
555 if (dst_img->rot & HAL_TRANSFORM_FLIP_H)
556 flip_h = 1;
557 if (dst_img->rot & HAL_TRANSFORM_FLIP_V)
558 flip_v = 1;
559 if (dst_img->rot & HAL_TRANSFORM_ROT_90)
560 rot = 90;
561 }
562
563 if (!sc->SetRotate(rot, flip_h, flip_v)) {
564 SC_LOGE("Failed to set rotation degree %d, hflip %d, vflip %d",
565 rot, flip_h, flip_v);
566 return -1;
567 }
568
569 int32_t src_color_space = hal_pixfmt_to_v4l2(src_img->format);
570 int32_t dst_color_space = hal_pixfmt_to_v4l2(dst_img->format);
571
572 if (!sc->SetSrcFormat(src_img->fw, src_img->fh, src_color_space))
573 return -1;
574
575 if (!sc->SetSrcCrop(src_img->x, src_img->y, src_img->w, src_img->h))
576 return -1;
577
578 if (!sc->SetDstFormat(dst_img->fw, dst_img->fh, dst_color_space))
579 return -1;
580
581 if (!sc->SetDstCrop(dst_img->x, dst_img->y, dst_img->w, dst_img->h))
582 return -1;
583
584 sc->SetCSCWide(!dst_img->narrowRgb);
585
586 sc->SetSrcCacheable(src_img->cacheable != 0);
587 sc->SetDstCacheable(dst_img->cacheable != 0);
588
589 sc->SetSrcPremultiplied(src_img->pre_multi);
590 sc->SetDstPremultiplied(dst_img->pre_multi);
591
592 sc->SetDRM(src_img->drmMode != 0 || dst_img->drmMode != 0);
593
594 return 0;
595 }
596
exynos_sc_run_exclusive(void * handle,exynos_sc_img * src_img,exynos_sc_img * dst_img)597 int exynos_sc_run_exclusive(
598 void *handle,
599 exynos_sc_img *src_img,
600 exynos_sc_img *dst_img)
601 {
602 CScalerV4L2 *sc = GetScaler(handle);
603 if (!sc)
604 return -1;
605
606 void *addr[SC_NUM_OF_PLANES];
607
608 addr[0] = (void *)src_img->yaddr;
609 addr[1] = (void *)src_img->uaddr;
610 addr[2] = (void *)src_img->vaddr;
611 sc->SetSrcAddr(addr, src_img->mem_type, src_img->acquireFenceFd);
612
613 addr[0] = (void *)dst_img->yaddr;
614 addr[1] = (void *)dst_img->uaddr;
615 addr[2] = (void *)dst_img->vaddr;
616 sc->SetDstAddr(addr, dst_img->mem_type, dst_img->acquireFenceFd);
617
618 if (!sc->DevSetCtrl())
619 return -1;
620
621 if (!sc->DevSetFormat())
622 return -1;
623
624 if (!sc->ReqBufs())
625 return -1;
626
627 int fdSrcReleaseFence, fdDstReleaseFence;
628
629 if (!sc->QBuf(&fdSrcReleaseFence, &fdDstReleaseFence))
630 return -1;
631
632 if (!sc->StreamOn()) {
633 close(fdSrcReleaseFence);
634 close(fdDstReleaseFence);
635 return -1;
636 }
637
638 src_img->releaseFenceFd = fdSrcReleaseFence;
639 dst_img->releaseFenceFd = fdDstReleaseFence;
640
641 return 0;
642 }
643
exynos_sc_create_blend_exclusive(int dev_num,int allow_drm)644 void *exynos_sc_create_blend_exclusive(
645 int dev_num,
646 int allow_drm
647 )
648 {
649 CScalerBlendV4L2 *sc;
650
651 sc = new CScalerBlendV4L2(dev_num, allow_drm);
652 if (!sc) {
653 SC_LOGE("Failed to allocate a Scaler blend handle for instance %d", dev_num);
654 return NULL;
655 }
656
657 if (!sc->Valid()) {
658 SC_LOGE("Failed to create a Scaler blend handle for instance %d", dev_num);
659 delete sc;
660 return NULL;
661 }
662
663 SC_LOGD("Scaler blend %d is successfully created", dev_num);
664 return reinterpret_cast<void *>(sc);
665 }
666
exynos_sc_config_blend_exclusive(void * handle,exynos_sc_img * src_img,exynos_sc_img * dst_img,struct SrcBlendInfo * srcblendinfo)667 int exynos_sc_config_blend_exclusive(
668 void *handle,
669 exynos_sc_img *src_img,
670 exynos_sc_img *dst_img,
671 struct SrcBlendInfo *srcblendinfo)
672 {
673
674 CScalerBlendV4L2 *sc = GetScalerBlend(handle);
675 if (!sc)
676 return -1;
677
678 if (src_img->drmMode && !sc->IsDRMAllowed()) {
679 SC_LOGE("Invalid DRM state request for Scaler%d (s=%d d=%d)",
680 sc->GetScalerID(), src_img->drmMode, dst_img->drmMode);
681 return -1;
682 }
683 unsigned int rot = 0;
684 unsigned int flip_h = 0;
685 unsigned int flip_v = 0;
686
687 if (dst_img->rot == HAL_TRANSFORM_ROT_270) {
688 rot = 270;
689 } else {
690 if (dst_img->rot & HAL_TRANSFORM_FLIP_H)
691 flip_h = 1;
692 if (dst_img->rot & HAL_TRANSFORM_FLIP_V)
693 flip_v = 1;
694 if (dst_img->rot & HAL_TRANSFORM_ROT_90)
695 rot = 90;
696 }
697
698 if (!sc->SetRotate(rot, flip_h, flip_v)) {
699 SC_LOGE("Failed to set rotation degree %d, hflip %d, vflip %d",
700 rot, flip_h, flip_v);
701 return -1;
702 }
703
704 int32_t src_color_space = hal_pixfmt_to_v4l2(src_img->format);
705 int32_t dst_color_space = hal_pixfmt_to_v4l2(dst_img->format);
706 int32_t src_blend_color_space = hal_pixfmt_to_v4l2(srcblendinfo->srcblendfmt);
707
708 sc->GetCustomAlphaBlendFmt(src_color_space, src_blend_color_space);
709 if (src_color_space < 0) {
710 SC_LOGE("src blending format not supported");
711 return -1;
712 }
713
714 sc->SetSrcBlendOp(srcblendinfo->blop);
715
716 sc->SetSrcGlobalAlpha(srcblendinfo->globalalpha.val,
717 srcblendinfo->globalalpha.enable);
718
719 sc->SetSrcBlendVPos(srcblendinfo->srcblendvpos);
720
721 sc->SetSrcBlendHPos(srcblendinfo->srcblendhpos);
722
723 sc->SetSrcBlendPremulti(srcblendinfo->srcblendpremulti);
724
725 sc->SetSrcBlendFmt(src_blend_color_space);
726
727 sc->SetSrcBlendStride(srcblendinfo->srcblendstride);
728
729 sc->SetSrcBlendWidth(srcblendinfo->srcblendwidth);
730
731 sc->SetSrcBlendHeight(srcblendinfo->srcblendheight);
732
733 sc->SetSrcBlendCSCSpace(srcblendinfo->cscspec.enable,
734 srcblendinfo->cscspec.space,
735 srcblendinfo->cscspec.wide);
736
737 if (!sc->SetSrcFormat(src_img->fw, src_img->fh, src_color_space))
738 return -1;
739
740 if (!sc->SetSrcCrop(src_img->x, src_img->y, src_img->w, src_img->h))
741 return -1;
742
743 if (!sc->SetDstFormat(dst_img->fw, dst_img->fh, dst_color_space))
744 return -1;
745
746 if (!sc->SetDstCrop(dst_img->x, dst_img->y, dst_img->w, dst_img->h))
747 return -1;
748
749 sc->SetSrcCacheable(src_img->cacheable != 0);
750 sc->SetDstCacheable(dst_img->cacheable != 0);
751
752 sc->SetDRM(src_img->drmMode != 0 || dst_img->drmMode != 0);
753
754 return 0;
755 }
756
exynos_sc_wait_frame_done_exclusive(void * handle)757 int exynos_sc_wait_frame_done_exclusive(
758 void *handle)
759 {
760 CScalerV4L2 *sc = GetScaler(handle);
761 if (!sc)
762 return -1;
763
764 return sc->DQBuf() ? 0 : -1;
765 }
766