summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorDongyeon Kim <dy5.kim@samsung.com>2015-02-03 20:36:41 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2015-02-10 14:48:53 +0900
commitc0d990c7246cde1c3b7286b22670e2fc01fce00b (patch)
tree966ea4ac5500910cc9c0378be494d60a7abe36eb /src/modules
parentdefcc1f2ace705de2abda836c0ee0cc545beabb9 (diff)
evas/software_x11: implement tbm native surface type
Summary: This native surface type is based on the tbm surface used for the tizen platform. For the software_x11 backend, image data is retrieved from tbm surface and color format converted appropriately. This will only work when libtbm.so is present in the system. @feature Test Plan: Local tests Reviewers: raster, cedric, jpeg, Hermet Subscribers: wonsik, cedric Signed-off-by: Jean-Philippe Andre <jp.andre@samsung.com>
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/evas/engines/software_generic/evas_engine.c2
-rw-r--r--src/modules/evas/engines/software_x11/evas_engine.c60
-rw-r--r--src/modules/evas/engines/software_x11/evas_engine.h1
-rw-r--r--src/modules/evas/engines/software_x11/evas_native_tbm.c341
4 files changed, 377 insertions, 27 deletions
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c
index 3c13f80cd2..a3b15b4dcc 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -1508,6 +1508,8 @@ eng_image_draw(void *data EINA_UNUSED, void *context, void *surface, void *image
1508 evas_common_cpu_end_opt(); 1508 evas_common_cpu_end_opt();
1509 } 1509 }
1510 1510
1511 if (im->native.func.unbind)
1512 im->native.func.unbind(data, image);
1511 return EINA_FALSE; 1513 return EINA_FALSE;
1512} 1514}
1513 1515
diff --git a/src/modules/evas/engines/software_x11/evas_engine.c b/src/modules/evas/engines/software_x11/evas_engine.c
index fa74a38a40..acc4412045 100644
--- a/src/modules/evas/engines/software_x11/evas_engine.c
+++ b/src/modules/evas/engines/software_x11/evas_engine.c
@@ -630,28 +630,31 @@ eng_image_native_set(void *data EINA_UNUSED, void *image, void *native)
630 630
631 if (!im || !ns) return im; 631 if (!im || !ns) return im;
632 632
633 if (ns) 633 if (ns->type == EVAS_NATIVE_SURFACE_X11)
634 { 634 {
635 if (ns->type == EVAS_NATIVE_SURFACE_X11) 635 if (im->native.data)
636 { 636 {
637 if (im->native.data) 637 //image have native surface already
638 { 638 Evas_Native_Surface *ens = im->native.data;
639 //image have native surface already 639
640 Evas_Native_Surface *ens = im->native.data; 640 if ((ens->type == ns->type) &&
641 641 (ens->data.x11.visual == ns->data.x11.visual) &&
642 if ((ens->type == ns->type) && 642 (ens->data.x11.pixmap == ns->data.x11.pixmap))
643 (ens->data.x11.visual == ns->data.x11.visual) && 643 return im;
644 (ens->data.x11.pixmap == ns->data.x11.pixmap)) 644 }
645 return im; 645 }
646 } 646 else if (ns->type == EVAS_NATIVE_SURFACE_TBM)
647 } 647 {
648 } 648 if (im->native.data)
649 else 649 {
650 { 650 //image have native surface already
651 return im; 651 Evas_Native_Surface *ens = im->native.data;
652 } 652
653 653 if ((ens->type == ns->type) &&
654 if ((!ns) && (!im->native.data)) return im; 654 (ens->data.tbm.buffer == ns->data.tbm.buffer))
655 return im;
656 }
657 }
655 658
656 //create new im and clean already existed im even though ns = NULL 659 //create new im and clean already existed im even though ns = NULL
657 im2 = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(), 660 im2 = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
@@ -664,21 +667,23 @@ eng_image_native_set(void *data EINA_UNUSED, void *image, void *native)
664 } 667 }
665 668
666#ifdef EVAS_CSERVE2 669#ifdef EVAS_CSERVE2
667 if (evas_cserve2_use_get() && evas_cache2_image_cached(&im->cache_entry)) 670 if (evas_cserve2_use_get() && evas_cache2_image_cached(&im->cache_entry))
668 evas_cache2_image_close(&im->cache_entry); 671 evas_cache2_image_close(&im->cache_entry);
669 else 672 else
670#endif 673#endif
671 evas_cache_image_drop(&im->cache_entry); 674 evas_cache_image_drop(&im->cache_entry);
672 im = im2; 675 im = im2;
673 676
674 if (!ns) return im;
675
676#ifdef BUILD_ENGINE_SOFTWARE_XLIB 677#ifdef BUILD_ENGINE_SOFTWARE_XLIB
677 if (ns->type == EVAS_NATIVE_SURFACE_X11) 678 if (ns->type == EVAS_NATIVE_SURFACE_X11)
678 { 679 {
679 return evas_xlib_image_native_set(re->generic.ob, im, ns); 680 return evas_xlib_image_native_set(re->generic.ob, im, ns);
680 } 681 }
681#endif 682#endif
683 if (ns->type == EVAS_NATIVE_SURFACE_TBM)
684 {
685 return evas_native_tbm_image_set(re->generic.ob, im, ns);
686 }
682 687
683 return im; 688 return im;
684} 689}
@@ -693,8 +698,9 @@ eng_image_native_get(void *data EINA_UNUSED, void *image)
693 n = im->native.data; 698 n = im->native.data;
694 if (!n) return NULL; 699 if (!n) return NULL;
695 return &(n->ns); 700 return &(n->ns);
696#endif 701#else
697 return NULL; 702 return NULL;
703#endif
698} 704}
699 705
700 706
diff --git a/src/modules/evas/engines/software_x11/evas_engine.h b/src/modules/evas/engines/software_x11/evas_engine.h
index c29f62deea..b561e2f83b 100644
--- a/src/modules/evas/engines/software_x11/evas_engine.h
+++ b/src/modules/evas/engines/software_x11/evas_engine.h
@@ -116,5 +116,6 @@ struct _Outbuf
116 116
117void evas_software_xlib_x_init(void); 117void evas_software_xlib_x_init(void);
118void evas_software_xcb_init(void); 118void evas_software_xcb_init(void);
119void *evas_native_tbm_image_set(void *data, void *image, void *native);
119 120
120#endif 121#endif
diff --git a/src/modules/evas/engines/software_x11/evas_native_tbm.c b/src/modules/evas/engines/software_x11/evas_native_tbm.c
new file mode 100644
index 0000000000..ec7d037a0f
--- /dev/null
+++ b/src/modules/evas/engines/software_x11/evas_native_tbm.c
@@ -0,0 +1,341 @@
1#include "evas_common_private.h"
2#include "evas_xlib_image.h"
3#include "evas_private.h"
4
5#include "Evas_Engine_Software_X11.h"
6#include "evas_engine.h"
7
8#ifdef HAVE_DLSYM
9# include <dlfcn.h> /* dlopen,dlclose,etc */
10#else
11# warning native_tbm should not get compiled if dlsym is not found on the system!
12#endif
13
14#define EVAS_ROUND_UP_4(num) (((num)+3) & ~3)
15#define EVAS_ROUND_UP_8(num) (((num)+7) & ~7)
16
17#define TBM_SURF_PLANE_MAX 4 /**< maximum number of the planes */
18
19/* option to map the tbm_surface */
20#define TBM_SURF_OPTION_READ (1 << 0) /**< access option to read */
21#define TBM_SURF_OPTION_WRITE (1 << 1) /**< access option to write */
22
23#define __tbm_fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \
24 ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
25
26#define TBM_FORMAT_RGBX8888 __tbm_fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */
27#define TBM_FORMAT_RGBA8888 __tbm_fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */
28#define TBM_FORMAT_BGRA8888 __tbm_fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */
29#define TBM_FORMAT_NV12 __tbm_fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */
30#define TBM_FORMAT_YUV420 __tbm_fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */
31#define TBM_FORMAT_YVU420 __tbm_fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */
32
33static void *tbm_lib = NULL;
34static int tbm_ref = 0;
35
36typedef struct _tbm_surface * tbm_surface_h;
37typedef uint32_t tbm_format;
38
39typedef struct _tbm_surface_plane
40{
41 unsigned char *ptr; /**< Plane pointer */
42 uint32_t size; /**< Plane size */
43 uint32_t offset; /**< Plane offset */
44 uint32_t stride; /**< Plane stride */
45
46 void *reserved1; /**< Reserved pointer1 */
47 void *reserved2; /**< Reserved pointer2 */
48 void *reserved3; /**< Reserved pointer3 */
49} tbm_surface_plane_s;
50
51typedef struct _tbm_surface_info
52{
53 uint32_t width; /**< TBM surface width */
54 uint32_t height; /**< TBM surface height */
55 tbm_format format; /**< TBM surface format*/
56 uint32_t bpp; /**< TBM surface bbp */
57 uint32_t size; /**< TBM surface size */
58
59 uint32_t num_planes; /**< The number of planes */
60 tbm_surface_plane_s planes[TBM_SURF_PLANE_MAX]; /**< Array of planes */
61
62 void *reserved4; /**< Reserved pointer4 */
63 void *reserved5; /**< Reserved pointer5 */
64 void *reserved6; /**< Reserved pointer6 */
65} tbm_surface_info_s;
66
67
68/* returns 0 on success */
69static int (*sym_tbm_surface_map) (tbm_surface_h surface, int opt, tbm_surface_info_s *info) = NULL;
70static int (*sym_tbm_surface_unmap) (tbm_surface_h surface) = NULL;
71
72static Eina_Bool
73tbm_init(void)
74{
75 if (tbm_lib)
76 {
77 tbm_ref++;
78 return EINA_TRUE;
79 }
80
81 const char *tbm_libs[] =
82 {
83 "libtbm.so.1",
84 "libtbm.so.0",
85 NULL,
86 };
87 int i, fail;
88#define SYM(lib, xx) \
89 do { \
90 sym_ ## xx = dlsym(lib, #xx); \
91 if (!(sym_ ## xx)) { \
92 ERR("%s", dlerror()); \
93 fail = 1; \
94 } \
95 } while (0)
96
97 for (i = 0; tbm_libs[i]; i++)
98 {
99 tbm_lib = dlopen(tbm_libs[i], RTLD_LOCAL | RTLD_LAZY);
100 if (tbm_lib)
101 {
102 fail = 0;
103 SYM(tbm_lib, tbm_surface_map);
104 SYM(tbm_lib, tbm_surface_unmap);
105 if (fail)
106 {
107 dlclose(tbm_lib);
108 tbm_lib = NULL;
109 }
110 else break;
111 }
112 }
113 if (!tbm_lib) return EINA_FALSE;
114
115 tbm_ref++;
116 return EINA_TRUE;
117}
118
119static void
120tbm_shutdown(void)
121{
122 if (tbm_ref > 0)
123 {
124 tbm_ref--;
125
126 if (tbm_ref == 0)
127 {
128 if (tbm_lib)
129 {
130 dlclose(tbm_lib);
131 tbm_lib = NULL;
132 }
133 }
134 }
135}
136
137static void
138_evas_video_yv12(unsigned char *evas_data, const unsigned char *source_data, unsigned int w, unsigned int h, unsigned int output_height)
139{
140 const unsigned char **rows;
141 unsigned int i, j;
142 unsigned int rh;
143 unsigned int stride_y, stride_uv;
144
145 rh = output_height;
146
147 rows = (const unsigned char **)evas_data;
148
149 stride_y = EVAS_ROUND_UP_4(w);
150 stride_uv = EVAS_ROUND_UP_8(w) / 2;
151
152 for (i = 0; i < rh; i++)
153 rows[i] = &source_data[i * stride_y];
154
155 for (j = 0; j < (rh / 2); j++, i++)
156 rows[i] = &source_data[h * stride_y +
157 (rh / 2) * stride_uv +
158 j * stride_uv];
159
160 for (j = 0; j < (rh / 2); j++, i++)
161 rows[i] = &source_data[h * stride_y + j * stride_uv];
162}
163
164static void
165_evas_video_i420(unsigned char *evas_data, const unsigned char *source_data, unsigned int w, unsigned int h, unsigned int output_height)
166{
167 const unsigned char **rows;
168 unsigned int i, j;
169 unsigned int rh;
170 unsigned int stride_y, stride_uv;
171
172 rh = output_height;
173
174 rows = (const unsigned char **)evas_data;
175
176 stride_y = EVAS_ROUND_UP_4(w);
177 stride_uv = EVAS_ROUND_UP_8(w) / 2;
178
179 for (i = 0; i < rh; i++)
180 rows[i] = &source_data[i * stride_y];
181
182 for (j = 0; j < (rh / 2); j++, i++)
183 rows[i] = &source_data[h * stride_y + j * stride_uv];
184
185 for (j = 0; j < (rh / 2); j++, i++)
186 rows[i] = &source_data[h * stride_y +
187 (rh / 2) * stride_uv +
188 j * stride_uv];
189}
190
191static void
192_evas_video_nv12(unsigned char *evas_data, const unsigned char *source_data, unsigned int w, unsigned int h EINA_UNUSED, unsigned int output_height)
193{
194 const unsigned char **rows;
195 unsigned int i, j;
196 unsigned int rh;
197
198 rh = output_height;
199
200 rows = (const unsigned char **)evas_data;
201
202 for (i = 0; i < rh; i++)
203 rows[i] = &source_data[i * w];
204
205 for (j = 0; j < (rh / 2); j++, i++)
206 rows[i] = &source_data[rh * w + j * w];
207}
208
209static void
210_native_bind_cb(void *data EINA_UNUSED, void *image, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED)
211{
212 RGBA_Image *im = image;
213 Native *n = im->native.data;
214
215 if (!im) return;
216 if ((n) && (n->ns.type == EVAS_NATIVE_SURFACE_TBM))
217 {
218 tbm_surface_info_s info;
219
220 if (sym_tbm_surface_map(n->ns.data.tbm.buffer, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info)) return;
221
222 im->image.data = (DATA32 *)info.planes[0].ptr;
223 }
224}
225
226static void
227_native_unbind_cb(void *data EINA_UNUSED, void *image)
228{
229 RGBA_Image *im = image;
230 Native *n = im->native.data;
231
232 if (!im) return;
233 if ((n) && (n->ns.type == EVAS_NATIVE_SURFACE_TBM))
234 {
235 sym_tbm_surface_unmap(n->ns.data.tbm.buffer);
236 }
237}
238
239static void
240_native_free_cb(void *data EINA_UNUSED, void *image)
241{
242 RGBA_Image *im = image;
243 Native *n = im->native.data;
244
245 if (!im) return;
246 im->native.data = NULL;
247 im->native.func.bind = NULL;
248 im->native.func.unbind = NULL;
249 im->native.func.free = NULL;
250 im->native.func.data = NULL;
251 im->image.data = NULL;
252
253 free(n);
254
255 tbm_shutdown();
256}
257
258void *
259evas_native_tbm_image_set(void *data EINA_UNUSED, void *image, void *native)
260{
261 Evas_Native_Surface *ns = native;
262 RGBA_Image *im = image;
263
264 if (!im) return NULL;
265 if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_TBM))
266 {
267 void *pixels_data;
268 int w, h, stride;
269 tbm_format format;
270 tbm_surface_info_s info;
271 Native *n;
272
273 if (!tbm_init())
274 {
275 ERR("Could not initialize TBM!");
276 return NULL;
277 }
278
279 n = calloc(1, sizeof(Native));
280 if (!n) return NULL;
281
282 if (sym_tbm_surface_map(ns->data.tbm.buffer, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info))
283 {
284 free(n);
285 return im;
286 }
287
288 w = info.width;
289 h = info.height;
290 stride = info.planes[0].stride;
291 format = info.format;
292 pixels_data = info.planes[0].ptr;
293 im->cache_entry.w = stride;
294 im->cache_entry.h = h;
295
296 // Handle all possible format here :"(
297 switch (format)
298 {
299 case TBM_FORMAT_RGBA8888:
300 case TBM_FORMAT_RGBX8888:
301 case TBM_FORMAT_BGRA8888:
302 im->cache_entry.w = stride / 4;
303 evas_cache_image_colorspace(&im->cache_entry, EVAS_COLORSPACE_ARGB8888);
304 im->cache_entry.flags.alpha = (format == TBM_FORMAT_RGBX8888 ? 0 : 1);
305 im->image.data = pixels_data;
306 im->image.no_free = 1;
307 break;
308 /* borrowing code from emotion here */
309 case TBM_FORMAT_YVU420: /* EVAS_COLORSPACE_YCBCR422P601_PL */
310 evas_cache_image_colorspace(&im->cache_entry, EVAS_COLORSPACE_YCBCR422P601_PL);
311 _evas_video_yv12(im->cs.data, pixels_data, w, h, h);
312 evas_common_image_colorspace_dirty(im);
313 break;
314 case TBM_FORMAT_YUV420: /* EVAS_COLORSPACE_YCBCR422P601_PL */
315 evas_cache_image_colorspace(&im->cache_entry, EVAS_COLORSPACE_YCBCR422P601_PL);
316 _evas_video_i420(im->cs.data, pixels_data, w, h, h);
317 evas_common_image_colorspace_dirty(im);
318 break;
319 case TBM_FORMAT_NV12: /* EVAS_COLORSPACE_YCBCR420NV12601_PL */
320 evas_cache_image_colorspace(&im->cache_entry, EVAS_COLORSPACE_YCBCR420NV12601_PL);
321 _evas_video_nv12(im->cs.data, pixels_data, w, h, h);
322 evas_common_image_colorspace_dirty(im);
323 break;
324 /* Not planning to handle those in software */
325 default:
326 sym_tbm_surface_unmap(ns->data.tbm.buffer);
327 free(n);
328 return im;
329 }
330
331 memcpy(n, ns, sizeof(Evas_Native_Surface));
332 im->native.data = n;
333 im->native.func.bind = _native_bind_cb;
334 im->native.func.unbind = _native_unbind_cb;
335 im->native.func.free = _native_free_cb;
336
337 sym_tbm_surface_unmap(ns->data.tbm.buffer);
338 }
339 return im;
340}
341