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.
24 #include <sys/types.h>
31 #include <X11/extensions/XShm.h>
32 #include <X11/Xutil.h>
39 #include "critical_log.h"
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 int sync_for_file(struct fb_info *info)
111 struct buffer *buffer;
113 buffer = info->buffer;
115 if (!buffer) /* Ignore this sync request */
118 if (buffer->state != CREATED) {
119 ErrPrint("Invalid state of a FB\n");
123 if (buffer->type != BUFFER_TYPE_FILE) {
124 DbgPrint("Invalid buffer\n");
128 fd = open(util_uri_to_path(info->id), O_RDONLY);
130 ErrPrint("Failed to open a file (%s) because of (%s)\n",
131 util_uri_to_path(info->id), strerror(errno));
135 * But return ZERO, even if we couldn't get a buffer file,
136 * the viewer can draw empty screen.
138 * and then update it after it gots update events
143 if (read(fd, buffer->data, info->bufsz) != info->bufsz) {
144 ErrPrint("read: %s\n", strerror(errno));
149 * But return ZERO, even if we couldn't get a buffer file,
150 * the viewer can draw empty screen.
152 * and then update it after it gots update events
161 static inline __attribute__((always_inline)) int sync_for_pixmap(struct fb_info *info)
163 struct buffer *buffer;
167 buffer = info->buffer;
168 if (!buffer) /*!< Ignore this sync request */
171 if (buffer->state != CREATED) {
172 ErrPrint("Invalid state of a FB\n");
176 if (buffer->type != BUFFER_TYPE_PIXMAP) {
177 DbgPrint("Invalid buffer\n");
182 s_info.disp = XOpenDisplay(NULL);
186 s_info.disp_is_opened = 1;
188 screen = DefaultScreenOfDisplay(s_info.disp);
190 s_info.screen = DefaultScreen(s_info.disp);
191 s_info.visual = DefaultVisualOfScreen(screen);
193 ErrPrint("Failed to open a display\n");
198 if (info->handle == 0) {
199 DbgPrint("Pixmap ID is not valid\n");
203 if (info->bufsz == 0) {
204 DbgPrint("Nothing can be sync\n");
208 si.shmid = shmget(IPC_PRIVATE, info->bufsz, IPC_CREAT | 0666);
210 ErrPrint("shmget: %s\n", strerror(errno));
215 si.shmaddr = shmat(si.shmid, NULL, 0);
216 if (si.shmaddr == (void *)-1) {
218 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
219 ErrPrint("shmctl: %s\n", strerror(errno));
226 * Use the 24 bits Pixmap for Video player
228 xim = XShmCreateImage(s_info.disp, s_info.visual,
229 24 /* (s_info.depth << 3) */, ZPixmap, NULL,
233 if (shmdt(si.shmaddr) < 0)
234 ErrPrint("shmdt: %s\n", strerror(errno));
236 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
237 ErrPrint("shmctl: %s\n", strerror(errno));
242 xim->data = si.shmaddr;
243 XShmAttach(s_info.disp, &si);
245 XShmGetImage(s_info.disp, info->handle, xim, 0, 0, 0xFFFFFFFF);
246 XSync(s_info.disp, False);
248 memcpy(buffer->data, xim->data, info->bufsz);
250 XShmDetach(s_info.disp, &si);
253 if (shmdt(si.shmaddr) < 0)
254 ErrPrint("shmdt: %s\n", strerror(errno));
256 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
257 ErrPrint("shmctl: %s\n", strerror(errno));
262 int fb_sync(struct fb_info *info)
265 ErrPrint("FB Handle is not valid\n");
269 if (!info->id || info->id[0] == '\0') {
270 DbgPrint("Ingore sync\n");
274 if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
275 return sync_for_file(info);
276 } else if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
277 return sync_for_pixmap(info);
278 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
279 /* No need to do sync */
286 struct fb_info *fb_create(const char *id, int w, int h)
288 struct fb_info *info;
290 if (!id || id[0] == '\0') {
291 ErrPrint("Invalid ID\n");
295 info = calloc(1, sizeof(*info));
297 CRITICAL_LOG("Heap: %s\n", strerror(errno));
301 info->id = strdup(id);
303 CRITICAL_LOG("Heap: %s\n", strerror(errno));
308 if (sscanf(info->id, SCHEMA_SHM "%d", &info->handle) == 1) {
309 DbgPrint("SHMID: %d is gotten\n", info->handle);
310 } else if (sscanf(info->id, SCHEMA_PIXMAP "%d", &info->handle) == 1) {
311 DbgPrint("PIXMAP-SHMID: %d is gotten\n", info->handle);
313 info->handle = -EINVAL;
324 int fb_destroy(struct fb_info *info)
327 ErrPrint("Handle is not valid\n");
332 struct buffer *buffer;
333 buffer = info->buffer;
343 int fb_is_created(struct fb_info *info)
346 ErrPrint("Handle is not valid\n");
350 if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && info->handle != 0) {
352 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM)) && info->handle > 0) {
356 path = util_uri_to_path(info->id);
357 if (path && access(path, F_OK | R_OK) == 0) {
360 ErrPrint("access: %s (%s)\n", strerror(errno), path);
367 void *fb_acquire_buffer(struct fb_info *info)
369 struct buffer *buffer;
372 ErrPrint("info == NIL\n");
377 if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
378 info->bufsz = info->w * info->h * s_info.depth;
379 buffer = calloc(1, sizeof(*buffer) + info->bufsz);
381 CRITICAL_LOG("Heap: %s\n", strerror(errno));
386 buffer->type = BUFFER_TYPE_PIXMAP;
388 buffer->state = CREATED;
390 info->buffer = buffer;
394 * Just update from here.
396 sync_for_pixmap(info);
397 } else if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
398 info->bufsz = info->w * info->h * s_info.depth;
399 buffer = calloc(1, sizeof(*buffer) + info->bufsz);
401 CRITICAL_LOG("Heap: %s\n", strerror(errno));
406 buffer->type = BUFFER_TYPE_FILE;
408 buffer->state = CREATED;
410 info->buffer = buffer;
413 } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
414 buffer = shmat(info->handle, NULL, 0);
415 if (buffer == (void *)-1) {
416 ErrPrint("shmat: %s\n", strerror(errno));
422 ErrPrint("Buffer is not created (%s)\n", info->id);
427 buffer = info->buffer;
429 switch (buffer->type) {
430 case BUFFER_TYPE_PIXMAP:
433 case BUFFER_TYPE_FILE:
437 DbgPrint("Unknwon FP: %d\n", buffer->type);
444 int fb_release_buffer(void *data)
446 struct buffer *buffer;
449 DbgPrint("buffer data == NIL\n");
453 buffer = container_of(data, struct buffer, data);
455 if (buffer->state != CREATED) {
456 ErrPrint("Invalid handle\n");
460 switch (buffer->type) {
461 case BUFFER_TYPE_SHM:
462 if (shmdt(buffer) < 0)
463 ErrPrint("shmdt: %s\n", strerror(errno));
465 case BUFFER_TYPE_PIXMAP:
467 if (buffer->refcnt == 0) {
468 struct fb_info *info;
471 buffer->state = DESTROYED;
474 if (info && info->buffer == buffer)
478 case BUFFER_TYPE_FILE:
480 if (buffer->refcnt == 0) {
481 struct fb_info *info;
484 buffer->state = DESTROYED;
487 if (info && info->buffer == buffer)
492 ErrPrint("Unknwon buffer type\n");
499 int fb_refcnt(void *data)
501 struct buffer *buffer;
508 buffer = container_of(data, struct buffer, data);
510 if (buffer->state != CREATED) {
511 ErrPrint("Invalid handle\n");
515 switch (buffer->type) {
516 case BUFFER_TYPE_SHM:
517 if (shmctl(buffer->refcnt, IPC_STAT, &buf) < 0) {
518 ErrPrint("Error: %s\n", strerror(errno));
522 ret = buf.shm_nattch;
524 case BUFFER_TYPE_PIXMAP:
525 ret = buffer->refcnt;
527 case BUFFER_TYPE_FILE:
528 ret = buffer->refcnt;
538 const char *fb_id(struct fb_info *info)
540 return info ? info->id : NULL;
543 int fb_get_size(struct fb_info *info, int *w, int *h)
546 ErrPrint("Handle is not valid\n");
555 int fb_size(struct fb_info *info)
557 info->bufsz = info->w * info->h * s_info.depth;
558 return info ? info->bufsz : 0;