diff --git a/src/newgal/surface-shared.c b/src/newgal/surface-shared.c
new file mode 100644
index 00000000..e2f5e3cc
--- /dev/null
+++ b/src/newgal/surface-shared.c
@@ -0,0 +1,421 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// 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) 2002~2020, 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
+ * .
+ */
+
+#include
+#include
+#include
+
+#include "common.h"
+#include "constants.h"
+
+#if IS_COMPOSITING_SCHEMA
+
+#include
+#include
+
+#include "misc.h"
+#include "newgal.h"
+#include "sysvideo.h"
+#include "pixels_c.h"
+#include "blit.h"
+
+/*
+ * Create a shared empty RGB surface of the appropriate depth
+ */
+GAL_Surface * GAL_CreateSharedRGBSurface (GAL_VideoDevice *video,
+ Uint32 flags, Uint32 rw_modes, int width, int height, int depth,
+ Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
+{
+ GAL_Surface *screen;
+ GAL_Surface *surface;
+
+ /* Check to see if we desire the surface in video memory */
+ if (video == NULL) {
+ video = __mg_current_video;
+ }
+
+ screen = GAL_PublicSurface;
+
+ if (screen && ((screen->flags & GAL_HWSURFACE) == GAL_HWSURFACE)) {
+ if ((flags & (GAL_SRCCOLORKEY | GAL_SRCALPHA)) != 0) {
+ flags |= GAL_HWSURFACE;
+ }
+
+ if ((flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY) {
+ if (! video->info.blit_hw_CC) {
+ flags &= ~GAL_HWSURFACE;
+ }
+ }
+ if ((flags & GAL_SRCALPHA) == GAL_SRCALPHA) {
+ if (! video->info.blit_hw_A) {
+ flags &= ~GAL_HWSURFACE;
+ }
+ }
+ }
+ else {
+ flags &= ~GAL_HWSURFACE;
+ }
+
+ /* Allocate the surface */
+ surface = (GAL_Surface *)malloc (sizeof (*surface));
+ if (surface == NULL) {
+ goto error;
+ }
+
+ if ((flags & GAL_HWSURFACE) == GAL_HWSURFACE)
+ surface->video = video;
+ else
+ surface->video = NULL;
+
+ surface->flags = GAL_SWSURFACE;
+ if (Amask) {
+ surface->flags |= GAL_SRCPIXELALPHA;
+ }
+
+ surface->format = GAL_AllocFormat (depth, Rmask, Gmask, Bmask, Amask);
+ if (surface->format == NULL) {
+ free (surface);
+ surface = NULL;
+ goto error;
+ }
+
+ surface->w = width;
+ surface->h = height;
+ surface->pitch = GAL_CalculatePitch (surface);
+ surface->pixels = NULL;
+ surface->offset = 0;
+ // for off-screen surface, DPI always be the default value
+ surface->dpi = GDCAP_DPI_DEFAULT;
+ surface->hwdata = NULL;
+ surface->map = NULL;
+ surface->format_version = 0;
+ surface->shared_header = NULL;
+ GAL_SetClipRect (surface, NULL);
+
+#ifdef _MGUSE_SYNC_UPDATE
+ /* Initialize update region */
+ InitClipRgn (&surface->update_region, &__mg_free_update_region_list);
+#endif
+
+ /* Get the pixels */
+ if (surface->w && surface->h) {
+ int fd = -1;
+ size_t buf_size;
+ off_t buf_off;
+ off_t map_size;
+ void* data_map;
+ GAL_SharedSurfaceHeader* hdr;
+ int byhw = 1;
+
+ if ((flags & GAL_HWSURFACE) == GAL_HWSURFACE &&
+ video->AllocSharedHWSurface) {
+ fd = video->AllocSharedHWSurface (video, surface,
+ &buf_size, &buf_off, rw_modes);
+ }
+
+ if (fd < 0) { // fallback to use software surface
+ off_t file_size;
+
+ byhw = 0;
+ buf_size = (surface->h * surface->pitch);
+ buf_off = sizeof (GAL_SharedSurfaceHeader);
+
+ /* rounde file size to multiple of page size */
+ file_size = buf_off + buf_size;
+ file_size &= ~(getpagesize () - 1);
+ buf_size = file_size - buf_off;
+
+ fd = __mg_create_anonymous_file (file_size, NULL, rw_modes);
+ if (fd < 0) {
+ goto error;
+ }
+ }
+
+ map_size = buf_off + buf_size;
+ data_map = mmap (NULL, map_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (data_map == MAP_FAILED) {
+ close (fd);
+ goto error;
+ }
+
+ surface->shared_header = hdr = (GAL_SharedSurfaceHeader*)data_map;
+
+ /* fill fileds of shared header */
+ memset (hdr, 0, sizeof(GAL_SharedSurfaceHeader));
+ hdr->semid = -1;
+ hdr->creator = getpid();
+ hdr->fd = fd;
+ hdr->byhw = byhw;
+ hdr->width = surface->w;
+ hdr->height = surface->h;
+ hdr->pitch = surface->pitch;
+ hdr->depth = depth;
+ hdr->Rmask = Rmask;
+ hdr->Gmask = Gmask;
+ hdr->Bmask = Bmask;
+ hdr->Amask = Amask;
+ hdr->buf_size = buf_size;
+ hdr->sem_num = __mg_alloc_mutual_sem (&hdr->semid);
+ if (hdr->sem_num < 0)
+ goto error;
+
+ surface->pixels = surface->shared_header->buf;
+ memset (surface->pixels, 0, buf_size);
+
+ if (byhw)
+ surface->flags |= GAL_HWSURFACE;
+ else
+ surface->flags &= ~GAL_HWSURFACE;
+ }
+
+ /* Allocate an empty mapping */
+ surface->map = GAL_AllocBlitMap();
+ if (surface->map == NULL) {
+ goto error;
+ }
+
+ /* The surface is ready to go */
+ surface->refcount = 1;
+ return(surface);
+
+error:
+ if (surface) {
+ if (surface->shared_header) {
+ if (surface->shared_header->semid >= 0) {
+ assert (surface->shared_header->sem_num >= 0);
+ __mg_free_mutual_sem (surface->shared_header->sem_num);
+ }
+
+ if (surface->shared_header->byhw) {
+ assert(video->FreeSharedHWSurface);
+ video->FreeSharedHWSurface (video, surface);
+ }
+ else {
+ close (surface->shared_header->fd);
+ munmap (surface->shared_header,
+ surface->shared_header->buf_size
+ + sizeof(GAL_SharedSurfaceHeader));
+ }
+ }
+
+ GAL_FreeSurface (surface);
+ }
+
+ GAL_OutOfMemory ();
+ return NULL;
+}
+
+/*
+ * Free data of a shared surface created by the above function.
+ */
+void GAL_FreeSharedSurfaceData (GAL_Surface *surface)
+{
+ GAL_VideoDevice *video = surface->video;
+
+ assert (surface->shared_header);
+
+ if (surface->shared_header->semid >= 0) {
+ assert (surface->shared_header->sem_num >= 0);
+ __mg_free_mutual_sem (surface->shared_header->sem_num);
+ }
+
+ if (surface->shared_header->byhw) {
+ assert (video->FreeSharedHWSurface);
+ video->FreeSharedHWSurface (video, surface);
+ }
+ else {
+ close (surface->shared_header->fd);
+ munmap (surface->shared_header,
+ surface->shared_header->buf_size
+ + sizeof (GAL_SharedSurfaceHeader));
+ }
+}
+
+/*
+ * Attach to a shared RGB surface
+ */
+GAL_Surface * GAL_AttachSharedRGBSurface (int fd, size_t map_size, Uint32 flags, BOOL with_wr)
+{
+ GAL_VideoDevice *video;
+ GAL_Surface *surface;
+ int prot = PROT_READ;
+ void* data_map = MAP_FAILED;
+ GAL_SharedSurfaceHeader* hdr;
+
+ if (with_wr) {
+ prot |= PROT_WRITE;
+ }
+
+ data_map = mmap (NULL, map_size, prot, MAP_SHARED, fd, 0);
+ if (data_map == MAP_FAILED) {
+ _ERR_PRINTF("NEWGAL: Failed to map shared RGB surface: %d\n", fd);
+ return NULL;
+ }
+
+ /* XXX: We may find the video according to engine name in the future */
+ video = __mg_current_video;
+
+ /* Allocate the surface */
+ surface = (GAL_Surface *)malloc (sizeof (*surface));
+ if (surface == NULL) {
+ goto error;
+ }
+
+ hdr = (GAL_SharedSurfaceHeader*) data_map;
+ surface->shared_header = hdr;
+
+ /* check flags */
+ if (hdr->byhw) {
+ if ((flags & (GAL_SRCCOLORKEY | GAL_SRCALPHA)) != 0) {
+ flags |= GAL_HWSURFACE;
+ }
+
+ if ((flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY) {
+ if (!video->info.blit_hw_CC) {
+ flags &= ~GAL_HWSURFACE;
+ }
+ }
+ if ((flags & GAL_SRCALPHA) == GAL_SRCALPHA) {
+ if (!video->info.blit_hw_A) {
+ flags &= ~GAL_HWSURFACE;
+ }
+ }
+ }
+ else {
+ flags &= ~GAL_HWSURFACE;
+ }
+
+ if ((flags & GAL_HWSURFACE) == GAL_HWSURFACE) {
+ surface->flags = GAL_HWSURFACE;
+ surface->video = video;
+ }
+ else {
+ surface->flags = GAL_SWSURFACE;
+ surface->video = NULL;
+ video = NULL;
+ }
+
+ if (hdr->Amask) {
+ surface->flags |= GAL_SRCPIXELALPHA;
+ }
+
+ surface->format = GAL_AllocFormat (hdr->depth,
+ hdr->Rmask, hdr->Gmask, hdr->Bmask, hdr->Amask);
+ if (surface->format == NULL) {
+ goto error;
+ }
+
+ surface->w = hdr->width;
+ surface->h = hdr->height;
+ surface->pitch = GAL_CalculatePitch (surface);
+ surface->pixels = NULL;
+ surface->offset = 0;
+ // for off-screen surface, DPI always be the default value
+ surface->dpi = GDCAP_DPI_DEFAULT;
+ surface->hwdata = NULL;
+ surface->map = NULL;
+ surface->format_version = 0;
+ GAL_SetClipRect (surface, NULL);
+
+#ifdef _MGUSE_SYNC_UPDATE
+ /* Initialize update region */
+ InitClipRgn (&surface->update_region, &__mg_free_update_region_list);
+#endif
+
+ /* Get the pixels */
+ if (surface->w && surface->h) {
+ if (video && video->AttachSharedHWSurface) {
+ video->AttachSharedHWSurface (video, surface, fd);
+ }
+
+ surface->pixels = surface->shared_header->buf;
+ }
+
+ /* Allocate an empty mapping */
+ surface->map = GAL_AllocBlitMap();
+ if (surface->map == NULL) {
+ goto error;
+ }
+
+ /* The surface is ready to go */
+ surface->refcount = 1;
+ return (surface);
+
+error:
+ if (data_map != MAP_FAILED) {
+ if (video && video->DettachSharedHWSurface) {
+ video->DettachSharedHWSurface (video, surface);
+ }
+
+ munmap (data_map, map_size);
+ GAL_FreeSurface (surface);
+ }
+
+ GAL_OutOfMemory ();
+ return NULL;
+}
+
+/*
+ * Free data of a shared surface created by the above function.
+ */
+void GAL_DettachSharedSurfaceData (GAL_Surface *surface)
+{
+ GAL_VideoDevice *video = surface->video;
+
+ assert (surface->shared_header);
+
+ if (video && video->DettachSharedHWSurface) {
+ video->DettachSharedHWSurface (video, surface);
+ }
+
+ munmap (surface->shared_header,
+ surface->shared_header->buf_size
+ + sizeof (GAL_SharedSurfaceHeader));
+}
+
+#endif /* IS_COMPOSITING_SCHEMA */
+