Compare commits

..
25 Commits
Author SHA1 Message Date
xueshuming ef713488e3 create flip_buffer if no driver_ops 2025-08-07 21:48:27 +08:00
xueshuming 60200cbbcd drm_page_flip not used for drm with driver_ops 2025-08-07 21:21:41 +08:00
xueshuming 6dec838cd8 drmvideo: check fd readable before call drmHandleEvent 2025-08-07 20:05:54 +08:00
xueshuming 2ccb876134 update impl for 'update_real_screen_memcpy';
call drmHandleEvent for drmModePageFlip
2025-08-07 19:49:15 +08:00
xueshuming d9da7747d0 drmvideo.c: used drmModePageFlip to update screen 2025-08-06 21:02:26 +08:00
xueshuming e48af7072a drmvideo: create/destroy flip_buffer for page flip 2025-08-06 19:30:29 +08:00
xueshuming 210e996b56 add 'neon_memcpy' for accelerated memcpy (arm64) 2025-08-06 16:04:59 +08:00
xueshuming 0d0246adbe update gitignore 2025-08-06 16:04:18 +08:00
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
21 changed files with 526 additions and 9179 deletions
+4
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
@@ -30,3 +32,5 @@ Makefile.in
/src/sysres/font_list
/src/sysres/license/dat_files/
/configure~
.cache
compile_commands.json
+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.
+2 -2
View File
@@ -1,6 +1,6 @@
Version 5.2.0 (2023/09/30)
Version 5.0.16 (2025/05/27)
This is a minor enhancement and bugfix release of MiniGUI 5.2.x, the stable version.
This is a minor enhancement and bugfix release of MiniGUI 5.0.x, the stable version.
Other packages for MiniGUI resource, tools, components, and samples:
+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.2.0)
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
#
@@ -15,10 +16,10 @@ dnl Set various version strings - taken gratefully from the SDL sources
# set MINIGUI_BINARY_AGE and MINIGUI_INTERFACE_AGE to 0.
#
MINIGUI_MAJOR_VERSION=5
MINIGUI_MINOR_VERSION=2
MINIGUI_MICRO_VERSION=0
MINIGUI_INTERFACE_AGE=0
MINIGUI_BINARY_AGE=0
MINIGUI_MINOR_VERSION=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,27 +41,24 @@ 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 stdatomic.h locale.h unistd.h termio.h sys/types.h sys/time.h sys/select.h sys/memfd.h)
@@ -68,7 +66,6 @@ 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}
-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
+4 -35
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;
+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);
+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 */
+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 ());
}
-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"
+274 -41
View File
@@ -837,6 +837,9 @@ static DrmSurfaceBuffer *drm_create_dumb_buffer(DrmVideoData* vdata,
static void drm_destroy_dumb_buffer(DrmVideoData* vdata,
DrmSurfaceBuffer *surface_buffer);
static void drm_destroy_flip_buffer(DrmVideoData* vdata,
DrmSurfaceBuffer *flip_buffer);
/*
* The following helpers derived from DRM HOWTO by David Herrmann.
*
@@ -909,6 +912,12 @@ static void drm_cleanup(DrmVideoData* vdata)
}
#endif /* _MGSCHEMA_COMPOSITING */
/* Clean up flip buffer used for page flipping */
if (vdata->flip_buff) {
drm_destroy_flip_buffer(vdata, vdata->flip_buff);
vdata->flip_buff = NULL;
}
if (vdata->scanout_buff_id) {
/* remove frame buffer */
drmModeRmFB(vdata->dev_fd, vdata->scanout_buff_id);
@@ -940,12 +949,22 @@ static void drm_cleanup(DrmVideoData* vdata)
static void DRM_DeleteDevice(GAL_VideoDevice *device)
{
if (device->hidden->real_screen) {
/* FIXME */
DrmSurfaceBuffer *surface_buffer =
(DrmSurfaceBuffer *)device->hidden->real_screen->hwdata;
if (surface_buffer && !device->hidden->driver) {
drm_destroy_dumb_buffer(device->hidden, surface_buffer);
device->hidden->real_screen->hwdata = NULL;
}
GAL_FreeSurface(device->hidden->real_screen);
device->hidden->real_screen = NULL;
}
drm_cleanup(device->hidden);
if (device->hidden->dev_name)
free (device->hidden->dev_name);
@@ -1663,6 +1682,9 @@ static int DRM_VideoInit(_THIS, GAL_PixelFormat *vformat)
}
#endif
/* Initialize page flipping capability */
this->hidden->flip_buff = NULL;
if (this->hidden->driver) {
if (this->hidden->driver_ops->fill_rect) {
this->info.blit_fill = 1;
@@ -2169,6 +2191,50 @@ err_destroy:
return NULL;
}
/* Create flip buffer for page flipping */
static DrmSurfaceBuffer *drm_create_flip_buffer(DrmVideoData *vdata,
uint32_t drm_format, int width, int height)
{
DrmSurfaceBuffer *flip_buffer = NULL;
int ret;
uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
flip_buffer = drm_create_dumb_buffer(vdata, drm_format, 0, width, height);
if (flip_buffer == NULL) {
_ERR_PRINTF("NEWGAL>DRM: Failed to create flip buffer\n");
goto error_exit;
}
/* Add framebuffer */
if (flip_buffer->fb_id == 0) {
/* Setup handles, pitches and offsets for FB2 */
handles[0] = flip_buffer->handle;
pitches[0] = flip_buffer->pitch;
offsets[0] = flip_buffer->offset;
/* Use drmModeAddFB2 for better format support */
ret = drmModeAddFB2(vdata->dev_fd, flip_buffer->width,
flip_buffer->height, flip_buffer->drm_format,
handles, pitches, offsets, &flip_buffer->fb_id, 0);
if (ret) {
_ERR_PRINTF(
"NEWGAL>DRM: Failed to add framebuffer for flip buffer: %m\n");
goto error_cleanup;
}
}
_DBG_PRINTF("NEWGAL>DRM: Created flip buffer: fb_id(%u)\n",
flip_buffer->fb_id);
return flip_buffer;
error_cleanup:
drm_destroy_dumb_buffer(vdata, flip_buffer);
error_exit:
return NULL;
}
static DrmSurfaceBuffer *drm_create_dumb_buffer_from_handle(DrmVideoData* vdata,
uint32_t handle, size_t size)
{
@@ -2362,6 +2428,17 @@ static void drm_destroy_dumb_buffer(DrmVideoData* vdata,
free (surface_buffer);
}
/* Destroy flip buffer used for page flipping */
static void drm_destroy_flip_buffer(DrmVideoData* vdata,
DrmSurfaceBuffer *flip_buffer)
{
if (flip_buffer == NULL) {
return;
}
drm_destroy_dumb_buffer(vdata, flip_buffer);
}
static DrmModeInfo* find_mode(DrmVideoData* vdata, int width, int height)
{
DrmModeInfo *iter;
@@ -2393,18 +2470,71 @@ static double get_elapsed_seconds(const struct timespec *ts_from,
}
#endif
#if defined(__arm__) && defined(__linux__)
// ARM64 NEON accelerated memcpy implementation
static void *neon_memcpy(void *dst, const void *src, size_t n)
{
// Backup original pointer for return
void *ret = dst;
// Handle unaligned portion
uintptr_t dst_addr = (uintptr_t)dst;
size_t pre_align = (16 - (dst_addr & 15)) & 15;
if (pre_align > 0) {
if (pre_align > n) {
pre_align = n;
}
memcpy(dst, src, pre_align);
dst = (char *)dst + pre_align;
src = (char *)src + pre_align;
n -= pre_align;
}
// NEON vector copy main loop, copy 128 bytes each time
if (n >= 128) {
size_t count = n >> 7;
asm volatile("1:\n"
// Load 128 bytes into v0-v7 registers
"ld1 {v0.2d, v1.2d, v2.2d, v3.2d}, [%1], #64\n"
"ld1 {v4.2d, v5.2d, v6.2d, v7.2d}, [%1], #64\n"
// Store 128 bytes
"st1 {v0.2d, v1.2d, v2.2d, v3.2d}, [%0], #64\n"
"st1 {v4.2d, v5.2d, v6.2d, v7.2d}, [%0], #64\n"
"subs %2, %2, #1\n"
"b.ne 1b\n"
: "+r"(dst), "+r"(src), "+r"(count)
:
: "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6",
"v7");
n &= 127;
}
// Handle remaining bytes
if (n > 0) {
memcpy(dst, src, n);
}
return ret;
}
#endif /* defined(__arm__) && defined(__linux__) */
static void update_real_screen_memcpy(_THIS, const GAL_Rect *dirty_rect)
{
DrmSurfaceBuffer *real_buff, *shadow_buff;
real_buff = (DrmSurfaceBuffer *)this->hidden->real_screen->hwdata;
shadow_buff = (DrmSurfaceBuffer *)this->hidden->shadow_screen->hwdata;
DrmSurfaceBuffer *target_buff, *shadow_buff;
DrmVideoData *vdata = this->hidden;
shadow_buff = (DrmSurfaceBuffer *)vdata->shadow_screen->hwdata;
if (!vdata->flip_buff || (vdata->curr_buff == vdata->flip_buff)) {
target_buff = (DrmSurfaceBuffer *)vdata->real_screen->hwdata;
}
else {
target_buff = (DrmSurfaceBuffer *)vdata->flip_buff;
}
uint32_t i;
uint8_t *src, *dst;
int cpp = real_buff->cpp;
int shadow_pitch = this->hidden->shadow_screen->pitch;
int real_pitch = real_buff->pitch;
size_t count = cpp * dirty_rect->w;
int shadow_pitch = vdata->shadow_screen->pitch;
int target_pitch = target_buff->pitch;
if (shadow_buff) {
src = shadow_buff->vaddr;
@@ -2415,16 +2545,18 @@ static void update_real_screen_memcpy(_THIS, const GAL_Rect *dirty_rect)
src += this->hidden->shadow_screen->pixels_off;
}
src += shadow_pitch * dirty_rect->y + cpp * dirty_rect->x;
dst = target_buff->vaddr;
dst += target_buff->offset;
dst = real_buff->vaddr;
dst += real_pitch * dirty_rect->y + cpp * dirty_rect->x;
dst += real_buff->offset;
for (i = 0; i < dirty_rect->h; i++) {
memcpy(dst, src, count);
for (uint32_t i = 0; i < target_buff->height; i++) {
#if defined(__arm__) && defined(__linux__)
neon_memcpy(dst, src, target_pitch);
#else
memcpy(dst, src, target_pitch);
#endif /* defined(__arm__) && defined(__linux__) */
src += shadow_pitch;
dst += real_pitch;
dst += target_pitch;
}
}
@@ -2518,18 +2650,99 @@ static inline void refresh_cursor(_THIS, const GAL_Rect *dirty_rect) {
}
#endif /* _MGSCHEMA_COMPOSITING */
static int is_fd_readable(int fd)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Initialize the file descriptor set */
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
/* Set timeout to 0 to return immediately */
tv.tv_sec = 0;
tv.tv_usec = 0;
/* Call select to check if fd is readable */
retval = select(fd + 1, &rfds, NULL, NULL, &tv);
if (retval == -1) {
/* Error occurred */
return -1;
} else if (retval) {
/* File descriptor is readable */
return 1;
} else {
/* Timeout occurred, file descriptor is not readable */
return 0;
}
}
/* Perform page flip between flip_buffer and real_screen->hwdata using curr_buff */
static int drm_page_flip(DrmVideoData* vdata)
{
int ret;
/* Perform the page flip */
if (!vdata->flip_buff || !vdata->flip_buff->fb_id) {
_ERR_PRINTF("NEWGAL>DRM: No valid flip buffer for page flipping\n");
return -1;
}
/* Get the next buffer to display */
DrmSurfaceBuffer *next_buffer;
if (vdata->curr_buff == vdata->flip_buff) {
next_buffer = (DrmSurfaceBuffer *)vdata->real_screen->hwdata;
} else {
next_buffer = vdata->flip_buff;
}
uint32_t next_fb_id = next_buffer->fb_id;
/* drmModePageFlip will wait for vertical sync signal internally */
ret = drmModePageFlip(vdata->dev_fd, vdata->saved_crtc->crtc_id,
next_fb_id, DRM_MODE_PAGE_FLIP_EVENT, NULL);
if (ret) {
_ERR_PRINTF("NEWGAL>DRM: Failed to perform page flip: %m\n");
return -1;
}
/* Update scanout buffer ID */
vdata->scanout_buff_id = next_fb_id;
/* Update current buffer pointer */
vdata->curr_buff = next_buffer;
return 0;
}
static void update_real_screen_helper(_THIS, const GAL_Rect *dirty_rect)
{
DrmVideoData* vdata = this->hidden;
DrmSurfaceBuffer *real_buff, *shadow_buff;
DrmSurfaceBuffer *target_buff, *shadow_buff;
/* Initialize curr_buff if not set */
if (!vdata->curr_buff) {
vdata->curr_buff = (DrmSurfaceBuffer *)vdata->real_screen->hwdata;
}
/* Use the buffer that is not currently displayed as the target buffer */
if (vdata->flip_buff) {
target_buff = (vdata->curr_buff == vdata->flip_buff)
? (DrmSurfaceBuffer *)vdata->real_screen->hwdata
: vdata->flip_buff;
}
else {
target_buff = (DrmSurfaceBuffer *)vdata->real_screen->hwdata;
}
real_buff = (DrmSurfaceBuffer *)vdata->real_screen->hwdata;
shadow_buff = (DrmSurfaceBuffer *)vdata->shadow_screen->hwdata;
#if 0 // def _DEBUG
_DBG_PRINTF("Copy pixels to real screen (pitch: %u, count: %u, %d x %d)\n",
(unsigned)real_buff->pitch, (unsigned)count,
RECTWP(update_rect), RECTHP(update_rect));
_DBG_PRINTF("Copy pixels to target buffer (pitch: %u, %d x %d)\n",
(unsigned)target_buff->pitch,
dirty_rect->w, dirty_rect->h);
struct timespec ts_start;
clock_gettime(CLOCK_REALTIME, &ts_start);
@@ -2539,7 +2752,7 @@ static void update_real_screen_helper(_THIS, const GAL_Rect *dirty_rect)
if (shadow_buff && vdata->driver && vdata->driver_ops->copy_buff) {
if ((dirty_rect->w * dirty_rect->h) >= vdata->min_pixels_using_hwaccl) {
if (vdata->driver_ops->copy_buff(vdata->driver, shadow_buff,
dirty_rect, real_buff, dirty_rect,
dirty_rect, target_buff, dirty_rect,
BLIT_COPY_TRANSLATE) == 0) {
hw_ok = TRUE;
}
@@ -2569,6 +2782,8 @@ static void* task_do_update(void *data)
{
_THIS = data;
DrmVideoData* vdata = this->hidden;
drmEventContext ev = {};
ev.version = DRM_EVENT_CONTEXT_VERSION;
if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) {
goto error;
@@ -2627,20 +2842,18 @@ static void* task_do_update(void *data)
RECTH(vdata->update_rect) };
update_real_screen_helper(this, &dirty_rect);
/* Flush driver buffer if needed */
if (vdata->driver && vdata->driver_ops->flush) {
DrmSurfaceBuffer *real_buff;
real_buff = (DrmSurfaceBuffer *)vdata->real_screen->hwdata;
vdata->driver_ops->flush(vdata->driver,
real_buff, &dirty_rect);
vdata->curr_buff, &dirty_rect);
}
else if (vdata->dirty_fb_ok) {
drmModeClip clip = {
vdata->update_rect.left,
vdata->update_rect.top,
vdata->update_rect.right,
vdata->update_rect.bottom };
drmModeDirtyFB(vdata->dev_fd,
vdata->scanout_buff_id, &clip, 1);
/* Perform page flip */
else if (vdata->flip_buff) {
drm_page_flip(vdata);
if (1 == is_fd_readable(vdata->dev_fd)) {
drmHandleEvent(vdata->dev_fd, &ev);
}
}
SetRectEmpty(&vdata->update_rect);
@@ -2788,6 +3001,20 @@ static GAL_Surface *DRM_SetVideoMode(_THIS, GAL_Surface *current,
_ERR_PRINTF("NEWGAL>DRM: cannot setup scanout buffer\n");
goto error;
}
real_buffer->fb_id = vdata->scanout_buff_id;
/* Create flip buffer for page flipping */
if (!vdata->driver) {
vdata->flip_buff =
drm_create_flip_buffer(vdata, drm_format, info->width, info->height);
if (vdata->flip_buff == NULL) {
_ERR_PRINTF("NEWGAL>DRM: failed to create flip buffer\n");
goto error;
}
}
/* Initialize curr_buff to point to real_screen buffer */
vdata->curr_buff = real_buffer;
if (vdata->crtc_idx >= 0)
this->WaitVBlank = DRM_WaitVBlank;
@@ -2924,6 +3151,12 @@ error:
}
}
/* Clean up flip buffer if created */
if (vdata->flip_buff) {
drm_destroy_flip_buffer(vdata, vdata->flip_buff);
vdata->flip_buff = NULL;
}
if (vdata->real_screen) {
GAL_FreeSurface (vdata->real_screen);
vdata->real_screen = NULL;
@@ -3834,16 +4067,16 @@ static BOOL DRM_SyncUpdate(_THIS)
refresh_cursor(this, &dirty_rect);
if (vdata->driver && vdata->driver_ops->flush) {
DrmSurfaceBuffer *real_buff;
real_buff = (DrmSurfaceBuffer *)vdata->real_screen->hwdata;
vdata->driver_ops->flush(vdata->driver,
real_buff, &dirty_rect);
vdata->driver_ops->flush(vdata->driver, vdata->curr_buff, &dirty_rect);
}
else if (vdata->dirty_fb_ok) {
drmModeClip clip = { clipped.left, clipped.top,
clipped.right, clipped.bottom };
drmModeDirtyFB(vdata->dev_fd,
vdata->scanout_buff_id, &clip, 1);
else if (vdata->dirty_fb_ok && vdata->flip_buff) {
/* Perform page flip */
drm_page_flip(vdata);
if (1 == is_fd_readable(vdata->dev_fd)) {
drmEventContext ev = {};
ev.version = DRM_EVENT_CONTEXT_VERSION;
drmHandleEvent(vdata->dev_fd, &ev);
}
}
ret:
+6
View File
@@ -89,6 +89,12 @@ typedef struct GAL_PrivateVideoData {
uint32_t real_name, shadow_name;
#endif /* not defined _MGSCHEMA_COMPOSITING */
/* flip buffer used for page flipping */
DrmSurfaceBuffer *flip_buff;
/* current buffer pointer for managing buffer switching */
DrmSurfaceBuffer *curr_buff;
sem_t *update_lock;
#if !IS_SHAREDFB_SCHEMA_PROCS
+81 -9
View File
@@ -1092,6 +1092,67 @@ nodraw_ret:
}
#ifdef _MGFONT_FT2
static RGB blend_pixel(RGB font_pixel, RGB fg_color, RGB bg_color)
{
RGB result;
Uint8 src_pre_r, src_pre_g, src_pre_b;
Uint8 bg_pre_r, bg_pre_g, bg_pre_b, alpha_bg;
Uint8 out_r, out_g, out_b, alpha_out;
uint8_t alpha_font = 0.299 * font_pixel.r + 0.587 * font_pixel.g +
0.114 * font_pixel.b;
uint16_t alpha_src = (fg_color.a * alpha_font + 127) / 255;
if (alpha_src == 0) {
result = bg_color;
goto out;
}
src_pre_r = (fg_color.r * alpha_src + 127) / 255;
src_pre_g = (fg_color.g * alpha_src + 127) / 255;
src_pre_b = (fg_color.b * alpha_src + 127) / 255;
bg_pre_r = (bg_color.r * bg_color.a + 127) / 255;
bg_pre_g = (bg_color.g * bg_color.a + 127) / 255;
bg_pre_b = (bg_color.b * bg_color.a + 127) / 255;
alpha_bg = bg_color.a;
out_r = src_pre_r + (bg_pre_r * (255 - alpha_src)) / 255;
out_g = src_pre_g + (bg_pre_g * (255 - alpha_src)) / 255;
out_b = src_pre_b + (bg_pre_b * (255 - alpha_src)) / 255;
alpha_out = alpha_src + (alpha_bg * (255 - alpha_src)) / 255;
if (out_r > 255) {
out_r = 255;
}
if (out_g > 255) {
out_g = 255;
}
if (out_b > 255) {
out_b = 255;
}
if (alpha_out > 0) {
result.r = (out_r * 255 + alpha_out / 2) / alpha_out;
result.g = (out_g * 255 + alpha_out / 2) / alpha_out;
result.b = (out_b * 255 + alpha_out / 2) / alpha_out;
result.a = (uint8_t) alpha_out;
} else {
result.r = 0;
result.g = 0;
result.b = 0;
result.a = 0;
}
out:
return result;
}
static void _dc_ft2subpixel_scan_line(PDC pdc, int xpos, int ypos,
SCANLINE_CTXT* ctxt)
{
@@ -1112,8 +1173,8 @@ static void _dc_ft2subpixel_scan_line(PDC pdc, int xpos, int ypos,
ctxt->glyph_ascent, ctxt->glyph_line,
ctxt->glyph_advance);
GAL_GetRGB (pdc->textcolor, pdc->surface->format, &rgba_fg.r,
&rgba_fg.g, &rgba_fg.b);
GAL_GetRGBA (pdc->textcolor, pdc->surface->format, &rgba_fg.r,
&rgba_fg.g, &rgba_fg.b, &rgba_fg.a);
for (x = 0; x < ctxt->bmp_w; x++) {
if (!PtInRect (&pdc->rc_output, x+xpos, ypos)) {
@@ -1130,8 +1191,8 @@ static void _dc_ft2subpixel_scan_line(PDC pdc, int xpos, int ypos,
_glyph_move_to_pixel (pdc, x+xpos, ypos);
pixel = _mem_get_pixel(pdc->cur_dst, GAL_BytesPerPixel (pdc->surface));
GAL_GetRGB (pixel, pdc->surface->format, &rgba_cur.r,
&rgba_cur.g, &rgba_cur.b);
GAL_GetRGBA (pixel, pdc->surface->format, &rgba_cur.r,
&rgba_cur.g, &rgba_cur.b, &rgba_cur.a);
#define C_ALPHA(p, Cs, Cd) \
if (*p++) { \
@@ -1140,14 +1201,25 @@ static void _dc_ft2subpixel_scan_line(PDC pdc, int xpos, int ypos,
Cd = sub_val >> 8; \
}
C_ALPHA(bits, rgba_fg.r, rgba_cur.r);
C_ALPHA(bits, rgba_fg.g, rgba_cur.g);
C_ALPHA(bits, rgba_fg.b, rgba_cur.b);
if (rgba_cur.r == 0 && rgba_cur.g == 0 && rgba_cur.b == 0 &&
rgba_cur.a == 0) {
RGB font_pixel = {bits[0], bits[1], bits[2], 255};
RGB ret = blend_pixel(font_pixel, rgba_fg, rgba_cur);
rgba_cur = ret;
bits += 3;
}
else {
C_ALPHA(bits, rgba_fg.r, rgba_cur.r);
C_ALPHA(bits, rgba_fg.g, rgba_cur.g);
C_ALPHA(bits, rgba_fg.b, rgba_cur.b);
rgba_cur.a = 255.0;
}
#undef C_ALPHA
pdc->cur_pixel = GAL_MapRGB (pdc->surface->format, rgba_cur.r,
rgba_cur.g, rgba_cur.b);
pdc->cur_pixel = GAL_MapRGBA (pdc->surface->format, rgba_cur.r,
rgba_cur.g, rgba_cur.b, rgba_cur.a);
if (pdc->cur_pixel != pixel) {
_glyph_draw_pixel (pdc, x+xpos, ypos, pdc->cur_pixel);
+2 -24
View File
@@ -84,20 +84,6 @@ extern DWORD __mg_tick_counter;
ON_NEW_DEL_CLIENT OnNewDelClient = NULL;
#if 0
/* Since 5.0.0, use RegisterEventHookFunc to implement SetServerEventHook */
static SRVEVTHOOK srv_evt_hook = NULL;
SRVEVTHOOK GUIAPI SetServerEventHook (SRVEVTHOOK SrvEvtHook)
{
SRVEVTHOOK old_hook = srv_evt_hook;
srv_evt_hook = SrvEvtHook;
return old_hook;
}
#endif /* deprecated code; moved to window.c */
static void ParseEvent (PMSGQUEUE msg_que, int event)
{
LWEVENT lwe;
@@ -331,7 +317,7 @@ BOOL GUIAPI ServerStartup (int nr_globals,
__mg_dsk_msg_queue->maxfd = listenfd;
maxi = -1;
mg_InitTimer (TRUE);
mg_InitTimer ();
__mg_start_server_desktop ();
@@ -363,7 +349,7 @@ void server_ServerCleanup (void)
__mg_nssurf_map_delete ();
#endif
mg_TerminateTimer (TRUE);
mg_TerminateTimer ();
unlink (CS_PATH);
}
@@ -381,14 +367,6 @@ BOOL server_IdleHandler4Server (PMSGQUEUE msg_queue, BOOL wait)
EXTRA_INPUT_EVENT extra; // Since 4.0.0; for extra input events
int nevts = 0; // Since 5.0.0; for timer and fd events
#if 0 /* deprecated code */
/* since 5.0.0, use __mg_update_tick_count instead */
if (__mg_tick_counter != SHAREDRES_TIMER_COUNTER) {
__mg_tick_counter = SHAREDRES_TIMER_COUNTER;
AlertDesktopTimerEvent ();
}
#endif /* deprecated code */
/* rset gets modified each time around */
rset = __mg_dsk_msg_queue->rfdset;
if (__mg_dsk_msg_queue->nr_wfds) {
+2 -2
View File
@@ -190,14 +190,14 @@ static void ParseEvent (PMSGQUEUE msg_que, int event)
BOOL GUIAPI salone_StandAloneStartup (void)
{
/* VW: do not use signal based interval timer; since 4.0 */
mg_InitTimer (FALSE);
mg_InitTimer ();
return TRUE;
}
void salone_StandAloneCleanup (void)
{
/* VW: do not use signal based interval timer; since 4.0 */
mg_TerminateTimer (FALSE);
mg_TerminateTimer ();
}
BOOL salone_IdleHandler4StandAlone (PMSGQUEUE msg_queue, BOOL wait)