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 */
40 #include "critical_log.h"
54 struct buffer { /*!< Must has to be sync with slave & provider */
57 DESTROYED = 0x00dead00
59 enum buffer_type type;
79 int fb_init(void *disp)
85 screen = DefaultScreenOfDisplay(s_info.disp);
87 s_info.screen = DefaultScreen(s_info.disp);
88 s_info.visual = DefaultVisualOfScreen(screen);
91 s_info.depth = sizeof(int); //DefaultDepthOfScreen(screen);
97 if (s_info.disp_is_opened && s_info.disp) {
98 XCloseDisplay(s_info.disp);
102 s_info.disp_is_opened = 0;
103 s_info.visual = NULL;
109 static inline int sync_for_file(struct fb_info *info)
112 struct buffer *buffer;
114 buffer = info->buffer;
116 if (!buffer) /* Ignore this sync request */
117 return LB_STATUS_SUCCESS;
119 if (buffer->state != CREATED) {
120 ErrPrint("Invalid state of a FB\n");
121 return LB_STATUS_ERROR_INVALID;
124 if (buffer->type != BUFFER_TYPE_FILE) {
125 ErrPrint("Invalid buffer\n");
126 return LB_STATUS_SUCCESS;
129 fd = open(util_uri_to_path(info->id), O_RDONLY);
131 ErrPrint("Failed to open a file (%s) because of (%s)\n",
132 util_uri_to_path(info->id), strerror(errno));
136 * But return ZERO, even if we couldn't get a buffer file,
137 * the viewer can draw empty screen.
139 * and then update it after it gots update events
141 return LB_STATUS_SUCCESS;
144 if (read(fd, buffer->data, info->bufsz) != info->bufsz) {
145 ErrPrint("read: %s\n", strerror(errno));
150 * But return ZERO, even if we couldn't get a buffer file,
151 * the viewer can draw empty screen.
153 * and then update it after it gots update events
155 return LB_STATUS_SUCCESS;
159 return LB_STATUS_SUCCESS;
162 static inline __attribute__((always_inline)) int sync_for_pixmap(struct fb_info *info)
164 struct buffer *buffer;
168 buffer = info->buffer;
169 if (!buffer) /*!< Ignore this sync request */
170 return LB_STATUS_SUCCESS;
172 if (buffer->state != CREATED) {
173 ErrPrint("Invalid state of a FB\n");
174 return LB_STATUS_ERROR_INVALID;
177 if (buffer->type != BUFFER_TYPE_PIXMAP) {
178 ErrPrint("Invalid buffer\n");
179 return LB_STATUS_SUCCESS;
183 s_info.disp = XOpenDisplay(NULL);
187 s_info.disp_is_opened = 1;
189 screen = DefaultScreenOfDisplay(s_info.disp);
191 s_info.screen = DefaultScreen(s_info.disp);
192 s_info.visual = DefaultVisualOfScreen(screen);
194 ErrPrint("Failed to open a display\n");
195 return LB_STATUS_ERROR_FAULT;
199 if (info->handle == 0) {
200 ErrPrint("Pixmap ID is not valid\n");
201 return LB_STATUS_ERROR_INVALID;
204 if (info->bufsz == 0) {
205 DbgPrint("Nothing can be sync\n");
206 return LB_STATUS_SUCCESS;
209 si.shmid = shmget(IPC_PRIVATE, info->bufsz, IPC_CREAT | 0666);
211 ErrPrint("shmget: %s\n", strerror(errno));
212 return LB_STATUS_ERROR_FAULT;
216 si.shmaddr = shmat(si.shmid, NULL, 0);
217 if (si.shmaddr == (void *)-1) {
219 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
220 ErrPrint("shmctl: %s\n", strerror(errno));
222 return LB_STATUS_ERROR_FAULT;
227 * Use the 24 bits Pixmap for Video player
229 xim = XShmCreateImage(s_info.disp, s_info.visual,
230 (s_info.depth << 3), ZPixmap, NULL,
234 if (shmdt(si.shmaddr) < 0)
235 ErrPrint("shmdt: %s\n", strerror(errno));
237 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
238 ErrPrint("shmctl: %s\n", strerror(errno));
240 return LB_STATUS_ERROR_FAULT;
243 xim->data = si.shmaddr;
244 XShmAttach(s_info.disp, &si);
246 XShmGetImage(s_info.disp, info->handle, xim, 0, 0, 0xFFFFFFFF);
247 XSync(s_info.disp, False);
249 memcpy(buffer->data, xim->data, info->bufsz);
251 XShmDetach(s_info.disp, &si);
254 if (shmdt(si.shmaddr) < 0)
255 ErrPrint("shmdt: %s\n", strerror(errno));
257 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
258 ErrPrint("shmctl: %s\n", strerror(errno));
260 return LB_STATUS_SUCCESS;
263 int fb_sync(struct fb_info *info)
266 ErrPrint("FB Handle is not valid\n");
267 return LB_STATUS_ERROR_INVALID;
270 if (!info->id || info->id[0] == '\0') {
271 DbgPrint("Ingore sync\n");
272 return LB_STATUS_SUCCESS;
275 if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
276 return sync_for_file(info);
277 } else if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
278 return sync_for_pixmap(info);
279 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
280 /* No need to do sync */
281 return LB_STATUS_SUCCESS;
284 return LB_STATUS_ERROR_INVALID;
287 struct fb_info *fb_create(const char *id, int w, int h)
289 struct fb_info *info;
291 if (!id || id[0] == '\0') {
292 ErrPrint("Invalid ID\n");
296 info = calloc(1, sizeof(*info));
298 CRITICAL_LOG("Heap: %s\n", strerror(errno));
302 info->id = strdup(id);
304 CRITICAL_LOG("Heap: %s\n", strerror(errno));
309 if (sscanf(info->id, SCHEMA_SHM "%d", &info->handle) == 1) {
310 DbgPrint("SHMID: %d is gotten\n", info->handle);
311 } else if (sscanf(info->id, SCHEMA_PIXMAP "%d", &info->handle) == 1) {
312 DbgPrint("PIXMAP-SHMID: %d is gotten\n", info->handle);
314 info->handle = LB_STATUS_ERROR_INVALID;
325 int fb_destroy(struct fb_info *info)
328 ErrPrint("Handle is not valid\n");
329 return LB_STATUS_ERROR_INVALID;
333 struct buffer *buffer;
334 buffer = info->buffer;
341 return LB_STATUS_SUCCESS;
344 int fb_is_created(struct fb_info *info)
347 ErrPrint("Handle is not valid\n");
351 if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && info->handle != 0) {
353 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM)) && info->handle > 0) {
357 path = util_uri_to_path(info->id);
358 if (path && access(path, F_OK | R_OK) == 0) {
361 ErrPrint("access: %s (%s)\n", strerror(errno), path);
368 void *fb_acquire_buffer(struct fb_info *info)
370 struct buffer *buffer;
373 ErrPrint("info == NIL\n");
378 if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
379 info->bufsz = info->w * info->h * s_info.depth;
380 buffer = calloc(1, sizeof(*buffer) + info->bufsz);
382 CRITICAL_LOG("Heap: %s\n", strerror(errno));
387 buffer->type = BUFFER_TYPE_PIXMAP;
389 buffer->state = CREATED;
391 info->buffer = buffer;
395 * Just update from here.
397 sync_for_pixmap(info);
398 } else if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
399 info->bufsz = info->w * info->h * s_info.depth;
400 buffer = calloc(1, sizeof(*buffer) + info->bufsz);
402 CRITICAL_LOG("Heap: %s\n", strerror(errno));
407 buffer->type = BUFFER_TYPE_FILE;
409 buffer->state = CREATED;
411 info->buffer = buffer;
414 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
415 buffer = shmat(info->handle, NULL, 0);
416 if (buffer == (void *)-1) {
417 ErrPrint("shmat: %s\n", strerror(errno));
423 ErrPrint("Buffer is not created (%s)\n", info->id);
428 buffer = info->buffer;
430 switch (buffer->type) {
431 case BUFFER_TYPE_PIXMAP:
434 case BUFFER_TYPE_FILE:
438 DbgPrint("Unknwon FP: %d\n", buffer->type);
445 int fb_release_buffer(void *data)
447 struct buffer *buffer;
450 ErrPrint("buffer data == NIL\n");
454 buffer = container_of(data, struct buffer, data);
456 if (buffer->state != CREATED) {
457 ErrPrint("Invalid handle\n");
458 return LB_STATUS_ERROR_INVALID;
461 switch (buffer->type) {
462 case BUFFER_TYPE_SHM:
463 if (shmdt(buffer) < 0)
464 ErrPrint("shmdt: %s\n", strerror(errno));
466 case BUFFER_TYPE_PIXMAP:
468 if (buffer->refcnt == 0) {
469 struct fb_info *info;
472 buffer->state = DESTROYED;
475 if (info && info->buffer == buffer)
479 case BUFFER_TYPE_FILE:
481 if (buffer->refcnt == 0) {
482 struct fb_info *info;
485 buffer->state = DESTROYED;
488 if (info && info->buffer == buffer)
493 ErrPrint("Unknwon buffer type\n");
500 int fb_refcnt(void *data)
502 struct buffer *buffer;
507 return LB_STATUS_ERROR_INVALID;
509 buffer = container_of(data, struct buffer, data);
511 if (buffer->state != CREATED) {
512 ErrPrint("Invalid handle\n");
513 return LB_STATUS_ERROR_INVALID;
516 switch (buffer->type) {
517 case BUFFER_TYPE_SHM:
518 if (shmctl(buffer->refcnt, IPC_STAT, &buf) < 0) {
519 ErrPrint("Error: %s\n", strerror(errno));
520 return LB_STATUS_ERROR_FAULT;
523 ret = buf.shm_nattch;
525 case BUFFER_TYPE_PIXMAP:
526 ret = buffer->refcnt;
528 case BUFFER_TYPE_FILE:
529 ret = buffer->refcnt;
532 ret = LB_STATUS_ERROR_INVALID;
539 const char *fb_id(struct fb_info *info)
541 return info ? info->id : NULL;
544 int fb_get_size(struct fb_info *info, int *w, int *h)
547 ErrPrint("Handle is not valid\n");
548 return LB_STATUS_ERROR_INVALID;
553 return LB_STATUS_SUCCESS;
556 int fb_size(struct fb_info *info)
561 info->bufsz = info->w * info->h * s_info.depth;