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 */
54 struct buffer { /*!< Must has to be sync with slave & provider */
57 DESTROYED = 0x00dead00
59 enum buffer_type type;
77 int fb_init(void *disp)
83 screen = DefaultScreenOfDisplay(s_info.disp);
85 s_info.screen = DefaultScreen(s_info.disp);
86 s_info.visual = DefaultVisualOfScreen(screen);
94 if (s_info.disp_is_opened && s_info.disp) {
95 XCloseDisplay(s_info.disp);
99 s_info.disp_is_opened = 0;
100 s_info.visual = NULL;
105 static inline void update_fb_size(struct fb_info *info)
107 info->bufsz = info->w * info->h * info->pixels;
110 static inline int sync_for_file(struct fb_info *info)
113 struct buffer *buffer;
115 buffer = info->buffer;
117 if (!buffer) { /* Ignore this sync request */
118 return LB_STATUS_SUCCESS;
121 if (buffer->state != CREATED) {
122 ErrPrint("Invalid state of a FB\n");
123 return LB_STATUS_ERROR_INVALID;
126 if (buffer->type != BUFFER_TYPE_FILE) {
127 ErrPrint("Invalid buffer\n");
128 return LB_STATUS_SUCCESS;
131 fd = open(util_uri_to_path(info->id), O_RDONLY);
133 ErrPrint("Failed to open a file (%s) because of (%s)\n",
134 util_uri_to_path(info->id), strerror(errno));
138 * But return ZERO, even if we couldn't get a buffer file,
139 * the viewer can draw empty screen.
141 * and then update it after it gots update events
143 return LB_STATUS_SUCCESS;
146 if (read(fd, buffer->data, info->bufsz) != info->bufsz) {
147 ErrPrint("read: %s\n", strerror(errno));
149 ErrPrint("close: %s\n", strerror(errno));
154 * But return ZERO, even if we couldn't get a buffer file,
155 * the viewer can draw empty screen.
157 * and then update it after it gots update events
159 return LB_STATUS_SUCCESS;
163 ErrPrint("close: %s\n", strerror(errno));
165 return LB_STATUS_SUCCESS;
168 static inline __attribute__((always_inline)) int sync_for_pixmap(struct fb_info *info)
170 struct buffer *buffer;
174 buffer = info->buffer;
175 if (!buffer) { /*!< Ignore this sync request */
176 return LB_STATUS_SUCCESS;
179 if (buffer->state != CREATED) {
180 ErrPrint("Invalid state of a FB\n");
181 return LB_STATUS_ERROR_INVALID;
184 if (buffer->type != BUFFER_TYPE_PIXMAP) {
185 ErrPrint("Invalid buffer\n");
186 return LB_STATUS_SUCCESS;
190 s_info.disp = XOpenDisplay(NULL);
194 s_info.disp_is_opened = 1;
196 screen = DefaultScreenOfDisplay(s_info.disp);
198 s_info.screen = DefaultScreen(s_info.disp);
199 s_info.visual = DefaultVisualOfScreen(screen);
201 ErrPrint("Failed to open a display\n");
202 return LB_STATUS_ERROR_FAULT;
206 if (info->handle == 0) {
207 ErrPrint("Pixmap ID is not valid\n");
208 return LB_STATUS_ERROR_INVALID;
211 if (info->bufsz == 0) {
213 * If the client does not acquire the buffer,
214 * This function will do nothing.
215 * It will work only if the buffer is acquired.
216 * To sync its contents.
218 DbgPrint("Nothing can be sync\n");
219 return LB_STATUS_SUCCESS;
222 si.shmid = shmget(IPC_PRIVATE, info->bufsz, IPC_CREAT | 0666);
224 ErrPrint("shmget: %s\n", strerror(errno));
225 return LB_STATUS_ERROR_FAULT;
229 si.shmaddr = shmat(si.shmid, NULL, 0);
230 if (si.shmaddr == (void *)-1) {
231 if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
232 ErrPrint("shmctl: %s\n", strerror(errno));
235 return LB_STATUS_ERROR_FAULT;
240 * Use the 24 bits Pixmap for Video player
242 xim = XShmCreateImage(s_info.disp, s_info.visual,
243 (info->pixels << 3), ZPixmap, NULL,
247 if (shmdt(si.shmaddr) < 0) {
248 ErrPrint("shmdt: %s\n", strerror(errno));
251 if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
252 ErrPrint("shmctl: %s\n", strerror(errno));
255 return LB_STATUS_ERROR_FAULT;
258 xim->data = si.shmaddr;
259 XShmAttach(s_info.disp, &si);
261 XShmGetImage(s_info.disp, info->handle, xim, 0, 0, 0xFFFFFFFF);
262 XSync(s_info.disp, False);
264 memcpy(buffer->data, xim->data, info->bufsz);
266 XShmDetach(s_info.disp, &si);
269 if (shmdt(si.shmaddr) < 0) {
270 ErrPrint("shmdt: %s\n", strerror(errno));
273 if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
274 ErrPrint("shmctl: %s\n", strerror(errno));
277 return LB_STATUS_SUCCESS;
280 int fb_sync(struct fb_info *info)
283 ErrPrint("FB Handle is not valid\n");
284 return LB_STATUS_ERROR_INVALID;
287 if (!info->id || info->id[0] == '\0') {
288 DbgPrint("Ingore sync\n");
289 return LB_STATUS_SUCCESS;
292 if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
293 return sync_for_file(info);
294 } else if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
295 return sync_for_pixmap(info);
296 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
297 /* No need to do sync */
298 return LB_STATUS_SUCCESS;
301 return LB_STATUS_ERROR_INVALID;
304 struct fb_info *fb_create(const char *id, int w, int h)
306 struct fb_info *info;
308 if (!id || id[0] == '\0') {
309 ErrPrint("Invalid ID\n");
313 info = calloc(1, sizeof(*info));
315 ErrPrint("Heap: %s\n", strerror(errno));
319 info->id = strdup(id);
321 ErrPrint("Heap: %s\n", strerror(errno));
326 info->pixels = sizeof(int); /* Use the default pixels(depth) */
328 if (sscanf(info->id, SCHEMA_SHM "%d", &info->handle) == 1) {
329 DbgPrint("SHMID: %d is gotten\n", info->handle);
330 } else if (sscanf(info->id, SCHEMA_PIXMAP "%d:%d", &info->handle, &info->pixels) == 2) {
331 DbgPrint("PIXMAP-SHMID: %d is gotten (%d)\n", info->handle, info->pixels);
333 info->handle = LB_STATUS_ERROR_INVALID;
344 int fb_destroy(struct fb_info *info)
347 ErrPrint("Handle is not valid\n");
348 return LB_STATUS_ERROR_INVALID;
352 struct buffer *buffer;
353 buffer = info->buffer;
360 return LB_STATUS_SUCCESS;
363 int fb_is_created(struct fb_info *info)
366 ErrPrint("Handle is not valid\n");
370 if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && info->handle != 0) {
372 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM)) && info->handle > 0) {
376 path = util_uri_to_path(info->id);
377 if (path && access(path, F_OK | R_OK) == 0) {
380 ErrPrint("access: %s (%s)\n", strerror(errno), path);
387 void *fb_acquire_buffer(struct fb_info *info)
389 struct buffer *buffer;
392 ErrPrint("info == NIL\n");
397 if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
398 update_fb_size(info);
400 buffer = calloc(1, sizeof(*buffer) + info->bufsz);
402 ErrPrint("Heap: %s\n", strerror(errno));
407 buffer->type = BUFFER_TYPE_PIXMAP;
409 buffer->state = CREATED;
411 info->buffer = buffer;
415 * Just update from here.
417 sync_for_pixmap(info);
418 } else if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
419 update_fb_size(info);
421 buffer = calloc(1, sizeof(*buffer) + info->bufsz);
423 ErrPrint("Heap: %s\n", strerror(errno));
428 buffer->type = BUFFER_TYPE_FILE;
430 buffer->state = CREATED;
432 info->buffer = buffer;
435 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
436 buffer = shmat(info->handle, NULL, 0);
437 if (buffer == (void *)-1) {
438 ErrPrint("shmat: %s (%d)\n", strerror(errno), info->handle);
444 ErrPrint("Buffer is not created (%s)\n", info->id);
449 buffer = info->buffer;
451 switch (buffer->type) {
452 case BUFFER_TYPE_PIXMAP:
455 case BUFFER_TYPE_FILE:
459 DbgPrint("Unknwon FP: %d\n", buffer->type);
466 int fb_release_buffer(void *data)
468 struct buffer *buffer;
471 ErrPrint("buffer data == NIL\n");
472 return LB_STATUS_ERROR_INVALID;
475 buffer = container_of(data, struct buffer, data);
477 if (buffer->state != CREATED) {
478 ErrPrint("Invalid handle\n");
479 return LB_STATUS_ERROR_INVALID;
482 switch (buffer->type) {
483 case BUFFER_TYPE_SHM:
484 if (shmdt(buffer) < 0) {
485 ErrPrint("shmdt: %s\n", strerror(errno));
488 case BUFFER_TYPE_PIXMAP:
490 if (buffer->refcnt == 0) {
491 struct fb_info *info;
494 buffer->state = DESTROYED;
497 if (info && info->buffer == buffer) {
502 case BUFFER_TYPE_FILE:
504 if (buffer->refcnt == 0) {
505 struct fb_info *info;
508 buffer->state = DESTROYED;
511 if (info && info->buffer == buffer) {
517 ErrPrint("Unknwon buffer type\n");
521 return LB_STATUS_SUCCESS;
524 int fb_refcnt(void *data)
526 struct buffer *buffer;
531 return LB_STATUS_ERROR_INVALID;
534 buffer = container_of(data, struct buffer, data);
536 if (buffer->state != CREATED) {
537 ErrPrint("Invalid handle\n");
538 return LB_STATUS_ERROR_INVALID;
541 switch (buffer->type) {
542 case BUFFER_TYPE_SHM:
543 if (shmctl(buffer->refcnt, IPC_STAT, &buf) < 0) {
544 ErrPrint("Error: %s\n", strerror(errno));
545 return LB_STATUS_ERROR_FAULT;
548 ret = buf.shm_nattch;
550 case BUFFER_TYPE_PIXMAP:
551 ret = buffer->refcnt;
553 case BUFFER_TYPE_FILE:
554 ret = buffer->refcnt;
557 ret = LB_STATUS_ERROR_INVALID;
564 const char *fb_id(struct fb_info *info)
566 return info ? info->id : NULL;
569 int fb_get_size(struct fb_info *info, int *w, int *h)
572 ErrPrint("Handle is not valid\n");
573 return LB_STATUS_ERROR_INVALID;
578 return LB_STATUS_SUCCESS;
581 int fb_size(struct fb_info *info)
587 update_fb_size(info);
592 int fb_type(struct fb_info *info)
594 struct buffer *buffer;
597 return BUFFER_TYPE_ERROR;
600 buffer = info->buffer;
602 int type = BUFFER_TYPE_ERROR;
605 * Try to get this from SCHEMA
608 if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
609 type = BUFFER_TYPE_FILE;
610 } else if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
611 type = BUFFER_TYPE_PIXMAP;
612 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
613 type = BUFFER_TYPE_SHM;