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