diff --git a/configure.ac b/configure.ac index 71e3ad12..5ec0fa35 100644 --- a/configure.ac +++ b/configure.ac @@ -253,6 +253,7 @@ enable_video_pc_xvfb="yes" enable_video_rtos_xvfb="no" enable_video_qvfb="no" enable_video_wvfb="no" +enable_video_usvfb="no" enable_video_dfb="no" enable_video_dfb_st7167="no" enable_video_stgfb="no" @@ -908,7 +909,7 @@ dnl Check Windows Virtual FrameBuffer CheckWVFB() { AC_ARG_ENABLE(videowvfb, -[ --enable-videowvfb include Windows Virtual FrameBuffer NEWGAL engine ], +[ --enable-videowvfb include Windows Virtual Frame Buffer NEWGAL engine ], enable_video_wvfb=$enableval) if test "x$enable_video_wvfb" = "xyes"; then @@ -920,6 +921,23 @@ CheckWVFB() fi } +dnl Set up the UnixSocket virtual Frame Buffer video driver. +CheckUSVFB() +{ + AC_ARG_ENABLE(videousvfb, +[ --enable-videousvfb include NEWGAL/IAL engines for UnixSocket Virtual Frame Buffer ], + enable_video_usvfb=$enableval) + + if test "x$enable_video_usvfb" = "xyes"; then + AC_DEFINE(_MGIAL_USVFB, 1, + [Define if include IAL engine for UnixSocket Virtual Frame Buffer]) + AC_DEFINE(_MGGAL_USVFB, 1, + [Define if include NEWGAL engine for UnixSocket Virtual Frame Buffer]) + VIDEO_SUBDIRS="$VIDEO_SUBDIRS usvfb" + VIDEO_DRIVERS="$VIDEO_DRIVERS usvfb/libvideo_usvfb.la" + fi +} + dnl Set up the Common LCD video driver. CheckCOMMLCD() { @@ -1280,6 +1298,7 @@ dnl Checks NewGAL Engine. CheckQVFB CheckXVFB CheckWVFB + CheckUSVFB CheckCOMMLCD CheckShadowVideo CheckMLShadowVideo @@ -2505,6 +2524,7 @@ src/newgal/sigma8654/Makefile src/newgal/mstar/Makefile src/newgal/gdl/Makefile src/newgal/stgfb/Makefile +src/newgal/usvfb/Makefile src/ial/Makefile src/ial/native/Makefile src/ial/netial/Makefile diff --git a/src/newgal/Makefile.am b/src/newgal/Makefile.am index 4ea6a770..b87335fd 100644 --- a/src/newgal/Makefile.am +++ b/src/newgal/Makefile.am @@ -8,7 +8,7 @@ noinst_LTLIBRARIES = libnewgal.la SUBDIRS = @VIDEO_SUBDIRS@ DIST_SUBDIRS = dummy fbcon qvfb wvfb em85xxyuv em85xxosd svpxxosd bf533 utpmc \ mb93493 commlcd shadow mlshadow dfb em86gfx hisi rtos_xvfb pcxvfb \ - nexus s3c6410 sigma8654 mstar gdl stgfb + nexus s3c6410 sigma8654 mstar gdl stgfb usvfb # x11 dga vgl svga ggi aalib EXTRA_DIST=makefile.ng makefile.msvc diff --git a/src/newgal/commlcd/commlcd.c b/src/newgal/commlcd/commlcd.c index 0120054c..5383a71b 100644 --- a/src/newgal/commlcd/commlcd.c +++ b/src/newgal/commlcd/commlcd.c @@ -292,7 +292,7 @@ static GAL_Surface *COMMLCD_SetVideoMode(_THIS, GAL_Surface *current, pthread_create (&this->hidden->update_th, &new_attr, task_do_update, this); pthread_attr_destroy (&new_attr); - pthread_mutex_init(&this->hidden->update_lock, NULL) + pthread_mutex_init (&this->hidden->update_lock, NULL); } else { this->hidden->update_th = 0; diff --git a/src/newgal/usvfb/CMakeLists.txt b/src/newgal/usvfb/CMakeLists.txt new file mode 100644 index 00000000..48e26820 --- /dev/null +++ b/src/newgal/usvfb/CMakeLists.txt @@ -0,0 +1,3 @@ + +mg_add_all_source_files() +mg_commit_source_files() diff --git a/src/newgal/usvfb/Makefile.am b/src/newgal/usvfb/Makefile.am new file mode 100644 index 00000000..35f27574 --- /dev/null +++ b/src/newgal/usvfb/Makefile.am @@ -0,0 +1,12 @@ +AM_CPPFLAGS = -I$(abs_top_srcdir)/src/include -I$(abs_top_srcdir)/include \ + -I$(abs_top_srcdir)/src/newgal/ + +SRC_FILES = usvfb.c +HDR_FILES = usvfb.h + +noinst_LTLIBRARIES = libvideo_usvfb.la +libvideo_usvfb_la_SOURCES = $(SRC_FILES) $(HDR_FILES) + +EXTRA_DIST=makefile.ng makefile.msvc + +LIB_NAME=libvideo_usvfb diff --git a/src/newgal/usvfb/makefile.msvc b/src/newgal/usvfb/makefile.msvc new file mode 100644 index 00000000..05e18bf0 --- /dev/null +++ b/src/newgal/usvfb/makefile.msvc @@ -0,0 +1,5 @@ +# Makefile defines for building the MiniGUI DLL with Microsoft VC + +!INCLUDE Makefile.am +!INCLUDE ..\..\..\build\Defs.win32 +!INCLUDE ..\..\..\build\makedefs.msvc diff --git a/src/newgal/usvfb/makefile.ng b/src/newgal/usvfb/makefile.ng new file mode 100644 index 00000000..17baec14 --- /dev/null +++ b/src/newgal/usvfb/makefile.ng @@ -0,0 +1,5 @@ +abs_top_srcdir=../../.. + +include Makefile.am +include ../../../rules.make + diff --git a/src/newgal/usvfb/usvfb.c b/src/newgal/usvfb/usvfb.c new file mode 100644 index 00000000..c37317e8 --- /dev/null +++ b/src/newgal/usvfb/usvfb.c @@ -0,0 +1,551 @@ +/* + * This file is part of MiniGUI, a mature cross-platform windowing + * and Graphics User Interface (GUI) support system for embedded systems + * and smart IoT devices. + * + * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. + * Copyright (C) 1998~2002, WEI Yongming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Or, + * + * As this program is a library, any link to this program must follow + * GNU General Public License version 3 (GPLv3). If you cannot accept + * GPLv3, you need to be licensed from FMSoft. + * + * If you have got a commercial license of this program, please use it + * under the terms and conditions of the commercial license. + * + * For more information about the commercial license, please refer to + * . + */ +/* + *usvfb.c: UnixSocket Virtual Frame Buffer NEWGAL video driver. + * + \verbatim + + The USVFB NEWGAL/IAL engines implement the communicate with the Web Display Server + in the following manner: + + 1. A websocket client connects to the server, tells the server the demo it want to run. + It will also tell the server the resolution (width and height in pixels) to show the demo. + + 2. The server forks and execute the MiniGUI program specified by the websocket client + in the child. Before this, the server should set the following environment variables + for the MiniGUI client. + + * MG_GAL_ENGINE: should be usvfb + * MG_DEFAULTMODE: should be a pattern like 320x240-16bpp + * MG_IAL_ENGINE: shold be usvfb + + 3. The server creates a UNIX domain socket at a well-known path (/var/tmp/mg-remote-sever) + and wait for the connection from the MiniGUI client. + + 4. The MiniGUI client connects to the UNIX socket, creates a shared memory as a + virtual frame buffer, and sends the identifier of the shared memory to the server + via the UNIX socket. + + 5. Note that the resolution of the virtual frame buffer should be sent by the server as + the first message. + + 6. The server accepts the connection request from the MiniGUI client, gets the + identifier of the shared memory sent by the client via the UNIX socket, + and attaches to the shared memory. + + 7. The MiniGUI client sends the dirty rectangle information via the + UNIX socket, and the server then sends the information and the pixel data + to the websocket client. + + 8. The server gets the input events from the websocket client and sends them + to the MiniGUI client via the UNIX socket. + + 9. Note that the MiniGUI client should run in MiniGUI-Processes or MiniGUI-Standalone + runmode. + + Copyright (C) 2018, Beijing FMSoft Technologies Co., Ltd (www.fmsoft.cn). + + \endverbatim +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "minigui.h" +#include "newgal.h" +#include "sysvideo.h" +#include "pixels_c.h" + +#ifdef _MGGAL_USVFB + +#include "usvfb.h" + +#define USVFBVID_DRIVER_NAME "usvfb" + +/* Initialization/Query functions */ +static int USVFB_VideoInit (_THIS, GAL_PixelFormat *vformat); +static GAL_Rect **USVFB_ListModes (_THIS, GAL_PixelFormat *format, Uint32 flags); +static GAL_Surface *USVFB_SetVideoMode (_THIS, GAL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int USVFB_SetColors (_THIS, int firstcolor, int ncolors, GAL_Color *colors); +static void USVFB_VideoQuit (_THIS); + +/* Hardware surface functions */ +static int USVFB_AllocHWSurface (_THIS, GAL_Surface *surface); +static void USVFB_FreeHWSurface (_THIS, GAL_Surface *surface); + +struct _frame_header { + int type; + size_t payload_len; + unsigned char payload[0]; +}; + +int __mg_usvfb_fd; +static struct _vfb_info _lcd_info; + +static int a_init (void) +{ + int len, retval; + struct sockaddr_un unix_addr; + + /* create a Unix domain stream socket */ + if ((__mg_usvfb_fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) { + retval = 1; + goto error; + } + + /* fill socket address structure w/our address */ + memset (&unix_addr, 0, sizeof (unix_addr)); + unix_addr.sun_family = AF_UNIX; + sprintf (unix_addr.sun_path, USC_PATH, getpid()); + len = sizeof (unix_addr.sun_family) + strlen (unix_addr.sun_path); + + unlink (unix_addr.sun_path); /* in case it already exists */ + if (bind (__mg_usvfb_fd, (struct sockaddr *) &unix_addr, len) < 0) { + retval = 2; + goto error; + } + + if (chmod (unix_addr.sun_path, USC_PERM) < 0) { + retval = 3; + goto error; + } + + /* fill socket address structure w/server's addr */ + memset (&unix_addr, 0, sizeof (unix_addr)); + unix_addr.sun_family = AF_UNIX; + strcpy (unix_addr.sun_path, USS_PATH); + len = sizeof (unix_addr.sun_family) + strlen (unix_addr.sun_path); + + if (connect (__mg_usvfb_fd, (struct sockaddr *) &unix_addr, len) < 0) { + retval = 4; + goto error; + } + + return 0; + +error: + if (__mg_usvfb_fd) { + close (__mg_usvfb_fd); + } + + return retval; +} + +/* return zero for success */ +static int a_getinfo (struct _vfb_info *li, int width, int height, int bpp) +{ + ssize_t n; + int retval = 0; + struct _frame_header header; + + if (width > 1024 || height > 768 || bpp != 16 || bpp != 32) { + retval = 1; + goto error; + } + + if (bpp == 16) { + _lcd_info.type = USVFB_TRUE_RGB565; + _lcd_info.rlen = (_lcd_info.width * 2 + 3)/4*4; + _lcd_info.bpp = 16; + } + else { + _lcd_info.type = USVFB_TRUE_RGB0888; + _lcd_info.rlen = (_lcd_info.width * 4 + 3)/4*4; + _lcd_info.bpp = 32; + } + + _lcd_info.fb = calloc (height * _lcd_info.rlen, sizeof (char)); + if (_lcd_info.fb == NULL) { + retval = 1; + goto error; + } + + header.type = FT_VFBINFO; + header.payload_len = sizeof (struct _vfb_info); + n = write (__mg_usvfb_fd, &header, sizeof (struct _frame_header)); + n += write (__mg_usvfb_fd, &_lcd_info, sizeof (struct _vfb_info)); + if (n != sizeof (struct _frame_header) + header.payload_len) { + retval = 2; + goto error; + } + + _lcd_info.async_update = 0; + memcpy (li, &_lcd_info, sizeof (struct _vfb_info)); + return retval; + +error: + if (__mg_usvfb_fd) { + close (__mg_usvfb_fd); + } + + return retval; +} + +static int a_update (const RECT* rc_dirty) +{ + int i, Bpp, dirty_w, dirty_h; + unsigned char* pixels; + ssize_t n; + size_t bytes; + struct _frame_header header; + + dirty_w = RECTWP (rc_dirty); + dirty_h = RECTHP (rc_dirty); + + if (dirty_w < 0 || rc_dirty->left < 0 || (rc_dirty->left + dirty_w) > _lcd_info.width + || dirty_h < 0 || rc_dirty->top < 0 || (rc_dirty->top + dirty_h) > _lcd_info.height) { + return 1; + } + + Bpp = 2; + if (_lcd_info.bpp == 32) + Bpp = 4; + + bytes = dirty_w * dirty_h * Bpp; + + header.type = FT_DIRTYPIXELS; + header.payload_len = sizeof (RECT) + bytes; + + n = write (__mg_usvfb_fd, &header, sizeof (struct _frame_header)); + n += write (__mg_usvfb_fd, rc_dirty, sizeof (RECT)); + + pixels = _lcd_info.fb + _lcd_info.rlen * rc_dirty->top + rc_dirty->left * Bpp; + for (i = 0; i < dirty_h; i++) { + n += write (__mg_usvfb_fd, pixels, dirty_w * Bpp); + + pixels += _lcd_info.rlen; + } + + if (n != header.payload_len) { + return 2; + } + + return 0; +} + +static int a_release (void) +{ + free (_lcd_info.fb); + close (__mg_usvfb_fd); + + return 0; +} + +/* USVFB driver bootstrap functions */ +static int USVFB_Available(void) +{ + return 1; +} + +static void USVFB_DeleteDevice(GAL_VideoDevice *device) +{ + free (device->hidden); + free (device); +} + +static void USVFB_UpdateRects (_THIS, int numrects, GAL_Rect *rects) +{ + int i; + RECT bound; + + if (this->hidden->update_th == 0) { + /* sync update */ + SetRect (&bound, 0, 0, 0, 0); + for (i = 0; i < numrects; i++) { + RECT rc; + SetRect (&rc, rects[i].x, rects[i].y, + rects[i].x + rects[i].w, rects[i].y + rects[i].h); + if (IsRectEmpty (&bound)) + bound = rc; + else + GetBoundRect (&bound, &bound, &rc); + } + + if (!IsRectEmpty (&bound)) { + a_update (&bound); + } + + return; + } + + pthread_mutex_lock (&this->hidden->update_lock); + + bound = this->hidden->rc_dirty; + for (i = 0; i < numrects; i++) { + RECT rc; + SetRect (&rc, rects[i].x, rects[i].y, + rects[i].x + rects[i].w, rects[i].y + rects[i].h); + if (IsRectEmpty (&bound)) + bound = rc; + else + GetBoundRect (&bound, &bound, &rc); + } + + if (!IsRectEmpty (&bound)) { + if (IntersectRect (&bound, &bound, &g_rcScr)) { + this->hidden->rc_dirty = bound; + this->hidden->dirty = TRUE; + } + } + + pthread_mutex_unlock (&this->hidden->update_lock); + return; +} + +static GAL_VideoDevice *USVFB_CreateDevice (int devindex) +{ + GAL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (GAL_VideoDevice *)malloc(sizeof(GAL_VideoDevice)); + if ( device ) { + memset(device, 0, (sizeof *device)); + device->hidden = (struct GAL_PrivateVideoData *) + malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + GAL_OutOfMemory(); + if ( device ) { + free(device); + } + return(0); + } + memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = USVFB_VideoInit; + device->ListModes = USVFB_ListModes; + device->SetVideoMode = USVFB_SetVideoMode; + device->SetColors = USVFB_SetColors; + device->VideoQuit = USVFB_VideoQuit; +#ifndef _MGRM_THREADS + device->RequestHWSurface = NULL; +#endif + device->AllocHWSurface = USVFB_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->FreeHWSurface = USVFB_FreeHWSurface; + device->UpdateRects = USVFB_UpdateRects; + + device->free = USVFB_DeleteDevice; + return device; +} + +VideoBootStrap USVFB_bootstrap = { + USVFBVID_DRIVER_NAME, "Common LCD video driver", + USVFB_Available, USVFB_CreateDevice +}; + +static int USVFB_VideoInit(_THIS, GAL_PixelFormat *vformat) +{ + /* Initialize LCD screen */ + if (a_init ()) { + _ERR_PRINTF ("NEWGAL>USVFB: Couldn't initialize\n"); + return -1; + } + + /* Determine the screen depth (use default 8-bit depth) */ + /* we change this during the GAL_SetVideoMode implementation... */ + vformat->BitsPerPixel = 8; + vformat->BytesPerPixel = 1; + + /* We're done! */ + return(0); +} + +static void* task_do_update (void* data) +{ + _THIS; + this = data; + + do { + pthread_mutex_lock (&this->hidden->update_lock); + if (this->hidden->dirty) { + a_update (&this->hidden->rc_dirty); + + SetRect (&this->hidden->rc_dirty, 0, 0, 0, 0); + this->hidden->dirty = FALSE; + } + pthread_mutex_unlock (&this->hidden->update_lock); + usleep (50*1000); /* 50 ms */ + } while (1); + + return NULL; +} + +static GAL_Surface *USVFB_SetVideoMode(_THIS, GAL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Uint32 Rmask = 0, Gmask = 0, Bmask = 0, Amask = 0; + struct _vfb_info li; + memset (&li, 0, sizeof (struct _vfb_info)); + + if (a_getinfo (&li, width, height, bpp)) { + _ERR_PRINTF ("NEWGAL>USVFB: Couldn't get the VFB information\n"); + return NULL; + } + + this->hidden->w = li.width; + this->hidden->h = li.height; + this->hidden->pitch = li.rlen; + this->hidden->fb = li.fb; + + memset (li.fb, 0, li.rlen * height); + + switch (li.type) { + case USVFB_PSEUDO_RGB332: + Rmask = 0xE0; + Gmask = 0x1C; + Bmask = 0x03; + break; + case USVFB_TRUE_RGB555: + Rmask = 0x7C00; + Gmask = 0x03E0; + Bmask = 0x001F; + break; + case USVFB_TRUE_RGB565: + Rmask = 0xF800; + Gmask = 0x07E0; + Bmask = 0x001F; + break; + case USVFB_TRUE_RGB888: + case USVFB_TRUE_RGB0888: + Rmask = 0x00FF0000; + Gmask = 0x0000FF00; + Bmask = 0x000000FF; + break; + case USVFB_TRUE_ARGB1555: + Amask = 0x8000; + Rmask = 0x7C00; + Gmask = 0x03E0; + Bmask = 0x001F; + break; + case USVFB_TRUE_ARGB8888: + Amask = 0xFF000000; + Rmask = 0x00FF0000; + Gmask = 0x0000FF00; + Bmask = 0x000000FF; + break; + } + + /* Allocate the new pixel format for the screen */ + if (!GAL_ReallocFormat (current, li.bpp, Rmask, Gmask, Bmask, Amask)) { + a_release (); + + this->hidden->fb = NULL; + fprintf (stderr, "NEWGAL>USVFB: " + "Couldn't allocate new pixel format for requested mode\n"); + return NULL; + } + + /* Set up the new mode framebuffer */ + current->flags = GAL_HWSURFACE | GAL_FULLSCREEN; + current->w = this->hidden->w; + current->h = this->hidden->h; + current->pitch = this->hidden->pitch; + current->pixels = this->hidden->fb; + + if (li.async_update) { + pthread_attr_t new_attr; + + pthread_attr_init (&new_attr); + pthread_attr_setdetachstate (&new_attr, PTHREAD_CREATE_DETACHED); + pthread_create (&this->hidden->update_th, &new_attr, + task_do_update, this); + pthread_attr_destroy (&new_attr); + pthread_mutex_init(&this->hidden->update_lock, NULL); + } + else { + this->hidden->update_th = 0; + } + + /* We're done */ + return current; +} + +static void USVFB_VideoQuit (_THIS) +{ + if (this->screen && this->screen->pixels) { + this->screen->pixels = NULL; + } + + if (this->hidden->update_th) { + /* quit the update task */ + } + + a_release (); + return; +} + +static GAL_Rect **USVFB_ListModes (_THIS, GAL_PixelFormat *format, + Uint32 flags) +{ + return (GAL_Rect **) -1; +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int USVFB_AllocHWSurface (_THIS, GAL_Surface *surface) +{ + return -1; +} + +static void USVFB_FreeHWSurface (_THIS, GAL_Surface *surface) +{ + surface->pixels = NULL; +} + +static int USVFB_SetColors (_THIS, int firstcolor, int ncolors, + GAL_Color *colors) +{ + return 0; +} + +#endif /* _MGGAL_USVFB */ + diff --git a/src/newgal/usvfb/usvfb.h b/src/newgal/usvfb/usvfb.h new file mode 100644 index 00000000..a50c25ac --- /dev/null +++ b/src/newgal/usvfb/usvfb.h @@ -0,0 +1,95 @@ +/* + * This file is part of MiniGUI, a mature cross-platform windowing + * and Graphics User Interface (GUI) support system for embedded systems + * and smart IoT devices. + * + * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. + * Copyright (C) 1998~2002, WEI Yongming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Or, + * + * As this program is a library, any link to this program must follow + * GNU General Public License version 3 (GPLv3). If you cannot accept + * GPLv3, you need to be licensed from FMSoft. + * + * If you have got a commercial license of this program, please use it + * under the terms and conditions of the commercial license. + * + * For more information about the commercial license, please refer to + * . + */ + +#ifndef _GAL_USVFB_H +#define _GAL_USVFB_H + +#include "sysvideo.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Hidden "this" pointer for the video functions */ +#define _THIS GAL_VideoDevice *this + +/* Private display data */ +struct GAL_PrivateVideoData { + int w, h, pitch; + void *fb; + + int fd_socket; + + int dirty; + RECT rc_dirty; + pthread_t update_th; + pthread_mutex_t update_lock; +}; + +/* The pixel format defined by depth */ +#define USVFB_PSEUDO_RGB332 1 +#define USVFB_TRUE_RGB555 2 +#define USVFB_TRUE_RGB565 3 +#define USVFB_TRUE_RGB888 4 +#define USVFB_TRUE_RGB0888 5 +#define USVFB_TRUE_ARGB1555 6 +#define USVFB_TRUE_ARGB8888 7 + +struct _vfb_info { + short height; // vertical resolution of the screen + short width; // horinzontal resolution of the screen + short bpp; // Depth (bits-per-pixel) + short type; // Pixel type + short rlen; // Length of one scan line in bytes + void *fb; // Frame buffer + + short async_update; // update asynchronously or synchronously. 0 for synchronously; others for asynchronously. +}; + +#define USS_PATH "/var/tmp/web-display-server" +#define USC_PATH "/var/tmp/web-display-client-P%d" + +#define USC_PERM S_IRWXU /* rwx for user only */ + +#define FT_VFBINFO 10 +#define FT_PING 11 +#define FT_PONG 12 +#define FT_EVENT 13 +#define FT_DIRTYPIXELS 14 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GAL_USVFB_H */