2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (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
8 * http://www.tizenopensource.org/license
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.
18 #include <unistd.h> /* access */
21 #include <sys/types.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>
40 #include <xf86drmMode.h>
41 #include <drm_slp_bufmgr.h>
51 #include "client_life.h"
52 #include "client_rpc.h"
53 #include "buffer_handler.h"
58 DESTROYED = 0x00dead00,
60 enum buffer_type type;
67 * \brief Allocate this in the buffer->data.
70 DRI2Buffer *dri2_buffer;
71 unsigned int attachments[1];
79 void *data; /* Gem layer */
82 void *compensate_data; /* Check the pitch value, copy this to data */
90 enum buffer_type type;
97 struct inst_info *inst;
101 drm_slp_bufmgr slp_bufmgr;
105 Eina_List *pixmap_list;
114 HAPI struct buffer_info *buffer_handler_create(struct inst_info *inst, enum buffer_type type, int w, int h, int pixel_size)
116 struct buffer_info *info;
118 info = malloc(sizeof(*info));
120 ErrPrint("Heap: %s\n", strerror(errno));
125 case BUFFER_TYPE_SHM:
126 info->id = strdup(SCHEMA_SHM "-1");
128 ErrPrint("Heap: %s\n", strerror(errno));
133 case BUFFER_TYPE_FILE:
134 info->id = strdup(SCHEMA_FILE "/tmp/.live.undefined");
136 ErrPrint("Heap: %s\n", strerror(errno));
141 case BUFFER_TYPE_PIXMAP:
142 info->id = strdup(SCHEMA_PIXMAP "0");
144 ErrPrint("Heap: %s\n", strerror(errno));
150 ErrPrint("Invalid type\n");
157 info->pixel_size = pixel_size;
163 DbgPrint("%dx%d size buffer is created\n", w, h);
167 static inline struct buffer *create_pixmap(struct buffer_info *info)
169 struct gem_data *gem;
170 struct buffer *buffer;
174 disp = ecore_x_display_get();
178 parent = DefaultRootWindow(disp);
180 buffer = calloc(1, sizeof(*buffer) + sizeof(*gem));
182 ErrPrint("Heap: %s\n", strerror(errno));
186 gem = (struct gem_data *)buffer->data;
188 buffer->type = BUFFER_TYPE_PIXMAP;
190 buffer->state = CREATED;
192 DbgPrint("Canvas %dx%d - %d is created\n", info->w, info->h, info->pixel_size);
194 gem->attachments[0] = DRI2BufferFrontLeft;
196 gem->w = info->w; /*!< This can be changed by DRI2GetBuffers */
197 gem->h = info->h; /*!< This can be changed by DRI2GetBuffers */
198 gem->depth = info->pixel_size;
202 * 32 Bits is not supported for video playing.
204 gem->pixmap = XCreatePixmap(disp, parent, info->w, info->h, 24 /* (info->pixel_size << 3) */);
205 if (gem->pixmap == (Pixmap)0) {
206 ErrPrint("Failed to create a pixmap\n");
213 DbgPrint("Pixmap:0x%X is created\n", gem->pixmap);
217 static inline int create_gem(struct buffer *buffer)
219 struct gem_data *gem;
222 disp = ecore_x_display_get();
224 ErrPrint("Failed to get display\n");
228 gem = (struct gem_data *)buffer->data;
231 gem->data = calloc(1, gem->w * gem->h * gem->depth);
233 ErrPrint("Heap: %s\n", strerror(errno));
237 DbgPrint("DRI2(gem) is not supported - Fallback to the S/W Backend\n");
241 DRI2CreateDrawable(disp, gem->pixmap);
242 DbgPrint("DRI2CreateDrawable is done\n");
244 gem->dri2_buffer = DRI2GetBuffers(disp, gem->pixmap,
245 &gem->w, &gem->h, gem->attachments, gem->count, &gem->buf_count);
246 if (!gem->dri2_buffer || !gem->dri2_buffer->name) {
247 ErrPrint("Failed to get a gem buffer\n");
248 DRI2DestroyDrawable(disp, gem->pixmap);
251 DbgPrint("dri2_buffer: %p, name: %p, %dx%d\n",
252 gem->dri2_buffer, gem->dri2_buffer->name, gem->w, gem->h);
253 DbgPrint("dri2_buffer->pitch : %d, buf_count: %d\n",
254 gem->dri2_buffer->pitch, gem->buf_count);
257 * \How can I destroy this?
259 gem->pixmap_bo = drm_slp_bo_import(s_info.slp_bufmgr, gem->dri2_buffer->name);
260 if (!gem->pixmap_bo) {
261 ErrPrint("Failed to import BO\n");
262 DRI2DestroyDrawable(disp, gem->pixmap);
266 if (gem->dri2_buffer->pitch != gem->w * gem->depth) {
267 gem->compensate_data = calloc(1, gem->w * gem->h * gem->depth);
268 if (!gem->compensate_data) {
269 ErrPrint("Failed to allocate heap\n");
271 DbgPrint("Allocate compensate buffer %p(%dx%d %d)\n",
272 gem->compensate_data,
273 gem->w, gem->h, gem->depth);
280 static inline void *acquire_gem(struct buffer *buffer)
282 struct gem_data *gem;
287 gem = (struct gem_data *)buffer->data;
289 DbgPrint("GEM is not supported - Use the fake gem buffer\n");
291 if (!gem->pixmap_bo) {
292 DbgPrint("GEM is not created\n");
298 ErrPrint("Already acquired. but the buffer is not valid\n");
302 gem->data = (void *)drm_slp_bo_map(gem->pixmap_bo, DRM_SLP_DEVICE_CPU, DRM_SLP_OPTION_READ|DRM_SLP_OPTION_WRITE);
310 * If there is a compensate canvas buffer,
313 return gem->compensate_data ? gem->compensate_data : gem->data;
316 static inline void release_gem(struct buffer *buffer)
318 struct gem_data *gem;
320 gem = (struct gem_data *)buffer->data;
321 if (s_info.fd >= 0 && !gem->pixmap_bo) {
322 DbgPrint("GEM is not created\n");
327 if (gem->refcnt > 0) {
328 ErrPrint("Reference count is not valid %d\n", gem->refcnt);
335 if (gem->refcnt == 0) {
337 DbgPrint("S/W Gem buffer has no reference\n");
341 * Update the gem buffer using compensate data buffer if it is exists
343 if (gem->compensate_data) {
350 pixel = gem->compensate_data;
351 gem_pixel = gem->data;
352 gap = gem->dri2_buffer->pitch - (gem->w * gem->depth);
354 for (y = 0; y < gem->h; y++) {
355 for (x = 0; x < gem->w; x++)
356 *gem_pixel++ = *pixel++;
358 gem_pixel = (int *)(((char *)gem_pixel) + gap);
363 drm_slp_bo_unmap(gem->pixmap_bo, DRM_SLP_DEVICE_CPU);
367 } else if (gem->refcnt < 0) {
368 DbgPrint("Invalid refcnt: %d (reset)\n", gem->refcnt);
373 static inline int destroy_pixmap(struct buffer *buffer)
375 struct gem_data *gem;
377 gem = (struct gem_data *)buffer->data;
382 disp = ecore_x_display_get();
386 DbgPrint("Free pixmap 0x%X\n", gem->pixmap);
387 XFreePixmap(disp, gem->pixmap);
390 buffer->state = DESTROYED;
395 static inline int destroy_gem(struct buffer *buffer)
397 struct gem_data *gem;
403 * Forcely release the acquire_buffer.
405 gem = (struct gem_data *)buffer->data;
409 if (s_info.fd >= 0) {
410 if (gem->compensate_data) {
411 DbgPrint("Release compensate buffer %p\n", gem->compensate_data);
412 free(gem->compensate_data);
413 gem->compensate_data = NULL;
416 if (gem->pixmap_bo) {
417 DbgPrint("unref pixmap bo\n");
418 drm_slp_bo_unref(gem->pixmap_bo);
419 gem->pixmap_bo = NULL;
421 DbgPrint("DRI2DestroyDrawable\n");
422 DRI2DestroyDrawable(ecore_x_display_get(), gem->pixmap);
424 } else if (gem->data) {
425 DbgPrint("Release fake gem buffer\n");
433 static inline int load_file_buffer(struct buffer_info *info)
435 struct buffer *buffer;
441 len = strlen(IMAGE_PATH) + 40;
442 new_id = malloc(len);
444 ErrPrint("Heap: %s\n", strerror(errno));
448 timestamp = util_timestamp();
449 snprintf(new_id, len, SCHEMA_FILE "%s%lf", IMAGE_PATH, timestamp);
451 size = sizeof(*buffer) + info->w * info->h * info->pixel_size;
453 ErrPrint("Canvas buffer size is ZERO\n");
458 buffer = calloc(1, size);
460 ErrPrint("Failed to allocate buffer\n");
465 buffer->type = BUFFER_TYPE_FILE;
467 buffer->state = CREATED;
472 info->buffer = buffer;
475 DbgPrint("FILE type %d created\n", size);
479 static inline int load_shm_buffer(struct buffer_info *info)
483 struct buffer *buffer; /* Just for getting a size */
487 size = info->w * info->h * info->pixel_size;
489 ErrPrint("Invalid buffer size\n");
493 id = shmget(IPC_PRIVATE, size + sizeof(*buffer), IPC_CREAT | 0666);
495 ErrPrint("shmget: %s\n", strerror(errno));
499 buffer = shmat(id, NULL, 0);
500 if (buffer == (void *)-1) {
501 ErrPrint("%s shmat: %s\n", info->id, strerror(errno));
503 if (shmctl(id, IPC_RMID, 0) < 0)
504 ErrPrint("%s shmctl: %s\n", info->id, strerror(errno));
509 buffer->type = BUFFER_TYPE_SHM;
511 buffer->state = CREATED; /*!< Needless */
512 buffer->info = NULL; /*!< This has not to be used, every process will see this. So, don't try to save anything on here */
514 len = strlen(SCHEMA_SHM) + 30; /* strlen("shm://") + 30 */
516 new_id = malloc(len);
518 ErrPrint("Heap: %s\n", strerror(errno));
519 if (shmdt(buffer) < 0)
520 ErrPrint("shmdt: %s\n", strerror(errno));
522 if (shmctl(id, IPC_RMID, 0) < 0)
523 ErrPrint("shmctl: %s\n", strerror(errno));
528 snprintf(new_id, len, SCHEMA_SHM "%d", id);
532 info->buffer = buffer;
537 static inline int load_pixmap_buffer(struct buffer_info *info)
539 struct buffer *buffer;
540 struct gem_data *gem;
546 * Before call the buffer_handler_pixmap_ref function,
547 * You should make sure that the is_loaded value is toggled (1)
548 * Or the buffer_handler_pixmap_ref function will return NULL
553 DbgPrint("Buffer is already exists, but override it with new one\n");
555 buffer = buffer_handler_pixmap_ref(info);
557 DbgPrint("Failed to make a reference of a pixmap\n");
562 len = strlen(SCHEMA_PIXMAP) + 30; /* strlen("pixmap://") + 30 */
563 new_id = malloc(len);
566 ErrPrint("Heap: %s\n", strerror(errno));
567 buffer_handler_pixmap_unref(buffer);
571 DbgPrint("Releaseo old id (%s)\n", info->id);
575 gem = (struct gem_data *)buffer->data;
576 DbgPrint("gem pointer: %p\n", gem);
578 snprintf(info->id, len, SCHEMA_PIXMAP "%d", (int)gem->pixmap);
579 DbgPrint("info->id: %s\n", info->id);
584 HAPI int buffer_handler_load(struct buffer_info *info)
589 DbgPrint("buffer handler is nil\n");
593 if (info->is_loaded) {
594 DbgPrint("Buffer is already loaded\n");
598 switch (info->type) {
599 case BUFFER_TYPE_FILE:
600 ret = load_file_buffer(info);
602 case BUFFER_TYPE_SHM:
603 ret = load_shm_buffer(info);
605 case BUFFER_TYPE_PIXMAP:
606 ret = load_pixmap_buffer(info);
609 ErrPrint("Invalid buffer\n");
617 static inline int unload_file_buffer(struct buffer_info *info)
622 new_id = strdup(SCHEMA_FILE "/tmp/.live.undefined");
624 ErrPrint("Heap: %s\n", strerror(errno));
628 DbgFree(info->buffer);
631 path = util_uri_to_path(info->id);
632 if (path && unlink(path) < 0)
633 ErrPrint("unlink: %s\n", strerror(errno));
640 static inline int unload_shm_buffer(struct buffer_info *info)
645 new_id = strdup(SCHEMA_SHM "-1");
647 ErrPrint("Heap: %s\n", strerror(errno));
651 if (sscanf(info->id, SCHEMA_SHM "%d", &id) != 1) {
652 ErrPrint("%s Invalid ID\n", info->id);
658 ErrPrint("(%s) Invalid id: %d\n", info->id, id);
663 if (shmdt(info->buffer) < 0)
664 ErrPrint("Detach shm: %s\n", strerror(errno));
666 if (shmctl(id, IPC_RMID, 0) < 0)
667 ErrPrint("Remove shm: %s\n", strerror(errno));
676 static inline int unload_pixmap_buffer(struct buffer_info *info)
681 new_id = strdup(SCHEMA_PIXMAP "0");
683 ErrPrint("Heap: %s\n", strerror(errno));
687 if (sscanf(info->id, SCHEMA_PIXMAP "%d", &id) != 1) {
688 ErrPrint("Invalid ID (%s)\n", info->id);
694 ErrPrint("(%s) Invalid id: %d\n", info->id, id);
700 * Decrease the reference counter.
702 buffer_handler_pixmap_unref(info->buffer);
706 * Just clear the info->buffer.
707 * It will be reallocated again.
716 HAPI int buffer_handler_unload(struct buffer_info *info)
721 DbgPrint("buffer handler is nil\n");
725 if (!info->is_loaded) {
726 ErrPrint("Buffer is not loaded\n");
730 switch (info->type) {
731 case BUFFER_TYPE_FILE:
732 ret = unload_file_buffer(info);
734 case BUFFER_TYPE_SHM:
735 ret = unload_shm_buffer(info);
737 case BUFFER_TYPE_PIXMAP:
738 ret = unload_pixmap_buffer(info);
741 ErrPrint("Invalid buffer\n");
752 HAPI int buffer_handler_destroy(struct buffer_info *info)
755 struct buffer *buffer;
758 DbgPrint("Buffer is not created yet. info is nil\n");
762 EINA_LIST_FOREACH(s_info.pixmap_list, l, buffer) {
763 if (buffer->info == info)
767 buffer_handler_unload(info);
773 HAPI const char *buffer_handler_id(const struct buffer_info *info)
775 return info ? info->id : "";
778 HAPI enum buffer_type buffer_handler_type(const struct buffer_info *info)
780 return info ? info->type : BUFFER_TYPE_ERROR;
783 HAPI void *buffer_handler_fb(struct buffer_info *info)
785 struct buffer *buffer;
790 buffer = info->buffer;
792 if (info->type == BUFFER_TYPE_PIXMAP) {
798 canvas = buffer_handler_pixmap_acquire_buffer(info);
799 ret = buffer_handler_pixmap_release_buffer(canvas);
800 DbgPrint("Canvas %p(%d) (released but still in use)\n", canvas, ret);
807 HAPI int buffer_handler_pixmap(const struct buffer_info *info)
810 struct gem_data *gem;
813 ErrPrint("Inavlid buffer handler\n");
817 if (info->type != BUFFER_TYPE_PIXMAP) {
818 ErrPrint("Invalid buffer type\n");
822 buf = (struct buffer *)info->buffer;
824 ErrPrint("Invalid buffer data\n");
828 gem = (struct gem_data *)buf->data;
832 HAPI void *buffer_handler_pixmap_acquire_buffer(struct buffer_info *info)
834 struct buffer *buffer;
836 if (!info || !info->is_loaded) {
837 ErrPrint("Buffer is not loaded\n");
841 buffer = buffer_handler_pixmap_ref(info);
845 return acquire_gem(buffer);
848 HAPI void *buffer_handler_pixmap_buffer(struct buffer_info *info)
850 struct buffer *buffer;
851 struct gem_data *gem;
856 if (!info->is_loaded) {
857 ErrPrint("Buffer is not loaded\n");
861 buffer = info->buffer;
865 gem = (struct gem_data *)buffer->data;
866 return gem->compensate_data ? gem->compensate_data : gem->data;
870 * \return "buffer" object (Not the buffer_info)
872 HAPI void *buffer_handler_pixmap_ref(struct buffer_info *info)
874 struct buffer *buffer;
876 if (!info->is_loaded) {
877 ErrPrint("Buffer is not loaded\n");
881 if (info->type != BUFFER_TYPE_PIXMAP) {
882 ErrPrint("Buffer type is not matched\n");
886 buffer = info->buffer;
890 buffer = create_pixmap(info);
892 DbgPrint("Failed to create a pixmap\n");
896 info->buffer = buffer;
899 struct pkg_info *pkg;
901 if (instance_lb_buffer(info->inst) == info) {
902 pkg = instance_package(info->inst);
903 if (package_lb_type(pkg) == LB_TYPE_BUFFER) {
904 DbgPrint("Doesn't need to create gem for LB\n");
907 } else if (instance_pd_buffer(info->inst) == info) {
908 pkg = instance_package(info->inst);
909 if (package_pd_type(pkg) == PD_TYPE_BUFFER) {
910 DbgPrint("Doesn't need to create gem for PD\n");
919 } else if (buffer->state != CREATED || buffer->type != BUFFER_TYPE_PIXMAP) {
920 ErrPrint("Invalid buffer\n");
922 } else if (buffer->refcnt > 0) {
927 s_info.pixmap_list = eina_list_append(s_info.pixmap_list, buffer);
934 HAPI void *buffer_handler_pixmap_find(int pixmap)
936 struct buffer *buffer;
937 struct gem_data *gem;
944 EINA_LIST_FOREACH_SAFE(s_info.pixmap_list, l, n, buffer) {
945 if (!buffer || buffer->state != CREATED || buffer->type != BUFFER_TYPE_PIXMAP) {
946 s_info.pixmap_list = eina_list_remove(s_info.pixmap_list, buffer);
947 DbgPrint("Invalid buffer (List Removed: %p)\n", buffer);
951 gem = (struct gem_data *)buffer->data;
952 if (gem->pixmap == pixmap)
959 HAPI int buffer_handler_pixmap_release_buffer(void *canvas)
961 struct buffer *buffer;
962 struct gem_data *gem;
970 EINA_LIST_FOREACH_SAFE(s_info.pixmap_list, l, n, buffer) {
971 if (!buffer || buffer->state != CREATED || buffer->type != BUFFER_TYPE_PIXMAP) {
972 s_info.pixmap_list = eina_list_remove(s_info.pixmap_list, buffer);
976 gem = (struct gem_data *)buffer->data;
977 _ptr = gem->compensate_data ? gem->compensate_data : gem->data;
982 if (_ptr == canvas) {
984 buffer_handler_pixmap_unref(buffer);
995 * \return Return NULL if the buffer is in still uses.
996 * Return buffer_ptr if it needs to destroy
998 HAPI int buffer_handler_pixmap_unref(void *buffer_ptr)
1000 struct buffer *buffer = buffer_ptr;
1001 struct buffer_info *info;
1004 if (buffer->refcnt > 0)
1005 return 0; /* Return NULL means, gem buffer still in use */
1007 s_info.pixmap_list = eina_list_remove(s_info.pixmap_list, buffer);
1009 if (destroy_gem(buffer) < 0)
1010 ErrPrint("Failed to destroy gem buffer\n");
1012 if (destroy_pixmap(buffer) < 0)
1013 ErrPrint("Failed to destroy pixmap\n");
1015 info = buffer->info;
1016 if (info && info->buffer == buffer)
1017 info->buffer = NULL;
1022 HAPI int buffer_handler_is_loaded(const struct buffer_info *info)
1024 return info ? info->is_loaded : 0;
1027 HAPI void buffer_handler_update_size(struct buffer_info *info, int w, int h)
1036 HAPI int buffer_handler_resize(struct buffer_info *info, int w, int h)
1041 ErrPrint("Invalid handler\n");
1045 if (info->w == w && info->h == h) {
1046 DbgPrint("No changes\n");
1050 buffer_handler_update_size(info, w, h);
1052 if (!info->is_loaded) {
1053 DbgPrint("Not yet loaded, just update the size [%dx%d]\n", w, h);
1057 ret = buffer_handler_unload(info);
1059 ErrPrint("Unload: %d\n", ret);
1061 ret = buffer_handler_load(info);
1063 ErrPrint("Load: %d\n", ret);
1068 HAPI int buffer_handler_get_size(struct buffer_info *info, int *w, int *h)
1081 HAPI struct inst_info *buffer_handler_instance(struct buffer_info *info)
1088 * Only for used S/W Backend
1090 static inline int sync_for_pixmap(struct buffer *buffer)
1096 struct gem_data *gem;
1100 if (buffer->state != CREATED) {
1101 ErrPrint("Invalid state of a FB\n");
1105 if (buffer->type != BUFFER_TYPE_PIXMAP) {
1106 DbgPrint("Invalid buffer\n");
1110 disp = ecore_x_display_get();
1112 ErrPrint("Failed to get a display\n");
1116 gem = (struct gem_data *)buffer->data;
1117 if (gem->w == 0 || gem->h == 0) {
1118 DbgPrint("Nothing can be sync\n");
1122 si.shmid = shmget(IPC_PRIVATE, gem->w * gem->h * gem->depth, IPC_CREAT | 0666);
1124 ErrPrint("shmget: %s\n", strerror(errno));
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));
1136 screen = DefaultScreenOfDisplay(disp);
1137 visual = DefaultVisualOfScreen(screen);
1140 * XCreatePixmap can only uses 24 bits depth only.
1142 xim = XShmCreateImage(disp, visual, 24 /* (gem->depth << 3) */, ZPixmap, NULL, &si, gem->w, gem->h);
1144 if (shmdt(si.shmaddr) < 0)
1145 ErrPrint("shmdt: %s\n", strerror(errno));
1147 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
1148 ErrPrint("shmctl: %s\n", strerror(errno));
1152 xim->data = si.shmaddr;
1153 XShmAttach(disp, &si);
1156 gc = XCreateGC(disp, gem->pixmap, 0, NULL);
1158 XShmDetach(disp, &si);
1161 if (shmdt(si.shmaddr) < 0)
1162 ErrPrint("shmdt: %s\n", strerror(errno));
1164 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
1165 ErrPrint("shmctl: %s\n", strerror(errno));
1170 memcpy(xim->data, gem->data, gem->w * gem->h * gem->depth);
1173 * \note Do not send the event.
1174 * Instead of X event, master will send the updated event to the viewer
1176 XShmPutImage(disp, gem->pixmap, gc, xim, 0, 0, 0, 0, gem->w, gem->h, False);
1180 XShmDetach(disp, &si);
1183 if (shmdt(si.shmaddr) < 0)
1184 ErrPrint("shmdt: %s\n", strerror(errno));
1186 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
1187 ErrPrint("shmctl: %s\n", strerror(errno));
1192 HAPI void buffer_handler_flush(struct buffer_info *info)
1196 struct buffer *buffer;
1198 if (!info || !info->buffer)
1201 buffer = info->buffer;
1203 if (buffer->type == BUFFER_TYPE_PIXMAP) {
1204 if (s_info.fd > 0) {
1206 XserverRegion region;
1210 rect.width = info->w;
1211 rect.height = info->h;
1213 region = XFixesCreateRegion(ecore_x_display_get(), &rect, 1);
1214 XDamageAdd(ecore_x_display_get(), buffer_handler_pixmap(info), region);
1215 XFixesDestroyRegion(ecore_x_display_get(), region);
1216 XFlush(ecore_x_display_get());
1218 if (sync_for_pixmap(buffer) < 0)
1219 ErrPrint("Failed to sync via S/W Backend\n");
1221 } else if (buffer->type == BUFFER_TYPE_FILE) {
1222 fd = open(util_uri_to_path(info->id), O_WRONLY | O_CREAT, 0644);
1224 ErrPrint("%s open falied: %s\n", util_uri_to_path(info->id), strerror(errno));
1228 size = info->w * info->h * info->pixel_size;
1229 if (write(fd, info->buffer, size) != size)
1230 ErrPrint("Write is not completed: %s\n", strerror(errno));
1234 DbgPrint("Flush nothing\n");
1238 HAPI int buffer_handler_init(void)
1240 int dri2Major, dri2Minor;
1241 char *driverName, *deviceName;
1244 if (!DRI2QueryExtension(ecore_x_display_get(), &s_info.evt_base, &s_info.err_base)) {
1245 DbgPrint("DRI2 is not supported\n");
1249 if (!DRI2QueryVersion(ecore_x_display_get(), &dri2Major, &dri2Minor)) {
1250 DbgPrint("DRI2 is not supported\n");
1251 s_info.evt_base = 0;
1252 s_info.err_base = 0;
1256 if (!DRI2Connect(ecore_x_display_get(), DefaultRootWindow(ecore_x_display_get()), &driverName, &deviceName)) {
1257 DbgPrint("DRI2 is not supported\n");
1258 s_info.evt_base = 0;
1259 s_info.err_base = 0;
1263 DbgPrint("Open: %s (driver: %s)", deviceName, driverName);
1265 if (USE_SW_BACKEND) {
1266 DbgPrint("Fallback to the S/W Backend\n");
1267 s_info.evt_base = 0;
1268 s_info.err_base = 0;
1269 DbgFree(deviceName);
1270 DbgFree(driverName);
1274 s_info.fd = open(deviceName, O_RDWR);
1275 DbgFree(deviceName);
1276 DbgFree(driverName);
1277 if (s_info.fd < 0) {
1278 DbgPrint("Failed to open a drm device: (%s)\n", strerror(errno));
1279 s_info.evt_base = 0;
1280 s_info.err_base = 0;
1284 drmGetMagic(s_info.fd, &magic);
1285 DbgPrint("DRM Magic: 0x%X\n", magic);
1286 if (!DRI2Authenticate(ecore_x_display_get(), DefaultRootWindow(ecore_x_display_get()), (unsigned int)magic)) {
1287 DbgPrint("Failed to do authenticate for DRI2\n");
1290 s_info.evt_base = 0;
1291 s_info.err_base = 0;
1295 s_info.slp_bufmgr = drm_slp_bufmgr_init(s_info.fd, NULL);
1296 if (!s_info.slp_bufmgr) {
1297 DbgPrint("Failed to init bufmgr\n");
1300 s_info.evt_base = 0;
1301 s_info.err_base = 0;
1308 HAPI int buffer_handler_fini(void)
1310 if (s_info.fd >= 0) {
1315 if (s_info.slp_bufmgr) {
1316 drm_slp_bufmgr_destroy(s_info.slp_bufmgr);
1317 s_info.slp_bufmgr = NULL;