diff --git a/Version.md b/Version.md index bdddfb20..a8482d39 100644 --- a/Version.md +++ b/Version.md @@ -1,6 +1,6 @@ -Version 5.0.13 (2023/08/31) +Version 5.2.0 (2023/09/30) -This is a minor enhancement and bugfix release of MiniGUI 5.0.x, the stable version. +This is a minor enhancement and bugfix release of MiniGUI 5.2.x, the stable version. Other packages for MiniGUI resource, tools, components, and samples: diff --git a/configure.ac b/configure.ac index 60a92486..81097332 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.60) -AC_INIT(libminigui, 5.0.14) +AC_INIT(libminigui, 5.2.0) AC_CONFIG_SRCDIR(src/main/main.c) dnl Set various version strings - taken gratefully from the SDL sources @@ -15,8 +15,8 @@ dnl Set various version strings - taken gratefully from the SDL sources # set MINIGUI_BINARY_AGE and MINIGUI_INTERFACE_AGE to 0. # MINIGUI_MAJOR_VERSION=5 -MINIGUI_MINOR_VERSION=0 -MINIGUI_MICRO_VERSION=14 +MINIGUI_MINOR_VERSION=2 +MINIGUI_MICRO_VERSION=0 MINIGUI_INTERFACE_AGE=0 MINIGUI_BINARY_AGE=0 MINIGUI_VERSION=$MINIGUI_MAJOR_VERSION.$MINIGUI_MINOR_VERSION.$MINIGUI_MICRO_VERSION diff --git a/include/gdi.h b/include/gdi.h index 8788b313..5f5977d2 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -1709,7 +1709,8 @@ struct GAL_Surface; typedef struct GAL_Surface *HSURF; /** - * \fn HSURF GUIAPI CreateSharedSurface (const char *name, DWORD flags, + * \fn HSURF GUIAPI CreateSharedSurface (GHANDLE video, + * const char *name, DWORD flags, * int width, int height, int depth, * Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) * \brief Creates a shared surface for specified size and pixel format. @@ -1717,8 +1718,8 @@ typedef struct GAL_Surface *HSURF; * This function creates a shared surface on the current video device with * the specified size and pixel format. This function also registers * the shared surface by using the specified name \a name to the server - * if \a name is not NULL. Another client can use the name to retrieve - * the shared surface by calling \a RetrieveSharedSurfaceFDByName(). + * if \a name is not NULL. Another client can use the name to get + * the shared surface by calling \a GetSharedSurfaceFDByName(). * \param video The handle to the video; NULL for the current default video. * \param name The gobal unique name for the shared surface. @@ -1740,11 +1741,12 @@ typedef struct GAL_Surface *HSURF; * * \note This function only available when _MGSCHEMA_COMPOSITING is defined. * - * \sa DestroySharedSurface, RetrieveSharedSurfaceFDByName + * \sa DestroySharedSurface, GetSharedSurfaceFDByName * * Since 5.2.0 */ -MG_EXPORT HSURF GUIAPI CreateSharedSurface (const char *name, DWORD flags, +MG_EXPORT HSURF GUIAPI CreateSharedSurface (GHANDLE video, + const char *name, DWORD flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); @@ -1792,7 +1794,7 @@ MG_EXPORT BOOL GUIAPI DestroySharedSurface (HSURF surf); * Since 5.2.0 */ MG_EXPORT int GUIAPI GetSharedSurfaceFDByClientWindow (int client, - HWND hwnd); + HWND hwnd, size_t *map_size, DWORD *flags); /** * \fn int GUIAPI GetSharedSurfaceFDByName (const char *name) @@ -1814,10 +1816,12 @@ MG_EXPORT int GUIAPI GetSharedSurfaceFDByClientWindow (int client, * * Since 5.2.0 */ -MG_EXPORT int GUIAPI GetSharedSurfaceFDByName (const char *name); +MG_EXPORT int GUIAPI GetSharedSurfaceFDByName (const char *name, + size_t *map_size, DWORD *flags); /** - * \fn HSURF GUIAPI AttachToSharedSurface (GHANDLE video, int fd) + * \fn HSURF GUIAPI AttachToSharedSurface (GHANDLE video, int fd, + * size_t map_size, DWORD flags) * \brief Attaches to a shared surface. * * This function attaches to the shared surface which is represents by @@ -1834,7 +1838,8 @@ MG_EXPORT int GUIAPI GetSharedSurfaceFDByName (const char *name); * * Since 5.2.0 */ -MG_EXPORT HSURF GUIAPI AttachToSharedSurface (GHANDLE video, int fd); +MG_EXPORT HSURF GUIAPI AttachToSharedSurface (GHANDLE video, int fd, + size_t map_size, DWORD flags); /** * \fn int GUIAPI GetSharedSurfaceInfo (HSURF surf, SIZE *size, int *pitch, diff --git a/src/include/client.h b/src/include/client.h index cd2771db..552af8a6 100644 --- a/src/include/client.h +++ b/src/include/client.h @@ -163,13 +163,13 @@ typedef struct OperateNSSurfInfo /* Since 5.0.0 */ typedef struct _SharedSurfInfo { + size_t size; // whole size of the surface + off_t offset; // offset of pixel data uint32_t flags; // the flags of the surface uint32_t width, height; uint32_t pitch; uint32_t name; // when use flink name uint32_t drm_format; // DRM pixel format - size_t size; // whole size of the surface - off_t offset; // offset of pixel data } SHAREDSURFINFO; typedef struct JoinLayerInfo { diff --git a/src/include/map.h b/src/include/map.h index 0ea02ccf..e4e704b7 100644 --- a/src/include/map.h +++ b/src/include/map.h @@ -119,7 +119,7 @@ int __mg_map_find_replace_or_insert (map_t* map, const void* key, int __mg_map_replace (map_t* map, const void* key, const void* val, free_val_fn free_val_alt); -int __mg_map_erase (map_t* map, void* key); +int __mg_map_erase (map_t* map, const void* key); int __mg_map_get_size (map_t* map); #if 0 /* deprecated code */ diff --git a/src/include/newgal.h b/src/include/newgal.h index 96ac1693..023c004a 100644 --- a/src/include/newgal.h +++ b/src/include/newgal.h @@ -166,6 +166,9 @@ typedef struct _SharedSurfaceHeader { size_t map_size; /* the offset of pixels data */ off_t pixels_off; + + /* the name of the shared surface. */ + char name[NAME_MAX + 1]; } GAL_SharedSurfaceHeader; #endif /* IS_COMPOSITING_SCHEMA */ diff --git a/src/include/server.h b/src/include/server.h index 96c0b6f2..658d13bf 100644 --- a/src/include/server.h +++ b/src/include/server.h @@ -135,6 +135,9 @@ void __mg_release_global_res (int cli); /* Since 5.2.0 */ int __mg_nssurf_map_new(void); void __mg_nssurf_map_delete(void); +int __mg_nssurf_map_operate_srv(const OPERATENSSURFINFO* req_info, + int cli, int fd); +int __mg_get_shared_surface_srv(const char *itn_name, SHAREDSURFINFO *info); void __mg_remove_client (int cli, int clifd); diff --git a/src/misc/map.c b/src/misc/map.c index e5e4a630..997ead11 100644 --- a/src/misc/map.c +++ b/src/misc/map.c @@ -243,7 +243,7 @@ map_entry_t* __mg_map_find (map_t* map, const void* key) return entry; } -int __mg_map_erase (map_t* map, void* key) +int __mg_map_erase (map_t* map, const void* key) { int retval = -1; map_entry_t* entry = NULL; diff --git a/src/newgdi/Makefile.am b/src/newgdi/Makefile.am index 438bff36..0c1cb378 100644 --- a/src/newgdi/Makefile.am +++ b/src/newgdi/Makefile.am @@ -14,7 +14,8 @@ SRC_FILES = gdi.c attr.c clip.c map.c coor.c rect.c \ simple-glyph-renderer.c glyph-shaped.c \ textruns.c \ shape-glyphs-basic.c shape-glyphs-complex.c \ - layout.c layout-utils.c layout-ellipsize.c + layout.c layout-utils.c layout-ellipsize.c \ + shared-surface.c HDR_FILES = glyph.h drawtext.h mi.h midc.h mistruct.h miwideline.h \ pixel_ops.h mifillarc.h mispans.h polygon.h mifpoly.h \ diff --git a/src/newgdi/shared-surface.c b/src/newgdi/shared-surface.c new file mode 100644 index 00000000..d5b01277 --- /dev/null +++ b/src/newgdi/shared-surface.c @@ -0,0 +1,282 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT NOTICE +// +// The following open source license statement does not apply to any +// entity in the Exception List published by FMSoft. +// +// For more information, please visit: +// +// https://www.fmsoft.cn/exception-list +// +////////////////////////////////////////////////////////////////////////////// +/* + * 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) 2023, Beijing FMSoft Technologies Co., Ltd. + * + * 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 + * . + */ +/* +** The graphics display interface module of MiniGUI. +** +** Current maintainer: Wei Yongming. +** +** Create date: 1999.01.03 +*/ + +#include +#include +#include + +#include "common.h" + +#ifdef _MGSCHEMA_COMPOSITING + +#include "minigui.h" +#include "gdi.h" +#include "window.h" +#include "cliprect.h" +#include "gal.h" +#include "cursor.h" +#include "internals.h" +#include "inline.h" +#include "dc.h" +#include "debug.h" +#include "client.h" +#include "server.h" + +HSURF GUIAPI CreateSharedSurface(GHANDLE video, const char *name, DWORD flags, + int width, int height, int depth, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + GAL_Surface *nssurf = NULL; + + if (name) { + OPERATENSSURFINFO nssurf_req = {}; + + if (strlen(name) + 1 > sizeof(nssurf_req.name)) { + _ERR_PRINTF("TOOLONG: too long name for shared surface: %s\n", + name); + goto failed; + } + + strcpy(nssurf_req.name, name); + nssurf_req.id_op = ID_NAMEDSSURFOP_REGISTER; + + int result; + if (IsServer()) { + result = __mg_nssurf_map_operate_srv(&nssurf_req, 0, -1); + } + else { + REQUEST req; + + req.id = REQID_OPERATENAMEDSSURF; + req.data = &nssurf_req; + req.len_data = sizeof(OPERATENSSURFINFO); + + if (ClientRequest(&req, &result, sizeof(result))) { + _ERR_PRINTF("BAD_REQUEST: when registering name for a new shared surface\n"); + goto failed; + } + } + + if (result) { + _ERR_PRINTF("FAILED_REQUEST: when registering name of shared surface\n"); + goto failed; + } + } + + nssurf = GAL_CreateSharedRGBSurface(video, flags, 0666, width, height, depth, + Rmask, Gmask, Bmask, Amask); + if (nssurf == NULL) { + goto failed; + } + + if (name) { + strcpy(nssurf->shared_header->name, name); + + OPERATENSSURFINFO nssurf_req = {}; + strcpy(nssurf_req.name, name); + nssurf_req.id_op = ID_NAMEDSSURFOP_SET; + nssurf_req.map_size = nssurf->shared_header->map_size; + + int result; + if (IsServer()) { + result = __mg_nssurf_map_operate_srv(&nssurf_req, 0, + nssurf->shared_header->fd); + } + else { + REQUEST req; + + req.id = REQID_OPERATENAMEDSSURF; + req.data = &nssurf_req; + req.len_data = sizeof(OPERATENSSURFINFO); + + if (ClientRequestEx2(&req, NULL, 0, nssurf->shared_header->fd, + &result, sizeof(result), NULL)) { + _ERR_PRINTF("BAD_REQUEST: when setting fd of the new shared surface.\n"); + goto failed; + } + } + + if (result) { + _ERR_PRINTF("FAILED_REQUEST: when setting fd of the shared surface\n"); + goto failed; + } + } + else { + nssurf->shared_header->name[0] = 0; + } + + return nssurf; + +failed: + if (nssurf) + GAL_FreeSurface(nssurf); + + return NULL; +} + +BOOL GUIAPI DestroySharedSurface(HSURF surf) +{ + if (surf->shared_header == NULL) { + _ERR_PRINTF("INVALID_ARG: surface handle: %p\n", surf); + goto failed; + } + + if (surf->shared_header->creator == getpid() && + surf->shared_header->name[0]) { + /* This is a named shared surface created by this client */ + + OPERATENSSURFINFO nssurf_req = {}; + strcpy(nssurf_req.name, surf->shared_header->name); + nssurf_req.id_op = ID_NAMEDSSURFOP_REVOKE; + + int result; + if (IsServer()) { + result = __mg_nssurf_map_operate_srv(&nssurf_req, 0, -1); + } + else { + REQUEST req; + + req.id = REQID_OPERATENAMEDSSURF; + req.data = &nssurf_req; + req.len_data = sizeof(OPERATENSSURFINFO); + + if (ClientRequest(&req, &result, sizeof(result))) { + _ERR_PRINTF("BAD_REQUEST: when revoking name of a shared surface.\n"); + goto failed; + } + } + + if (result) { + _ERR_PRINTF("FAILED_REQUEST: when revoking name of a shared surface\n"); + goto failed; + } + } + + GAL_FreeSurface(surf); + return TRUE; + +failed: + return FALSE; +} + +static int get_shared_surface(const char *name, size_t *map_size, DWORD *flags) +{ + int fd = -1; + SHAREDSURFINFO info; + + if (IsServer()) { + fd = __mg_get_shared_surface_srv(name, &info); + } + else { + REQUEST req; + + req.id = REQID_GETSHAREDSURFACE; + req.data = name; + req.len_data = strlen(name) + 1; + + if (ClientRequestEx2(&req, NULL, 0, -1, + &info, sizeof(SHAREDSURFINFO), &fd) < 0) { + _ERR_PRINTF("BAD_REQUEST: when getting shared surface: %s\n", name); + goto failed; + } + + if (fd < 0) { + _ERR_PRINTF("FAILED_REQUEST: when getting shared surface: %s\n", name); + goto failed; + } + + _DBG_PRINTF("REQID_GETSHAREDSURFACE: size (%lu), flags (0x%x), fd: %d\n", + info.size, info.flags, fd); + + } + + if (fd >= 0) { + if (map_size) + *map_size = info.size; + if (flags) + *flags = info.flags; + } + return fd; + +failed: + return -1; +} + +int GUIAPI GetSharedSurfaceFDByClientWindow(int client, HWND hwnd, + size_t *map_size, DWORD *flags) +{ + char itn_name[sizeof(APPSF_NAME_PREFIX) + NAME_MAX + 1]; + + int ret = snprintf(itn_name, sizeof(itn_name), APPSF_HWND_PATTER, + client, hwnd); + if (ret <= 0 || (size_t)ret >= sizeof(itn_name)) { + return -1; + } + + return get_shared_surface(itn_name, map_size, flags); +} + +int GUIAPI GetSharedSurfaceFDByName(const char *name, + size_t *map_size, DWORD *flags) +{ + char itn_name[sizeof(APPSF_NAME_PREFIX) + NAME_MAX + 1]; + + int ret = snprintf(itn_name, sizeof(itn_name), APPSF_NAME_PATTER, name); + if (ret <= 0 || (size_t)ret >= sizeof(itn_name)) { + return -1; + } + + return get_shared_surface(itn_name, map_size, flags); +} + +#endif /* defined _MGSCHEMA_COMPOSITING */ + diff --git a/src/server/request.c b/src/server/request.c index 78fc08f8..7b761ff4 100644 --- a/src/server/request.c +++ b/src/server/request.c @@ -812,68 +812,13 @@ void __mg_nssurf_map_delete(void) __mg_map_destroy(__nssurf_map); } -/* get the fake screen surface (wallpaper pattern surface) */ -static int get_shared_surface (int cli, int clifd, void* buff, size_t len) -{ - SHAREDSURFINFO info = {}; - int fd = -1; - - assert (__gal_fake_screen); - - if (strcmp(buff, SYSSF_WALLPAPER_PATTER) == 0 && - __gal_fake_screen->shared_header) { - info.flags = __gal_fake_screen->flags; - info.size = __gal_fake_screen->shared_header->map_size; - fd = __gal_fake_screen->shared_header->fd; - } - else if (strncmp(buff, APPSF_NAME_PREFIX, - sizeof(APPSF_NAME_PREFIX) - 1) == 0) { - const char *name = buff + sizeof(APPSF_NAME_PREFIX) - 1; - map_entry_t *entry = __mg_map_find(__nssurf_map, name); - if (entry == NULL) - goto failed; - - struct nssurf_info *nssurf_info = entry->val; - assert(nssurf_info); - info.size = nssurf_info->map_size; - fd = nssurf_info->fd; - } - else if (strncmp(buff, APPSF_HWND_PREFIX, - sizeof(APPSF_HWND_PREFIX) - 1) == 0) { - int client; - HWND hwnd; - int ret = sscanf(buff, APPSF_HWND_PATTER, &client, &hwnd); - if (ret != 2) - goto failed; - - ZORDERNODE *znode = __mg_find_znode_by_client_hwnd(client, hwnd); - if (znode == NULL) - goto failed; - - PDC pdc = dc_HDC2PDC(znode->mem_dc); - assert(pdc->surface->shared_header); - info.size = pdc->surface->shared_header->map_size; - info.width = pdc->surface->shared_header->width; - info.height = pdc->surface->shared_header->height; - info.pitch = pdc->surface->shared_header->pitch; - info.offset = pdc->surface->shared_header->pixels_off; - fd = pdc->surface->shared_header->fd; - } - - return ServerSendReplyEx (clifd, &info, sizeof (SHAREDSURFINFO), fd); - -failed: - return ServerSendReplyEx (clifd, &info, sizeof (SHAREDSURFINFO), -1); -} - -static int -operate_nssurface(int cli, int clifd, void* buff, size_t len, int fd) +int __mg_nssurf_map_operate_srv(const OPERATENSSURFINFO* req_info, + int cli, int fd) { int result = -1; map_entry_t *entry; struct nssurf_info *nssurf_info; - OPERATENSSURFINFO* req_info = (OPERATENSSURFINFO*)buff; switch (req_info->id_op) { case ID_NAMEDSSURFOP_REGISTER: entry = __mg_map_find(__nssurf_map, req_info->name); @@ -930,6 +875,75 @@ operate_nssurface(int cli, int clifd, void* buff, size_t len, int fd) } done: + return result; +} + +int __mg_get_shared_surface_srv(const char *itn_name, SHAREDSURFINFO *info) +{ + int fd = -1; + assert (__gal_fake_screen); + + if (strcmp(itn_name, SYSSF_WALLPAPER_PATTER) == 0 && + __gal_fake_screen->shared_header) { + info->flags = __gal_fake_screen->flags; + info->size = __gal_fake_screen->shared_header->map_size; + fd = __gal_fake_screen->shared_header->fd; + } + else if (strncmp(itn_name, APPSF_NAME_PREFIX, + sizeof(APPSF_NAME_PREFIX) - 1) == 0) { + const char *name = itn_name + sizeof(APPSF_NAME_PREFIX) - 1; + map_entry_t *entry = __mg_map_find(__nssurf_map, name); + if (entry == NULL) + goto done; + + struct nssurf_info *nssurf_info = entry->val; + assert(nssurf_info); + info->size = nssurf_info->map_size; + fd = nssurf_info->fd; + } + else if (strncmp(itn_name, APPSF_HWND_PREFIX, + sizeof(APPSF_HWND_PREFIX) - 1) == 0) { + int client; + HWND hwnd; + int ret = sscanf(itn_name, APPSF_HWND_PATTER, &client, &hwnd); + if (ret != 2) + goto done; + + ZORDERNODE *znode = __mg_find_znode_by_client_hwnd(client, hwnd); + if (znode == NULL) + goto done; + + PDC pdc = dc_HDC2PDC(znode->mem_dc); + assert(pdc->surface->shared_header); + info->size = pdc->surface->shared_header->map_size; + info->width = pdc->surface->shared_header->width; + info->height = pdc->surface->shared_header->height; + info->pitch = pdc->surface->shared_header->pitch; + info->offset = pdc->surface->shared_header->pixels_off; + fd = pdc->surface->shared_header->fd; + } + +done: + return fd; +} + +/* get the fake screen surface (wallpaper pattern surface) */ +static int get_shared_surface (int cli, int clifd, void* buff, size_t len) +{ + SHAREDSURFINFO info = {}; + int fd = __mg_get_shared_surface_srv(buff, &info); + + return ServerSendReplyEx (clifd, &info, sizeof (SHAREDSURFINFO), fd); +} + +static int +operate_nssurface(int cli, int clifd, void* buff, size_t len, int fd) +{ + int result = -1; + + assert(len >= sizeof(OPERATENSSURFINFO)); + OPERATENSSURFINFO* req_info = (OPERATENSSURFINFO*)buff; + result = __mg_nssurf_map_operate_srv(req_info, cli, fd); return ServerSendReply(clifd, &result, sizeof(int)); }