Compare commits

..
35 Commits
Author SHA1 Message Date
VincentWei 08d4ab78e5 do not check pciaccess library if the cpu is not i386 2025-05-29 11:25:25 +08:00
Vincent Wei 0cda03a2eb Merge branch 'subpixel' into 'rel-5-0'
add func blend_pixel to fix font rendering issues on transparent backgrounds(SUBPIXEL)

See merge request VincentWei/minigui!18
2025-05-29 02:59:47 +00:00
xueshuming 4cf4d204e7 add func blend_pixel to fix font rendering issues on transparent backgrounds(SUBPIXEL) 2025-05-28 20:55:38 +08:00
VincentWei 6aa294e75b ignore ltmain.sh 2025-05-28 14:45:58 +08:00
VincentWei 7718be5200 ignore m4/*.m4 2025-05-28 14:44:43 +08:00
VincentWei 78e6d6581e update Makefile.am 2025-05-28 14:43:56 +08:00
VincentWei 62b3dc11d0 update libtool files 2025-05-28 14:43:25 +08:00
Vincent Wei 67cddafa19 change version to 5.0.16 2025-05-27 16:04:53 +08:00
Vincent Wei 4ae46a4b94 update 2025-05-27 15:53:44 +08:00
xueshuming 2791dc99ef Init Order: call 'mg_InitTimer' before call 'SystemThreads' 2025-05-27 15:45:03 +08:00
Vincent Wei b7525f3001 fix a bug: MSG_TIMEOUT for desktop thread was not fired correctly 2025-05-27 14:45:53 +08:00
Vincent Wei 4c55f2eac3 use sem_timedwait in the idle handler for desktop threads 2025-05-27 11:08:55 +08:00
Vincent Wei 3ad600d1bf Merge branch 'rel-5-0' 2025-05-09 14:02:57 +08:00
Vincent Wei 3c233a4164 update version to 5.0.15 2025-05-09 13:59:17 +08:00
Vincent Wei 3643606a7f restore the system interval timer for the server under runmode procs 2025-04-30 14:12:19 +08:00
Vincent Wei 3ef2340749 restore old logic to update timer_expected 2025-04-30 12:10:47 +08:00
Vincent Wei a583dc1cbb optimize and cleanup the timer module to fix the bad update of tick counter 2025-04-30 12:00:38 +08:00
xueshuming 0abaeef4c7 impl : __mg_save_png 2024-02-20 19:28:14 +08:00
Vincent Wei c2779cbf09 implement a new API: TestIfSharedSurfaceChanged() 2023-09-26 10:52:09 +08:00
Vincent Wei e118805eef fix a bug of GetUpdateRect: intersect bouding rectangle of invalid region with client rect 2023-09-16 15:43:07 +08:00
Vincent Wei 7513d461bf remove code about semaphhore for shared surface 2023-09-08 18:14:20 +08:00
Vincent Wei b131f00a79 fix compiling errors for MiniGUI-Standalone runmode 2023-09-04 10:45:05 +08:00
Vincent Wei 649fbf571e change copyright year 2023-09-01 16:07:56 +08:00
Vincent Wei e38fd05cb4 debug: use fcntl() instead of flock() 2023-09-01 16:03:50 +08:00
Vincent Wei ce53f2c703 use MSG_WINCOMPOSITED to reset the dirty information of a shared surface of a window 2023-09-01 12:25:04 +08:00
Vincent Wei fbebc94718 use GAL_RefSurface() in CreateMemDCFromSurface() 2023-09-01 10:01:11 +08:00
Vincent Wei b4ce6f9f10 helpers for locking/unlocking a file 2023-09-01 08:36:08 +08:00
Vincent Wei c04dde31e5 use flock() instead of semaphore for shared surfaces 2023-09-01 08:35:32 +08:00
Vincent Wei 5a2b425012 debug 2023-08-31 17:00:50 +08:00
Vincent Wei fa18025350 debug APIs for shared surfaces 2023-08-31 16:02:06 +08:00
Vincent Wei 890ab1db44 debug 2023-08-30 15:40:13 +08:00
Vincent Wei 3d963b3d25 Extend JoinLayer() to JoinLayerEx() to return the client identifier; Add a new API GetClientId() 2023-08-30 12:23:26 +08:00
Vincent Wei 29ac6a4277 initial implementation of new APIs of shared surface: AttachToSharedSurface(), GetSharedSurfaceInfo(), LockSharedSurfaceIfDirty(), UnlockSharedSurface(), and DetachFromSharedSurface() 2023-08-29 16:21:49 +08:00
Vincent Wei 96ecf5e9b7 Tune layout of struct _SharedSurfaceHeader; Change interface of GetWindowSharedSurfaceFD() 2023-08-29 12:50:58 +08:00
Vincent Wei 50aafa3faa initial implementation of CreateSharedSurface(), DestroySharedSurface(), GetSharedSurfaceFDByClientWindow(), and GetSharedSurfaceFDByName() 2023-08-29 12:12:51 +08:00
58 changed files with 1694 additions and 9514 deletions
+2
View File
@@ -10,6 +10,7 @@ Makefile
Makefile.in
.deps/
.libs/
m4/*.m4
/acinclude.m4
/aclocal.m4
/autom4te.cache
@@ -21,6 +22,7 @@ Makefile.in
/depcomp
/install-sh
/libtool
/ltmain.sh
/*.pc
/*config.h
/*config.h.in
+2
View File
@@ -1,3 +1,5 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src 3rd-party include rtos etc m4 cmake build
EXTRA_DIST = minigui.pc.in \
+3 -2
View File
@@ -460,7 +460,7 @@ for examples:
## HISTORY
21 years have pasted since MiniGUI was initially created at
27 years have pasted since MiniGUI was initially created at
the end of 1998, and now it becomes much reliable and stable.
During the past years, many remarkable changes have taken place in
the MiniGUI project.
@@ -566,13 +566,14 @@ A brief history description of the development progress is listed as follow:
1. Jan., 2022: FMSoft released MiniGUI version 5.0.9.
1. Sep., 2022: FMSoft released MiniGUI version 5.0.10.
1. Aug., 2023: FMSoft released MiniGUI version 5.0.13.
1. May., 2025: FMSoft released MiniGUI version 5.0.16.
## AUTHORS AND COPYING
The original author of MiniGUI is Vincent Wei, and now MiniGUI is maintained by FMSoft.
For more information, please refer to <http://www.fmsoft.cn>.
Copyright (C) 2002 ~ 2023, Beijing FMSoft Technologies Co., Ltd.
Copyright (C) 2002 ~ 2025, Beijing FMSoft Technologies Co., Ltd.
Copyright (C) 1998 ~ 2002, Vincent Wei
This program is free software: you can redistribute it and/or modify
+21 -5
View File
@@ -1,7 +1,9 @@
# Release Notes
- [Version 5.2.0](#version-520)
+ [What's new in version 5.2.0](#whats-new-in-version-520)
- [Version 5.0.16](#version-5016)
+ [What's new in version 5.0.16](#whats-new-in-version-5016)
- [Version 5.0.15](#version-5015)
+ [What's new in version 5.0.15](#whats-new-in-version-5015)
- [Version 5.0.13](#version-5013)
+ [What's new in version 5.0.13](#whats-new-in-version-5013)
- [Version 5.0.12](#version-5012)
@@ -34,10 +36,24 @@
+ [Changes leading to incompatibility](#changes-leading-to-incompatibility)
+ [Deprecated APIs](#deprecated-apis)
## Version 5.2.0
## Version 5.0.16
On Nov. 30, 2023, FMSoft announces the availability of MiniGUI 5.2.0,
which is an mainline release with some major enhancements:
On May 27, 2025, FMSoft announces the availability of MiniGUI 5.0.16,
which is a bugfix release with some minor enhancements of MiniGUI 5.0.x.
* BUGFIXING:
- The desktop thread can not handle the request from other threads as soon as possible.
- The `MSG_TIMEOUT` message can not be fired correctly under MiniGUI-Threads mode.
- Bad subpixel rendering when background color is RGBA0000.
* TUNING:
- Tune `configure.ac` and `Makefile.am` to use the system libtool scripts.
- Do not check `pciaccess` if the target architecture is not `i386`.
## Version 5.0.15
On May 09, 2025, FMSoft announces the availability of MiniGUI 5.0.15,
which is an enhancement release with some minor enhancements
of MiniGUI 5.0.x.
* ENHANCEMENTS:
- Optimize NEWGAL engines: `shadow`, `drm`, and `fbcon` for large resolution.
+1 -1
View File
@@ -1,4 +1,4 @@
Version 5.0.13 (2023/08/31)
Version 5.0.16 (2025/05/27)
This is a minor enhancement and bugfix release of MiniGUI 5.0.x, the stable version.
+2 -1
View File
@@ -1,6 +1,7 @@
#!/bin/sh
cat m4/*.m4 > acinclude.m4
libtoolize
cat m4/*.m4 > aclocal.m4
aclocal
autoheader
automake --add-missing --foreign --copy
+31 -29
View File
@@ -1,7 +1,8 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.60)
AC_INIT(libminigui, 5.0.14)
AC_PREREQ([2.71])
AC_INIT([libminigui],[5.0.16])
AC_CONFIG_SRCDIR(src/main/main.c)
AC_CONFIG_MACRO_DIRS([m4])
dnl Set various version strings - taken gratefully from the SDL sources
#
@@ -16,9 +17,9 @@ dnl Set various version strings - taken gratefully from the SDL sources
#
MINIGUI_MAJOR_VERSION=5
MINIGUI_MINOR_VERSION=0
MINIGUI_MICRO_VERSION=14
MINIGUI_INTERFACE_AGE=0
MINIGUI_BINARY_AGE=0
MINIGUI_MICRO_VERSION=16
MINIGUI_INTERFACE_AGE=1
MINIGUI_BINARY_AGE=1
MINIGUI_VERSION=$MINIGUI_MAJOR_VERSION.$MINIGUI_MINOR_VERSION.$MINIGUI_MICRO_VERSION
AC_SUBST(MINIGUI_MAJOR_VERSION)
@@ -40,35 +41,31 @@ AC_SUBST(LT_CURRENT)
AC_SUBST(LT_REVISION)
AC_SUBST(LT_AGE)
AC_CANONICAL_SYSTEM
AC_CANONICAL_TARGET
dnl ========================================================================
dnl Init automake
AM_INIT_AUTOMAKE
AC_CONFIG_HEADER(mgconfig.h)
AC_CONFIG_HEADERS([mgconfig.h])
dnl ========================================================================
dnl Check for tools
AC_PROG_LIBTOOL
AC_PROG_CC
AC_PROG_LD
AC_PROG_RANLIB
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
LT_INIT
dnl ========================================================================
dnl Checks for header files.
AC_HEADER_STDC
AC_HEADER_DIRENT
AC_CHECK_HEADERS(limits.h math.h locale.h unistd.h termio.h sys/types.h sys/time.h sys/select.h sys/memfd.h)
AC_CHECK_HEADERS(limits.h math.h stdatomic.h locale.h unistd.h termio.h sys/types.h sys/time.h sys/select.h sys/memfd.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
AC_HEADER_TIME
AC_STRUCT_TM
dnl Checks for library functions.
@@ -884,14 +881,14 @@ CheckFBCON()
if test "x$enable_video_fbcon" = "xyes"; then
AC_MSG_CHECKING(for FrameBuffer console support)
video_fbcon=no
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <linux/fb.h>
#include <linux/kd.h>
#include <linux/keyboard.h>
],[
],[
]], [[
]])],[
video_fbcon=yes
])
],[])
AC_MSG_RESULT($video_fbcon)
if test "x$video_fbcon" = "xyes"; then
AC_DEFINE(_MGGAL_FBCON, 1,
@@ -899,9 +896,13 @@ CheckFBCON()
VIDEO_SUBDIRS="$VIDEO_SUBDIRS fbcon"
VIDEO_DRIVERS="$VIDEO_DRIVERS fbcon/libvideo_fbcon.la"
have_pciaccess="yes"
AC_CHECK_LIB(pciaccess, pci_system_init,
DEP_LIBS="$DEP_LIBS -lpciaccess", have_pciaccess="no")
if test "x$target_cpu" = "xi386"; then
have_pciaccess="yes"
AC_CHECK_LIB(pciaccess, pci_system_init,
DEP_LIBS="$DEP_LIBS -lpciaccess", have_pciaccess="no")
else
have_pciaccess="no"
fi
if test "x$have_pciaccess" = "xyes"; then
AC_DEFINE(_MGHAVE_PCIACCESS, 1,
@@ -1170,12 +1171,12 @@ CheckDirectFBVideo()
if test "x$enable_video_dfb" = "xyes"; then
AC_MSG_CHECKING(for DirectFB support)
video_dfb=no
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <directfb.h>
],[
],[
]], [[
]])],[
video_dfb=yes
])
],[])
AC_MSG_RESULT($video_dfb)
if test "x$video_dfb" = "xyes"; then
AC_DEFINE(_MGGAL_DFB, 1,
@@ -2641,7 +2642,7 @@ if test "x$devel_mode" = "xyes"; then
CPPFLAGS="$CPPFLAGS -D_DEBUG"
fi
if test "$ac_cv_prog_gcc" = "yes"; then
if test "$ac_cv_c_compiler_gnu" = "yes"; then
CFLAGS="$CFLAGS -Wall -Werror"
fi
@@ -2651,7 +2652,7 @@ else
CPPFLAGS="$CPPFLAGS -DNDEBUG"
fi
if test "$ac_cv_prog_gcc" = "yes"; then
if test "$ac_cv_c_compiler_gnu" = "yes"; then
CFLAGS="$CFLAGS -fmax-errors=10 -Wstrict-prototypes -pipe"
fi
@@ -2688,8 +2689,7 @@ AM_CONDITIONAL(MGLIB_MVFB, test "x$with_libsuffix" = "xmvfb")
AM_CONDITIONAL(MG_ENABLE_SPLASH, test "x$build_splash" = "xyes")
AM_CONDITIONAL(MG_ENABLE_SCREENSAVER, test "x$build_screensaver" = "xyes")
AC_OUTPUT(
minigui.pc
AC_CONFIG_FILES([minigui.pc
Makefile
cmake/Makefile
src/Makefile
@@ -2756,7 +2756,8 @@ etc/Makefile
3rd-party/scripteasy/Makefile
m4/Makefile
build/Makefile
)
])
AC_OUTPUT
CCVERSION=`$CC --version | head -n 1`
@@ -2765,6 +2766,7 @@ AC_MSG_NOTICE([
# Main building configuration:
## Global Features:
* Architecture: ${target_cpu}
* Operating system: ${osname}
* Runtime mode: ${runtime_mode}
* Virtual Window: ${virtual_window}
+2
View File
@@ -268,6 +268,8 @@ MGUI_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8);
#define MG_UNLIKELY(expr) (expr)
#endif
#define HAVE(FEATURE) (defined HAVE_##FEATURE && HAVE_##FEATURE)
/**
* \defgroup endian_info Endianness information
* @{
+99 -58
View File
@@ -1704,12 +1704,13 @@ MG_EXPORT BOOL GUIAPI IsScreenDC (HDC hdc);
*/
MG_EXPORT BOOL GUIAPI IsWindowDC (HDC hdc);
#ifdef _MGSCHEMA_COMPOSITING
struct GAL_Surface;
typedef struct GAL_Surface *HSURF;
#ifdef _MGSCHEMA_COMPOSITING
/**
* \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);
@@ -1770,7 +1772,7 @@ MG_EXPORT BOOL GUIAPI DestroySharedSurface (HSURF surf);
/**
* \fn int GUIAPI GetSharedSurfaceFDByClientWindow (int client,
* HWND hwnd)
* HWND hwnd, size_t *map_size, DWORD *flags)
* \brief Gets the file descriptor of the shared surface of a window created
* by another client.
*
@@ -1781,21 +1783,26 @@ MG_EXPORT BOOL GUIAPI DestroySharedSurface (HSURF surf);
*
* \param client The client identifier.
* \param hwnd The handle to the window created by the client.
* \param map_size The pointer to a buffer of size_t to receive the whole size
* of the shared surface in bytes; nullable.
* \param flags The pointer to a buffer of DWORD to receive the flags of
* the shared surface; nullable.
*
* \return The file descriptor which represents the shared surface on success;
* a value less than 0 for failure.
*
* \note This function only available when _MGSCHEMA_COMPOSITING is defined.
*
* \sa CreateSharedSurface
* \sa AttachToSharedSurface, GetWindowSharedSurfaceFD
*
* 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)
* \fn int GUIAPI GetSharedSurfaceFDByName (const char *name,
* size_t *map_size, DWORD *flags)
* \brief Gets the file descriptor of a shared surface by name.
*
* This function gets the file descriptor of the shared surface created
@@ -1804,6 +1811,10 @@ MG_EXPORT int GUIAPI GetSharedSurfaceFDByClientWindow (int client,
* the shared surface.
*
* \param name The gobal unique name for the shared surface.
* \param map_size The pointer to a buffer of size_t to receive the whole size
* of the shared surface in bytes; nullable.
* \param flags The pointer to a buffer of DWORD to receive the flags of
* the shared surface; nullable.
*
* \return The file descriptor which represents the shared surface on success;
* a value less than 0 for failure.
@@ -1814,10 +1825,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,18 +1847,22 @@ 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,
* size_t *file_size, size_t *pixel_off)
* \brief Gets the file descriptor of a shared surface.
* \fn const char *GUIAPI GetSharedSurfaceInfo (HSURF surf, int *fd,
* SIZE *size, int *pitch, size_t *map_size, off_t *pixels_off)
* \brief Gets the basic information of a shared surface.
*
* This function gets the file descriptor of the shared surface. It also
* returns the size and the pitch of the surface if \a size or \a pitch is
* not NULL.
* This function gets the name and other information of
* the given shared surface \a surf. It also returns the file descriptor,
* the size, or the pitch of the surface if \a fd, \a size or \a pitch
* is not NULL.
*
* \param surf The handle to the shared surface.
* \param fd The pointer to a buffer of int to return the file descriptor of
* the shared surface; nullable.
* \param size The pointer to a buffer of SIZE to return the size of
* the shared surface; nullable.
* \param pitch The pointer to a buffer of int for value of pitch; nullable.
@@ -1854,8 +1871,8 @@ MG_EXPORT HSURF GUIAPI AttachToSharedSurface (GHANDLE video, int fd);
* \param pixel_off The pointer to a buffer of size_t for the offset of
* pixel data; nullable.
*
* \return The file descriptor of the shared surface on success;
* a value less than zero for failure.
* \return The name of the shared surface on success; NULL for failure.
* Note that if the name is an empty string, it is an anonymous surface.
*
* \note This function only available when _MGSCHEMA_COMPOSITING is defined.
*
@@ -1863,30 +1880,48 @@ MG_EXPORT HSURF GUIAPI AttachToSharedSurface (GHANDLE video, int fd);
*
* Since 5.2.0
*/
MG_EXPORT int GUIAPI GetSharedSurfaceInfo (HSURF surf, SIZE *size, int *pitch,
size_t *file_size, size_t *pixel_off);
MG_EXPORT const char *GUIAPI GetSharedSurfaceInfo (HSURF surf, int *fd,
SIZE *size, int *pitch, size_t *map_size, off_t *pixels_off);
/**
* \fn BOOL GUIAPI LockSharedSurfaceIfDirty (HSURF surf,
* unsigned old_dirty_age, unsigned *dirty_age,
* int *nr_dirty_rects, RECT *const *dirty_rects)
* \brief Locks the shared surface if it is dirty.
* \fn BOOL GUIAPI TestIfSharedSurfaceChanged (HSURF surf,
* unsigned dirty_age)
* \brief Tests if a shared surface changed.
*
* This function compares the dirty age of the shared surface with the value
* containing in \a dirty_age, and lock the shared surface if it has
* a larger dirty age value.
* This function tests if the given shared surface \a surf had changed, i.e.,
* it has a different dirty age value against the specified value \a dirty_age.
*
* \param surf The handle to the shared surface.
* \param old_dirty_age The old dirty age.
* \param dirty_age The pointer to a buffer of unsigned integer to return
* the current dirty age of the shared surface.
* \param dirty_age The dirty age to compare.
*
* \return TRUE for changed; FALSE for no change or failure.
*
* \note This function only available when _MGSCHEMA_COMPOSITING is defined.
*
* \sa LockSharedSurface
*
* Since 5.2.0
*/
MG_EXPORT BOOL GUIAPI TestIfSharedSurfaceChanged (HSURF surf,
unsigned dirty_age);
/**
* \fn BOOL GUIAPI LockSharedSurface (HSURF surf,
* unsigned *dirty_age, int *nr_dirty_rects, const RECT **dirty_rects)
* \brief Locks the shared surface for read.
*
* This function locks the given shared surface \a surf and returns
* the dirty information.
*
* \param surf The handle to the shared surface.
* \param dirty_age The pointer to a buffer of unsigned integer to
* return the latest dirty age of the shared surface; nullable.
* \param nr_dirty_rects The pointer to a buffer of integer to return the valid
* dirty rectangles; nullable.
* \param dirty_rects The pointer to a buffer of (const RECT *) for the array
* of dirty rectangles; nullable.
*
* \return TRUE for success and if the value contains in \a dirty_age is larger
* than \a old_dirty_age, the surface was locked; otherwise failure.
* \return TRUE for locked; FALSE for failure.
*
* \note This function only available when _MGSCHEMA_COMPOSITING is defined.
*
@@ -1894,31 +1929,26 @@ MG_EXPORT int GUIAPI GetSharedSurfaceInfo (HSURF surf, SIZE *size, int *pitch,
*
* Since 5.2.0
*/
MG_EXPORT BOOL GUIAPI LockSharedSurfaceIfDirty (HSURF surf,
unsigned old_dirty_age, unsigned *dirty_age,
int *nr_dirty_rects, RECT *const *dirty_rects);
MG_EXPORT BOOL GUIAPI LockSharedSurface (HSURF surf,
unsigned *dirty_age, int *nr_dirty_rects, const RECT **dirty_rects);
/**
* \fn BOOL GUIAPI UnlockSharedSurface (HSURF surf, BOOL clear_dirty)
* \brief Unocks the shared surface and clears the dirty information.
* \fn BOOL GUIAPI UnlockSharedSurface (HSURF surf)
* \brief Unlocks the shared surface.
*
* This function compares the dirty age of the shared surface with the value
* containing in \a dirty_age, and lock the shared surface if it has
* a larger dirty age value.
* This function unlocks the given shared surface \a surf.
*
* \param surf The handle to the shared surface.
* \param clear_dirty A boolean value indicates whether to clear the dirty
* information of the shared surface.
*
* \return TRUE on success; otherwise failure.
*
* \note This function only available when _MGSCHEMA_COMPOSITING is defined.
*
* \sa LockSharedSurfaceIfDirty
* \sa LockSharedSurface
*
* Since 5.2.0
*/
MG_EXPORT BOOL GUIAPI UnlockSharedSurface (HSURF surf, BOOL clear_dirty);
MG_EXPORT BOOL GUIAPI UnlockSharedSurface (HSURF surf);
/**
* \fn BOOL GUIAPI DetachFromSharedSurface (HSURF surf)
@@ -1938,28 +1968,39 @@ MG_EXPORT BOOL GUIAPI UnlockSharedSurface (HSURF surf, BOOL clear_dirty);
* Since 5.2.0
*/
MG_EXPORT BOOL GUIAPI DetachFromSharedSurface (HSURF surf);
#endif /* _MGSCHEMA_COMPOSITING */
/**
* \fn HDC GUIAPI CreateMemDCOnSharedSurface (HSURF surf, const RECT *rect);
* \brief Creates a memory DC on a shared surface.
* \fn HDC GUIAPI CreateMemDCFromSurface (HSURF surf);
* \brief Creates a memory DC from a surface.
*
* This function creates a memory DC on the specified shared surface \a surf
* within the specified rectangle \a rect on the surface.
* This function creates a memory DC on the specified surface \a surf.
*
* \param surf The handle to the shared surface.
* \param rect A rectangle in the surface which defines the bounds of memory DC;
* NULL for whole surface.
*
* \return The handle to a new memory DC, HDC_INVALID indicates an error.
*
* \note This function only available when _MGSCHEMA_COMPOSITING is defined.
*
* \sa DeleteMemDC
*
* Since 5.0.13
* Since 5.2.0
*/
MG_EXPORT HDC GUIAPI CreateMemDCOnSharedSurface (HSURF surf, const RECT *rect);
#endif /* _MGSCHEMA_COMPOSITING */
MG_EXPORT HDC GUIAPI CreateMemDCFromSurface(HSURF surf);
/**
* \fn HSURF GUIAPI GetSurfaceFromDC(HDC hdc);
* \brief Gets surface handle from a DC.
*
* This function returns the handle to the surface of the given DC \a hdc.
*
* \param hdc The handle to the DC.
*
* \return The handle to the surface, NULL for failure.
*
* \sa CreateMemDCFromSurface
*
* Since 5.2.0
*/
MG_EXPORT HSURF GUIAPI GetSurfaceFromDC(HDC hdc);
/**
* \fn HDC GUIAPI CreateMemDCEx (int width, int height, int depth, DWORD flags, \
+86 -5
View File
@@ -456,6 +456,45 @@ MG_EXPORT void GUIAPI MiniGUIPanic (int exitcode);
* @{
*/
/**
* \fn GHANDLE GUIAPI JoinLayerEx (const char* layer_name,
const char* client_name,
int max_nr_highers, int max_nr_normals, int *cli_id)
* \brief Joins to a layer and returns the client identifier if success.
*
* This function should be called by clients before calling any other MiniGUI
* functions. You can call \a GetLayerInfo to get the layer information.
* If the layer to be joined does not exist, the server, i.e. \a mginit, will
* try to create a new one. If you passed a NULL pointer or a null string for
* \a layer_name, the client will join to the default layer.
*
* If the client want to create a new layer, you should specify the maximal
* number of z-nodes in the higher level (max_nr_highers) and the maximal
* number of z-nodes in the normal level (max_nr_normals) of the new layer.
* Passing zero to \a max_nr_highers and max_nr_normals will use the default
* values, and the default values are specified by ServerStartup.
*
* Note that the server will create a default layer named "mginit".
*
* \param layer_name The name of the layer. You can use NAME_TOPMOST_LAYER to
* specify the current topmost layer.
* \param client_name The name of the client.
* \param max_nr_highers The maximal number of z-nodes in the higher level of
* the new layer.
* \param max_nr_normals The maximal number of z-nodes in the normal level of
* the new layer.
* \param cli_id The pointer to a buffer of int to return the client identifier.
*
* \return The handle to the layer on success, INV_LAYER_HANDLE on error.
*
* \note Only call this function in clients of MiniGUI-Processes.
*
* \sa GetLayerInfo, ServerStartup, ServerCreateLayer
*/
MG_EXPORT GHANDLE GUIAPI JoinLayerEx (const char* layer_name,
const char* client_name,
int max_nr_highers, int max_nr_normals, int *cli_id);
/**
* \fn GHANDLE GUIAPI JoinLayer (const char* layer_name,
const char* client_name,
@@ -490,9 +529,30 @@ MG_EXPORT void GUIAPI MiniGUIPanic (int exitcode);
*
* \sa GetLayerInfo, ServerStartup, ServerCreateLayer
*/
MG_EXPORT GHANDLE GUIAPI JoinLayer (const char* layer_name,
static inline GHANDLE GUIAPI JoinLayer (const char* layer_name,
const char* client_name,
int max_nr_highers, int max_nr_normals);
int max_nr_highers, int max_nr_normals)
{
return JoinLayerEx (layer_name, client_name,
max_nr_highers, max_nr_normals, NULL);
}
/**
* \fn int GUIAPI GetClientId (void)
* \brief Gets the client identifier.
*
* You can get the information of a layer through this function.
* The information will be returned through the pointer arguments
* if the specific pointer is not NULL.
*
* \return Returns the client identifier of the current process.
* Note that the server always returns 0.
*
* \sa JoinLayerEx
*
* Since 5.2.0
*/
MG_EXPORT int GUIAPI GetClientId (void);
/**
* \fn GHANDLE GUIAPI GetLayerInfo (const char* layer_name,
@@ -1958,7 +2018,7 @@ const CompositorOps* __ex_compositor_get (const char* name,
*
* \sa RegisterRequestHandler
*/
#define MAX_SYS_REQID 0x0024
#define MAX_SYS_REQID 0x0023
/**
* \def MAX_REQID
@@ -2125,7 +2185,7 @@ MG_EXPORT int GUIAPI ServerSendReplyEx (int clifd,
* \fn int GUIAPI ServerSendReply (int clifd, const void* reply, int len)
* \brief Sends the reply to the client.
*
* This function sends a replay pointed to by \a reply which is
* This function sends a reply pointed to by \a reply which is
* \a len bytes long to the client.
*
* \note Only used by the server to send the reply to the client.
@@ -2673,6 +2733,26 @@ MG_EXPORT void GUIAPI DesktopUpdateAllWindow (void);
#define DUMMY_LAYER_HANDLE (GHANDLE)(-1)
/**
* \fn GHANDLE GUIAPI JoinLayerEx (const char* layer_name,
const char* client_name,
int max_nr_highers, int max_nr_normals, int *cli_fd)
* \brief The dummy replacement of the same function for MiniGUI-Processes.
*
* This function is a replacment of the same function for MiniGUI-Processes
* runtime mode. We provide this function for MiniGUI-Threads and
* MiniGUI-Standalone runtime modes, in order to avoid using the
* conditional compilation instructions in your source code.
*
* \return Always returns DUMMY_LAYER_HANDLE to indicate success.
*/
static inline GHANDLE GUIAPI JoinLayerEx (const char* layer_name,
const char* client_name,
int max_nr_highers, int max_nr_normals, int *cli_fd)
{
return DUMMY_LAYER_HANDLE;
}
/**
* \fn GHANDLE GUIAPI JoinLayer (const char* layer_name,
const char* client_name,
@@ -2687,7 +2767,8 @@ MG_EXPORT void GUIAPI DesktopUpdateAllWindow (void);
* \return Always returns DUMMY_LAYER_HANDLE to indicate success.
*/
static inline GHANDLE GUIAPI JoinLayer (const char* layer_name,
const char* client_name, int max_nr_highers, int max_nr_normals)
const char* client_name,
int max_nr_highers, int max_nr_normals)
{
return DUMMY_LAYER_HANDLE;
}
+11 -5
View File
@@ -2990,18 +2990,22 @@ typedef struct _WINMASKINFO {
if the client moved to a new layer */
#define MSG_LAYERCHANGED 0x0149
/* Since 5.2.0; the server send this message to the client
if a window has been composited to the screen. */
#define MSG_WINCOMPOSITED 0x014A
#endif /* defined _MGRM_PROCESSES */
/* Since 5.0.0: for managing message thread */
#define MSG_MANAGE_MSGTHREAD 0x014A
#define MSG_MANAGE_MSGTHREAD 0x014B
#define MSGTHREAD_SIGNIN 0x00
#define MSGTHREAD_SIGNOUT 0x01
/* Since 5.0.0: for calculating the default position */
#define MSG_CALC_POSITION 0x014B
#define MSG_CALC_POSITION 0x014C
/* Since 5.0.6: for waking up the client */
#define MSG_WAKEUP_CLIENT 0x014C
#define MSG_WAKEUP_CLIENT 0x014D
/**
* \def MSG_DOESNEEDIME
@@ -7238,7 +7242,8 @@ MG_EXPORT BOOL GUIAPI SetMainWindowGestureFlags (HWND hWnd, DWORD dwFlags);
#ifdef _MGSCHEMA_COMPOSITING
/**
* \fn int GUIAPI GetWindowSharedSurfaceFD (HWND hwnd)
* \fn int GUIAPI GetWindowSharedSurfaceFD (HWND hwnd, size_t *map_size,
* DWORD *flags)
* \brief Gets the file descriptor of the surface buffer for a window or
* the main window it locates.
*
@@ -7258,7 +7263,8 @@ MG_EXPORT BOOL GUIAPI SetMainWindowGestureFlags (HWND hWnd, DWORD dwFlags);
*
* Since 5.0.13
*/
MG_EXPORT int GUIAPI GetWindowSharedSurfaceFD (HWND hWnd);
MG_EXPORT int GUIAPI GetWindowSharedSurfaceFD (HWND hWnd, size_t *map_size,
DWORD *flags);
/**
* \fn BOOL GUIAPI SetMainWindowCompositing (HWND hWnd,
-5064
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,4 +1,4 @@
# This file does not do anything, except making sure these files are included
# when you run 'make dist'.
EXTRA_DIST = libtool.m4
EXTRA_DIST =
-3724
View File
File diff suppressed because it is too large Load Diff
+32 -3
View File
@@ -184,6 +184,23 @@ static void process_socket_message (MSG *msg)
LOSWORD(msg->wParam), HISWORD(msg->wParam),
LOSWORD(msg->lParam), HISWORD(msg->lParam));
}
#ifdef _MGSCHEMA_COMPOSITING
else if (msg->message == MSG_WINCOMPOSITED) {
/* Since 5.2.0 */
int slot = (int)msg->wParam;
HWND hwnd = (HWND)msg->lParam;
unsigned dirty_age = (unsigned)msg->time;
if (__mg_client_check_znode_hwnd(slot, hwnd, __mg_client_id)) {
GAL_Surface *ssurf = ((PMAINWIN)hwnd)->surf;
assert(ssurf->shared_header);
__mg_lock_file_for_write(ssurf->fd);
if (ssurf->dirty_info->dirty_age == dirty_age) {
ssurf->dirty_info->nr_dirty_rcs = 0;
}
__mg_unlock_file_for_write(ssurf->fd);
}
}
#endif
else {
if (msg->hwnd == HWND_NULL) {
msg->hwnd = HWND_DESKTOP;
@@ -518,8 +535,8 @@ BOOL client_IdleHandler4Client (PMSGQUEUE msg_queue, BOOL wait)
return (n > 0);
}
GHANDLE GUIAPI JoinLayer (const char* layer_name, const char* client_name,
int max_nr_topmosts, int max_nr_normals)
GHANDLE GUIAPI JoinLayerEx (const char* layer_name, const char* client_name,
int max_nr_topmosts, int max_nr_normals, int *cli_id)
{
GHANDLE layer_handle = INV_LAYER_HANDLE;
REQUEST req;
@@ -529,8 +546,12 @@ GHANDLE GUIAPI JoinLayer (const char* layer_name, const char* client_name,
if (mgIsServer)
return layer_handle;
if (__mg_client_id != 0) /* Already joined, return the handle */
if (__mg_client_id != 0) {
/* Already joined, return the handle */
if (cli_id)
*cli_id = __mg_client_id;
return GetLayerInfo (NAME_SELF_LAYER, NULL, NULL, NULL);
}
if (layer_name) {
strncpy (info.layer_name, layer_name, LEN_LAYER_NAME);
@@ -593,10 +614,18 @@ GHANDLE GUIAPI JoinLayer (const char* layer_name, const char* client_name,
__mg_start_client_desktop ();
if (cli_id)
*cli_id = __mg_client_id;
ret:
return layer_handle;
}
int GUIAPI GetClientId (void)
{
return __mg_client_id;
}
GHANDLE GUIAPI GetLayerInfo (const char* layer_name,
int* nr_clients, BOOL* is_topmost, int* cli_active)
{
+1 -1
View File
@@ -2185,7 +2185,7 @@ static int create_memdc_for_menu (TRACKMENUINFO* ptmi)
return -1;
}
ptmi->dc = CreateMemDCFromSurface (surf);
ptmi->dc = __mg_create_memdc_for_surface (surf);
if (ptmi->dc == HDC_INVALID) {
GAL_FreeSurface (surf);
return -1;
+24 -13
View File
@@ -4476,10 +4476,10 @@ HWND GUIAPI CreateMainWindowEx2 (PMAINWINCREATE pCreateInfo, LINT id,
#endif
#ifdef _MGSCHEMA_COMPOSITING
// Close file descriptor to free kernel memory?
if (pWin->surf->shared_header) {
close (pWin->surf->shared_header->fd);
pWin->surf->shared_header->fd = -1;
/* Since 5.2.0: keep fd available. */
if (0 && pWin->surf->shared_header) {
close (pWin->surf->fd);
pWin->surf->fd = -1;
}
#endif
@@ -5585,11 +5585,13 @@ BOOL GUIAPI ValidateRegion (HWND hWnd, const CLIPRGN* pRgn)
BOOL GUIAPI GetUpdateRect (HWND hWnd, RECT* update_rect)
{
PMAINWIN pWin;
RECT rcClient;
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
pWin = MG_GET_WINDOW_PTR (hWnd);
*update_rect = pWin->InvRgn.rgn.rcBound;
GetClientRect(hWnd, &rcClient);
IntersectRect(update_rect, &pWin->InvRgn.rgn.rcBound, &rcClient);
return TRUE;
}
@@ -6036,10 +6038,10 @@ HWND GUIAPI CreateWindowEx2 (const char* spClassName,
}
#ifdef _MGSCHEMA_COMPOSITING
// Close file descriptor to free kernel memory?
if (dwExStyle & WS_EX_CTRLASMAINWIN && pNewCtrl->surf->shared_header) {
close (pNewCtrl->surf->shared_header->fd);
pNewCtrl->surf->shared_header->fd = -1;
/* Since 5.2.0: keep fd available. */
if (0 && dwExStyle & WS_EX_CTRLASMAINWIN && pNewCtrl->surf->shared_header) {
close (pNewCtrl->surf->fd);
pNewCtrl->surf->fd = -1;
}
#endif
@@ -6067,13 +6069,22 @@ error:
}
#ifdef _MGSCHEMA_COMPOSITING
int GUIAPI GetWindowSharedSurfaceFD (HWND hWnd)
int GUIAPI GetWindowSharedSurfaceFD (HWND hWnd, size_t *map_size, DWORD *flags)
{
MG_CHECK_RET (MG_IS_APP_WINDOW (hWnd), -1);
MG_CHECK_RET (MG_IS_NORMAL_WINDOW (hWnd), -1);
PMAINWIN pWin = (PMAINWIN)hWnd;
if (pWin->surf->shared_header)
return pWin->surf->shared_header->fd;
if (pWin->surf->shared_header) {
if (map_size)
*map_size = pWin->surf->shared_header->map_size;
if (flags) {
*flags = MEMDC_FLAG_SWSURFACE;
if (pWin->surf->shared_header->byhw)
*flags |= MEMDC_FLAG_HWSURFACE;
}
return pWin->surf->fd;
}
return -1;
}
+11 -50
View File
@@ -46,7 +46,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "common.h"
@@ -66,18 +65,14 @@
#define LEN_TOUCH_DEV 127
#define AUTO_MOUSE_UP_TICKCOUNT 20
static int sg_tp_event_fd = -1, sg_key_event_fd = -1;
static short MOUSEX = 0, MOUSEY = 0, MOUSEBUTTON = 0;
static DWORD g_last_tickcount = 0;
static bool g_has_auto_event = false;
static int get_touch_data (short *x, short *y, short *button)
{
struct input_event data;
if (read (sg_tp_event_fd, &data, sizeof (data)) == sizeof (data)) {
while (read (sg_tp_event_fd, &data, sizeof (data)) == sizeof (data)) {
/* do nothing for EV_SYN due to non-blocking read.
if (data.type == EV_SYN) {
@@ -96,12 +91,10 @@ static int get_touch_data (short *x, short *y, short *button)
if (data.type == EV_KEY) {
switch (data.code) {
case BTN_TOUCH:
if (data.value == 0) {
if (data.value > 0)
*button = IAL_MOUSE_LEFTBUTTON;
else
*button = 0;
g_last_tickcount = 0;
return 0;
}
g_last_tickcount = GetTickCount();
break;
default:
@@ -110,7 +103,6 @@ static int get_touch_data (short *x, short *y, short *button)
}
}
else if (data.type == EV_ABS) {
g_last_tickcount = GetTickCount();
switch (data.code) {
case ABS_X:
*x = data.value;
@@ -118,8 +110,7 @@ static int get_touch_data (short *x, short *y, short *button)
case ABS_Y:
*y = data.value;
*button = IAL_MOUSE_LEFTBUTTON;
return 0;
break;
case ABS_MT_POSITION_X:
*x = data.value;
@@ -127,8 +118,7 @@ static int get_touch_data (short *x, short *y, short *button)
case ABS_MT_POSITION_Y:
*y = data.value;
*button = IAL_MOUSE_LEFTBUTTON;
return 0;
break;
case ABS_MT_TOUCH_MAJOR:
break;
@@ -146,20 +136,13 @@ static int get_touch_data (short *x, short *y, short *button)
}
}
if (g_has_auto_event) {
g_has_auto_event = false;
return 0;
}
return -1;
return 0;
}
static int mouse_update (void)
{
static int idx = 0;
if (get_touch_data (&MOUSEX, &MOUSEY, &MOUSEBUTTON) == 0) {
if (get_touch_data (&MOUSEX, &MOUSEY, &MOUSEBUTTON) == 0)
return 1;
}
return 0;
}
@@ -210,32 +193,10 @@ static int wait_event (int which, int maxfd, fd_set *in, fd_set *out, fd_set *ex
}
}
else if (e < 0) {
if (g_last_tickcount > 0) {
DWORD tickcount = GetTickCount();
if (tickcount - g_last_tickcount >= AUTO_MOUSE_UP_TICKCOUNT) {
MOUSEBUTTON = 0;
retvalue |= IAL_MOUSEEVENT;
g_last_tickcount = 0;
g_has_auto_event = true;
}
}
else {
retvalue = -1;
}
retvalue = -1;
}
else {
if (g_last_tickcount > 0) {
DWORD tickcount = GetTickCount();
if (tickcount - g_last_tickcount >= AUTO_MOUSE_UP_TICKCOUNT) {
MOUSEBUTTON = 0;
retvalue |= IAL_MOUSEEVENT;
g_last_tickcount = 0;
g_has_auto_event = true;
}
}
else {
retvalue = 0;
}
retvalue = 0;
}
return retvalue;
@@ -253,7 +214,7 @@ BOOL ial_InitSingleTouchKey (INPUT* input, const char* mdev, const char* mtype)
return FALSE;
}
sg_tp_event_fd = open (touch_dev, O_RDONLY);
sg_tp_event_fd = open (touch_dev, O_RDONLY | O_NONBLOCK);
if (sg_tp_event_fd < 0) {
_WRN_PRINTF ("failed when opening touch event device: %s\n", touch_dev);
return FALSE;
+16 -10
View File
@@ -117,10 +117,22 @@
#define REQID_LOADCURSOR_PNG 0x001D
// Load cursor from in-memory PNG
#define REQID_LOADCURSOR_PNG_MEM 0x001E
#if 0 // Deprecated since 5.2.0
// allocate semaphore for shared surface
#define REQID_ALLOC_SURF_SEM 0x001F
// free semaphore of shared surface
#define REQID_FREE_SURF_SEM 0x0020
#endif
/* Since 5.2.0 */
// Operate a shared surface to register/revoke the name and set the fd
#define REQID_OPERATENAMEDSSURF 0x001F
#define ID_NAMEDSSURFOP_REGISTER 1
#define ID_NAMEDSSURFOP_SET 2
#define ID_NAMEDSSURFOP_REVOKE 3
#define REQID_RESERVED 0x0020
// Move the current client to another layer
#define REQID_MOVETOLAYER 0x0021
@@ -130,14 +142,7 @@
// Authenticate client
#define REQID_AUTHCLIENT 0x0023
/* Since 5.2.0 */
// Operate a shared surface to register/revoke the name and set the fd
#define REQID_OPERATENAMEDSSURF 0x0024
#define ID_NAMEDSSURFOP_REGISTER 1
#define ID_NAMEDSSURFOP_SET 2
#define ID_NAMEDSSURFOP_REVOKE 3
#define REQID_SYS_LAST REQID_OPERATENAMEDSSURF
#define REQID_SYS_LAST REQID_AUTHCLIENT
/*
* XXX: To fellows who need to add a new REQID,
@@ -163,13 +168,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 {
@@ -378,6 +383,7 @@ void __mg_start_client_desktop (void);
void __mg_update_window (HWND hwnd, int left, int top, int right, int bottom);
BOOL __mg_client_check_znode_hwnd (int slot, HWND hwnd, int cli);
BOOL __mg_client_check_hwnd (HWND hwnd, int cli);
BOOL __mg_client_on_layer_changed (GHANDLE layer_handle, int zi_shmid);
+6 -4
View File
@@ -521,14 +521,16 @@ static inline void _dc_step_y (PDC pdc, int step)
# define BLOCK_DRAW_SEM(pdc) \
do { \
if (pdc->surface->shared_header) \
LOCK_SURFACE_SEM (pdc->surface->shared_header->sem_num); \
if (pdc->surface->shared_header) { \
__mg_lock_file_for_write(pdc->surface->fd); \
} \
} while (0)
# define UNBLOCK_DRAW_SEM(pdc) \
do { \
if (pdc->surface->shared_header) \
UNLOCK_SURFACE_SEM (pdc->surface->shared_header->sem_num); \
if (pdc->surface->shared_header) { \
__mg_unlock_file_for_write(pdc->surface->fd); \
} \
} while (0)
# define IS_SCREEN_SURFACE(pdc) \
+10 -8
View File
@@ -51,12 +51,10 @@
#ifndef GUI_DRAWSEMOP_H
#define GUI_DRAWSEMOP_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <errno.h>
#include "misc.h"
static inline void my_sem_op (int semid, int num, int op)
{
struct sembuf sb;
@@ -70,6 +68,9 @@ again:
if (errno == EINTR) {
goto again;
}
else {
_ERR_PRINTF("Failed semop: %m\n");
}
}
}
@@ -79,10 +80,7 @@ again:
#define LOCK_SCREEN_SEM() my_sem_op(SHAREDRES_SEMID, _IDX_SEM_SCR, -1)
#define UNLOCK_SCREEN_SEM() my_sem_op(SHAREDRES_SEMID, _IDX_SEM_SCR, 1)
#ifdef _MGSCHEMA_COMPOSITING
# define LOCK_SURFACE_SEM(num) my_sem_op(SHAREDRES_SEMID_SHARED_SURF, num, -1)
# define UNLOCK_SURFACE_SEM(num) my_sem_op(SHAREDRES_SEMID_SHARED_SURF, num, 1)
#endif
extern int __mg_client_id;
#ifdef _MGHAVE_CURSOR
@@ -157,6 +155,10 @@ again:
# define UNLOCK_MOUSEMOVE_SEM() my_sem_op(SHAREDRES_SEMID, _IDX_SEM_MOUSEMOVE, 1)
#endif /* _MGRM_PROCESSES */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifdef __cplusplus
}
#endif /* __cplusplus */
+5 -38
View File
@@ -258,7 +258,7 @@ struct _MSGQUEUE
int loop_depth; // message loop depth, for dialog boxes
int idle_counter; // the idle connter for MSG_IDLE
DWORD last_ticks_desktop; // the last tick count for desktop timer
DWORD last_ticks; // the last tick count saved; since 5.0.14
/* Since 5.0.0, MiniGUI provides support for timers per message thread */
int nr_timers; // the number of active timers
@@ -911,40 +911,9 @@ static inline MSGQUEUE* getMsgQueueIfMainWindowInThisThread (PMAINWIN pMainWin)
#endif /* defined _MGHAVE_VIRTUAL_WINDOW */
#if 0 /* deprecated code */
/* since 5.0.0, we always use QS_DESKTIMER for desktop timer */
/* since 5.0.0, we no longer use the timer thread */
static inline void AlertDesktopTimerEvent (void)
{
if (__mg_dsk_msg_queue) {
__mg_dsk_msg_queue->expired_timer_mask = 1;
POST_MSGQ (__mg_dsk_msg_queue);
}
}
static inline void AlertDesktopTimerEvent (void)
{
__mg_dsk_msg_queue->dwState |= QS_DESKTIMER;
#ifdef _MGHAVE_VIRTUAL_WINDOW
if (getMsgQueueForThisThread() != __mg_dsk_msg_queue)
POST_MSGQ (__mg_dsk_msg_queue);
#endif /* defined _MGHAVE_VIRTUAL_WINDOW */
}
static inline void setMsgQueueTimerFlag (PMSGQUEUE pMsgQueue, int slot)
{
pMsgQueue->expired_timer_mask |= (0x01UL << slot);
POST_MSGQ (pMsgQueue);
}
static inline void removeMsgQueueTimerFlag (PMSGQUEUE pMsgQueue, int slot)
{
pMsgQueue->expired_timer_mask &= ~(0x01UL << slot);
}
#endif /* deprecated code */
BOOL mg_InitTimer (BOOL use_sys_timer);
void mg_TerminateTimer (BOOL use_sys_timer);
/* Since 5.0.14, remove arg use_sys_timer */
BOOL mg_InitTimer (void);
void mg_TerminateTimer (void);
/*window element renderer manager interface*/
extern WINDOW_ELEMENT_RENDERER * __mg_def_renderer;
@@ -958,9 +927,7 @@ BOOL gui_LoadIconRes(HDC hdc, const char* rdr_name, char* file);
void gui_WndRect(HWND hWnd, PRECT prc);
void gui_WndClientRect(HWND hWnd, PRECT prc);
/* Undisclosed APIs */
HDC CreateMemDCFromSurface (struct GAL_Surface* surface);
struct GAL_Surface* GetSurfaceFromDC (HDC hdc);
HDC __mg_create_memdc_for_surface (struct GAL_Surface* surface);
/* Since 5.0.0 */
#ifdef _MGRM_PROCESSES
+9 -2
View File
@@ -105,8 +105,15 @@ int __mg_map_get_size (map_t* map);
map_entry_t* __mg_map_find (map_t* map, const void* key);
int __mg_map_insert_ex (map_t* map, const void* key,
map_entry_t* __mg_map_insert_ex2 (map_t* map, const void* key,
const void* val, free_val_fn free_val_alt);
static int __mg_map_insert_ex (map_t* map, const void* key,
const void* val, free_val_fn free_val_alt)
{
return __mg_map_insert_ex2(map, key, val, NULL) ? 0 : -1;
}
static inline int __mg_map_insert (map_t* map, const void* key,
const void* val)
{
@@ -119,7 +126,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 */
+7 -1
View File
@@ -79,6 +79,11 @@ struct timezone {
extern "C" {
#endif /* __cplusplus */
void __mg_lock_file_for_read(int fd);
void __mg_unlock_file_for_read(int fd);
void __mg_lock_file_for_write(int fd);
void __mg_unlock_file_for_write(int fd);
unsigned int __mg_os_get_random_seed (void);
void __mg_os_time_delay (int ms);
void __mg_os_start_time (void);
@@ -115,10 +120,11 @@ void mg_TerminateMisc (void);
BOOL mg_InitSystemRes (void);
void mg_TerminateSystemRes (void);
/* Deprecated since 5.2.0
#ifdef _MGSCHEMA_COMPOSITING
int __mg_alloc_sem_for_shared_surf (void);
int __mg_free_sem_for_shared_surf (int sem_num);
#endif /* _MGSCHEMA_COMPOSITING */
#endif _MGSCHEMA_COMPOSITING */
size_t __mg_lookfor_unused_slot (unsigned char* bitmap, size_t len_bmp, int set);
+4 -4
View File
@@ -396,10 +396,10 @@ char * __mg_msgstr3 [] =
"MSG_SRVNOTIFY", // 0x0147
"MSG_UPDATECLIWIN", // 0x0148
"MSG_LAYERCHANGED", // 0x0149
"MSG_MANAGE_MSGTHREAD", // 0x014A
"MSG_CALC_POSITION", // 0x014B
"", // 0x014C
"", // 0x014D
"MSG_WINCOMPOSITED", // 0x014A
"MSG_MANAGE_MSGTHREAD", // 0x014B
"MSG_CALC_POSITION", // 0x014C
"MSG_WAKEUP_CLIENT", // 0x014D
"", // 0x014E
"", // 0x014F
+31 -14
View File
@@ -139,20 +139,25 @@ typedef struct _DirtyInfo {
* than the creator.
*/
typedef struct _SharedSurfaceHeader {
/* The number of semphore for this surface.
The SysV semaphore set id for synchronizing this shared surface:
SHAREDRES_SEMID_SHARED_SURF. */
int sem_num;
/* the name of the shared surface; since 5.2.0. */
char name[NAME_MAX + 1];
/* The pid of the creator */
pid_t creator;
/* The client identifier of the creator. */
int create_cli;
/* The file descriptor in context of the creator. */
int fd;
/* Not zero for hardware surface. */
int byhw;
/* The dirty information */
GAL_DirtyInfo dirty_info;
/* Deprecated since 5.2.0.
The number of semphore for this surface.
The SysV semaphore set id for synchronizing this shared surface:
SHAREDRES_SEMID_SHARED_SURF.
int sem_num; */
/* Deprecated since 5.2.0.
The file descriptor in context of the creator.
int fd; */
/* the size of the surface */
int width, height;
/* the pitch of the surface */
@@ -166,6 +171,9 @@ typedef struct _SharedSurfaceHeader {
size_t map_size;
/* the offset of pixels data */
off_t pixels_off;
/* The dirty information */
GAL_DirtyInfo dirty_info;
} GAL_SharedSurfaceHeader;
#endif /* IS_COMPOSITING_SCHEMA */
@@ -230,6 +238,8 @@ typedef struct GAL_Surface {
GAL_SharedSurfaceHeader *shared_header; /* Private */
/* The dirty info for non-shared surface. */
GAL_DirtyInfo *dirty_info; /* Private */
/* The file descriptor if the surface is a shared surface. */
int fd; /* Private; since 5.2.0. */
#endif
} GAL_Surface;
@@ -252,6 +262,8 @@ typedef struct GAL_Surface {
#define GAL_PREALLOC 0x01000000 /* Surface uses preallocated memory */
#define GAL_FORMAT_CHECKED 0x02000000 /* Pixman format checked */
#define GAL_SSURF_ATTACHED 0x04000000 /* The shared surface is attached to. */
#define GAL_SSURF_LOCKED 0x08000000 /* The shared surface is locked. */
/* Available for GAL_SetVideoMode() */
#define GAL_ANYFORMAT 0x10000000 /* Allow any video depth/pixel-format */
@@ -571,6 +583,11 @@ GAL_Surface *GAL_CreateRGBSurface
GAL_Surface *GAL_CreateRGBSurfaceFrom (void *pixels,
int width, int height, int depth, int pitch,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
/* Since 5.2.0 */
static GAL_Surface *GAL_RefSurface (GAL_Surface *surface) {
surface->refcount++;
return surface;
}
void GAL_FreeSurface (GAL_Surface *surface);
typedef struct REQ_HWSURFACE {
@@ -651,11 +668,11 @@ GAL_Surface *GAL_CreateSurfaceForZNodeAs (const GAL_Surface* ref_surf,
void GAL_FreeSharedSurfaceData (GAL_Surface *surface);
/* Attach to a shared RGB surface. */
GAL_Surface *GAL_AttachSharedRGBSurface (int fd, size_t map_size,
Uint32 flags, BOOL with_wr);
GAL_Surface *GAL_AttachSharedRGBSurface (GAL_VideoDevice* video,
int fd, size_t map_size, Uint32 flags, BOOL with_wr);
/* Dettach from a shared RGB surface from the specific video device. */
void GAL_DettachSharedSurfaceData (GAL_Surface *surface);
/* Detach from a shared RGB surface from the specific video device. */
void GAL_DetachSharedSurfaceData (GAL_Surface *surface);
/* Create a cursor surface from the specific video device. */
GAL_Surface* GAL_CreateCursorSurface (GAL_VideoDevice* video,
+3
View File
@@ -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);
+2 -2
View File
@@ -112,7 +112,7 @@ typedef struct tagG_RES {
int nr_layers;
int semid_layer;
#ifdef _MGSCHEMA_COMPOSITING
#if 0 && defined(_MGSCHEMA_COMPOSITING) // deprecated since 5.2.0
int semid_shared_surf; /* the id of semaphore set for shared surfaces */
#endif
@@ -208,7 +208,7 @@ typedef G_RES* PG_RES;
#define SHAREDRES_NR_LAYSERS (((PG_RES)mgSharedRes)->nr_layers)
#define SHAREDRES_SEMID_LAYER (((PG_RES)mgSharedRes)->semid_layer)
#ifdef _MGSCHEMA_COMPOSITING
#if 0 && defined(_MGSCHEMA_COMPOSITING) // Deprecated since 5.2.0
# define SHAREDRES_SEMID_SHARED_SURF (((PG_RES)mgSharedRes)->semid_shared_surf)
#endif
+1 -1
View File
@@ -74,7 +74,7 @@ typedef struct _MSGQUEUE MSGQUEUE;
extern "C" {
#endif /* __cplusplus */
void __mg_update_tick_count (void* data);
DWORD __mg_update_tick_count (MSGQUEUE* msg_queue);
int __mg_check_expired_timers (MSGQUEUE* msg_queue, DWORD inter);
void __mg_remove_timers_by_msg_queue (MSGQUEUE* msg_queue);
void __mg_remove_timer (MSGQUEUE* msg_queue, int slot);
+18 -1
View File
@@ -679,6 +679,19 @@ static BOOL merge_dirty_ppp (CompositorCtxt* ctxt, MG_Layer* layer, int zidx)
return rc;
}
#if 0
static void dump_dirty_region(CompositorCtxt* ctxt, const char *prefix, int zidx)
{
CLIPRGN* rgn = &ctxt->dirty_rgn;
_WRN_PRINTF("%s (%d): dirty region on screen: (%d, %d) %d x %d; "
"highest dirty win: %d; lowest dirty win: %d\n",
prefix, zidx,
rgn->rcBound.left, rgn->rcBound.top,
RECTW (rgn->rcBound), RECTH (rgn->rcBound),
ctxt->highest_dirty_win, ctxt->lowest_dirty_win);
}
#endif
static BOOL merge_dirty_win (CompositorCtxt* ctxt, MG_Layer* layer, int zidx)
{
BOOL rc = FALSE;
@@ -722,9 +735,13 @@ static BOOL merge_dirty_wpp (CompositorCtxt* ctxt, MG_Layer* layer)
static BOOL refresh_dirty_region (CompositorCtxt* ctxt, MG_Layer* layer)
{
/* the fallback compositor only manages znodes on the topmost layer. */
if (layer != mgTopmostLayer || IsEmptyClipRgn (&ctxt->dirty_rgn))
if (layer != mgTopmostLayer)
return FALSE;
if (IsEmptyClipRgn (&ctxt->dirty_rgn)) {
return FALSE;
}
if (ctxt->highest_dirty_ppp >= 0) {
composite_ppp_znodes (ctxt);
}
+32 -16
View File
@@ -56,7 +56,6 @@
#include <string.h>
#include <errno.h>
#define _DEBUG
#include "common.h"
#if defined(_MGRM_PROCESSES) && defined(_MGSCHEMA_COMPOSITING)
@@ -69,6 +68,7 @@
#include "constants.h"
#include "zorder.h"
#include "dc.h"
#include "server.h"
#define MAX_NR_COMPOSITORS 8
#define LEN_COMPOSITOR_NAME 15
@@ -133,31 +133,51 @@ static void lock_znode_surface (PDC pdc, ZORDERNODE* node)
{
if (node->lock_count == 0) {
if (pdc->surface->shared_header) {
LOCK_SURFACE_SEM (pdc->surface->shared_header->sem_num);
__mg_lock_file_for_read(pdc->surface->fd);
}
node->dirty_age = pdc->surface->dirty_info->dirty_age;
node->nr_dirty_rcs = pdc->surface->dirty_info->nr_dirty_rcs;
node->dirty_rcs = pdc->surface->dirty_info->dirty_rcs;
}
node->lock_count++;
}
static void unlock_znode_surface (PDC pdc, ZORDERNODE* node)
static BOOL unlock_znode_surface (PDC pdc, ZORDERNODE* node)
{
BOOL need_reset = FALSE;
if (node->lock_count > 0) {
node->lock_count--;
if (node->lock_count == 0) {
if (pdc->surface->shared_header)
UNLOCK_SURFACE_SEM (pdc->surface->shared_header->sem_num);
if (node->changes != pdc->surface->dirty_info->dirty_age) {
node->changes = pdc->surface->dirty_info->dirty_age;
need_reset = TRUE;
}
if (pdc->surface->shared_header) {
__mg_unlock_file_for_read(pdc->surface->fd);
}
node->dirty_age = 0;
node->nr_dirty_rcs = 0;
node->dirty_rcs = NULL;
}
}
return need_reset;
}
static void reset_znode_surface_dirty (PDC pdc, ZORDERNODE* node, int slot)
{
if (node->cli == 0 || slot == 0) {
pdc->surface->dirty_info->nr_dirty_rcs = 0;
}
else if (node->hwnd) {
MSG msg = { HWND_NULL, MSG_WINCOMPOSITED,
slot, (LPARAM)node->hwnd, (DWORD)node->changes };
__mg_send2client(&msg, mgClients + node->cli);
}
}
#if 0 /* not optimized */
@@ -322,10 +342,8 @@ static void composite_layer (MG_Layer* layer, CompositorCtxt* ctxt,
nodes = GET_MENUNODE(zi);
for (i = 0; i < zi->nr_popupmenus; i++) {
pdc = dc_HDC2PDC (nodes[i].mem_dc);
nodes[i].changes = pdc->surface->dirty_info->dirty_age;
pdc->surface->dirty_info->nr_dirty_rcs = 0;
unlock_znode_surface (pdc, nodes + i);
if (unlock_znode_surface (pdc, nodes + i))
reset_znode_surface_dirty (pdc, nodes + i, i);
}
}
@@ -335,9 +353,8 @@ static void composite_layer (MG_Layer* layer, CompositorCtxt* ctxt,
while ((next = __kernel_get_next_znode (zi, next)) > 0) {
if (nodes [next].flags & ZOF_VISIBLE) {
pdc = dc_HDC2PDC (nodes[next].mem_dc);
nodes[next].changes = pdc->surface->dirty_info->dirty_age;
pdc->surface->dirty_info->nr_dirty_rcs = 0;
unlock_znode_surface (pdc, nodes + next);
if (unlock_znode_surface (pdc, nodes + next))
reset_znode_surface_dirty (pdc, nodes + next, next);
}
}
@@ -346,9 +363,8 @@ static void composite_layer (MG_Layer* layer, CompositorCtxt* ctxt,
if (layer == mgTopmostLayer) {
pdc = dc_HDC2PDC (HDC_SCREEN);
if (pdc->surface->w > 0 && pdc->surface->h > 0) {
nodes[0].changes = pdc->surface->dirty_info->dirty_age;
pdc->surface->dirty_info->nr_dirty_rcs = 0;
unlock_znode_surface (pdc, nodes);
if (unlock_znode_surface (pdc, nodes))
reset_znode_surface_dirty (pdc, nodes, 0);
}
}
}
+36 -16
View File
@@ -365,7 +365,7 @@ static intptr_t cliAllocZOrderNode (PMAINWIN pWin, const COMPOSITINGINFO* ct_inf
}
if (ClientRequestEx2 (&req, caption, strlen(caption) + 1,
pWin->surf->shared_header->fd,
pWin->surf->fd,
&ret, sizeof (intptr_t), NULL) < 0)
return -1;
#else /* ndef _MGSCHEMA_COMPOSITING */
@@ -524,7 +524,7 @@ static intptr_t cliStartTrackPopupMenu (PTRACKMENUINFO ptmi)
info.surf_flags = surf->flags;
info.surf_size = surf->shared_header->map_size;
if (ClientRequestEx2 (&req, NULL, 0, surf->shared_header->fd,
if (ClientRequestEx2 (&req, NULL, 0, surf->fd,
&ret, sizeof (intptr_t), NULL) < 0)
return -1;
}
@@ -837,8 +837,10 @@ static int srvAllocZOrderNode (int cli, HWND hwnd, HWND main_win,
surf->refcount++;
}
else if (fd >= 0) {
surf = GAL_AttachSharedRGBSurface (fd, surf_size, surf_flags, TRUE);
close (fd);
surf = GAL_AttachSharedRGBSurface (NULL, fd,
surf_size, surf_flags, TRUE);
/* Since 5.2.0: keep fd available.
close (fd); */
}
else {
_ERR_PRINTF("KERNEL: not server but fd for shared surface is invalid\n");
@@ -846,7 +848,7 @@ static int srvAllocZOrderNode (int cli, HWND hwnd, HWND main_win,
}
if (surf) {
memdc = CreateMemDCFromSurface (surf);
memdc = __mg_create_memdc_for_surface (surf);
if (memdc == HDC_INVALID) {
if (cli > 0) {
GAL_FreeSurface (surf);
@@ -994,12 +996,14 @@ static int srvMoveWindow (int cli, int idx_znode, const RECT* rcWin,
surf->refcount++;
}
else {
surf = GAL_AttachSharedRGBSurface (fd, surf_size, surf_flags, TRUE);
close (fd);
surf = GAL_AttachSharedRGBSurface (NULL, fd,
surf_size, surf_flags, TRUE);
/* Since 5.2.0: keep fd available.
close (fd); */
}
if (surf) {
memdc = CreateMemDCFromSurface (surf);
memdc = __mg_create_memdc_for_surface (surf);
if (memdc == HDC_INVALID) {
if (cli > 0) {
GAL_FreeSurface (surf);
@@ -1014,7 +1018,6 @@ static int srvMoveWindow (int cli, int idx_znode, const RECT* rcWin,
return -1;
}
}
#endif /* def _MGSCHEMA_COMPOSITING */
ret = dskMoveWindow (cli, idx_znode, memdc, rcWin);
@@ -2208,7 +2211,7 @@ static int resize_window_surface (PMAINWIN pWin, const RECT* prcResult)
pWin->surf = new_surf;
if (pWin->surf->shared_header)
return pWin->surf->shared_header->fd;
return pWin->surf->fd;
else
return 0;
}
@@ -2253,9 +2256,10 @@ static int dskMoveGlobalControl (PMAINWIN pCtrl, RECT* prcExpect)
}
#ifdef _MGSCHEMA_COMPOSITING
if (pCtrl->surf->shared_header && pCtrl->surf->shared_header->fd >= 0) {
close (pCtrl->surf->shared_header->fd);
pCtrl->surf->shared_header->fd = -1;
/* Since 5.2.0: keep fd available. */
if (0 && pCtrl->surf->shared_header && pCtrl->surf->fd >= 0) {
close (pCtrl->surf->fd);
pCtrl->surf->fd = -1;
}
#endif
@@ -2284,9 +2288,10 @@ static int dskMoveMainWindow (PMAINWIN pWin, RECT* prcExpect)
__mg_update_dc_on_surface_changed ((HWND)pWin, pWin->surf);
}
if (pWin->surf->shared_header && pWin->surf->shared_header->fd >= 0) {
close (pWin->surf->shared_header->fd);
pWin->surf->shared_header->fd = -1;
/* Since 5.2.0: keep fd available. */
if (0 && pWin->surf->shared_header && pWin->surf->fd >= 0) {
close (pWin->surf->fd);
pWin->surf->fd = -1;
}
#endif
@@ -2902,6 +2907,21 @@ int __mg_handle_mouse_hook (int message, WPARAM wParam, LPARAM lParam)
}
#endif /* deprecated code */
/* used by client to check the validation of a hwnd in the given znode slot. */
BOOL __mg_client_check_znode_hwnd (int slot, HWND hwnd, int cli)
{
BOOL ret = FALSE;
ZORDERINFO* zi = __mg_zorder_info;
ZORDERNODE* nodes;
nodes = GET_ZORDERNODE(zi);
lock_zi_for_read (zi);
if (nodes[slot].hwnd == hwnd && nodes[slot].cli == cli)
ret = TRUE;
unlock_zi_for_read (zi);
return ret;
}
/* used by client to check the validation of a hwnd */
BOOL __mg_client_check_hwnd (HWND hwnd, int cli)
{
+24 -5
View File
@@ -55,6 +55,7 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include "common.h"
@@ -141,12 +142,31 @@ BOOL mg_InitDesktop (void)
#include "debug.h"
static IDLEHANDLER std_idle_handler;
/* According to a bug report, we use sem_timedwait() instead of
calling std_idle_handler for desktop thread.
Otherwise, the desktop might not handle the request from other GUI threads
as soon as possible. */
static BOOL idle_handler_for_desktop_thread (MSGQUEUE *msg_queue, BOOL wait)
{
__mg_update_tick_count (NULL);
return std_idle_handler (msg_queue, wait);
int retv, n = 0;
__mg_update_tick_count (msg_queue);
if (wait) {
struct timespec ts;
if (clock_gettime (CLOCK_REALTIME, &ts) != -1) {
ts.tv_nsec += 10 * 1000 * 1000L; // 10ms
if (ts.tv_nsec >= 1000 * 1000 * 1000L) {
ts.tv_sec += 1;
ts.tv_nsec -= 1000 * 1000 * 1000L;
}
if (sem_timedwait (&msg_queue->wait, &ts) == 0)
return TRUE;
}
}
return n > 0;
}
void* __kernel_desktop_main (void* data)
@@ -162,7 +182,6 @@ void* __kernel_desktop_main (void* data)
/* For bug reported in Issue #116, under threads mode, the idle handler
for the desktop thread should call __mg_update_tick_count () */
std_idle_handler = __mg_dsk_msg_queue->OnIdle;
__mg_dsk_msg_queue->OnIdle = idle_handler_for_desktop_thread;
/* init desktop window */
+10 -3
View File
@@ -1603,8 +1603,10 @@ static int srvStartTrackPopupMenu (int cli, const RECT* rc, HWND ptmi,
surf->refcount++;
}
else if (fd >= 0) {
surf = GAL_AttachSharedRGBSurface (fd, surf_size, surf_flags, TRUE);
close (fd);
surf = GAL_AttachSharedRGBSurface (NULL, fd,
surf_size, surf_flags, TRUE);
/* Since 5.2.0: keep fd available.
close (fd); */
}
else {
_WRN_PRINTF("not server but fd for shared surface is invalid\n");
@@ -1612,7 +1614,7 @@ static int srvStartTrackPopupMenu (int cli, const RECT* rc, HWND ptmi,
}
if (surf) {
memdc = CreateMemDCFromSurface (surf);
memdc = __mg_create_memdc_for_surface (surf);
if (memdc == HDC_INVALID) {
GAL_FreeSurface (surf);
_WRN_PRINTF("failed to create memory dc for znode\n");
@@ -1646,11 +1648,14 @@ static int srvStartTrackPopupMenu (int cli, const RECT* rc, HWND ptmi,
menu_nodes [zi->nr_popupmenus].flags = ZOF_TYPE_POPUPMENU;
menu_nodes [zi->nr_popupmenus].rc = *rc;
menu_nodes [zi->nr_popupmenus].hwnd = ptmi;
menu_nodes [zi->nr_popupmenus].cli = 0;
#ifdef _MGSCHEMA_COMPOSITING
menu_nodes [zi->nr_popupmenus].changes = 0;
menu_nodes [zi->nr_popupmenus].ct = CT_OPAQUE;
menu_nodes [zi->nr_popupmenus].ct_arg = 0;
menu_nodes [zi->nr_popupmenus].mem_dc = memdc;
menu_nodes [zi->nr_popupmenus].dirty_age = 0;
menu_nodes [zi->nr_popupmenus].nr_dirty_rcs = 0;
menu_nodes [zi->nr_popupmenus].dirty_rcs = NULL;
#endif
menu_nodes [zi->nr_popupmenus].priv_data = NULL;
@@ -2356,6 +2361,8 @@ static int AllocZOrderNodeEx (ZORDERINFO* zi, int cli, HWND hwnd, HWND main_win,
nodes [free_slot].ct = validate_compositing_type (flags, ct);
nodes [free_slot].ct_arg = ct_arg;
nodes [free_slot].mem_dc = mem_dc;
nodes [free_slot].dirty_age = 0;
nodes [free_slot].nr_dirty_rcs = 0;
nodes [free_slot].dirty_rcs = NULL;
#else
nodes [free_slot].age = 1;
+8 -8
View File
@@ -562,6 +562,13 @@ int GUIAPI InitGUI (int args, const char *agr[])
_is_minigui_running = 1;
/* init timer for tick counter */
step++;
if (!mg_InitTimer()) {
_ERR_PRINTF ("KERNEL>InitGUI: failed to start time counter\n");
goto failure;
}
step++;
if (!SystemThreads()) {
_ERR_PRINTF ("KERNEL>InitGUI: failed to init system threads!\n");
@@ -575,13 +582,6 @@ int GUIAPI InitGUI (int args, const char *agr[])
goto failure;
}
/* init timer for tick counter */
step++;
if (!mg_InitTimer (FALSE)) {
_ERR_PRINTF ("KERNEL>InitGUI: failed to start time counter\n");
goto failure;
}
SetKeyboardLayout ("default");
SetCursor (GetSystemCursor (IDC_ARROW));
@@ -602,7 +602,7 @@ failure1:
void GUIAPI TerminateGUI (int not_used)
{
mg_TerminateTimer (FALSE);
mg_TerminateTimer ();
mg_FreeMsgQueueForThisThread (TRUE);
+58 -142
View File
@@ -44,7 +44,7 @@
* <http://www.minigui.com/blog/minigui-licensing-policy/>.
*/
/*
** timer.c: The Timer module for MiniGUI-Threads.
** timer.c: The Timer module for MiniGUI.
**
** Current maintainer: Wei Yongming.
**
@@ -79,82 +79,45 @@
DWORD __mg_tick_counter = 0;
/* update timer count for desktop thread */
void __mg_update_tick_count (void *data)
/* update timer count for message and desktop thread */
DWORD __mg_update_tick_count (MSGQUEUE* msg_queue)
{
DWORD ticks;
#if defined(_MGRM_PROCESSES)
if (mgIsServer) {
__mg_tick_counter = __mg_os_get_time_ticks ();
SHAREDRES_TIMER_COUNTER = __mg_tick_counter;
ticks = __mg_os_get_time_ticks ();
SHAREDRES_TIMER_COUNTER = ticks;
}
else {
__mg_tick_counter = SHAREDRES_TIMER_COUNTER;
ticks = SHAREDRES_TIMER_COUNTER;
}
#else /* defined _MGRM_PROCESSES */
__mg_tick_counter = __mg_os_get_time_ticks ();
ticks = __mg_os_get_time_ticks ();
#endif /* not defined _MGRM_PROCESSES */
/* Since 5.0.0, the desktop only handles caret blinking in MSG_TIMEOUT
message, and the interval for the timer of desktop changes to 0.05s. */
if (__mg_tick_counter >
__mg_dsk_msg_queue->last_ticks_desktop + DESKTOP_TIMER_INERTVAL) {
__mg_dsk_msg_queue->dwState |= QS_DESKTIMER;
if (msg_queue && ticks != msg_queue->last_ticks) {
/* Since 5.0.0, the desktop only handles caret blinking in MSG_TIMEOUT
message, and the interval for the timer of desktop changes to 0.05s.
*/
if (msg_queue == __mg_dsk_msg_queue &&
ticks > __mg_dsk_msg_queue->old_tick_count +
DESKTOP_TIMER_INERTVAL) {
__mg_dsk_msg_queue->dwState |= QS_DESKTIMER;
#ifdef _MGRM_THREADS /* only wake up desktop for threads mode */
POST_MSGQ (__mg_dsk_msg_queue);
POST_MSGQ (__mg_dsk_msg_queue);
#endif
__mg_dsk_msg_queue->last_ticks_desktop = __mg_tick_counter;
__mg_dsk_msg_queue->old_tick_count = ticks;
}
msg_queue->last_ticks = ticks;
}
#if 0 /* deprecated code */
__mg_tick_counter = ticks;
return ticks;
}
#if defined(_MGRM_PROCESSES)
if (mgIsServer) {
DWORD elapsed_ticks;
/* Since 5.0.0, we use elapsed time in ms to count the ticks */
elapsed_ticks = __mg_os_get_elapsed_ms ();
elapsed_ticks = (elapsed_ticks + 5) / 10;
__mg_tick_counter += elapsed_ticks;
SHAREDRES_TIMER_COUNTER = __mg_tick_counter;
}
else {
__mg_tick_counter = SHAREDRES_TIMER_COUNTER;
}
#else /* defined _MGRM_PROCESSES */
DWORD elapsed_ticks;
/* Since 5.0.0, we use elapsed time in ms to count the ticks */
elapsed_ticks = __mg_os_get_elapsed_ms ();
elapsed_ticks = (elapsed_ticks + 5) / 10;
__mg_tick_counter += elapsed_ticks;
#endif /* not defined _MGRM_PROCESSES */
/* Since 5.0.0, the desktop only handles caret blinking in MSG_TIMEOUT
message, and the interval for the timer of desktop changes to 0.05s. */
if (__mg_tick_counter >
__mg_dsk_msg_queue->last_ticks_desktop + DESKTOP_TIMER_INERTVAL) {
__mg_dsk_msg_queue->dwState |= QS_DESKTIMER;
#ifdef _MGRM_THREADS /* only wake up desktop for threads mode */
POST_MSGQ (__mg_dsk_msg_queue);
#endif
__mg_dsk_msg_queue->last_ticks_desktop = __mg_tick_counter;
}
#endif /* deprecated code */
}
#ifdef __NOUNIX__
static BOOL install_system_timer (void)
{
return TRUE;
}
static BOOL unintall_system_timer (void)
{
return TRUE;
}
#else /* defined __NOUNIX__ */
#include <signal.h>
#include <unistd.h>
@@ -163,6 +126,12 @@ static BOOL unintall_system_timer (void)
static struct sigaction old_alarm_handler;
static struct itimerval old_timer;
static void timer_handler(int sig)
{
(void)sig;
__mg_update_tick_count(NULL);
}
static BOOL install_system_timer (void)
{
struct itimerval timerv;
@@ -171,20 +140,12 @@ static BOOL install_system_timer (void)
sigaction (SIGALRM, NULL, &old_alarm_handler);
siga = old_alarm_handler;
siga.sa_handler = (void(*)(int))__mg_update_tick_count;
#ifndef _MGRM_STANDALONE
siga.sa_handler = timer_handler;
siga.sa_flags = 0;
#else
siga.sa_flags = SA_RESTART;
#endif
sigaction (SIGALRM, &siga, NULL);
timerv.it_interval.tv_sec = 0;
#if defined(__uClinux__) && defined(_MGRM_STANDALONE)
timerv.it_interval.tv_usec = 100000; /* 100 ms */
#else
timerv.it_interval.tv_usec = 10000; /* 10 ms */
#endif
timerv.it_value = timerv.it_interval;
if (setitimer (ITIMER_REAL, &timerv, &old_timer) == -1) {
@@ -209,26 +170,30 @@ static BOOL unintall_system_timer (void)
return TRUE;
}
#endif /* defined(_MGRM_PROCESSES) */
#endif /* not defined __NOUNIX__ */
BOOL mg_InitTimer (BOOL use_sys_timer)
BOOL mg_InitTimer ()
{
__mg_tick_counter = 0;
__mg_os_start_time();
if (use_sys_timer) {
#if defined(_MGRM_PROCESSES)
if (mgIsServer) {
install_system_timer ();
}
#endif
return TRUE;
}
void mg_TerminateTimer (BOOL use_sys_timer)
void mg_TerminateTimer (void)
{
if (use_sys_timer)
#if defined(_MGRM_PROCESSES)
if (mgIsServer) {
unintall_system_timer ();
}
#endif
}
/************************* Functions run in message thread *******************/
@@ -247,34 +212,19 @@ int __mg_check_expired_timers (MSGQUEUE* msg_queue, DWORD inter)
int i;
TIMER** timer_slots = msg_queue->timer_slots;
__mg_update_tick_count (msg_queue);
for (i = 0; i < DEF_NR_TIMERS; i++) {
if (timer_slots[i]) {
if (__mg_tick_counter >= timer_slots[i]->ticks_expected) {
if (msg_queue->last_ticks >= timer_slots[i]->ticks_expected) {
/* setting timer flag is simple, we do not need to lock
msgq, or else we may encounter dead lock here */
msg_queue->expired_timer_mask |= (0x01UL << i);
POST_MSGQ (msg_queue);
timer_slots[i]->ticks_expected += timer_slots[i]->interv;
timer_slots[i]->ticks_fired = __mg_tick_counter;
timer_slots[i]->ticks_fired = msg_queue->last_ticks;
nr++;
}
#if 0 /* deprecated code */
timer_slots[i]->count += inter;
if (timer_slots[i]->count >= timer_slots[i]->interv) {
#ifdef _MGRM_PROCESSES
timer_slots[i]->ticks_current = SHAREDRES_TIMER_COUNTER;
#else
timer_slots[i]->ticks_current = __mg_tick_counter;
#endif
/* setting timer flag is simple, we do not need to lock msgq,
or else we may encounter dead lock here */
msg_queue->expired_timer_mask |= (0x01UL << i);
POST_MSGQ (msg_queue);
timer_slots[i]->count -= timer_slots[i]->interv;
nr++;
}
#endif /* deprecated code */
}
}
}
@@ -291,12 +241,7 @@ BOOL GUIAPI SetTimerEx (HWND hWnd, LINT id, DWORD interv,
int i;
int slot = -1;
TIMER** timer_slots;
PMSGQUEUE pMsgQueue;
#ifndef _MGRM_THREADS
/* Force to update tick count */
GetTickCount();
#endif
PMSGQUEUE msg_queue;
if (id == 0) {
_WRN_PRINTF ("bad identifier (%ld).\n", id);
@@ -307,12 +252,14 @@ BOOL GUIAPI SetTimerEx (HWND hWnd, LINT id, DWORD interv,
interv = 1;
}
timer_slots = getTimerSlotsForThisThread (&pMsgQueue);
timer_slots = getTimerSlotsForThisThread (&msg_queue);
if (MG_UNLIKELY (timer_slots == NULL)) {
_WRN_PRINTF ("called for non message thread\n");
goto badret;
}
__mg_update_tick_count (msg_queue);
/* Since 5.0.0: only check hWnd if timer_proc is NULL */
if (MG_UNLIKELY (timer_proc == NULL &&
!getMainWinIfWindowInThisThread (hWnd))) {
@@ -331,7 +278,7 @@ BOOL GUIAPI SetTimerEx (HWND hWnd, LINT id, DWORD interv,
/* Since 5.0.0: we reset timer parameters for duplicated call of
this function */
timer_slots[i]->interv = interv;
timer_slots[i]->ticks_expected = __mg_tick_counter + interv;
timer_slots[i]->ticks_expected = msg_queue->last_ticks + interv;
timer_slots[i]->ticks_fired = 0;
timer_slots[i]->proc = timer_proc;
return TRUE;
@@ -348,14 +295,14 @@ BOOL GUIAPI SetTimerEx (HWND hWnd, LINT id, DWORD interv,
timer_slots[slot]->hWnd = hWnd;
timer_slots[slot]->id = id;
timer_slots[slot]->interv = interv;
timer_slots[slot]->ticks_expected = __mg_tick_counter + interv;
timer_slots[slot]->ticks_expected = msg_queue->last_ticks + interv;
timer_slots[slot]->ticks_fired = 0;
timer_slots[slot]->proc = timer_proc;
_DBG_PRINTF ("ticks_expected (%d): %lu, tick_counter: %lu\n",
slot, timer_slots[slot]->ticks_expected, __mg_tick_counter);
slot, timer_slots[slot]->ticks_expected, msg_queue->last_ticks);
pMsgQueue->nr_timers++;
msg_queue->nr_timers++;
return TRUE;
@@ -363,24 +310,6 @@ badret:
return FALSE;
}
#if 0 /* deprected code */
#ifdef _MGRM_PROCESSES
static void reset_select_timeout (TIMER** timer_slots)
{
int i;
unsigned int interv = 0;
for (i = 0; i < DEF_NR_TIMERS; i++) {
if (timer_slots[i]) {
if (interv == 0 || timer_slots[i]->interv < interv)
interv = timer_slots[i]->interv;
}
}
__mg_set_select_timeout (USEC_10MS * interv);
}
#endif
#endif /* deprecated code */
void __mg_remove_timer (MSGQUEUE* msg_queue, int slot)
{
TIMER** timer_slots;
@@ -470,13 +399,14 @@ BOOL GUIAPI ResetTimerEx (HWND hWnd, LINT id, DWORD interv,
if (MG_LIKELY (msg_queue)) {
TIMER** timer_slots = msg_queue->timer_slots;
__mg_update_tick_count (msg_queue);
for (i = 0; i < DEF_NR_TIMERS; i++) {
if (timer_slots[i] &&
timer_slots[i]->hWnd == hWnd && timer_slots[i]->id == id) {
/* Should clear old timer flags */
msg_queue->expired_timer_mask &= ~(0x01UL << i);
timer_slots[i]->interv = interv;
timer_slots[i]->ticks_expected = __mg_tick_counter + interv;
timer_slots[i]->ticks_expected = msg_queue->last_ticks + interv;
timer_slots[i]->ticks_fired = 0;
if (timer_proc != (TIMERPROC)INV_PTR)
timer_slots[i]->proc = timer_proc;
@@ -548,20 +478,6 @@ BOOL GUIAPI HaveFreeTimer (void)
DWORD GUIAPI GetTickCount (void)
{
#if defined(_MGRM_PROCESSES)
if (mgIsServer) {
__mg_tick_counter = __mg_os_get_time_ticks ();
SHAREDRES_TIMER_COUNTER = __mg_tick_counter;
}
else {
__mg_tick_counter = SHAREDRES_TIMER_COUNTER;
}
#elif defined(_MGRM_STANDALONE)
__mg_tick_counter = __mg_os_get_time_ticks ();
#else /* not defined _MGRM_PROCESSES and _MGRM_PROCESSES */
/* do nothing here because the desktop thread updates the tick count */
#endif /* not defined _MGRM_PROCESSES and _MGRM_PROCESSES */
return __mg_tick_counter;
return __mg_update_tick_count(getMsgQueueForThisThread ());
}
+1 -1
View File
@@ -7,7 +7,7 @@ EXTRA_DIST= misc.c systext.c rwops.c endianrw.c nposix.c clipboard.c \
libmisc_la_SOURCES = misc.c systext.c rwops.c endianrw.c nposix.c clipboard.c \
math.c about.c license.c anon_file.c rbtree.c map.c \
error.c sockio.c
error.c sockio.c lock_file.c
SRC_FILES = $(libmisc_la_SOURCES)
LIB_NAME=libmisc
+1 -1
View File
@@ -114,7 +114,7 @@ static LRESULT AboutWinProc (HWND hWnd, UINT message,
DrawText (hdc,
"MiniGUI -- a mature cross-platform windowing system "
"and GUI support system for embedded or IoT devices.\n\n"
"Copyright (C) 2002 ~ 2020 FMSoft Co., Ltd.",
"Copyright (C) 2002 ~ 2023 FMSoft Co., Ltd.",
-1, &rcClient, DT_WORDBREAK | DT_CENTER);
EndPaint (hWnd, hdc);
+112
View File
@@ -0,0 +1,112 @@
///////////////////////////////////////////////////////////////////////////////
//
// 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 <http://www.gnu.org/licenses/>.
*
* 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
* <http://www.minigui.com/blog/minigui-licensing-policy/>.
*/
/*
** lock_file.c: This file include functions for locking/unlocking a file.
**
** Create date: 2023/09/10
**
** Current maintainer: Wei Yongming.
*/
#include "common.h"
#ifndef __NOUNIX__
#include "misc.h"
#include <unistd.h>
#include <sys/file.h>
#include <fcntl.h>
#include <errno.h>
void __mg_lock_file_for_read(int fd)
{
struct flock lock;
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
while (fcntl(fd, F_SETLKW, &lock) == -1 && errno == EINTR);
}
void __mg_unlock_file_for_read(int fd)
{
struct flock lock;
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
fcntl(fd, F_SETLK, &lock);
}
void __mg_lock_file_for_write(int fd)
{
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
while (fcntl(fd, F_SETLKW, &lock) == -1 && errno == EINTR);
}
void __mg_unlock_file_for_write(int fd)
{
struct flock lock;
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
fcntl(fd, F_SETLK, &lock);
}
#endif /* __NOUNIX__ */
+5 -5
View File
@@ -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;
@@ -299,7 +299,7 @@ ret:
return retval;
}
int __mg_map_insert_ex (map_t* map, const void* key,
map_entry_t* __mg_map_insert_ex2 (map_t* map, const void* key,
const void* val, free_val_fn free_val_alt)
{
map_entry_t **pentry;
@@ -307,7 +307,7 @@ int __mg_map_insert_ex (map_t* map, const void* key,
map_entry_t *parent;
if (map == NULL)
return -1;
return NULL;
WRLOCK_MAP (map);
@@ -317,7 +317,7 @@ int __mg_map_insert_ex (map_t* map, const void* key,
while (*pentry) {
int ret;
if (map->comp_key)
ret = map->comp_key (key, (*pentry)->key);
else
@@ -354,7 +354,7 @@ int __mg_map_insert_ex (map_t* map, const void* key,
}
UNLOCK_MAP (map);
return 0;
return entry;
}
int __mg_map_find_replace_or_insert (map_t* map, const void* key,
-84
View File
@@ -495,28 +495,6 @@ DWORD __mg_os_get_time_ticks (void)
return (current - startup_time_win32) / 10;
}
#if 0 /* deprecated code */
DWORD __mg_os_get_elapsed_ms (void)
{
static DWORD last;
DWORD current = timeGetTime();
DWORD elapsed;
if (current >= last) {
elapsed = current - last;
return elapsed;
}
else {
/* overflowed */
elapsed = BITMASK_DWORD - last;
elapsed += current;
}
last = current;
return elapsed;
}
#endif /* deprecated code */
#elif defined (HAVE_CLOCK_GETTIME)
static struct timespec timeval_startup;
@@ -573,68 +551,6 @@ DWORD __mg_os_get_time_ticks (void)
return ds * 100 + dms;
}
#if 0 /* deprecated code */
DWORD __mg_os_get_elapsed_ms (void)
{
static struct timespec last;
DWORD ds, dms;
struct timespec current;
clock_gettime (CLOCK_MONOTONIC, &current);
ds = (current.tv_sec - last.tv_sec);
if (current.tv_sec == last.tv_sec) {
dms = (current.tv_nsec - last.tv_nsec) / 1000000L;
}
else if (current.tv_nsec >= last.tv_nsec) {
dms = (current.tv_nsec - last.tv_nsec) / 1000000L;
}
else {
assert (ds > 0);
ds--;
dms = 1000L - (last.tv_nsec - current.tv_nsec) / 1000000L;
}
last = current;
return ds * 1000 + dms;
}
#include <unistd.h>
#include <poll.h>
#include <sys/time.h>
static struct timeval timeval_startup;
void __mg_os_start_time(void)
{
gettimeofday(&timeval_startup, NULL);
}
DWORD __mg_os_get_time_ms(void)
{
DWORD ds, dms;
struct timeval current;
gettimeofday(&current, NULL);
ds = (current.tv_sec - timeval_startup.tv_sec);
if (current.tv_sec == timeval_startup.tv_sec) {
dms = (current.tv_usec - timeval_startup.tv_usec) / 1000L;
}
else if (current.tv_usec >= timeval_startup.tv_usec) {
dms = (current.tv_usec - timeval_startup.tv_usec) / 1000L;
}
else {
assert(ds > 0);
ds--;
dms = 1000L - (timeval_startup.tv_usec - current.tv_usec) / 1000L;
}
return ds * 1000 + dms;
}
#endif /* deprecated code */
#else /* defined HAVE_CLOCK_GETTIME */
#error "Please implement __mg_os_start_time and __mg_os_get_time_ticks for your OS"
+4
View File
@@ -96,8 +96,12 @@ static BITMAP_TYPE_INFO bitmap_types [MAX_BITMAP_TYPES] =
{ "jpeg", __mg_init_jpg, __mg_load_jpg, __mg_cleanup_jpg, __mg_save_jpg, __mg_check_jpg },
#endif
#ifdef _MGIMAGE_PNG
#if _MGLIBPNG_VER == 16
{ "png", __mg_init_png, __mg_load_png, __mg_cleanup_png, __mg_save_png, __mg_check_png },
#else
{ "png", __mg_init_png, __mg_load_png, __mg_cleanup_png, NULL, __mg_check_png },
#endif
#endif
#ifdef _MGIMAGE_WEBP
{ "webp", __mg_init_webp, __mg_load_webp, __mg_cleanup_webp, NULL, __mg_check_webp },
#endif
+281
View File
@@ -381,6 +381,287 @@ BOOL __mg_check_png (MG_RWops* fp)
return png_check_sig (sig, 8);
}
static void png_error_callback (png_structp png, png_const_charp error_msg)
{
int *error = png_get_error_ptr (png);
*error = ERR_BMP_CANT_SAVE;
#ifdef PNG_SETJMP_SUPPORTED
longjmp (png_jmpbuf (png), 1);
#endif
}
static void png_warning_callback (png_structp png, png_const_charp error_msg)
{
}
static void png_output_flush_fn (png_structp png_ptr)
{
}
static void my_write_data_fn (png_structp png_ptr, png_bytep data,
png_size_t length)
{
png_size_t check;
png_voidp io_ptr = png_get_io_ptr(png_ptr);
if (MGUI_RWwrite((MG_RWops*)io_ptr, data, 1, length) !=
(size_t) length) {
png_error(png_ptr, "Write Error");
}
}
typedef BYTE* (*MYBITMAP_get_pixel_row)(unsigned int cinfo,
MYBITMAP* mybmp,RGB* pal);
static BYTE* MYBITMAP_get_pixel_row_pal16(unsigned int next_scanline,
MYBITMAP* mybmp, RGB* pal)
{
RGB rgb0, rgb1;
BYTE *bits = mybmp->bits + next_scanline * mybmp->pitch;
int nr_data = mybmp->w * 4;
BYTE *data = (BYTE *)malloc(nr_data);
uint8_t alpha = 0xFF;
for (int i = 0, j = 0, end_i = (mybmp->w + 1) >> 1; i < end_i; ++i) {
rgb0 = pal[ (bits[ i ] & 0XF0) >> 4 ];
rgb1 = pal[ bits[ i ] & 0X0F ];
data[ j ++ ] = rgb0.r;
data[ j ++ ] = rgb0.g;
data[ j ++ ] = rgb0.b;
data[ j ++ ] = alpha;
data[ j ++ ] = rgb1.r;
data[ j ++ ] = rgb1.g;
data[ j ++ ] = rgb1.b;
data[ j ++ ] = alpha;
}
return data;
}
static BYTE* MYBITMAP_get_pixel_row_pal256(unsigned int next_scanline,
MYBITMAP* mybmp, RGB* pal)
{
RGB rgb;
BYTE *bits = mybmp->bits + next_scanline * mybmp->pitch;
int nr_data = mybmp->w * 4;
BYTE *data = (BYTE *)malloc(nr_data);
uint8_t alpha = 0xFF;
for (int i = 0, j = 0; i < mybmp->w; i++, j += 4) {
rgb = pal [bits[i] ];
data[0] = rgb.r;
data[1] = rgb.g;
data[2] = rgb.b;
data[3] = alpha;
}
return data;
}
#define RGB_FROM_RGB565(pixel, r, g, b) \
{ \
r = (((pixel&0xF800)>>11)<<3); \
g = (((pixel&0x07E0)>>5)<<2); \
b = ((pixel&0x001F)<<3); \
}
static BYTE* MYBITMAP_get_pixel_row_RGB565(unsigned int next_scanline,
MYBITMAP* mybmp, RGB* pal)
{
Uint16* bits = (Uint16*)(mybmp->bits + next_scanline * mybmp->pitch);
int nr_data = mybmp->w * 4;
BYTE* data = (BYTE *)malloc(nr_data);
uint8_t alpha = 0xFF;
for (int i = 0, j = 0; i < nr_data; i += 4, j++) {
uint8_t *b = data + i;
Uint16 *pixel = bits + j;
RGB_FROM_RGB565(pixel[j], b[0], b[1], b[2])
b[3] = alpha;
}
return data;
}
static BYTE* MYBITMAP_get_pixel_row_RGB(unsigned int next_scanline,
MYBITMAP* mybmp, RGB* pal)
{
BYTE *bits = mybmp->bits + next_scanline * mybmp->pitch;
int nr_data = mybmp->w * 4;
BYTE *data = (BYTE *)malloc(nr_data);
uint8_t alpha = 0xFF;
for (int i = 0, j = 0; i < nr_data; i += 4, j += 3) {
uint8_t *b = data + i;
BYTE *pixel = bits + j;
b[0] = pixel[2];
b[1] = pixel[1];
b[2] = pixel[0];
b[3] = alpha;
}
return data;
}
static BYTE* MYBITMAP_get_pixel_row_BGR(unsigned int next_scanline,
MYBITMAP* mybmp, RGB* pal)
{
BYTE *bits = mybmp->bits + next_scanline * mybmp->pitch;
int nr_data = mybmp->w * 4;
BYTE *data = (BYTE *)malloc(nr_data);
uint8_t alpha = 0xFF;
for (int i = 0, j = 0; i < nr_data; i += 4, j += 3) {
uint8_t *b = data + i;
BYTE *pixel = bits + j;
b[0] = pixel[0];
b[1] = pixel[1];
b[2] = pixel[2];
b[3] = alpha;
}
return data;
}
static BYTE* MYBITMAP_get_pixel_row_RGBA(unsigned int next_scanline,
MYBITMAP* mybmp, RGB* pal)
{
BYTE *bits = mybmp->bits + next_scanline * mybmp->pitch;
int nr_data = mybmp->w * 4;
BYTE *data = (BYTE *)malloc(nr_data);
for (int i = 0; i < nr_data; i += 4) {
uint8_t *b = data + i;
BYTE *pixel = bits + i;
uint8_t alpha = pixel[3];
if (alpha == 0) {
b[0] = b[1] = b[2] = b[3] = 0;
} else {
b[0] = (pixel[2] * 255 + alpha / 2) / alpha; /* red */
b[1] = (pixel[1] * 255 + alpha / 2) / alpha; /* green */
b[2] = (pixel[0] * 255 + alpha / 2) / alpha; /* blue */
b[3] = alpha;
}
}
return data;
}
int __mg_save_png (MG_RWops* fp, MYBITMAP* bmp, RGB* pal)
{
png_struct *png;
png_info *info;
png_byte **volatile rows = NULL;
MYBITMAP_get_pixel_row get_row;
png_color_16 white;
int png_color_type;
int retcode = ERR_BMP_CANT_SAVE;
int bpc;
int bmp_type;
rows = calloc(bmp->h, sizeof(png_byte*));
if (rows == NULL) {
retcode = ERR_BMP_CANT_SAVE;
goto failed;
}
png = png_create_write_struct (PNG_LIBPNG_VER_STRING, &retcode,
png_error_callback, png_warning_callback);
if (png == NULL) {
retcode = ERR_BMP_MEM;
goto failed_clear_rows;
}
info = png_create_info_struct (png);
if (info == NULL) {
retcode = ERR_BMP_MEM;
goto failed_clear_struct;
}
#ifdef PNG_SETJMP_SUPPORTED
if (setjmp (png_jmpbuf (png))) {
goto failed_clear_struct;
}
#endif
png_set_write_fn (png, fp, my_write_data_fn, png_output_flush_fn);
bmp_type = bmp->flags & MYBMP_TYPE_MASK;
switch(bmp->depth) {
case 4:
get_row = MYBITMAP_get_pixel_row_pal16;
break;
case 8:
get_row = MYBITMAP_get_pixel_row_pal256;
break;
case 16:
get_row = MYBITMAP_get_pixel_row_RGB565;
break;
case 24:
if(MYBMP_TYPE_RGB == bmp_type)
get_row = MYBITMAP_get_pixel_row_RGB;
else
get_row = MYBITMAP_get_pixel_row_BGR;
break;
case 32:
get_row = MYBITMAP_get_pixel_row_RGBA;
break;
default:
_ERR_PRINTF("MYBMP>PNG: invalid MYBITMAP.depth = %d\n", bmp->depth);
goto failed_clear_struct;
}
for (int i = 0; i < bmp->h; i++) {
rows[i] = get_row(i, bmp, pal);
}
bpc = 8;
png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
png_set_IHDR (png, info,
bmp->w,
bmp->h, bpc,
png_color_type,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
white.gray = (1 << bpc) - 1;
white.red = white.blue = white.green = white.gray;
png_set_bKGD (png, info, &white);
png_write_info (png, info);
png_write_image (png, rows);
png_write_end (png, info);
retcode = ERR_BMP_OK;
failed_clear_struct:
png_destroy_write_struct (&png, &info);
failed_clear_rows:
for (int i = 0; i < bmp->h; i++) {
if (rows[i]) {
free(rows[i]);
}
}
free (rows);
failed:
return retcode;
}
#endif /* _MGLIBPNG_VER == 16 */
#endif /* _MGIMAGE_PNG */
+3 -3
View File
@@ -144,7 +144,7 @@ static int DRM_AllocSharedHWSurface(_THIS, GAL_Surface *surface,
static int DRM_FreeSharedHWSurface(_THIS, GAL_Surface *surface);
static int DRM_AttachSharedHWSurface(_THIS, GAL_Surface *surface,
int prime_fd, size_t mapsize, BOOL with_rw);
static int DRM_DettachSharedHWSurface(_THIS, GAL_Surface *surface);
static int DRM_DetachSharedHWSurface(_THIS, GAL_Surface *surface);
static int DRM_SetCursor(_THIS, GAL_Surface *surface, int hot_x, int hot_y);
static int DRM_MoveCursor(_THIS, int x, int y);
@@ -1410,7 +1410,7 @@ static GAL_VideoDevice *DRM_CreateDevice(int devindex)
device->AllocSharedHWSurface = DRM_AllocSharedHWSurface;
device->FreeSharedHWSurface = DRM_FreeSharedHWSurface;
device->AttachSharedHWSurface = DRM_AttachSharedHWSurface;
device->DettachSharedHWSurface = DRM_DettachSharedHWSurface;
device->DetachSharedHWSurface = DRM_DetachSharedHWSurface;
}
#endif /* IS_COMPOSITING_SCHEMA */
@@ -3127,7 +3127,7 @@ error:
return retval;
}
static int DRM_DettachSharedHWSurface(_THIS, GAL_Surface *surface)
static int DRM_DetachSharedHWSurface(_THIS, GAL_Surface *surface)
{
int retval = -1;
DrmVideoData* vdata = this->hidden;
+1 -1
View File
@@ -247,7 +247,7 @@ static GAL_Surface* create_wp_surface(GAL_Surface* screen)
_DBG_PRINTF ("REQID_GETSHAREDSURFACE: size (%lu), flags (0x%x), fd: %d\n",
info.size, info.flags, fd);
wp_surf = GAL_AttachSharedRGBSurface (fd, info.size,
wp_surf = GAL_AttachSharedRGBSurface (NULL, fd, info.size,
info.flags, TRUE);
close (fd);
+41 -35
View File
@@ -15,7 +15,7 @@
* 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) 2002~2023, Beijing FMSoft Technologies Co., Ltd.
* Copyright (C) 1998~2002, WEI Yongming
*
* This program is free software: you can redistribute it and/or modify
@@ -59,6 +59,7 @@
#include <sys/mman.h>
#include <unistd.h>
#include "internals.h"
#include "misc.h"
#include "newgal.h"
#include "sysvideo.h"
@@ -68,7 +69,7 @@
/*
* Create a shared empty RGB surface of the appropriate depth and pixel format
*/
GAL_Surface * GAL_CreateSharedRGBSurface (GAL_VideoDevice *video,
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)
{
@@ -142,6 +143,7 @@ GAL_Surface * GAL_CreateSharedRGBSurface (GAL_VideoDevice *video,
#endif
surface->shared_header = NULL;
surface->dirty_info = NULL;
surface->fd = -1;
GAL_SetClipRect (surface, NULL);
#ifdef _MGUSE_UPDATE_REGION
@@ -201,10 +203,12 @@ GAL_Surface * GAL_CreateSharedRGBSurface (GAL_VideoDevice *video,
surface->shared_header = hdr = (GAL_SharedSurfaceHeader*)data_map;
}
surface->fd = fd; /* Since 5.2.0 */
/* fill fileds of shared header */
memset (hdr, 0, sizeof(GAL_SharedSurfaceHeader));
hdr->creator = getpid();
hdr->fd = fd;
hdr->create_cli = __mg_client_id;
// hdr->fd = fd;
hdr->byhw = byhw;
hdr->width = surface->w;
hdr->height = surface->h;
@@ -221,7 +225,8 @@ GAL_Surface * GAL_CreateSharedRGBSurface (GAL_VideoDevice *video,
surface->dirty_info->dirty_age = 0;
surface->dirty_info->nr_dirty_rcs = 0;
/* allocate semaphore from semaphore for shared surface */
/* Deprecated since 5.2.0.
allocate semaphore from semaphore for shared surface
if (IsServer() && __gal_fake_screen == NULL) {
// use 0 for wallpaper pattern,
// because the semaphore set manager is not ready.
@@ -232,7 +237,7 @@ GAL_Surface * GAL_CreateSharedRGBSurface (GAL_VideoDevice *video,
if (hdr->sem_num < 0) {
goto error;
}
}
} */
surface->pixels = (uint8_t*)surface->shared_header + pixels_off;
@@ -254,16 +259,16 @@ GAL_Surface * GAL_CreateSharedRGBSurface (GAL_VideoDevice *video,
error:
if (surface) {
if (surface->shared_header) {
#if 0
if (sem_inited) {
sem_destroy (&surface->shared_header->sem_lock);
}
#endif
if (surface->fd >= 0) {
close(surface->fd);
surface->fd = -1;
}
if (surface->shared_header) {
/* Deprecated since 5.2.0
if (surface->shared_header->sem_num >= 0) {
__mg_free_sem_for_shared_surf (surface->shared_header->sem_num);
}
} */
if (surface->shared_header->byhw) {
assert(video->FreeSharedHWSurface);
@@ -271,7 +276,6 @@ error:
surface->hwdata = NULL; /* set to NULL for GAL_FreeSurface */
}
else {
close (surface->shared_header->fd);
munmap (surface->shared_header,
surface->shared_header->map_size);
}
@@ -300,20 +304,16 @@ void GAL_FreeSharedSurfaceData (GAL_Surface *surface)
GAL_VideoDevice *video = surface->video;
assert (surface->shared_header);
assert (surface->fd >= 0);
#if 0
sem_destroy (&surface->shared_header->sem_lock);
#endif
/* Deprecated since 5.2.0
if (surface->shared_header->sem_num >= 0) {
__mg_free_sem_for_shared_surf (surface->shared_header->sem_num);
}
// the file descriptor may have been closed.
if (surface->shared_header->fd >= 0) {
close (surface->shared_header->fd);
surface->shared_header->fd = -1;
}
} */
if (surface->shared_header->byhw) {
assert (video->FreeSharedHWSurface);
@@ -325,6 +325,8 @@ void GAL_FreeSharedSurfaceData (GAL_Surface *surface)
surface->shared_header->map_size);
}
close(surface->fd);
surface->pixels = NULL;
#ifdef _MGUSE_PIXMAN
surface->pix_img = NULL;
@@ -332,15 +334,15 @@ void GAL_FreeSharedSurfaceData (GAL_Surface *surface)
#endif
surface->shared_header = NULL;
surface->dirty_info = NULL;
surface->fd = -1;
}
/*
* Attach to a shared RGB surface
*/
GAL_Surface * GAL_AttachSharedRGBSurface (int fd, size_t map_size,
Uint32 flags, BOOL with_wr)
GAL_Surface * GAL_AttachSharedRGBSurface (GAL_VideoDevice *video,
int fd, size_t map_size, Uint32 flags, BOOL with_wr)
{
GAL_VideoDevice *video = NULL;
GAL_Surface *surface;
void* data_map = MAP_FAILED;
GAL_SharedSurfaceHeader* hdr;
@@ -362,11 +364,10 @@ GAL_Surface * GAL_AttachSharedRGBSurface (int fd, size_t map_size,
goto error;
}
if ((flags & GAL_HWSURFACE) == GAL_HWSURFACE) {
video = __mg_current_video;
}
else {
video = NULL;
if (video == NULL) {
if ((flags & GAL_HWSURFACE) == GAL_HWSURFACE) {
video = __mg_current_video;
}
}
surface->video = video;
@@ -374,6 +375,8 @@ GAL_Surface * GAL_AttachSharedRGBSurface (int fd, size_t map_size,
surface->shared_header = NULL;
surface->hwdata = NULL;
surface->fd = fd;
if (video && video->AttachSharedHWSurface) {
// this method should fill hwdata and shared_header fields if success
video->AttachSharedHWSurface (video, surface, fd, map_size, with_wr);
@@ -389,7 +392,7 @@ GAL_Surface * GAL_AttachSharedRGBSurface (int fd, size_t map_size,
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);
_ERR_PRINTF("NEWGAL: Failed to map shared RGB surface: %d (%m)\n", fd);
goto error;
}
@@ -439,14 +442,17 @@ GAL_Surface * GAL_AttachSharedRGBSurface (int fd, size_t map_size,
goto error;
}
/* Since 5.2.0 */
surface->flags |= GAL_SSURF_ATTACHED;
/* The surface is ready to go */
surface->refcount = 1;
return (surface);
error:
if (video && surface && surface->hwdata) {
assert (video->DettachSharedHWSurface);
video->DettachSharedHWSurface (video, surface);
assert (video->DetachSharedHWSurface);
video->DetachSharedHWSurface (video, surface);
}
else if (data_map != MAP_FAILED) {
munmap (data_map, map_size);
@@ -462,15 +468,15 @@ error:
/*
* Free data of a shared surface created by the above function.
*/
void GAL_DettachSharedSurfaceData (GAL_Surface *surface)
void GAL_DetachSharedSurfaceData (GAL_Surface *surface)
{
GAL_VideoDevice *video = surface->video;
assert (surface->shared_header);
if (video && surface->hwdata) {
assert (video->DettachSharedHWSurface);
video->DettachSharedHWSurface (video, surface);
assert (video->DetachSharedHWSurface);
video->DetachSharedHWSurface (video, surface);
surface->hwdata = NULL;
}
else {
+8 -3
View File
@@ -1836,10 +1836,15 @@ void GAL_FreeSurface (GAL_Surface *surface)
}
if (surface->shared_header) {
if (surface->shared_header->creator == getpid())
GAL_FreeSharedSurfaceData(surface);
if (surface->flags & GAL_SSURF_ATTACHED)
GAL_DetachSharedSurfaceData(surface);
else
GAL_DettachSharedSurfaceData(surface);
GAL_FreeSharedSurfaceData(surface);
if (surface->fd >= 0) {
close(surface->fd);
surface->fd = -1;
}
surface->hwdata = NULL;
surface->pixels = NULL;
+2 -2
View File
@@ -174,10 +174,10 @@ struct GAL_VideoDevice {
int (*AttachSharedHWSurface)(_THIS, GAL_Surface *surface,
int prime_fd, size_t mapsize, BOOL with_rw);
/* Dettach from a shared surface in hardware video memory.
/* Detach from a shared surface in hardware video memory.
Set to NULL if no hardware shared surface supported.
Return 0 if success, otherwise -1. */
int (*DettachSharedHWSurface)(_THIS, GAL_Surface *surface);
int (*DetachSharedHWSurface)(_THIS, GAL_Surface *surface);
/* Allocate a dumb surface from hardware.
Set to NULL if dumb surface is not supported.
+2 -2
View File
@@ -918,9 +918,9 @@ BOOL GAL_SyncUpdate (GAL_Surface *surface)
#ifdef _MGSCHEMA_COMPOSITING
if (surface->shared_header) {
LOCK_SURFACE_SEM (surface->shared_header->sem_num);
__mg_lock_file_for_write (surface->fd);
mark_surface_dirty (surface, numrects, rects);
UNLOCK_SURFACE_SEM (surface->shared_header->sem_num);
__mg_unlock_file_for_write (surface->fd);
}
else if (surface->dirty_info) {
mark_surface_dirty (surface, numrects, rects);
+2 -1
View File
@@ -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 \

Some files were not shown because too many files have changed in this diff Show More