2 * Copyright 2013 Samsung Electronics Co., Ltd
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
8 * http://floralicense.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.
24 #include <sys/types.h>
31 #include <X11/extensions/XShm.h>
32 #include <X11/Xutil.h>
35 #include <livebox-errno.h> /* For error code */
53 struct buffer { /*!< Must has to be sync with slave & provider */
56 DESTROYED = 0x00dead00
58 enum buffer_type type;
78 int fb_init(void *disp)
84 screen = DefaultScreenOfDisplay(s_info.disp);
86 s_info.screen = DefaultScreen(s_info.disp);
87 s_info.visual = DefaultVisualOfScreen(screen);
90 s_info.depth = sizeof(int); //DefaultDepthOfScreen(screen);
96 if (s_info.disp_is_opened && s_info.disp) {
97 XCloseDisplay(s_info.disp);
101 s_info.disp_is_opened = 0;
102 s_info.visual = NULL;
108 static inline void update_fb_size(struct fb_info *info)
110 info->bufsz = info->w * info->h * s_info.depth;
113 static inline int sync_for_file(struct fb_info *info)
116 struct buffer *buffer;
118 buffer = info->buffer;
120 if (!buffer) { /* Ignore this sync request */
121 return LB_STATUS_SUCCESS;
124 if (buffer->state != CREATED) {
125 ErrPrint("Invalid state of a FB\n");
126 return LB_STATUS_ERROR_INVALID;
129 if (buffer->type != BUFFER_TYPE_FILE) {
130 ErrPrint("Invalid buffer\n");
131 return LB_STATUS_SUCCESS;
134 fd = open(util_uri_to_path(info->id), O_RDONLY);
136 ErrPrint("Failed to open a file (%s) because of (%s)\n",
137 util_uri_to_path(info->id), strerror(errno));
141 * But return ZERO, even if we couldn't get a buffer file,
142 * the viewer can draw empty screen.
144 * and then update it after it gots update events
146 return LB_STATUS_SUCCESS;
149 if (read(fd, buffer->data, info->bufsz) != info->bufsz) {
150 ErrPrint("read: %s\n", strerror(errno));
152 ErrPrint("close: %s\n", strerror(errno));
157 * But return ZERO, even if we couldn't get a buffer file,
158 * the viewer can draw empty screen.
160 * and then update it after it gots update events
162 return LB_STATUS_SUCCESS;
166 ErrPrint("close: %s\n", strerror(errno));
168 return LB_STATUS_SUCCESS;
171 static inline __attribute__((always_inline)) int sync_for_pixmap(struct fb_info *info)
173 struct buffer *buffer;
177 buffer = info->buffer;
178 if (!buffer) { /*!< Ignore this sync request */
179 return LB_STATUS_SUCCESS;
182 if (buffer->state != CREATED) {
183 ErrPrint("Invalid state of a FB\n");
184 return LB_STATUS_ERROR_INVALID;
187 if (buffer->type != BUFFER_TYPE_PIXMAP) {
188 ErrPrint("Invalid buffer\n");
189 return LB_STATUS_SUCCESS;
193 s_info.disp = XOpenDisplay(NULL);
197 s_info.disp_is_opened = 1;
199 screen = DefaultScreenOfDisplay(s_info.disp);
201 s_info.screen = DefaultScreen(s_info.disp);
202 s_info.visual = DefaultVisualOfScreen(screen);
204 ErrPrint("Failed to open a display\n");
205 return LB_STATUS_ERROR_FAULT;
209 if (info->handle == 0) {
210 ErrPrint("Pixmap ID is not valid\n");
211 return LB_STATUS_ERROR_INVALID;
214 if (info->bufsz == 0) {
216 * If the client does not acquire the buffer,
217 * This function will do nothing.
218 * It will work only if the buffer is acquired.
219 * To sync its contents.
221 DbgPrint("Nothing can be sync\n");
222 return LB_STATUS_SUCCESS;
225 si.shmid = shmget(IPC_PRIVATE, info->bufsz, IPC_CREAT | 0666);
227 ErrPrint("shmget: %s\n", strerror(errno));
228 return LB_STATUS_ERROR_FAULT;
232 si.shmaddr = shmat(si.shmid, NULL, 0);
233 if (si.shmaddr == (void *)-1) {
234 if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
235 ErrPrint("shmctl: %s\n", strerror(errno));
238 return LB_STATUS_ERROR_FAULT;
243 * Use the 24 bits Pixmap for Video player
245 xim = XShmCreateImage(s_info.disp, s_info.visual,
246 (s_info.depth << 3), ZPixmap, NULL,
250 if (shmdt(si.shmaddr) < 0) {
251 ErrPrint("shmdt: %s\n", strerror(errno));
254 if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
255 ErrPrint("shmctl: %s\n", strerror(errno));
258 return LB_STATUS_ERROR_FAULT;
261 xim->data = si.shmaddr;
262 XShmAttach(s_info.disp, &si);
264 XShmGetImage(s_info.disp, info->handle, xim, 0, 0, 0xFFFFFFFF);
265 XSync(s_info.disp, False);
267 memcpy(buffer->data, xim->data, info->bufsz);
269 XShmDetach(s_info.disp, &si);
272 if (shmdt(si.shmaddr) < 0) {
273 ErrPrint("shmdt: %s\n", strerror(errno));
276 if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
277 ErrPrint("shmctl: %s\n", strerror(errno));
280 return LB_STATUS_SUCCESS;
283 int fb_sync(struct fb_info *info)
286 ErrPrint("FB Handle is not valid\n");
287 return LB_STATUS_ERROR_INVALID;
290 if (!info->id || info->id[0] == '\0') {
291 DbgPrint("Ingore sync\n");
292 return LB_STATUS_SUCCESS;
295 if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
296 return sync_for_file(info);
297 } else if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
298 return sync_for_pixmap(info);
299 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
300 /* No need to do sync */
301 return LB_STATUS_SUCCESS;
304 return LB_STATUS_ERROR_INVALID;
307 struct fb_info *fb_create(const char *id, int w, int h)
309 struct fb_info *info;
311 if (!id || id[0] == '\0') {
312 ErrPrint("Invalid ID\n");
316 info = calloc(1, sizeof(*info));
318 ErrPrint("Heap: %s\n", strerror(errno));
322 info->id = strdup(id);
324 ErrPrint("Heap: %s\n", strerror(errno));
329 if (sscanf(info->id, SCHEMA_SHM "%d", &info->handle) == 1) {
330 DbgPrint("SHMID: %d is gotten\n", info->handle);
331 } else if (sscanf(info->id, SCHEMA_PIXMAP "%d", &info->handle) == 1) {
332 DbgPrint("PIXMAP-SHMID: %d is gotten\n", info->handle);
334 info->handle = LB_STATUS_ERROR_INVALID;
345 int fb_destroy(struct fb_info *info)
348 ErrPrint("Handle is not valid\n");
349 return LB_STATUS_ERROR_INVALID;
353 struct buffer *buffer;
354 buffer = info->buffer;
361 return LB_STATUS_SUCCESS;
364 int fb_is_created(struct fb_info *info)
367 ErrPrint("Handle is not valid\n");
371 if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && info->handle != 0) {
373 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM)) && info->handle > 0) {
377 path = util_uri_to_path(info->id);
378 if (path && access(path, F_OK | R_OK) == 0) {
381 ErrPrint("access: %s (%s)\n", strerror(errno), path);
388 void *fb_acquire_buffer(struct fb_info *info)
390 struct buffer *buffer;
393 ErrPrint("info == NIL\n");
398 if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
399 update_fb_size(info);
401 buffer = calloc(1, sizeof(*buffer) + info->bufsz);
403 ErrPrint("Heap: %s\n", strerror(errno));
408 buffer->type = BUFFER_TYPE_PIXMAP;
410 buffer->state = CREATED;
412 info->buffer = buffer;
416 * Just update from here.
418 sync_for_pixmap(info);
419 } else if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
420 update_fb_size(info);
422 buffer = calloc(1, sizeof(*buffer) + info->bufsz);
424 ErrPrint("Heap: %s\n", strerror(errno));
429 buffer->type = BUFFER_TYPE_FILE;
431 buffer->state = CREATED;
433 info->buffer = buffer;
436 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
437 buffer = shmat(info->handle, NULL, 0);
438 if (buffer == (void *)-1) {
439 ErrPrint("shmat: %s\n", strerror(errno));
445 ErrPrint("Buffer is not created (%s)\n", info->id);
450 buffer = info->buffer;
452 switch (buffer->type) {
453 case BUFFER_TYPE_PIXMAP:
456 case BUFFER_TYPE_FILE:
460 DbgPrint("Unknwon FP: %d\n", buffer->type);
467 int fb_release_buffer(void *data)
469 struct buffer *buffer;
472 ErrPrint("buffer data == NIL\n");
473 return LB_STATUS_ERROR_INVALID;
476 buffer = container_of(data, struct buffer, data);
478 if (buffer->state != CREATED) {
479 ErrPrint("Invalid handle\n");
480 return LB_STATUS_ERROR_INVALID;
483 switch (buffer->type) {
484 case BUFFER_TYPE_SHM:
485 if (shmdt(buffer) < 0) {
486 ErrPrint("shmdt: %s\n", strerror(errno));
489 case BUFFER_TYPE_PIXMAP:
491 if (buffer->refcnt == 0) {
492 struct fb_info *info;
495 buffer->state = DESTROYED;
498 if (info && info->buffer == buffer) {
503 case BUFFER_TYPE_FILE:
505 if (buffer->refcnt == 0) {
506 struct fb_info *info;
509 buffer->state = DESTROYED;
512 if (info && info->buffer == buffer) {
518 ErrPrint("Unknwon buffer type\n");
522 return LB_STATUS_SUCCESS;
525 int fb_refcnt(void *data)
527 struct buffer *buffer;
532 return LB_STATUS_ERROR_INVALID;
535 buffer = container_of(data, struct buffer, data);
537 if (buffer->state != CREATED) {
538 ErrPrint("Invalid handle\n");
539 return LB_STATUS_ERROR_INVALID;
542 switch (buffer->type) {
543 case BUFFER_TYPE_SHM:
544 if (shmctl(buffer->refcnt, IPC_STAT, &buf) < 0) {
545 ErrPrint("Error: %s\n", strerror(errno));
546 return LB_STATUS_ERROR_FAULT;
549 ret = buf.shm_nattch;
551 case BUFFER_TYPE_PIXMAP:
552 ret = buffer->refcnt;
554 case BUFFER_TYPE_FILE:
555 ret = buffer->refcnt;
558 ret = LB_STATUS_ERROR_INVALID;
565 const char *fb_id(struct fb_info *info)
567 return info ? info->id : NULL;
570 int fb_get_size(struct fb_info *info, int *w, int *h)
573 ErrPrint("Handle is not valid\n");
574 return LB_STATUS_ERROR_INVALID;
579 return LB_STATUS_SUCCESS;
582 int fb_size(struct fb_info *info)
588 update_fb_size(info);
593 int fb_type(struct fb_info *info)
595 struct buffer *buffer;
598 return BUFFER_TYPE_ERROR;
601 buffer = info->buffer;
603 int type = BUFFER_TYPE_ERROR;
606 * Try to get this from SCHEMA
609 if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
610 type = BUFFER_TYPE_FILE;
611 } else if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
612 type = BUFFER_TYPE_PIXMAP;
613 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
614 type = BUFFER_TYPE_SHM;