bump up version 1.1.4
[platform/core/uifw/libtbm.git] / src / tbm_surface_internal.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include "config.h"
33 #include "tbm_bufmgr.h"
34 #include "tbm_bufmgr_int.h"
35 #include "tbm_surface_internal.h"
36 #include "list.h"
37
38 static tbm_bufmgr g_surface_bufmgr = NULL;
39 struct list_head g_surface_list; /* list of surfaces belonging to bufmgr */
40
41 static pthread_mutex_t tbm_surface_lock;
42
43 static bool
44 _tbm_surface_mutex_init (void)
45 {
46     static bool tbm_surface_mutex_init = false;
47
48     if (tbm_surface_mutex_init)
49         return true;
50
51     if (pthread_mutex_init (&tbm_surface_lock, NULL))
52     {
53         TBM_LOG ("[libtbm] fail: tbm_surface mutex init\n");
54         return false;
55     }
56
57     tbm_surface_mutex_init = true;
58
59     return true;
60 }
61
62 void
63 _tbm_surface_mutex_lock (void)
64 {
65     if (!_tbm_surface_mutex_init ())
66         return;
67
68     pthread_mutex_lock (&tbm_surface_lock);
69 }
70
71 void
72 _tbm_surface_mutex_unlock (void)
73 {
74     pthread_mutex_unlock (&tbm_surface_lock);
75 }
76
77 static void
78 _init_surface_bufmgr()
79 {
80     g_surface_bufmgr = tbm_bufmgr_init (-1);
81 }
82
83 static void
84 _deinit_surface_bufmgr()
85 {
86     if (!g_surface_bufmgr)
87         return;
88
89     tbm_bufmgr_deinit (g_surface_bufmgr);
90     g_surface_bufmgr = NULL;
91 }
92
93 static int
94 _tbm_surface_internal_query_size (tbm_surface_h surface)
95 {
96     TBM_RETURN_VAL_IF_FAIL (surface, 0);
97
98     struct _tbm_surface *surf = (struct _tbm_surface *) surface;
99     struct _tbm_bufmgr *mgr = surf->bufmgr;
100     int size = 0;
101
102     TBM_RETURN_VAL_IF_FAIL (mgr != NULL, 0);
103     TBM_RETURN_VAL_IF_FAIL (surf->info.width > 0, 0);
104     TBM_RETURN_VAL_IF_FAIL (surf->info.height > 0, 0);
105     TBM_RETURN_VAL_IF_FAIL (surf->info.format > 0, 0);
106
107     size = mgr->backend->surface_get_size (surf, surf->info.width, surf->info.height, surf->info.format);
108
109     return size;
110 }
111
112 static int
113 _tbm_surface_internal_query_plane_data (tbm_surface_h surface, int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch)
114 {
115     TBM_RETURN_VAL_IF_FAIL (surface, 0);
116     TBM_RETURN_VAL_IF_FAIL (plane_idx > -1, 0);
117
118     struct _tbm_surface *surf = (struct _tbm_surface *) surface;
119     struct _tbm_bufmgr *mgr = surf->bufmgr;
120     int ret = 0;
121
122     TBM_RETURN_VAL_IF_FAIL (mgr != NULL, 0);
123     TBM_RETURN_VAL_IF_FAIL (surf->info.width > 0, 0);
124     TBM_RETURN_VAL_IF_FAIL (surf->info.height > 0, 0);
125     TBM_RETURN_VAL_IF_FAIL (surf->info.format > 0, 0);
126
127     ret = mgr->backend->surface_get_plane_data (surf, surf->info.width, surf->info.height, surf->info.format, plane_idx, size, offset, pitch);
128     if (!ret)
129         return 0;
130
131     return 1;
132 }
133
134 int
135 tbm_surface_internal_query_supported_formats (uint32_t **formats, uint32_t *num)
136 {
137     struct _tbm_bufmgr *mgr;
138     int ret = 0;
139
140     _tbm_surface_mutex_lock();
141
142     if (!g_surface_bufmgr)
143     {
144         _init_surface_bufmgr();
145         LIST_INITHEAD (&g_surface_list);
146     }
147
148     mgr = g_surface_bufmgr;
149     ret = mgr->backend->surface_supported_format (formats, num);
150
151     _tbm_surface_mutex_unlock();
152
153     return ret;
154 }
155
156 int tbm_surface_internal_get_num_planes (tbm_format format)
157 {
158     int num_planes = 0;
159
160     switch (format)
161     {
162         case TBM_FORMAT_C8:
163         case TBM_FORMAT_RGB332:
164         case TBM_FORMAT_BGR233:
165         case TBM_FORMAT_XRGB4444:
166         case TBM_FORMAT_XBGR4444:
167         case TBM_FORMAT_RGBX4444:
168         case TBM_FORMAT_BGRX4444:
169         case TBM_FORMAT_ARGB4444:
170         case TBM_FORMAT_ABGR4444:
171         case TBM_FORMAT_RGBA4444:
172         case TBM_FORMAT_BGRA4444:
173         case TBM_FORMAT_XRGB1555:
174         case TBM_FORMAT_XBGR1555:
175         case TBM_FORMAT_RGBX5551:
176         case TBM_FORMAT_BGRX5551:
177         case TBM_FORMAT_ARGB1555:
178         case TBM_FORMAT_ABGR1555:
179         case TBM_FORMAT_RGBA5551:
180         case TBM_FORMAT_BGRA5551:
181         case TBM_FORMAT_RGB565:
182         case TBM_FORMAT_BGR565:
183         case TBM_FORMAT_RGB888:
184         case TBM_FORMAT_BGR888:
185         case TBM_FORMAT_XRGB8888:
186         case TBM_FORMAT_XBGR8888:
187         case TBM_FORMAT_RGBX8888:
188         case TBM_FORMAT_BGRX8888:
189         case TBM_FORMAT_ARGB8888:
190         case TBM_FORMAT_ABGR8888:
191         case TBM_FORMAT_RGBA8888:
192         case TBM_FORMAT_BGRA8888:
193         case TBM_FORMAT_XRGB2101010:
194         case TBM_FORMAT_XBGR2101010:
195         case TBM_FORMAT_RGBX1010102:
196         case TBM_FORMAT_BGRX1010102:
197         case TBM_FORMAT_ARGB2101010:
198         case TBM_FORMAT_ABGR2101010:
199         case TBM_FORMAT_RGBA1010102:
200         case TBM_FORMAT_BGRA1010102:
201         case TBM_FORMAT_YUYV:
202         case TBM_FORMAT_YVYU:
203         case TBM_FORMAT_UYVY:
204         case TBM_FORMAT_VYUY:
205         case TBM_FORMAT_AYUV:
206             num_planes = 1;
207             break;
208         case TBM_FORMAT_NV12:
209         case TBM_FORMAT_NV21:
210         case TBM_FORMAT_NV16:
211         case TBM_FORMAT_NV61:
212             num_planes = 2;
213             break;
214         case TBM_FORMAT_YUV410:
215         case TBM_FORMAT_YVU410:
216         case TBM_FORMAT_YUV411:
217         case TBM_FORMAT_YVU411:
218         case TBM_FORMAT_YUV420:
219         case TBM_FORMAT_YVU420:
220         case TBM_FORMAT_YUV422:
221         case TBM_FORMAT_YVU422:
222         case TBM_FORMAT_YUV444:
223         case TBM_FORMAT_YVU444:
224             num_planes = 3;
225             break;
226
227         default :
228             break;
229     }
230
231     return num_planes;
232 }
233
234 int tbm_surface_internal_get_bpp (tbm_format format)
235 {
236     int bpp = 0;
237
238     switch (format)
239     {
240         case TBM_FORMAT_C8:
241         case TBM_FORMAT_RGB332:
242         case TBM_FORMAT_BGR233:
243             bpp = 8;
244             break;
245         case TBM_FORMAT_XRGB4444:
246         case TBM_FORMAT_XBGR4444:
247         case TBM_FORMAT_RGBX4444:
248         case TBM_FORMAT_BGRX4444:
249         case TBM_FORMAT_ARGB4444:
250         case TBM_FORMAT_ABGR4444:
251         case TBM_FORMAT_RGBA4444:
252         case TBM_FORMAT_BGRA4444:
253         case TBM_FORMAT_XRGB1555:
254         case TBM_FORMAT_XBGR1555:
255         case TBM_FORMAT_RGBX5551:
256         case TBM_FORMAT_BGRX5551:
257         case TBM_FORMAT_ARGB1555:
258         case TBM_FORMAT_ABGR1555:
259         case TBM_FORMAT_RGBA5551:
260         case TBM_FORMAT_BGRA5551:
261         case TBM_FORMAT_RGB565:
262         case TBM_FORMAT_BGR565:
263             bpp = 16;
264             break;
265         case TBM_FORMAT_RGB888:
266         case TBM_FORMAT_BGR888:
267             bpp = 24;
268             break;
269         case TBM_FORMAT_XRGB8888:
270         case TBM_FORMAT_XBGR8888:
271         case TBM_FORMAT_RGBX8888:
272         case TBM_FORMAT_BGRX8888:
273         case TBM_FORMAT_ARGB8888:
274         case TBM_FORMAT_ABGR8888:
275         case TBM_FORMAT_RGBA8888:
276         case TBM_FORMAT_BGRA8888:
277         case TBM_FORMAT_XRGB2101010:
278         case TBM_FORMAT_XBGR2101010:
279         case TBM_FORMAT_RGBX1010102:
280         case TBM_FORMAT_BGRX1010102:
281         case TBM_FORMAT_ARGB2101010:
282         case TBM_FORMAT_ABGR2101010:
283         case TBM_FORMAT_RGBA1010102:
284         case TBM_FORMAT_BGRA1010102:
285         case TBM_FORMAT_YUYV:
286         case TBM_FORMAT_YVYU:
287         case TBM_FORMAT_UYVY:
288         case TBM_FORMAT_VYUY:
289         case TBM_FORMAT_AYUV:
290             bpp = 32;
291             break;
292         case TBM_FORMAT_NV12:
293         case TBM_FORMAT_NV21:
294             bpp = 12;
295             break;
296         case TBM_FORMAT_NV16:
297         case TBM_FORMAT_NV61:
298             bpp = 16;
299             break;
300         case TBM_FORMAT_YUV410:
301         case TBM_FORMAT_YVU410:
302             bpp = 9;
303             break;
304         case TBM_FORMAT_YUV411:
305         case TBM_FORMAT_YVU411:
306         case TBM_FORMAT_YUV420:
307         case TBM_FORMAT_YVU420:
308             bpp = 12;
309             break;
310         case TBM_FORMAT_YUV422:
311         case TBM_FORMAT_YVU422:
312             bpp = 16;
313             break;
314         case TBM_FORMAT_YUV444:
315         case TBM_FORMAT_YVU444:
316             bpp = 24;
317             break;
318         default :
319             break;
320     }
321
322     return bpp;
323 }
324
325
326 tbm_surface_h
327 tbm_surface_internal_create_with_flags (int width, int height, int format, int flags)
328 {
329     TBM_RETURN_VAL_IF_FAIL (width > 0, NULL);
330     TBM_RETURN_VAL_IF_FAIL (height > 0, NULL);
331
332     struct _tbm_bufmgr *mgr;
333     struct _tbm_surface *surf = NULL;
334     uint32_t size = 0;
335     uint32_t offset = 0;
336     uint32_t stride = 0;
337     int i;
338
339     _tbm_surface_mutex_lock();
340
341     if (!g_surface_bufmgr)
342     {
343         _init_surface_bufmgr();
344         LIST_INITHEAD (&g_surface_list);
345     }
346
347     mgr = g_surface_bufmgr;
348     if (!TBM_BUFMGR_IS_VALID(mgr))
349     {
350         _tbm_surface_mutex_unlock();
351         return NULL;
352     }
353     surf = calloc (1, sizeof(struct _tbm_surface));
354     if (!surf)
355     {
356         _tbm_surface_mutex_unlock();
357         return NULL;
358     }
359
360     surf->bufmgr = mgr;
361     surf->info.width = width;
362     surf->info.height = height;
363     surf->info.format = format;
364     surf->info.bpp = tbm_surface_internal_get_bpp (format);
365     surf->info.size = _tbm_surface_internal_query_size (surf);
366     surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
367
368     /* get size, stride and offset */
369     for (i = 0; i < surf->info.num_planes; i++)
370     {
371         _tbm_surface_internal_query_plane_data (surf, i, &size, &offset, &stride);
372         surf->info.planes[i].size = size;
373         surf->info.planes[i].offset = offset;
374         surf->info.planes[i].stride = stride;
375     }
376
377     surf->flags = flags;
378
379     /* create only one bo */
380     surf->num_bos = 1;
381     surf->bos[0] = tbm_bo_alloc (mgr, surf->info.size, flags);
382     if (!surf->bos[0])
383     {
384         free (surf);
385         surf = NULL;
386
387         if(LIST_IS_EMPTY (&g_surface_list))
388         {
389             _deinit_surface_bufmgr ();
390             LIST_DELINIT (&g_surface_list);
391             _tbm_surface_mutex_unlock();
392             return NULL;
393         }
394     }
395
396     LIST_ADD (&surf->item_link, &g_surface_list);
397
398     _tbm_surface_mutex_unlock();
399
400     return surf;
401 }
402
403 tbm_surface_h
404 tbm_surface_internal_create_with_bos (tbm_surface_info_s *info, tbm_bo *bos, int num)
405 {
406     TBM_RETURN_VAL_IF_FAIL (bos, NULL);
407     TBM_RETURN_VAL_IF_FAIL (info, NULL);
408
409     struct _tbm_bufmgr *mgr;
410     struct _tbm_surface *surf = NULL;
411     int i;
412
413     _tbm_surface_mutex_lock();
414
415     if (!g_surface_bufmgr)
416     {
417         _init_surface_bufmgr();
418         LIST_INITHEAD (&g_surface_list);
419     }
420
421     mgr = g_surface_bufmgr;
422     if (!TBM_BUFMGR_IS_VALID(mgr))
423     {
424         _tbm_surface_mutex_unlock();
425         return NULL;
426     }
427     surf = calloc (1, sizeof(struct _tbm_surface));
428     if (!surf)
429     {
430         _tbm_surface_mutex_unlock();
431         return NULL;
432     }
433
434     surf->bufmgr = mgr;
435     surf->info.width = info->width;
436     surf->info.height = info->height;
437     surf->info.format = info->format;
438     surf->info.bpp = info->bpp;
439     surf->info.size = info->size;
440     surf->info.num_planes = info->num_planes;
441
442     /* get size, stride and offset */
443     for (i = 0; i < info->num_planes; i++)
444     {
445         surf->info.planes[i].size = info->planes[i].size;
446         surf->info.planes[i].offset = info->planes[i].offset;
447         surf->info.planes[i].stride = info->planes[i].stride;
448     }
449
450     surf->flags = TBM_BO_DEFAULT;
451
452     /* create only one bo */
453     surf->num_bos = num;
454     for (i = 0; i < num; i++)
455     {
456         if (bos[i] == NULL)
457             goto bail1;
458
459         surf->bos[i] = tbm_bo_ref(bos[i]);
460     }
461
462     LIST_ADD (&surf->item_link, &g_surface_list);
463
464     _tbm_surface_mutex_unlock();
465
466     return surf;
467 bail1:
468     for (i = 0; i < num; i++)
469     {
470         if (surf->bos[i])
471         {
472             tbm_bo_unref (surf->bos[i]);
473             surf->bos[i] = NULL;
474         }
475     }
476
477     free (surf);
478     surf = NULL;
479
480     if(LIST_IS_EMPTY (&g_surface_list))
481     {
482         _deinit_surface_bufmgr ();
483         LIST_DELINIT (&g_surface_list);
484     }
485
486     _tbm_surface_mutex_unlock();
487
488     return NULL;
489 }
490
491
492 void
493 tbm_surface_internal_destroy (tbm_surface_h surface)
494 {
495     int i;
496
497     if (!surface)
498         return;
499
500     _tbm_surface_mutex_lock();
501
502     surface = (struct _tbm_surface *)surface;
503
504     for (i = 0; i < surface->num_bos; i++)
505     {
506         tbm_bo_unref (surface->bos[i]);
507         surface->bos[i] = NULL;
508     }
509
510     LIST_DEL (&surface->item_link);
511
512     free (surface);
513     surface = NULL;
514
515     if(LIST_IS_EMPTY (&g_surface_list))
516     {
517         _deinit_surface_bufmgr ();
518         LIST_DELINIT (&g_surface_list);
519     }
520
521     _tbm_surface_mutex_unlock();
522 }
523
524
525 int
526 tbm_surface_internal_get_num_bos (tbm_surface_h surface)
527 {
528     TBM_RETURN_VAL_IF_FAIL (surface, 0);
529
530     struct _tbm_surface *surf;
531     int num;
532
533     _tbm_surface_mutex_lock();
534
535     surf = (struct _tbm_surface *) surface;
536     num = surf->num_bos;
537
538     _tbm_surface_mutex_unlock();
539
540     return num;
541 }
542
543 tbm_bo
544 tbm_surface_internal_get_bo (tbm_surface_h surface, int bo_idx)
545 {
546     TBM_RETURN_VAL_IF_FAIL (surface, NULL);
547     TBM_RETURN_VAL_IF_FAIL (bo_idx > -1, NULL);
548
549     struct _tbm_surface *surf;
550     tbm_bo bo;
551
552     _tbm_surface_mutex_lock();
553
554     surf = (struct _tbm_surface *) surface;
555     bo = surf->bos[bo_idx];
556
557     _tbm_surface_mutex_unlock();
558
559     return bo;
560 }
561
562 int
563 tbm_surface_internal_get_size (tbm_surface_h surface)
564 {
565     TBM_RETURN_VAL_IF_FAIL (surface, 0);
566
567     struct _tbm_surface *surf;
568     unsigned int size;
569
570     _tbm_surface_mutex_lock();
571
572     surf = (struct _tbm_surface *) surface;
573     size = surf->info.size;
574
575     _tbm_surface_mutex_unlock();
576
577     return size;
578 }
579
580 int
581 tbm_surface_internal_get_plane_data (tbm_surface_h surface, int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch)
582 {
583     TBM_RETURN_VAL_IF_FAIL (surface, 0);
584     TBM_RETURN_VAL_IF_FAIL (plane_idx > -1, 0);
585
586     struct _tbm_surface *surf;
587
588     _tbm_surface_mutex_lock();
589
590     surf = (struct _tbm_surface *) surface;
591
592     if (plane_idx >= surf->info.num_planes)
593     {
594         _tbm_surface_mutex_unlock();
595         return 0;
596     }
597
598     *size = surf->info.planes[plane_idx].size;
599     *offset = surf->info.planes[plane_idx].offset;
600     *pitch = surf->info.planes[plane_idx].stride;
601
602     _tbm_surface_mutex_unlock();
603
604     return 1;
605 }
606
607 int
608 tbm_surface_internal_get_info (tbm_surface_h surface, int opt, tbm_surface_info_s *info, int map)
609 {
610     struct _tbm_surface *surf;
611     tbm_bo_handle bo_handles[4];
612     int i;
613
614     _tbm_surface_mutex_lock();
615
616     surf = (struct _tbm_surface *)surface;
617
618     info->width = surf->info.width;
619     info->height = surf->info.height;
620     info->format = surf->info.format;
621     info->bpp = surf->info.bpp;
622     info->size = surf->info.size;
623     info->num_planes = surf->info.num_planes;
624
625     if (surf->num_bos == 1)
626     {
627         if (map == 1)
628         {
629             bo_handles[0] = tbm_bo_map (surf->bos[0], TBM_DEVICE_CPU, opt);
630             if (bo_handles[0].ptr == NULL)
631             {
632                 _tbm_surface_mutex_unlock();
633                 return 0;
634             }
635         }
636         else
637         {
638             bo_handles[0] = tbm_bo_get_handle (surf->bos[0], TBM_DEVICE_CPU);
639             if (bo_handles[0].ptr == NULL)
640             {
641                 _tbm_surface_mutex_unlock();
642                 return 0;
643             }
644         }
645
646         for (i = 0; i < surf->info.num_planes; i++)
647         {
648             info->planes[i].size = surf->info.planes[i].size;
649             info->planes[i].offset = surf->info.planes[i].offset;
650             info->planes[i].stride = surf->info.planes[i].stride;
651             info->planes[i].ptr = bo_handles[0].ptr + surf->info.planes[i].offset;
652         }
653     }
654     else
655     {
656         /* TODO: calculate the virtaul address when num_bos is over 1 */
657     }
658
659     _tbm_surface_mutex_unlock();
660
661     return 1;
662 }
663
664 void
665 tbm_surface_internal_unmap (tbm_surface_h surface)
666 {
667     struct _tbm_surface *surf;
668     int i;
669
670     _tbm_surface_mutex_lock();
671
672     surf = (struct _tbm_surface *)surface;
673
674     for (i = 0; i < surf->num_bos; i++)
675         tbm_bo_unmap (surf->bos[i]);
676
677     _tbm_surface_mutex_unlock();
678 }
679
680 unsigned int
681 tbm_surface_internal_get_width (tbm_surface_h surface)
682 {
683     struct _tbm_surface *surf;
684     unsigned int width;
685
686     _tbm_surface_mutex_lock();
687
688     surf = (struct _tbm_surface *)surface;
689     width = surf->info.width;
690
691     _tbm_surface_mutex_unlock();
692
693     return width;
694 }
695
696 unsigned int
697 tbm_surface_internal_get_height (tbm_surface_h surface)
698 {
699     struct _tbm_surface *surf;
700     unsigned int height;
701
702     _tbm_surface_mutex_lock();
703
704     surf = (struct _tbm_surface *)surface;
705     height = surf->info.height;
706
707     _tbm_surface_mutex_unlock();
708
709     return height;
710
711 }
712
713 tbm_format
714 tbm_surface_internal_get_format (tbm_surface_h surface)
715 {
716     struct _tbm_surface *surf;
717     tbm_format format;
718
719     _tbm_surface_mutex_lock();
720
721     surf = (struct _tbm_surface *)surface;
722     format = surf->info.format;
723
724     _tbm_surface_mutex_unlock();
725
726     return format;
727 }
728