tizen 2.3 release
[apps/livebox/data-provider-master.git] / src / buffer_handler.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <unistd.h> /* access */
19 #include <sys/mman.h>
20 #include <errno.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <sys/shm.h>
25 #include <sys/ipc.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #include <Ecore.h>
30 #include <Ecore_X.h>
31 #include <X11/Xlib.h>
32 #include <X11/Xutil.h>
33 #include <X11/Xproto.h>
34 #include <X11/extensions/Xdamage.h>
35 #include <X11/extensions/Xfixes.h>
36 #include <X11/extensions/XShm.h>
37
38 #include <dri2.h>
39 #include <xf86drm.h>
40 #include <xf86drmMode.h>
41 #include <tbm_bufmgr.h>
42
43 #include <dlog.h>
44 #include <packet.h>
45 #include <dynamicbox_errno.h>
46 #include <dynamicbox_service.h>
47 #include <dynamicbox_buffer.h>
48 #include <dynamicbox_conf.h>
49
50 #include "debug.h"
51 #include "conf.h"
52 #include "util.h"
53 #include "instance.h"
54 #include "package.h"
55 #include "client_life.h"
56 #include "client_rpc.h"
57 #include "buffer_handler.h"
58 #include "script_handler.h" // Reverse dependency. must has to be broken
59
60 /*!
61  * \brief Allocate this in the buffer->data.
62  */
63 struct gem_data {
64         DRI2Buffer *dri2_buffer;
65         unsigned int attachments[1];
66         tbm_bo pixmap_bo;
67         int count;
68         int buf_count;
69         int w;
70         int h;
71         int depth;
72         Pixmap pixmap;
73         void *data; /* Gem layer */
74         int refcnt;
75
76         void *compensate_data; /* Check the pitch value, copy this to data */
77 };
78
79 struct buffer_info
80 {
81         void *buffer;
82         char *id;
83         dynamicbox_lock_info_t lock_info;
84
85         enum dynamicbox_fb_type type;
86
87         int w;
88         int h;
89         int pixel_size;
90         int is_loaded;
91
92         struct inst_info *inst;
93         void *data;
94 };
95
96 static struct {
97         tbm_bufmgr slp_bufmgr;
98         int evt_base;
99         int err_base;
100         int fd;
101         Eina_List *pixmap_list;
102 } s_info = {
103         .slp_bufmgr = NULL,
104         .evt_base = 0,
105         .err_base = 0,
106         .fd = -1,
107         .pixmap_list = NULL,
108 };
109
110 static inline dynamicbox_fb_t create_pixmap(struct buffer_info *info)
111 {
112         struct gem_data *gem;
113         dynamicbox_fb_t buffer;
114         Display *disp;
115         Window parent;
116         XGCValues gcv;
117         GC gc;
118
119         disp = ecore_x_display_get();
120         if (!disp) {
121                 return NULL;
122         }
123
124         parent = DefaultRootWindow(disp);
125
126         buffer = calloc(1, sizeof(*buffer) + sizeof(*gem));
127         if (!buffer) {
128                 ErrPrint("Heap: %s\n", strerror(errno));
129                 return NULL;
130         }
131
132         gem = (struct gem_data *)buffer->data;
133
134         buffer->type = DBOX_FB_TYPE_PIXMAP;
135         buffer->refcnt = 1;
136         buffer->state = DBOX_FB_STATE_CREATED;
137
138         gem->attachments[0] = DRI2BufferFrontLeft;
139         gem->count = 1;
140         gem->w = info->w; /*!< This can be changed by DRI2GetBuffers */
141         gem->h = info->h; /*!< This can be changed by DRI2GetBuffers */
142         gem->depth = info->pixel_size;
143         /*!
144          * \NOTE
145          * Use the 24 Bits
146          * 32 Bits is not supported for video playing.
147          * But for the transparent background, use the 32 bits, and give up video.
148          */
149         gem->pixmap = XCreatePixmap(disp, parent, info->w, info->h, (info->pixel_size << 3));
150         if (gem->pixmap == (Pixmap)0) {
151                 ErrPrint("Failed to create a pixmap\n");
152                 DbgFree(buffer);
153                 return NULL;
154         }
155
156         /*!
157          * \note
158          * Clear pixmap
159          */
160         memset(&gcv, 0, sizeof(gcv));
161         gc = XCreateGC(disp, gem->pixmap, GCForeground, &gcv);
162         if (gc) {
163                 XFillRectangle(disp, gem->pixmap, gc, 0, 0, info->w, info->h);
164                 XSync(disp, False);
165                 XFreeGC(disp, gc);
166         } else {
167                 XSync(disp, False);
168                 ErrPrint("Unable to clear the pixmap\n");
169         }
170
171         return buffer;
172 }
173
174 static inline int create_gem(dynamicbox_fb_t buffer)
175 {
176         struct gem_data *gem;
177         Display *disp;
178
179         disp = ecore_x_display_get();
180         if (!disp) {
181                 ErrPrint("Failed to get display\n");
182                 return DBOX_STATUS_ERROR_IO_ERROR;
183         }
184
185         gem = (struct gem_data *)buffer->data;
186
187         if (s_info.fd < 0) {
188                 gem->data = calloc(1, gem->w * gem->h * gem->depth);
189                 if (!gem->data) {
190                         ErrPrint("Heap: %s\n", strerror(errno));
191                         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
192                 }
193
194                 ErrPrint("DRI2(gem) is not supported - Fallback to the S/W Backend\n");
195                 return DBOX_STATUS_ERROR_NONE;
196         }
197
198         DRI2CreateDrawable(disp, gem->pixmap);
199
200         gem->dri2_buffer = DRI2GetBuffers(disp, gem->pixmap,
201                         &gem->w, &gem->h, gem->attachments, gem->count, &gem->buf_count);
202         if (!gem->dri2_buffer || !gem->dri2_buffer->name) {
203                 ErrPrint("Failed to get a gem buffer\n");
204                 DRI2DestroyDrawable(disp, gem->pixmap);
205                 return DBOX_STATUS_ERROR_FAULT;
206         }
207         /*!
208          * \How can I destroy this?
209          */
210         gem->pixmap_bo = tbm_bo_import(s_info.slp_bufmgr, gem->dri2_buffer->name);
211         if (!gem->pixmap_bo) {
212                 ErrPrint("Failed to import BO\n");
213                 DRI2DestroyDrawable(disp, gem->pixmap);
214                 return DBOX_STATUS_ERROR_FAULT;
215         }
216
217         if (DYNAMICBOX_CONF_AUTO_ALIGN && gem->dri2_buffer->pitch != gem->w * gem->depth) {
218                 gem->compensate_data = calloc(1, gem->w * gem->h * gem->depth);
219                 if (!gem->compensate_data) {
220                         ErrPrint("Failed to allocate heap\n");
221                 }
222         }
223
224         DbgPrint("dri2_buffer: %p, name: %p, %dx%d, pitch: %d, buf_count: %d, depth: %d, compensate: %p (%d)\n",
225                         gem->dri2_buffer, gem->dri2_buffer->name, gem->w, gem->h,
226                         gem->dri2_buffer->pitch, gem->buf_count, gem->depth, gem->compensate_data, DYNAMICBOX_CONF_AUTO_ALIGN);
227
228         return DBOX_STATUS_ERROR_NONE;
229 }
230
231 static inline void *acquire_gem(dynamicbox_fb_t buffer)
232 {
233         struct gem_data *gem;
234
235         if (!buffer) {
236                 return NULL;
237         }
238
239         gem = (struct gem_data *)buffer->data;
240         if (s_info.fd < 0) {
241                 ErrPrint("GEM is not supported - Use the fake gem buffer\n");
242         } else {
243                 if (!gem->pixmap_bo) {
244                         ErrPrint("GEM is not created\n");
245                         return NULL;
246                 }
247
248                 if (!gem->data) {
249                         tbm_bo_handle handle;
250
251                         if (gem->refcnt) {
252                                 ErrPrint("Already acquired. but the buffer is not valid\n");
253                                 return NULL;
254                         }
255
256                         handle = tbm_bo_map(gem->pixmap_bo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
257                         gem->data = handle.ptr;
258                 }
259         }
260
261         gem->refcnt++;
262
263         /*!
264          * \note
265          * If there is a compensate canvas buffer,
266          * use it
267          */
268         return gem->compensate_data ? gem->compensate_data : gem->data;
269 }
270
271 static inline void release_gem(dynamicbox_fb_t buffer)
272 {
273         struct gem_data *gem;
274
275         gem = (struct gem_data *)buffer->data;
276         if (s_info.fd >= 0 && !gem->pixmap_bo) {
277                 ErrPrint("GEM is not created\n");
278                 return;
279         }
280
281         if (!gem->data) {
282                 if (gem->refcnt > 0) {
283                         ErrPrint("Reference count is not valid %d\n", gem->refcnt);
284                         gem->refcnt = 0;
285                 }
286                 return;
287         }
288
289         gem->refcnt--;
290         if (gem->refcnt == 0) {
291                 if (s_info.fd < 0) {
292                         DbgPrint("S/W Gem buffer has no reference\n");
293                 } else {
294                         /*!
295                          * \note
296                          * Update the gem buffer using compensate data buffer if it is exists
297                          */
298                         if (gem->compensate_data) {
299                                 register int x;
300                                 register int y;
301                                 int *gem_pixel;
302                                 int *pixel;
303                                 int gap;
304
305                                 pixel = gem->compensate_data;
306                                 gem_pixel = gem->data;
307                                 gap = gem->dri2_buffer->pitch - (gem->w * gem->depth);
308
309                                 for (y = 0; y < gem->h; y++) {
310                                         for (x = 0; x < gem->w; x++) {
311                                                 *gem_pixel++ = *pixel++;
312                                         }
313
314                                         gem_pixel = (int *)(((char *)gem_pixel) + gap);
315                                 }
316                         }
317
318                         if (gem->pixmap_bo) {
319                                 tbm_bo_unmap(gem->pixmap_bo);
320                         }
321
322                         gem->data = NULL;
323                 }
324         } else if (gem->refcnt < 0) {
325                 ErrPrint("Invalid refcnt: %d (reset)\n", gem->refcnt);
326                 gem->refcnt = 0;
327         }
328 }
329
330 static inline int destroy_pixmap(dynamicbox_fb_t buffer)
331 {
332         struct gem_data *gem;
333
334         gem = (struct gem_data *)buffer->data;
335
336         if (gem->pixmap) {
337                 Display *disp;
338
339                 disp = ecore_x_display_get();
340                 if (!disp) {
341                         return DBOX_STATUS_ERROR_IO_ERROR;
342                 }
343
344                 DbgPrint("pixmap %lu\n", gem->pixmap);
345                 XFreePixmap(disp, gem->pixmap);
346         }
347
348         buffer->state = DBOX_FB_STATE_DESTROYED;
349         DbgFree(buffer);
350         return DBOX_STATUS_ERROR_NONE;
351 }
352
353 static inline int destroy_gem(dynamicbox_fb_t buffer)
354 {
355         struct gem_data *gem;
356
357         if (!buffer) {
358                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
359         }
360
361         /*!
362          * Forcely release the acquire_buffer.
363          */
364         gem = (struct gem_data *)buffer->data;
365         if (!gem) {
366                 return DBOX_STATUS_ERROR_FAULT;
367         }
368
369         if (s_info.fd >= 0) {
370                 if (gem->compensate_data) {
371                         DbgPrint("Release compensate buffer %p\n", gem->compensate_data);
372                         DbgFree(gem->compensate_data);
373                         gem->compensate_data = NULL;
374                 }
375
376                 if (gem->pixmap_bo) {
377                         DbgPrint("unref pixmap bo\n");
378                         tbm_bo_unref(gem->pixmap_bo);
379                         gem->pixmap_bo = NULL;
380
381                         DRI2DestroyDrawable(ecore_x_display_get(), gem->pixmap);
382                 }
383         } else if (gem->data) {
384                 DbgPrint("Release fake gem buffer\n");
385                 DbgFree(gem->data);
386                 gem->data = NULL;
387         }
388
389         return DBOX_STATUS_ERROR_NONE;
390 }
391
392 static inline int load_file_buffer(struct buffer_info *info)
393 {
394         dynamicbox_fb_t buffer;
395         double timestamp;
396         int size;
397         char *new_id;
398         int len;
399
400         len = strlen(DYNAMICBOX_CONF_IMAGE_PATH) + 40;
401         new_id = malloc(len);
402         if (!new_id) {
403                 ErrPrint("Heap: %s\n", strerror(errno));
404                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
405         }
406
407         timestamp = util_timestamp();
408         snprintf(new_id, len, SCHEMA_FILE "%s%lf", DYNAMICBOX_CONF_IMAGE_PATH, timestamp);
409
410         size = sizeof(*buffer) + info->w * info->h * info->pixel_size;
411         if (!size) {
412                 ErrPrint("Canvas buffer size is ZERO\n");
413                 DbgFree(new_id);
414                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
415         }
416
417         buffer = calloc(1, size);
418         if (!buffer) {
419                 ErrPrint("Failed to allocate buffer\n");
420                 DbgFree(new_id);
421                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
422         }
423
424         buffer->type = DBOX_FB_TYPE_FILE;
425         buffer->refcnt = 0;
426         buffer->state = DBOX_FB_STATE_CREATED;
427         buffer->info = info;
428
429         DbgFree(info->id);
430         info->id = new_id;
431         info->buffer = buffer;
432         info->is_loaded = 1;
433
434         DbgPrint("FILE type %d created\n", size);
435         return DBOX_STATUS_ERROR_NONE;
436 }
437
438 static inline int load_shm_buffer(struct buffer_info *info)
439 {
440         int id;
441         int size;
442         dynamicbox_fb_t buffer; /* Just for getting a size */
443         char *new_id;
444         int len;
445
446         size = info->w * info->h * info->pixel_size;
447         if (!size) {
448                 ErrPrint("Invalid buffer size\n");
449                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
450         }
451
452         id = shmget(IPC_PRIVATE, size + sizeof(*buffer), IPC_CREAT | 0666);
453         if (id < 0) {
454                 ErrPrint("shmget: %s\n", strerror(errno));
455                 return DBOX_STATUS_ERROR_FAULT;
456         }
457
458         buffer = shmat(id, NULL, 0);
459         if (buffer == (void *)-1) {
460                 ErrPrint("%s shmat: %s\n", info->id, strerror(errno));
461
462                 if (shmctl(id, IPC_RMID, 0) < 0) {
463                         ErrPrint("%s shmctl: %s\n", info->id, strerror(errno));
464                 }
465
466                 return DBOX_STATUS_ERROR_FAULT;
467         }
468
469         buffer->type = DBOX_FB_TYPE_SHM;
470         buffer->refcnt = id;
471         buffer->state = DBOX_FB_STATE_CREATED; /*!< Needless */
472         buffer->info = (void *)size; /*!< Use this field to indicates the size of SHM */
473
474         len = strlen(SCHEMA_SHM) + 30; /* strlen("shm://") + 30 */
475
476         new_id = malloc(len);
477         if (!new_id) {
478                 ErrPrint("Heap: %s\n", strerror(errno));
479                 if (shmdt(buffer) < 0) {
480                         ErrPrint("shmdt: %s\n", strerror(errno));
481                 }
482
483                 if (shmctl(id, IPC_RMID, 0) < 0) {
484                         ErrPrint("shmctl: %s\n", strerror(errno));
485                 }
486
487                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
488         }
489
490         snprintf(new_id, len, SCHEMA_SHM "%d", id);
491
492         DbgFree(info->id);
493         info->id = new_id;
494         info->buffer = buffer;
495         info->is_loaded = 1;
496         return DBOX_STATUS_ERROR_NONE;
497 }
498
499 static inline int load_pixmap_buffer(struct buffer_info *info)
500 {
501         dynamicbox_fb_t buffer;
502         struct gem_data *gem;
503         char *new_id;
504         int len;
505
506         /*!
507          * \NOTE
508          * Before call the buffer_handler_pixmap_ref function,
509          * You should make sure that the is_loaded value is toggled (1)
510          * Or the buffer_handler_pixmap_ref function will return NULL
511          */
512         info->is_loaded = 1;
513
514         if (info->buffer) {
515                 DbgPrint("Buffer is already exists, but override it with new one\n");
516         }
517
518         buffer = buffer_handler_pixmap_ref(info);
519         if (!buffer) {
520                 DbgPrint("Failed to make a reference of a pixmap\n");
521                 info->is_loaded = 0;
522                 return DBOX_STATUS_ERROR_FAULT;
523         }
524
525         len = strlen(SCHEMA_PIXMAP) + 30; /* strlen("pixmap://") + 30 */
526         new_id = malloc(len);
527         if (!new_id) {
528                 ErrPrint("Heap: %s\n", strerror(errno));
529                 info->is_loaded = 0;
530                 buffer_handler_pixmap_unref(buffer);
531                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
532         }
533
534         DbgFree(info->id);
535         info->id = new_id;
536
537         gem = (struct gem_data *)buffer->data;
538
539         snprintf(info->id, len, SCHEMA_PIXMAP "%d:%d", (int)gem->pixmap, info->pixel_size);
540         DbgPrint("Loaded pixmap(info->id): %s\n", info->id);
541         return DBOX_STATUS_ERROR_NONE;
542 }
543
544 EAPI int buffer_handler_load(struct buffer_info *info)
545 {
546         int ret;
547         dynamicbox_target_type_e type = DBOX_TYPE_GBAR;
548
549         if (!info) {
550                 ErrPrint("buffer handler is nil\n");
551                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
552         }
553
554         if (info->is_loaded) {
555                 DbgPrint("Buffer is already loaded\n");
556                 return DBOX_STATUS_ERROR_NONE;
557         }
558
559         switch (info->type) {
560         case DBOX_FB_TYPE_FILE:
561                 ret = load_file_buffer(info);
562
563                 if (script_handler_buffer_info(instance_gbar_script(info->inst)) != info && instance_gbar_buffer(info->inst) != info) {
564                         type = DBOX_TYPE_DBOX;
565                 }
566                 info->lock_info = dynamicbox_service_create_lock(instance_id(info->inst), type, DBOX_LOCK_WRITE);
567                 break;
568         case DBOX_FB_TYPE_SHM:
569                 ret = load_shm_buffer(info);
570
571                 if (script_handler_buffer_info(instance_gbar_script(info->inst)) != info && instance_gbar_buffer(info->inst) != info) {
572                         type = DBOX_TYPE_DBOX;
573                 }
574                 info->lock_info = dynamicbox_service_create_lock(instance_id(info->inst), type, DBOX_LOCK_WRITE);
575                 break;
576         case DBOX_FB_TYPE_PIXMAP:
577                 ret = load_pixmap_buffer(info);
578                 break;
579         default:
580                 ErrPrint("Invalid buffer\n");
581                 ret = DBOX_STATUS_ERROR_INVALID_PARAMETER;
582                 break;
583         }
584
585         return ret;
586 }
587
588 static inline int unload_file_buffer(struct buffer_info *info)
589 {
590         const char *path;
591         char *new_id;
592
593         new_id = strdup(SCHEMA_FILE "/tmp/.live.undefined");
594         if (!new_id) {
595                 ErrPrint("Heap: %s\n", strerror(errno));
596                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
597         }
598
599         DbgFree(info->buffer);
600         info->buffer = NULL;
601
602         path = util_uri_to_path(info->id);
603         if (path && unlink(path) < 0) {
604                 ErrPrint("unlink: %s\n", strerror(errno));
605         }
606
607         DbgFree(info->id);
608         info->id = new_id;
609         return DBOX_STATUS_ERROR_NONE;
610 }
611
612 static inline int unload_shm_buffer(struct buffer_info *info)
613 {
614         int id;
615         char *new_id;
616
617         new_id = strdup(SCHEMA_SHM "-1");
618         if (!new_id) {
619                 ErrPrint("Heap: %s\n", strerror(errno));
620                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
621         }
622
623         if (sscanf(info->id, SCHEMA_SHM "%d", &id) != 1) {
624                 ErrPrint("%s Invalid ID\n", info->id);
625                 DbgFree(new_id);
626                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
627         }
628
629         if (id < 0) {
630                 ErrPrint("(%s) Invalid id: %d\n", info->id, id);
631                 DbgFree(new_id);
632                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
633         }
634
635         if (shmdt(info->buffer) < 0) {
636                 ErrPrint("Detach shm: %s\n", strerror(errno));
637         }
638
639         if (shmctl(id, IPC_RMID, 0) < 0) {
640                 ErrPrint("Remove shm: %s\n", strerror(errno));
641         }
642
643         info->buffer = NULL;
644
645         DbgFree(info->id);
646         info->id = new_id;
647         return DBOX_STATUS_ERROR_NONE;
648 }
649
650 static inline int unload_pixmap_buffer(struct buffer_info *info)
651 {
652         int id;
653         char *new_id;
654         int pixels;
655
656         new_id = strdup(SCHEMA_PIXMAP "0:0");
657         if (!new_id) {
658                 ErrPrint("Heap: %s\n", strerror(errno));
659                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
660         }
661
662         if (sscanf(info->id, SCHEMA_PIXMAP "%d:%d", &id, &pixels) != 2) {
663                 ErrPrint("Invalid ID (%s)\n", info->id);
664                 DbgFree(new_id);
665                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
666         }
667
668         if (id == 0) {
669                 ErrPrint("(%s) Invalid id: %d\n", info->id, id);
670                 DbgFree(new_id);
671                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
672         }
673
674         /*!
675          * Decrease the reference counter.
676          */
677         buffer_handler_pixmap_unref(info->buffer);
678
679         /*!
680          * \note
681          * Just clear the info->buffer.
682          * It will be reallocated again.
683          */
684         info->buffer = NULL;
685
686         DbgFree(info->id);
687         info->id = new_id;
688         return DBOX_STATUS_ERROR_NONE;
689 }
690
691 EAPI int buffer_handler_unload(struct buffer_info *info)
692 {
693         int ret;
694
695         if (!info) {
696                 ErrPrint("buffer handler is NIL\n");
697                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
698         }
699
700         if (!info->is_loaded) {
701                 ErrPrint("Buffer is not loaded\n");
702                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
703         }
704
705         switch (info->type) {
706         case DBOX_FB_TYPE_FILE:
707                 dynamicbox_service_destroy_lock(info->lock_info);
708                 info->lock_info = NULL;
709                 ret = unload_file_buffer(info);
710                 break;
711         case DBOX_FB_TYPE_SHM:
712                 dynamicbox_service_destroy_lock(info->lock_info);
713                 info->lock_info = NULL;
714                 ret = unload_shm_buffer(info);
715                 break;
716         case DBOX_FB_TYPE_PIXMAP:
717                 ret = unload_pixmap_buffer(info);
718                 break;
719         default:
720                 ErrPrint("Invalid buffer\n");
721                 ret = DBOX_STATUS_ERROR_INVALID_PARAMETER;
722                 break;
723         }
724
725         if (ret == 0) {
726                 info->is_loaded = 0;
727         }
728
729         return ret;
730 }
731
732 EAPI const char *buffer_handler_id(const struct buffer_info *info)
733 {
734         return info ? info->id : "";
735 }
736
737 EAPI enum dynamicbox_fb_type buffer_handler_type(const struct buffer_info *info)
738 {
739         return info ? info->type : DBOX_FB_TYPE_ERROR;
740 }
741
742 EAPI void *buffer_handler_fb(struct buffer_info *info)
743 {
744         dynamicbox_fb_t buffer;
745
746         if (!info) {
747                 return NULL;
748         }
749
750         buffer = info->buffer;
751
752         if (info->type == DBOX_FB_TYPE_PIXMAP) {
753                 void *canvas;
754                 int ret;
755
756                 /*!
757                  * \note
758                  * For getting the buffer address of gem.
759                  */
760                 canvas = buffer_handler_pixmap_acquire_buffer(info);
761                 ret = buffer_handler_pixmap_release_buffer(canvas);
762                 if (ret < 0) {
763                         ErrPrint("Failed to release buffer: %d\n", ret);
764                 }
765                 return canvas;
766         }
767
768         return buffer->data;
769 }
770
771 EAPI int buffer_handler_pixmap(const struct buffer_info *info)
772 {
773         dynamicbox_fb_t buf;
774         struct gem_data *gem;
775
776         if (!info) {
777                 ErrPrint("Inavlid buffer handler\n");
778                 return 0;
779         }
780
781         if (info->type != DBOX_FB_TYPE_PIXMAP) {
782                 ErrPrint("Invalid buffer type\n");
783                 return 0;
784         }
785
786         buf = (dynamicbox_fb_t)info->buffer;
787         if (!buf) {
788                 ErrPrint("Invalid buffer data\n");
789                 return 0;
790         }
791
792         gem = (struct gem_data *)buf->data;
793         return gem->pixmap;
794 }
795
796 EAPI void *buffer_handler_pixmap_acquire_buffer(struct buffer_info *info)
797 {
798         dynamicbox_fb_t buffer;
799
800         if (!info || !info->is_loaded) {
801                 ErrPrint("Buffer is not loaded\n");
802                 return NULL;
803         }
804
805         buffer = buffer_handler_pixmap_ref(info);
806         if (!buffer) {
807                 return NULL;
808         }
809
810         return acquire_gem(buffer);
811 }
812
813 EAPI void *buffer_handler_pixmap_buffer(struct buffer_info *info)
814 {
815         dynamicbox_fb_t buffer;
816         struct gem_data *gem;
817
818         if (!info) {
819                 return NULL;
820         }
821
822         if (!info->is_loaded) {
823                 ErrPrint("Buffer is not loaded\n");
824                 return NULL;
825         }
826
827         buffer = info->buffer;
828         if (!buffer) {
829                 return NULL;
830         }
831
832         gem = (struct gem_data *)buffer->data;
833         return gem->compensate_data ? gem->compensate_data : gem->data;
834 }
835
836 /**
837  * @return "buffer" object (Not the buffer_info)
838  */
839 EAPI void *buffer_handler_pixmap_ref(struct buffer_info *info)
840 {
841         dynamicbox_fb_t buffer;
842
843         if (!info->is_loaded) {
844                 ErrPrint("Buffer is not loaded\n");
845                 return NULL;
846         }
847
848         if (info->type != DBOX_FB_TYPE_PIXMAP) {
849                 ErrPrint("Buffer type is not matched\n");
850                 return NULL;
851         }
852
853         buffer = info->buffer;
854         if (!buffer) {
855                 int need_gem = 1;
856
857                 buffer = create_pixmap(info);
858                 if (!buffer) {
859                         ErrPrint("Failed to create a pixmap\n");
860                         return NULL;
861                 }
862
863                 info->buffer = buffer;
864
865                 if (info->inst) {
866                         struct pkg_info *pkg;
867
868                         pkg = instance_package(info->inst);
869
870                         if (instance_dbox_buffer(info->inst) == info) {
871                                 if (package_dbox_type(pkg) == DBOX_TYPE_BUFFER) {
872                                         need_gem = 0;
873                                 }
874                         } else if (instance_gbar_buffer(info->inst) == info) {
875                                 if (package_gbar_type(pkg) == GBAR_TYPE_BUFFER) {
876                                         need_gem = 0;
877                                 }
878                         } else {
879                                 int idx;
880
881                                 for (idx = 0; idx < DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT; idx++) {
882                                         if (instance_dbox_extra_buffer(info->inst, idx) == info) {
883                                                 if (package_dbox_type(pkg) == DBOX_TYPE_BUFFER) {
884                                                         need_gem = 0;
885                                                         break;
886                                                 }
887                                         }
888
889                                         if (instance_gbar_extra_buffer(info->inst, idx) == info) {
890                                                 if (package_gbar_type(pkg) == GBAR_TYPE_BUFFER) {
891                                                         need_gem = 0;
892                                                         break;
893                                                 }
894                                         }
895                                 }
896                         }
897                 }
898
899                 if (need_gem) {
900                         if (create_gem(buffer) < 0) {
901                                 /* okay, something goes wrong */
902                         }
903                 }
904         } else if (buffer->state != DBOX_FB_STATE_CREATED || buffer->type != DBOX_FB_TYPE_PIXMAP) {
905                 ErrPrint("Invalid buffer\n");
906                 return NULL;
907         } else if (buffer->refcnt > 0) {
908                 buffer->refcnt++;
909                 return buffer;
910         }
911
912         s_info.pixmap_list = eina_list_append(s_info.pixmap_list, buffer);
913         return buffer;
914 }
915
916 /*!
917  * \return "buffer"
918  */
919 EAPI void *buffer_handler_pixmap_find(int pixmap)
920 {
921         dynamicbox_fb_t buffer;
922         struct gem_data *gem;
923         Eina_List *l;
924         Eina_List *n;
925
926         if (pixmap == 0) {
927                 return NULL;
928         }
929
930         EINA_LIST_FOREACH_SAFE(s_info.pixmap_list, l, n, buffer) {
931                 if (!buffer || buffer->state != DBOX_FB_STATE_CREATED || buffer->type != DBOX_FB_TYPE_PIXMAP) {
932                         s_info.pixmap_list = eina_list_remove(s_info.pixmap_list, buffer);
933                         DbgPrint("Invalid buffer (List Removed: %p)\n", buffer);
934                         continue;
935                 }
936
937                 gem = (struct gem_data *)buffer->data;
938                 if (gem->pixmap == pixmap) {
939                         return buffer;
940                 }
941         }
942
943         return NULL;
944 }
945
946 EAPI int buffer_handler_pixmap_release_buffer(void *canvas)
947 {
948         dynamicbox_fb_t buffer;
949         struct gem_data *gem;
950         Eina_List *l;
951         Eina_List *n;
952         void *_ptr;
953
954         if (!canvas) {
955                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
956         }
957
958         EINA_LIST_FOREACH_SAFE(s_info.pixmap_list, l, n, buffer) {
959                 if (!buffer || buffer->state != DBOX_FB_STATE_CREATED || buffer->type != DBOX_FB_TYPE_PIXMAP) {
960                         s_info.pixmap_list = eina_list_remove(s_info.pixmap_list, buffer);
961                         continue;
962                 }
963
964                 gem = (struct gem_data *)buffer->data;
965                 _ptr = gem->compensate_data ? gem->compensate_data : gem->data;
966
967                 if (!_ptr) {
968                         continue;
969                 }
970
971                 if (_ptr == canvas) {
972                         release_gem(buffer);
973                         buffer_handler_pixmap_unref(buffer);
974                         return DBOX_STATUS_ERROR_NONE;
975                 }
976         }
977
978         return DBOX_STATUS_ERROR_NOT_EXIST;
979 }
980
981 /*!
982  * \note
983  *
984  * \return Return NULL if the buffer is in still uses.
985  *         Return buffer_ptr if it needs to destroy
986  */
987 EAPI int buffer_handler_pixmap_unref(void *buffer_ptr)
988 {
989         dynamicbox_fb_t buffer = buffer_ptr;
990         struct buffer_info *info;
991
992         buffer->refcnt--;
993         if (buffer->refcnt > 0) {
994                 return DBOX_STATUS_ERROR_NONE; /* Return NULL means, gem buffer still in use */
995         }
996
997         s_info.pixmap_list = eina_list_remove(s_info.pixmap_list, buffer);
998
999         info = buffer->info;
1000
1001         if (destroy_gem(buffer) < 0) {
1002                 ErrPrint("Failed to destroy gem buffer\n");
1003         }
1004
1005         if (destroy_pixmap(buffer) < 0) {
1006                 ErrPrint("Failed to destroy pixmap\n");
1007         }
1008
1009         if (info && info->buffer == buffer) {
1010                 info->buffer = NULL;
1011         }
1012
1013         return DBOX_STATUS_ERROR_NONE;
1014 }
1015
1016 EAPI int buffer_handler_is_loaded(const struct buffer_info *info)
1017 {
1018         return info ? info->is_loaded : 0;
1019 }
1020
1021 EAPI void buffer_handler_update_size(struct buffer_info *info, int w, int h)
1022 {
1023         if (!info) {
1024                 return;
1025         }
1026
1027         info->w = w;
1028         info->h = h;
1029 }
1030
1031 EAPI int buffer_handler_resize(struct buffer_info *info, int w, int h)
1032 {
1033         int ret;
1034
1035         if (!info) {
1036                 ErrPrint("Invalid handler\n");
1037                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1038         }
1039
1040         if (info->w == w && info->h == h) {
1041                 DbgPrint("No changes\n");
1042                 return DBOX_STATUS_ERROR_NONE;
1043         }
1044
1045         buffer_handler_update_size(info, w, h);
1046
1047         if (!info->is_loaded) {
1048                 DbgPrint("Buffer size is updated[%dx%d]\n", w, h);
1049                 return DBOX_STATUS_ERROR_NONE;
1050         }
1051
1052         ret = buffer_handler_unload(info);
1053         if (ret < 0) {
1054                 ErrPrint("Unload: %d\n", ret);
1055         }
1056
1057         ret = buffer_handler_load(info);
1058         if (ret < 0) {
1059                 ErrPrint("Load: %d\n", ret);
1060         }
1061
1062         return DBOX_STATUS_ERROR_NONE;
1063 }
1064
1065 EAPI int buffer_handler_get_size(struct buffer_info *info, int *w, int *h)
1066 {
1067         if (!info) {
1068                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1069         }
1070
1071         if (w) {
1072                 *w = info->w;
1073         }
1074         if (h) {
1075                 *h = info->h;
1076         }
1077
1078         return DBOX_STATUS_ERROR_NONE;
1079 }
1080
1081 EAPI struct inst_info *buffer_handler_instance(struct buffer_info *info)
1082 {
1083         return info->inst;
1084 }
1085
1086 /*!
1087  * \note
1088  * Only for used S/W Backend
1089  */
1090 static inline int sync_for_pixmap(dynamicbox_fb_t buffer)
1091 {
1092         XShmSegmentInfo si;
1093         XImage *xim;
1094         GC gc;
1095         Display *disp;
1096         struct gem_data *gem;
1097         Screen *screen;
1098         Visual *visual;
1099
1100         if (buffer->state != DBOX_FB_STATE_CREATED) {
1101                 ErrPrint("Invalid state of a FB\n");
1102                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1103         }
1104
1105         if (buffer->type != DBOX_FB_TYPE_PIXMAP) {
1106                 ErrPrint("Invalid buffer\n");
1107                 return DBOX_STATUS_ERROR_NONE;
1108         }
1109
1110         disp = ecore_x_display_get();
1111         if (!disp) {
1112                 ErrPrint("Failed to get a display\n");
1113                 return DBOX_STATUS_ERROR_FAULT;
1114         }
1115
1116         gem = (struct gem_data *)buffer->data;
1117         if (gem->w == 0 || gem->h == 0) {
1118                 DbgPrint("Nothing can be sync\n");
1119                 return DBOX_STATUS_ERROR_NONE;
1120         }
1121
1122         si.shmid = shmget(IPC_PRIVATE, gem->w * gem->h * gem->depth, IPC_CREAT | 0666);
1123         if (si.shmid < 0) {
1124                 ErrPrint("shmget: %s\n", strerror(errno));
1125                 return DBOX_STATUS_ERROR_FAULT;
1126         }
1127
1128         si.readOnly = False;
1129         si.shmaddr = shmat(si.shmid, NULL, 0);
1130         if (si.shmaddr == (void *)-1) {
1131                 if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
1132                         ErrPrint("shmctl: %s\n", strerror(errno));
1133                 }
1134                 return DBOX_STATUS_ERROR_FAULT;
1135         }
1136
1137         screen = DefaultScreenOfDisplay(disp);
1138         visual = DefaultVisualOfScreen(screen);
1139         /*!
1140          * \NOTE
1141          * XCreatePixmap can only uses 24 bits depth only.
1142          */
1143         xim = XShmCreateImage(disp, visual, (gem->depth << 3), ZPixmap, NULL, &si, gem->w, gem->h);
1144         if (xim == NULL) {
1145                 if (shmdt(si.shmaddr) < 0) {
1146                         ErrPrint("shmdt: %s\n", strerror(errno));
1147                 }
1148
1149                 if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
1150                         ErrPrint("shmctl: %s\n", strerror(errno));
1151                 }
1152                 return DBOX_STATUS_ERROR_FAULT;
1153         }
1154
1155         xim->data = si.shmaddr;
1156         XShmAttach(disp, &si);
1157         XSync(disp, False);
1158
1159         gc = XCreateGC(disp, gem->pixmap, 0, NULL);
1160         if (!gc) {
1161                 XShmDetach(disp, &si);
1162                 XDestroyImage(xim);
1163
1164                 if (shmdt(si.shmaddr) < 0) {
1165                         ErrPrint("shmdt: %s\n", strerror(errno));
1166                 }
1167
1168                 if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
1169                         ErrPrint("shmctl: %s\n", strerror(errno));
1170                 }
1171
1172                 return DBOX_STATUS_ERROR_FAULT;
1173         }
1174
1175         memcpy(xim->data, gem->data, gem->w * gem->h * gem->depth);
1176
1177         /*!
1178          * \note Do not send the event.
1179          *       Instead of X event, master will send the updated event to the viewer
1180          */
1181         XShmPutImage(disp, gem->pixmap, gc, xim, 0, 0, 0, 0, gem->w, gem->h, False);
1182         XSync(disp, False);
1183
1184         XFreeGC(disp, gc);
1185         XShmDetach(disp, &si);
1186         XDestroyImage(xim);
1187
1188         if (shmdt(si.shmaddr) < 0) {
1189                 ErrPrint("shmdt: %s\n", strerror(errno));
1190         }
1191
1192         if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
1193                 ErrPrint("shmctl: %s\n", strerror(errno));
1194         }
1195
1196         return DBOX_STATUS_ERROR_NONE;
1197 }
1198
1199 EAPI void buffer_handler_flush(struct buffer_info *info)
1200 {
1201         int fd;
1202         int size;
1203         dynamicbox_fb_t buffer;
1204
1205         if (!info || !info->buffer) {
1206                 return;
1207         }
1208
1209         buffer = info->buffer;
1210
1211         if (buffer->type == DBOX_FB_TYPE_PIXMAP) {
1212                 if (s_info.fd > 0) {
1213                         //return;
1214                         //PERF_INIT();
1215                         //PERF_BEGIN();
1216                         XRectangle rect;
1217                         XserverRegion region;
1218
1219                         rect.x = 0;
1220                         rect.y = 0;
1221                         rect.width = info->w;
1222                         rect.height = info->h;
1223
1224                         region = XFixesCreateRegion(ecore_x_display_get(), &rect, 1);
1225                         XDamageAdd(ecore_x_display_get(), buffer_handler_pixmap(info), region);
1226                         XFixesDestroyRegion(ecore_x_display_get(), region);
1227                         XFlush(ecore_x_display_get());
1228                         //PERF_MARK("XFlush");
1229                 } else {
1230                         if (sync_for_pixmap(buffer) < 0) {
1231                                 ErrPrint("Failed to sync via S/W Backend\n");
1232                         }
1233                 }
1234         } else if (buffer->type == DBOX_FB_TYPE_FILE) {
1235                 fd = open(util_uri_to_path(info->id), O_WRONLY | O_CREAT, 0644);
1236                 if (fd < 0) {
1237                         ErrPrint("%s open falied: %s\n", util_uri_to_path(info->id), strerror(errno));
1238                         return;
1239                 }
1240
1241                 size = info->w * info->h * info->pixel_size;
1242                 dynamicbox_service_acquire_lock(info->lock_info);
1243                 if (write(fd, info->buffer, size) != size) {
1244                         ErrPrint("Write is not completed: %s\n", strerror(errno));
1245                 }
1246                 dynamicbox_service_release_lock(info->lock_info);
1247
1248                 if (close(fd) < 0) {
1249                         ErrPrint("close: %s\n", strerror(errno));
1250                 }
1251         } else {
1252                 DbgPrint("Flush nothing\n");
1253         }
1254 }
1255
1256 HAPI int buffer_handler_init(void)
1257 {
1258         int dri2Major, dri2Minor;
1259         char *driverName, *deviceName;
1260         drm_magic_t magic;
1261
1262         if (!DRI2QueryExtension(ecore_x_display_get(), &s_info.evt_base, &s_info.err_base)) {
1263                 ErrPrint("DRI2 is not supported\n");
1264                 return DBOX_STATUS_ERROR_NONE;
1265         }
1266
1267         if (!DRI2QueryVersion(ecore_x_display_get(), &dri2Major, &dri2Minor)) {
1268                 ErrPrint("DRI2 is not supported\n");
1269                 s_info.evt_base = 0;
1270                 s_info.err_base = 0;
1271                 return DBOX_STATUS_ERROR_NONE;
1272         }
1273
1274         if (!DRI2Connect(ecore_x_display_get(), DefaultRootWindow(ecore_x_display_get()), &driverName, &deviceName)) {
1275                 ErrPrint("DRI2 is not supported\n");
1276                 s_info.evt_base = 0;
1277                 s_info.err_base = 0;
1278                 return DBOX_STATUS_ERROR_NONE;
1279         }
1280
1281         if (DYNAMICBOX_CONF_USE_SW_BACKEND) {
1282                 DbgPrint("Fallback to the S/W Backend\n");
1283                 s_info.evt_base = 0;
1284                 s_info.err_base = 0;
1285                 DbgFree(deviceName);
1286                 DbgFree(driverName);
1287                 return DBOX_STATUS_ERROR_NONE;
1288         }
1289
1290         s_info.fd = open(deviceName, O_RDWR);
1291         DbgFree(deviceName);
1292         DbgFree(driverName);
1293         if (s_info.fd < 0) {
1294                 ErrPrint("Failed to open a drm device: (%s)\n", strerror(errno));
1295                 s_info.evt_base = 0;
1296                 s_info.err_base = 0;
1297                 return DBOX_STATUS_ERROR_NONE;
1298         }
1299
1300         drmGetMagic(s_info.fd, &magic);
1301         DbgPrint("DRM Magic: 0x%X\n", magic);
1302         if (!DRI2Authenticate(ecore_x_display_get(), DefaultRootWindow(ecore_x_display_get()), (unsigned int)magic)) {
1303                 ErrPrint("Failed to do authenticate for DRI2\n");
1304                 if (close(s_info.fd) < 0) {
1305                         ErrPrint("close: %s\n", strerror(errno));
1306                 }
1307                 s_info.fd = -1;
1308                 s_info.evt_base = 0;
1309                 s_info.err_base = 0;
1310                 return DBOX_STATUS_ERROR_NONE;
1311         }
1312
1313         s_info.slp_bufmgr = tbm_bufmgr_init(s_info.fd);
1314         if (!s_info.slp_bufmgr) {
1315                 ErrPrint("Failed to init bufmgr\n");
1316                 if (close(s_info.fd) < 0) {
1317                         ErrPrint("close: %s\n", strerror(errno));
1318                 }
1319                 s_info.fd = -1;
1320                 s_info.evt_base = 0;
1321                 s_info.err_base = 0;
1322                 return DBOX_STATUS_ERROR_NONE;
1323         }
1324
1325         return DBOX_STATUS_ERROR_NONE;
1326 }
1327
1328 HAPI int buffer_handler_fini(void)
1329 {
1330         if (s_info.fd >= 0) {
1331                 if (close(s_info.fd) < 0) {
1332                         ErrPrint("close: %s\n", strerror(errno));
1333                 }
1334                 s_info.fd = -1;
1335         }
1336
1337         if (s_info.slp_bufmgr) {
1338                 tbm_bufmgr_deinit(s_info.slp_bufmgr);
1339                 s_info.slp_bufmgr = NULL;
1340         }
1341
1342         return DBOX_STATUS_ERROR_NONE;
1343 }
1344
1345 static inline dynamicbox_fb_t raw_open_file(const char *filename)
1346 {
1347         dynamicbox_fb_t buffer;
1348         int fd;
1349         off_t off;
1350         int ret;
1351
1352         fd = open(filename, O_RDONLY);
1353         if (fd < 0) {
1354                 ErrPrint("open: %s\n", strerror(errno));
1355                 return NULL;
1356         }
1357
1358         off = lseek(fd, 0L, SEEK_END);
1359         if (off == (off_t)-1) {
1360                 ErrPrint("lseek: %s\n", strerror(errno));
1361
1362                 if (close(fd) < 0) {
1363                         ErrPrint("close: %s\n", strerror(errno));
1364                 }
1365
1366                 return NULL;
1367         }
1368
1369         if (lseek(fd, 0L, SEEK_SET) == (off_t)-1) {
1370                 ErrPrint("lseek: %s\n", strerror(errno));
1371
1372                 if (close(fd) < 0) {
1373                         ErrPrint("close: %s\n", strerror(errno));
1374                 }
1375
1376                 return NULL;
1377         }
1378
1379         buffer = calloc(1, sizeof(*buffer) + off);
1380         if (!buffer) {
1381                 ErrPrint("Heap: %s\n", strerror(errno));
1382
1383                 if (close(fd) < 0) {
1384                         ErrPrint("close: %s\n", strerror(errno));
1385                 }
1386
1387                 return NULL;
1388         }
1389
1390         buffer->state = DBOX_FB_STATE_CREATED;
1391         buffer->type = DBOX_FB_TYPE_FILE;
1392         buffer->refcnt = 0;
1393         buffer->info = (void *)off;
1394
1395         ret = read(fd, buffer->data, off);
1396         if (ret < 0) {
1397                 ErrPrint("read: %s\n", strerror(errno));
1398                 DbgFree(buffer);
1399
1400                 if (close(fd) < 0) {
1401                         ErrPrint("close: %s\n", strerror(errno));
1402                 }
1403
1404                 return NULL;
1405         }
1406
1407         if (close(fd) < 0) {
1408                 ErrPrint("close: %s\n", strerror(errno));
1409         }
1410
1411         return buffer;
1412 }
1413
1414 static inline int raw_close_file(dynamicbox_fb_t buffer)
1415 {
1416         DbgFree(buffer);
1417         return 0;
1418 }
1419
1420 static inline dynamicbox_fb_t raw_open_shm(int shm)
1421 {
1422         dynamicbox_fb_t buffer;
1423
1424         buffer = (dynamicbox_fb_t)shmat(shm, NULL, SHM_RDONLY);
1425         if (buffer == (dynamicbox_fb_t)-1) {
1426                 ErrPrint("shmat: %s\n", strerror(errno));
1427                 return NULL;
1428         }
1429
1430         return buffer;
1431 }
1432
1433 static inline int raw_close_shm(dynamicbox_fb_t buffer)
1434 {
1435         int ret;
1436
1437         ret = shmdt(buffer);
1438         if (ret < 0) {
1439                 ErrPrint("shmdt: %s\n", strerror(errno));
1440         }
1441
1442         return ret;
1443 }
1444
1445 static inline dynamicbox_fb_t raw_open_pixmap(unsigned int pixmap)
1446 {
1447         dynamicbox_fb_t buffer;
1448
1449         buffer = calloc(1, sizeof(*buffer) + DYNAMICBOX_CONF_DEFAULT_PIXELS);
1450         if (!buffer) {
1451                 ErrPrint("Heap: %s\n", strerror(errno));
1452                 return NULL;
1453         }
1454
1455         buffer->state = DBOX_FB_STATE_CREATED;
1456         buffer->type = DBOX_FB_TYPE_PIXMAP;
1457
1458         return buffer;
1459 }
1460
1461 static inline int raw_close_pixmap(dynamicbox_fb_t buffer)
1462 {
1463         DbgFree(buffer);
1464         return 0;
1465 }
1466
1467 EAPI void *buffer_handler_raw_data(dynamicbox_fb_t buffer)
1468 {
1469         if (!buffer || buffer->state != DBOX_FB_STATE_CREATED) {
1470                 return NULL;
1471         }
1472
1473         return buffer->data;
1474 }
1475
1476 EAPI int buffer_handler_raw_size(dynamicbox_fb_t buffer)
1477 {
1478         if (!buffer || buffer->state != DBOX_FB_STATE_CREATED) {
1479                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1480         }
1481
1482         return (int)buffer->info;
1483 }
1484
1485 EAPI dynamicbox_fb_t buffer_handler_raw_open(enum dynamicbox_fb_type dynamicbox_fb_type, void *resource)
1486 {
1487         dynamicbox_fb_t handle;
1488
1489         switch (dynamicbox_fb_type) {
1490         case DBOX_FB_TYPE_SHM:
1491                 handle = raw_open_shm((int)resource);
1492                 break;
1493         case DBOX_FB_TYPE_FILE:
1494                 handle = raw_open_file(resource);
1495                 break;
1496         case DBOX_FB_TYPE_PIXMAP:
1497                 handle = raw_open_pixmap((unsigned int)resource);
1498                 break;
1499         default:
1500                 handle = NULL;
1501                 break;
1502         }
1503
1504         return handle;
1505 }
1506
1507 EAPI int buffer_handler_raw_close(dynamicbox_fb_t buffer)
1508 {
1509         int ret;
1510
1511         if (!buffer || buffer->state != DBOX_FB_STATE_CREATED) {
1512                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1513         }
1514
1515         switch (buffer->type) {
1516         case DBOX_FB_TYPE_SHM:
1517                 ret = raw_close_shm(buffer);
1518                 break;
1519         case DBOX_FB_TYPE_FILE:
1520                 ret = raw_close_file(buffer);
1521                 break;
1522         case DBOX_FB_TYPE_PIXMAP:
1523                 ret = raw_close_pixmap(buffer);
1524                 break;
1525         default:
1526                 ret = DBOX_STATUS_ERROR_INVALID_PARAMETER;
1527                 break;
1528         }
1529
1530         return ret;
1531 }
1532
1533 EAPI int buffer_handler_lock(struct buffer_info *info)
1534 {
1535         if (!info) {
1536                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1537         }
1538
1539         if (info->type == DBOX_FB_TYPE_PIXMAP) {
1540                 return DBOX_STATUS_ERROR_NONE;
1541         }
1542
1543         if (info->type == DBOX_FB_TYPE_FILE) {
1544                 return DBOX_STATUS_ERROR_NONE;
1545         }
1546
1547         return dynamicbox_service_acquire_lock(info->lock_info);
1548 }
1549
1550 EAPI int buffer_handler_unlock(struct buffer_info *info)
1551 {
1552         if (!info) {
1553                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1554         }
1555
1556         if (info->type == DBOX_FB_TYPE_PIXMAP) {
1557                 return DBOX_STATUS_ERROR_NONE;
1558         }
1559
1560         if (info->type == DBOX_FB_TYPE_FILE) {
1561                 return DBOX_STATUS_ERROR_NONE;
1562         }
1563
1564         return dynamicbox_service_release_lock(info->lock_info);
1565 }
1566
1567 EAPI int buffer_handler_pixels(struct buffer_info *info)
1568 {
1569         if (!info) {
1570                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1571         }
1572
1573         return info->pixel_size;
1574 }
1575
1576 EAPI int buffer_handler_auto_align(void)
1577 {
1578         return DYNAMICBOX_CONF_AUTO_ALIGN;
1579 }
1580
1581 EAPI int buffer_handler_stride(struct buffer_info *info)
1582 {
1583         dynamicbox_fb_t buffer;
1584         struct gem_data *gem;
1585         int stride;
1586
1587         if (!info) {
1588                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1589         }
1590
1591         switch (info->type) {
1592         case DBOX_FB_TYPE_FILE:
1593         case DBOX_FB_TYPE_SHM:
1594                 stride = info->w * info->pixel_size;
1595                 break;
1596         case DBOX_FB_TYPE_PIXMAP:
1597                 buffer = info->buffer;
1598                 if (!buffer) {
1599                         stride = DBOX_STATUS_ERROR_INVALID_PARAMETER;
1600                         break;
1601                 }
1602
1603                 gem = (struct gem_data *)buffer->data;
1604                 if (!gem) {
1605                         stride = DBOX_STATUS_ERROR_INVALID_PARAMETER;
1606                         break;
1607                 }
1608
1609                 if (!gem->dri2_buffer) {
1610                         /*
1611                          * Uhm...
1612                          */
1613                         ErrPrint("dri2_buffer info is not ready yet!\n");
1614                         stride = DBOX_STATUS_ERROR_INVALID_PARAMETER;
1615                         break;
1616                 }
1617
1618                 stride = gem->dri2_buffer->pitch;
1619                 break;
1620         default:
1621                 stride = DBOX_STATUS_ERROR_INVALID_PARAMETER;
1622                 break;
1623         }
1624
1625         return stride;
1626 }
1627
1628 /*!
1629  * \note
1630  * Only can be used by master.
1631  * Plugin cannot access the user data
1632  */
1633
1634 HAPI int buffer_handler_set_data(struct buffer_info *info, void *data)
1635 {
1636         if (!info) {
1637                 ErrPrint("Invalid handle\n");
1638                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1639         }
1640
1641         info->data = data;
1642         return DBOX_STATUS_ERROR_NONE;
1643 }
1644
1645 HAPI void *buffer_handler_data(struct buffer_info *info)
1646 {
1647         if (!info) {
1648                 ErrPrint("Invalid handle\n");
1649                 return NULL;
1650         }
1651
1652         return info->data;
1653 }
1654
1655 HAPI int buffer_handler_destroy(struct buffer_info *info)
1656 {
1657         Eina_List *l;
1658         dynamicbox_fb_t buffer;
1659
1660         if (!info) {
1661                 DbgPrint("Buffer is not created yet. info is NIL\n");
1662                 return DBOX_STATUS_ERROR_NONE;
1663         }
1664
1665         EINA_LIST_FOREACH(s_info.pixmap_list, l, buffer) {
1666                 if (buffer->info == info) {
1667                         buffer->info = NULL;
1668                 }
1669         }
1670
1671         buffer_handler_unload(info);
1672         DbgFree(info->id);
1673         DbgFree(info);
1674         return DBOX_STATUS_ERROR_NONE;
1675 }
1676
1677 HAPI struct buffer_info *buffer_handler_create(struct inst_info *inst, enum dynamicbox_fb_type type, int w, int h, int pixel_size)
1678 {
1679         struct buffer_info *info;
1680
1681         info = malloc(sizeof(*info));
1682         if (!info) {
1683                 ErrPrint("Heap: %s\n", strerror(errno));
1684                 return NULL;
1685         }
1686
1687         switch (type) {
1688         case DBOX_FB_TYPE_SHM:
1689                 if (pixel_size != DYNAMICBOX_CONF_DEFAULT_PIXELS) {
1690                         DbgPrint("SHM only supportes %d bytes pixels (requested: %d)\n", DYNAMICBOX_CONF_DEFAULT_PIXELS, pixel_size);
1691                         pixel_size = DYNAMICBOX_CONF_DEFAULT_PIXELS;
1692                 }
1693
1694                 info->id = strdup(SCHEMA_SHM "-1");
1695                 if (!info->id) {
1696                         ErrPrint("Heap: %s\n", strerror(errno));
1697                         DbgFree(info);
1698                         return NULL;
1699                 }
1700                 break;
1701         case DBOX_FB_TYPE_FILE:
1702                 if (pixel_size != DYNAMICBOX_CONF_DEFAULT_PIXELS) {
1703                         DbgPrint("FILE only supportes %d bytes pixels (requested: %d)\n", DYNAMICBOX_CONF_DEFAULT_PIXELS, pixel_size);
1704                         pixel_size = DYNAMICBOX_CONF_DEFAULT_PIXELS;
1705                 }
1706
1707                 info->id = strdup(SCHEMA_FILE "/tmp/.live.undefined");
1708                 if (!info->id) {
1709                         ErrPrint("Heap: %s\n", strerror(errno));
1710                         DbgFree(info);
1711                         return NULL;
1712                 }
1713                 break;
1714         case DBOX_FB_TYPE_PIXMAP:
1715                 info->id = strdup(SCHEMA_PIXMAP "0:0");
1716                 if (!info->id) {
1717                         ErrPrint("Heap: %s\n", strerror(errno));
1718                         DbgFree(info);
1719                         return NULL;
1720                 }
1721                 break;
1722         default:
1723                 ErrPrint("Invalid type\n");
1724                 DbgFree(info);
1725                 return NULL;
1726         }
1727
1728         info->lock_info = NULL;
1729         info->w = w;
1730         info->h = h;
1731         info->pixel_size = pixel_size;
1732         info->type = type;
1733         info->is_loaded = 0;
1734         info->inst = inst;
1735         info->buffer = NULL;
1736         info->data = NULL;
1737
1738         return info;
1739 }
1740
1741 /* End of a file */