mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-09-24 00:54:18 +08:00
Compare commits
3
Commits
master
...
update_threads
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e6809618a | ||
|
|
9befaeb68a | ||
|
|
87b9facc84 |
+32
-5
@@ -95,6 +95,7 @@ message_string="no"
|
|||||||
osname="unspecified"
|
osname="unspecified"
|
||||||
runtime_mode="procs"
|
runtime_mode="procs"
|
||||||
compositing_schema="yes"
|
compositing_schema="yes"
|
||||||
|
nr_concurrent_tasks=0
|
||||||
virtual_window="no"
|
virtual_window="no"
|
||||||
use_shmopen="no"
|
use_shmopen="no"
|
||||||
mgslice_use_fallback="no"
|
mgslice_use_fallback="no"
|
||||||
@@ -853,12 +854,16 @@ build_ctrl_animation=$enableval)
|
|||||||
|
|
||||||
if test "x$runtime_mode" == "xprocs"; then
|
if test "x$runtime_mode" == "xprocs"; then
|
||||||
AC_ARG_ENABLE(compositing,
|
AC_ARG_ENABLE(compositing,
|
||||||
[ --enable-compositing enable compositing schema (MiniGUI-Processes runmode only) <default=yes>],
|
[ --enable-compositing enable compositing schema (MiniGUI-Processes runmode only) <default=yes>],
|
||||||
compositing_schema=$enableval)
|
compositing_schema=$enableval)
|
||||||
|
|
||||||
AC_ARG_ENABLE(shmopen,
|
AC_ARG_ENABLE(shmopen,
|
||||||
[ --enable-shmopen use shm_open <default=no>],
|
[ --enable-shmopen use shm_open <default=no>],
|
||||||
use_shmopen=$enableval)
|
use_shmopen=$enableval)
|
||||||
|
|
||||||
|
AC_ARG_WITH(concurrent_tasks,
|
||||||
|
[ --with-concurrent-tasks=[0/1/3/7]],
|
||||||
|
nr_concurrent_tasks=$withval)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$runtime_mode" != "xths"; then
|
if test "x$runtime_mode" != "xths"; then
|
||||||
@@ -1755,7 +1760,7 @@ case "$runtime_mode" in
|
|||||||
[Define if build MiniGUI-Processes])
|
[Define if build MiniGUI-Processes])
|
||||||
MINIGUI_RUNMODE="procs"
|
MINIGUI_RUNMODE="procs"
|
||||||
if test "x$compositing_schema" = "xyes"; then
|
if test "x$compositing_schema" = "xyes"; then
|
||||||
surface_schema="compositing"
|
surface_schema="compositing"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$use_shmopen" = "xyes"; then
|
if test "x$use_shmopen" = "xyes"; then
|
||||||
@@ -1777,9 +1782,30 @@ esac
|
|||||||
if test "x$surface_schema" = "xcompositing"; then
|
if test "x$surface_schema" = "xcompositing"; then
|
||||||
AC_DEFINE(_MGSCHEMA_COMPOSITING, 1,
|
AC_DEFINE(_MGSCHEMA_COMPOSITING, 1,
|
||||||
[Define if use compositing schema for the current runmode])
|
[Define if use compositing schema for the current runmode])
|
||||||
|
|
||||||
|
case "$nr_concurrent_tasks" in
|
||||||
|
1)
|
||||||
|
AC_DEFINE(_MGNR_CONCURRENT_TASKS, 1,
|
||||||
|
[The number of concurrent threads.])
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
AC_DEFINE(_MGNR_CONCURRENT_TASKS, 3,
|
||||||
|
[The number of concurrent threads.])
|
||||||
|
;;
|
||||||
|
7)
|
||||||
|
AC_DEFINE(_MGNR_CONCURRENT_TASKS, 7,
|
||||||
|
[The number of concurrent threads.])
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_DEFINE(_MGNR_CONCURRENT_TASKS, 0,
|
||||||
|
[The number of concurrent threads.])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
else
|
else
|
||||||
AC_DEFINE(_MGSCHEMA_SHAREDFB, 1,
|
AC_DEFINE(_MGSCHEMA_SHAREDFB, 1,
|
||||||
[Define if use legacy schema (shared frame buffer) for the current runmode])
|
[Define if use legacy schema (shared frame buffer) for the current runmode])
|
||||||
|
AC_DEFINE(_MGNR_CONCURRENT_TASKS, 0,
|
||||||
|
[The number of concurrent threads.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$virtual_window" = "xyes"; then
|
if test "x$virtual_window" = "xyes"; then
|
||||||
@@ -2794,6 +2820,7 @@ AC_MSG_NOTICE([
|
|||||||
* Runtime mode: ${runtime_mode}
|
* Runtime mode: ${runtime_mode}
|
||||||
* Virtual Window: ${virtual_window}
|
* Virtual Window: ${virtual_window}
|
||||||
* Surface schema: ${surface_schema}
|
* Surface schema: ${surface_schema}
|
||||||
|
* Concurrent Tasks: ${nr_concurrent_tasks}
|
||||||
* Use shm_open: ${use_shmopen}
|
* Use shm_open: ${use_shmopen}
|
||||||
* Incore resource: ${incore_res}
|
* Incore resource: ${incore_res}
|
||||||
* Fallback mgslice: ${mgslice_use_fallback}
|
* Fallback mgslice: ${mgslice_use_fallback}
|
||||||
|
|||||||
+1
-1
@@ -6455,7 +6455,7 @@ MG_EXPORT RES_KEY Str2Key (const char* str);
|
|||||||
* \fn int GUIAPI GetWindowZOrder(HWND hWnd);
|
* \fn int GUIAPI GetWindowZOrder(HWND hWnd);
|
||||||
* \brief Get The Control ZOrder in the parent window
|
* \brief Get The Control ZOrder in the parent window
|
||||||
*
|
*
|
||||||
* \param hWnd Handler of a control
|
* \param hWnd Handle of a control
|
||||||
*
|
*
|
||||||
* \return return index of ZOrder or 0 if hWnd is a MainWindow or -1 if error
|
* \return return index of ZOrder or 0 if hWnd is a MainWindow or -1 if error
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1303,7 +1303,7 @@ static void transit_to_layer (CompositorCtxt* ctxt, MG_Layer* to_layer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_DBG_PRINTF ("Average time to composite the layers: %u (times: %u)\n", total_time_ms / total_times, total_times);
|
_WRN_PRINTF ("Average time to composite the layers: %u (times: %u)\n", total_time_ms / total_times, total_times);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompositorOps __mg_fallback_compositor = {
|
CompositorOps __mg_fallback_compositor = {
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ COMMON_SRCS = \
|
|||||||
surface-shm.c \
|
surface-shm.c \
|
||||||
shadow-screen.h \
|
shadow-screen.h \
|
||||||
shadow-screen.c \
|
shadow-screen.c \
|
||||||
|
concurrent-tasks.h \
|
||||||
|
concurrent-tasks.c \
|
||||||
$(NULL_FILE)
|
$(NULL_FILE)
|
||||||
|
|
||||||
libnewgal_la_SOURCES = $(COMMON_SRCS)
|
libnewgal_la_SOURCES = $(COMMON_SRCS)
|
||||||
|
|||||||
+2
-2
@@ -77,13 +77,13 @@ static int GAL_SoftBlit(GAL_Surface *src, GAL_Rect *srcrect,
|
|||||||
GAL_loblit RunBlit;
|
GAL_loblit RunBlit;
|
||||||
|
|
||||||
/* Set up the blit information */
|
/* Set up the blit information */
|
||||||
info.s_pixels = (Uint8 *)src->pixels +
|
info.s_pixels = (Uint8 *)src->pixels + src->pixels_off +
|
||||||
(Uint16)srcrect->y*src->pitch +
|
(Uint16)srcrect->y*src->pitch +
|
||||||
(Uint16)srcrect->x*src->format->BytesPerPixel;
|
(Uint16)srcrect->x*src->format->BytesPerPixel;
|
||||||
info.s_width = srcrect->w;
|
info.s_width = srcrect->w;
|
||||||
info.s_height = srcrect->h;
|
info.s_height = srcrect->h;
|
||||||
info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel;
|
info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel;
|
||||||
info.d_pixels = (Uint8 *)dst->pixels +
|
info.d_pixels = (Uint8 *)dst->pixels + dst->pixels_off +
|
||||||
(Uint16)dstrect->y*dst->pitch +
|
(Uint16)dstrect->y*dst->pitch +
|
||||||
(Uint16)dstrect->x*dst->format->BytesPerPixel;
|
(Uint16)dstrect->x*dst->format->BytesPerPixel;
|
||||||
info.d_width = dstrect->w;
|
info.d_width = dstrect->w;
|
||||||
|
|||||||
@@ -0,0 +1,324 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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) 2021, 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/>.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
** concurrent-tasks.c:
|
||||||
|
** This file implements the concurrent tasks by using POSIX threads.
|
||||||
|
**
|
||||||
|
** Current maintainer: Wei Yongming.
|
||||||
|
**
|
||||||
|
** Create date: 2021/05/21
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#ifdef _MGRM_PROCESSES
|
||||||
|
|
||||||
|
#include "minigui.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "newgal.h"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
#include "concurrent-tasks.h"
|
||||||
|
|
||||||
|
typedef void (*task_proc)(void* context, int loop_idx);
|
||||||
|
|
||||||
|
typedef struct _ConcurrentTasksInfo {
|
||||||
|
pthread_t pths[_MGNR_CONCURRENT_TASKS];
|
||||||
|
sem_t sem_loop;
|
||||||
|
sem_t sem_lock;
|
||||||
|
sem_t sem_sync;
|
||||||
|
|
||||||
|
int nr_loops;
|
||||||
|
CCTaskProc proc;
|
||||||
|
void* ctxt;
|
||||||
|
} ConcurrentTasksInfo;
|
||||||
|
|
||||||
|
static ConcurrentTasksInfo *cctasks_info;
|
||||||
|
|
||||||
|
static inline int cc_sem_wait (sem_t *sem)
|
||||||
|
{
|
||||||
|
try_again:
|
||||||
|
if (sem_wait (sem) < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
goto try_again;
|
||||||
|
else {
|
||||||
|
_WRN_PRINTF ("Failed sem_wait: %s\n", strerror (errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* cc_task_entry (void* data)
|
||||||
|
{
|
||||||
|
int task_idx = (int)(intptr_t)data;
|
||||||
|
|
||||||
|
if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
int loop_idx;
|
||||||
|
|
||||||
|
if (cc_sem_wait (&cctasks_info->sem_loop)) {
|
||||||
|
_ERR_PRINTF ("CCTasks: thread %d failed on sem_wait\n", task_idx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_sem_wait (&cctasks_info->sem_lock);
|
||||||
|
loop_idx = cctasks_info->nr_loops++;
|
||||||
|
sem_post (&cctasks_info->sem_lock);
|
||||||
|
|
||||||
|
pthread_testcancel ();
|
||||||
|
|
||||||
|
cctasks_info->proc (cctasks_info->ctxt, loop_idx);
|
||||||
|
|
||||||
|
if (sem_post (&cctasks_info->sem_sync)) {
|
||||||
|
_ERR_PRINTF ("CCTasks: thread %d failed on sem_post\n", task_idx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_testcancel ();
|
||||||
|
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int concurrentTasks_SplitRect (GAL_Rect* rcs, const GAL_Rect* rc, int count)
|
||||||
|
{
|
||||||
|
if (count == 1) {
|
||||||
|
rcs[0] = *rc;
|
||||||
|
}
|
||||||
|
else if (count == 2) {
|
||||||
|
rcs[0].x = rc->x;
|
||||||
|
rcs[0].y = rc->y;
|
||||||
|
rcs[0].w = rc->w;
|
||||||
|
rcs[0].h = rc->h >> 1;
|
||||||
|
|
||||||
|
rcs[1].x = rc->x;
|
||||||
|
rcs[1].y = rcs[0].y + rcs[0].h;
|
||||||
|
rcs[1].w = rc->w;
|
||||||
|
rcs[1].h = rc->h - rcs[0].h;
|
||||||
|
}
|
||||||
|
else if (count == 4) {
|
||||||
|
rcs[0].x = rc->x;
|
||||||
|
rcs[0].y = rc->y;
|
||||||
|
rcs[0].w = rc->w;
|
||||||
|
rcs[0].h = rc->h >> 2;
|
||||||
|
|
||||||
|
rcs[1].x = rc->x;
|
||||||
|
rcs[1].y = rcs[0].y + rcs[0].h;
|
||||||
|
rcs[1].w = rc->w;
|
||||||
|
rcs[1].h = rc->h >> 2;
|
||||||
|
|
||||||
|
rcs[2].x = rc->x;
|
||||||
|
rcs[2].y = rcs[1].y + rcs[1].h;
|
||||||
|
rcs[2].w = rc->w;
|
||||||
|
rcs[2].h = rc->h >> 2;
|
||||||
|
|
||||||
|
rcs[3].x = rc->x;
|
||||||
|
rcs[3].y = rcs[2].y + rcs[2].h;
|
||||||
|
rcs[3].w = rc->w;
|
||||||
|
rcs[3].h = rc->h - rcs[0].h * 3;
|
||||||
|
}
|
||||||
|
else if (count == 8) {
|
||||||
|
rcs[0].x = rc->x;
|
||||||
|
rcs[0].y = rc->y;
|
||||||
|
rcs[0].w = rc->w;
|
||||||
|
rcs[0].h = rc->h >> 3;
|
||||||
|
|
||||||
|
rcs[1].x = rc->x;
|
||||||
|
rcs[1].y = rcs[0].y + rcs[0].h;
|
||||||
|
rcs[1].w = rc->w;
|
||||||
|
rcs[1].h = rc->h >> 3;
|
||||||
|
|
||||||
|
rcs[2].x = rc->x;
|
||||||
|
rcs[2].y = rcs[1].y + rcs[1].h;
|
||||||
|
rcs[2].w = rc->w;
|
||||||
|
rcs[2].h = rc->h >> 3;
|
||||||
|
|
||||||
|
rcs[3].x = rc->x;
|
||||||
|
rcs[3].y = rcs[2].y + rcs[2].h;
|
||||||
|
rcs[3].w = rc->w;
|
||||||
|
rcs[3].h = rc->h >> 3;
|
||||||
|
|
||||||
|
rcs[4].x = rc->x;
|
||||||
|
rcs[4].y = rcs[3].y + rcs[3].h;
|
||||||
|
rcs[4].w = rc->w;
|
||||||
|
rcs[4].h = rc->h >> 3;
|
||||||
|
|
||||||
|
rcs[5].x = rc->x;
|
||||||
|
rcs[5].y = rcs[4].y + rcs[4].h;
|
||||||
|
rcs[5].w = rc->w;
|
||||||
|
rcs[5].h = rc->h >> 3;
|
||||||
|
|
||||||
|
rcs[6].x = rc->x;
|
||||||
|
rcs[6].y = rcs[5].y + rcs[5].h;
|
||||||
|
rcs[6].w = rc->w;
|
||||||
|
rcs[6].h = rc->h >> 3;
|
||||||
|
|
||||||
|
rcs[7].x = rc->x;
|
||||||
|
rcs[7].y = rcs[6].y + rcs[6].h;
|
||||||
|
rcs[7].w = rc->w;
|
||||||
|
rcs[7].h = rc->h - rcs[0].h * 7;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int concurrentTasks_Do (void* context, CCTaskProc proc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (_MGNR_CONCURRENT_TASKS > 0) {
|
||||||
|
cctasks_info->nr_loops = 1; // reserve 0 for the current thread
|
||||||
|
cctasks_info->proc = proc;
|
||||||
|
cctasks_info->ctxt = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// wake up the concurrent task threads
|
||||||
|
for (i = 0; i < _MGNR_CONCURRENT_TASKS; i++) {
|
||||||
|
sem_post (&cctasks_info->sem_loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
proc (context, 0);
|
||||||
|
|
||||||
|
// wait for finish of concurrent task threads
|
||||||
|
for (i = 0; i < _MGNR_CONCURRENT_TASKS; i++) {
|
||||||
|
if (cc_sem_wait (&cctasks_info->sem_sync) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int concurrentTasks_Init (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (_MGNR_CONCURRENT_TASKS <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((cctasks_info = calloc (1, sizeof (ConcurrentTasksInfo))) == NULL) {
|
||||||
|
_ERR_PRINTF ("CCTasks: failed to allocate memory\n");
|
||||||
|
goto failed_sem_loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sem_init (&cctasks_info->sem_loop, 0, 0)) {
|
||||||
|
_ERR_PRINTF ("CCTasks: failed to create loop semaphore: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
goto failed_sem_loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sem_init (&cctasks_info->sem_sync, 0, 0)) {
|
||||||
|
_ERR_PRINTF ("CCTasks: failed to create sync semaphore: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
goto failed_sem_sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sem_init (&cctasks_info->sem_lock, 0, 1)) {
|
||||||
|
_ERR_PRINTF ("CCTasks: failed to create lock semaphore: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
goto failed_sem_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < _MGNR_CONCURRENT_TASKS; i++) {
|
||||||
|
if (pthread_create (cctasks_info->pths + i, NULL, cc_task_entry,
|
||||||
|
(void*)(intptr_t)(i + 1))) {
|
||||||
|
_ERR_PRINTF ("CCTasks: failed to create update thread (%d): %s\n",
|
||||||
|
i, strerror (errno));
|
||||||
|
goto failed_threads;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failed_threads:
|
||||||
|
sem_destroy (&cctasks_info->sem_lock);
|
||||||
|
|
||||||
|
failed_sem_lock:
|
||||||
|
sem_destroy (&cctasks_info->sem_sync);
|
||||||
|
|
||||||
|
failed_sem_sync:
|
||||||
|
sem_destroy (&cctasks_info->sem_loop);
|
||||||
|
|
||||||
|
failed_sem_loop:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int concurrentTasks_Term (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (_MGNR_CONCURRENT_TASKS <= 0 && cctasks_info == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < _MGNR_CONCURRENT_TASKS; i++) {
|
||||||
|
_WRN_PRINTF ("Cancelling concurrent task thread: %d\n", i);
|
||||||
|
/* send cancel request */
|
||||||
|
pthread_cancel (cctasks_info->pths [i]);
|
||||||
|
pthread_join (cctasks_info->pths [i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
sem_destroy (&cctasks_info->sem_sync);
|
||||||
|
sem_destroy (&cctasks_info->sem_loop);
|
||||||
|
sem_destroy (&cctasks_info->sem_lock);
|
||||||
|
|
||||||
|
free (cctasks_info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _MGRM_PROCESSES */
|
||||||
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// IMPORTANT NOTICE
|
||||||
|
//
|
||||||
|
// The following open source license statement does not apply to any
|
||||||
|
// entity in the Exception List published by FMSoft.
|
||||||
|
//
|
||||||
|
// For more information, please visit:
|
||||||
|
//
|
||||||
|
// https://www.fmsoft.cn/exception-list
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* This file is part of MiniGUI, a mature cross-platform windowing
|
||||||
|
* and Graphics User Interface (GUI) support system for embedded systems
|
||||||
|
* and smart IoT devices.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002~2020, Beijing FMSoft Technologies Co., Ltd.
|
||||||
|
* Copyright (C) 1998~2002, WEI Yongming
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <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/>.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
** The helpers for concurrent tasks.
|
||||||
|
**
|
||||||
|
** Current maintainer: Wei Yongming.
|
||||||
|
**
|
||||||
|
** Create date: 2021/05/21
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GAL_concurrent_tasks_h
|
||||||
|
#define _GAL_concurrent_tasks_h
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
typedef void (*CCTaskProc)(void* context, int loop_idx);
|
||||||
|
|
||||||
|
int concurrentTasks_Init (void);
|
||||||
|
int concurrentTasks_Term (void);
|
||||||
|
int concurrentTasks_SplitRect (GAL_Rect* rcs, const GAL_Rect* rc, int count);
|
||||||
|
int concurrentTasks_Do (void* context, CCTaskProc proc);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* _GAL_concurrent_tasks_h */
|
||||||
@@ -49,6 +49,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "newgal.h"
|
#include "newgal.h"
|
||||||
#include "blit.h"
|
#include "blit.h"
|
||||||
|
#include "concurrent-tasks.h"
|
||||||
|
|
||||||
#define DEFINE_COPY_ROW(name, type) \
|
#define DEFINE_COPY_ROW(name, type) \
|
||||||
static void name(type *src, int src_w, type *dst, int dst_w) \
|
static void name(type *src, int src_w, type *dst, int dst_w) \
|
||||||
@@ -377,6 +378,31 @@ int GAL_CleanupStretchBlit (GAL_Surface *src, GAL_Surface *dst)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _MGRM_PROCESSES
|
||||||
|
typedef struct _ContextStretch {
|
||||||
|
pixman_op_t op;
|
||||||
|
pixman_image_t *src_img;
|
||||||
|
pixman_image_t *msk_img;
|
||||||
|
pixman_image_t *dst_img;
|
||||||
|
|
||||||
|
GAL_Rect dst_rects [_MGNR_CONCURRENT_TASKS + 1];
|
||||||
|
} ContextStretch;
|
||||||
|
|
||||||
|
static void stretch_proc (void* context, int loop_idx)
|
||||||
|
{
|
||||||
|
ContextStretch *ctxt = context;
|
||||||
|
|
||||||
|
if (ctxt->dst_rects[loop_idx].h > 0) {
|
||||||
|
GAL_Rect* dstrect = ctxt->dst_rects + loop_idx;
|
||||||
|
pixman_image_composite32 (ctxt->op, ctxt->src_img, ctxt->msk_img, ctxt->dst_img,
|
||||||
|
dstrect->x, dstrect->y,
|
||||||
|
0, 0,
|
||||||
|
dstrect->x, dstrect->y,
|
||||||
|
dstrect->w, dstrect->h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int GAL_StretchBlt (GAL_Surface *src, GAL_Rect *srcrect,
|
int GAL_StretchBlt (GAL_Surface *src, GAL_Rect *srcrect,
|
||||||
GAL_Surface *dst, GAL_Rect *dstrect,
|
GAL_Surface *dst, GAL_Rect *dstrect,
|
||||||
const STRETCH_EXTRA_INFO* sei, DWORD ops)
|
const STRETCH_EXTRA_INFO* sei, DWORD ops)
|
||||||
@@ -409,11 +435,27 @@ int GAL_StretchBlt (GAL_Surface *src, GAL_Rect *srcrect,
|
|||||||
dst->clip_rect.x, dst->clip_rect.y, dst->clip_rect.w, dst->clip_rect.h);
|
dst->clip_rect.x, dst->clip_rect.y, dst->clip_rect.w, dst->clip_rect.h);
|
||||||
pixman_image_set_clip_region32 (dst_img, &clip_region);
|
pixman_image_set_clip_region32 (dst_img, &clip_region);
|
||||||
|
|
||||||
|
#ifdef _MGRM_PROCESSES
|
||||||
|
// we use concurrent tasks only under MiniGUI-Processes.
|
||||||
|
{
|
||||||
|
ContextStretch ctxt;
|
||||||
|
|
||||||
|
ctxt.op = op;
|
||||||
|
ctxt.src_img = src_img;
|
||||||
|
ctxt.msk_img = msk_img;
|
||||||
|
ctxt.dst_img = dst_img;
|
||||||
|
|
||||||
|
concurrentTasks_SplitRect (ctxt.dst_rects, dstrect, _MGNR_CONCURRENT_TASKS + 1);
|
||||||
|
|
||||||
|
concurrentTasks_Do (&ctxt, stretch_proc);
|
||||||
|
}
|
||||||
|
#else
|
||||||
pixman_image_composite32 (op, src_img, msk_img, dst_img,
|
pixman_image_composite32 (op, src_img, msk_img, dst_img,
|
||||||
dstrect->x, dstrect->y,
|
dstrect->x, dstrect->y,
|
||||||
0, 0,
|
0, 0,
|
||||||
dstrect->x, dstrect->y,
|
dstrect->x, dstrect->y,
|
||||||
dstrect->w, dstrect->h);
|
dstrect->w, dstrect->h);
|
||||||
|
#endif
|
||||||
|
|
||||||
pixman_region32_fini (&clip_region);
|
pixman_region32_fini (&clip_region);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+41
-25
@@ -56,6 +56,7 @@
|
|||||||
#include "pixels_c.h"
|
#include "pixels_c.h"
|
||||||
#include "memops.h"
|
#include "memops.h"
|
||||||
#include "leaks.h"
|
#include "leaks.h"
|
||||||
|
#include "concurrent-tasks.h"
|
||||||
|
|
||||||
#ifdef _MGRM_PROCESSES
|
#ifdef _MGRM_PROCESSES
|
||||||
#include <sys/mman.h> /* for munmap */
|
#include <sys/mman.h> /* for munmap */
|
||||||
@@ -493,6 +494,28 @@ static int own_overlapped_bitblit(GAL_blit real_blit, struct GAL_Surface *src, G
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MGRM_PROCESSES
|
||||||
|
typedef struct _ContextBlit {
|
||||||
|
GAL_Surface *src;
|
||||||
|
GAL_Surface *dst;
|
||||||
|
|
||||||
|
GAL_blit real_blit;
|
||||||
|
|
||||||
|
GAL_Rect src_rects [_MGNR_CONCURRENT_TASKS + 1];
|
||||||
|
GAL_Rect dst_rects [_MGNR_CONCURRENT_TASKS + 1];
|
||||||
|
} ContextBlit;
|
||||||
|
|
||||||
|
static void blit_proc (void* context, int loop_idx)
|
||||||
|
{
|
||||||
|
ContextBlit *ctxt = context;
|
||||||
|
|
||||||
|
if (ctxt->src_rects[loop_idx].h > 0) {
|
||||||
|
ctxt->real_blit (ctxt->src, ctxt->src_rects + loop_idx,
|
||||||
|
ctxt->dst, ctxt->dst_rects + loop_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up a blit between two surfaces -- split into three parts:
|
* Set up a blit between two surfaces -- split into three parts:
|
||||||
* The upper part, GAL_UpperBlit(), performs clipping and rectangle
|
* The upper part, GAL_UpperBlit(), performs clipping and rectangle
|
||||||
@@ -538,38 +561,31 @@ int GAL_LowerBlit (GAL_Surface *src, GAL_Rect *srcrect,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MG_CONFIG_USE_OWN_OVERLAPPED_BITBLIT
|
#ifdef _MGRM_PROCESSES
|
||||||
ret = own_overlapped_bitblit(do_blit, src, srcrect, dst, dstrect);
|
// we use concurrent tasks only under MiniGUI-Processes.
|
||||||
#else
|
|
||||||
ret = do_blit(src, srcrect, dst, dstrect);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
{
|
{
|
||||||
static int n_sw=0, n_hw=0;
|
ContextBlit ctxt;
|
||||||
if ((src->flags & GAL_HWACCEL) == GAL_HWACCEL)
|
|
||||||
{
|
ctxt.src = src;
|
||||||
n_hw ++;
|
ctxt.dst = dst;
|
||||||
}
|
ctxt.real_blit = do_blit;
|
||||||
else
|
|
||||||
{
|
concurrentTasks_SplitRect (ctxt.src_rects, srcrect, _MGNR_CONCURRENT_TASKS + 1);
|
||||||
n_sw ++;
|
concurrentTasks_SplitRect (ctxt.dst_rects, dstrect, _MGNR_CONCURRENT_TASKS + 1);
|
||||||
}
|
|
||||||
printf("[%06u] hw/blit=%d/%d %c size=%dX%d src=(%d %d),%p dst=(%d %d),%p\n",
|
concurrentTasks_Do (&ctxt, blit_proc);
|
||||||
times(NULL) % 1000000,
|
|
||||||
n_hw, n_hw+n_sw,
|
|
||||||
do_blit == src->map->sw_blit ? 'S':'H',
|
|
||||||
srcrect->w, srcrect->h,
|
|
||||||
srcrect->x, srcrect->y, src,
|
|
||||||
dstrect->x, dstrect->y, dst
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
# ifdef MG_CONFIG_USE_OWN_OVERLAPPED_BITBLIT
|
||||||
|
ret = own_overlapped_bitblit(do_blit, src, srcrect, dst, dstrect);
|
||||||
|
# else
|
||||||
|
ret = do_blit(src, srcrect, dst, dstrect);
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int GAL_UpperBlit (GAL_Surface *src, GAL_Rect *srcrect,
|
int GAL_UpperBlit (GAL_Surface *src, GAL_Rect *srcrect,
|
||||||
GAL_Surface *dst, GAL_Rect *dstrect, DWORD op)
|
GAL_Surface *dst, GAL_Rect *dstrect, DWORD op)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
#include "pixels_c.h"
|
#include "pixels_c.h"
|
||||||
#include "license.h"
|
#include "license.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "concurrent-tasks.h"
|
||||||
|
|
||||||
/* Available video drivers */
|
/* Available video drivers */
|
||||||
static VideoBootStrap *bootstrap[] = {
|
static VideoBootStrap *bootstrap[] = {
|
||||||
@@ -288,6 +289,12 @@ int GAL_VideoInit (const char *driver_name, Uint32 flags)
|
|||||||
|
|
||||||
video->info.vfmt = GAL_VideoSurface->format;
|
video->info.vfmt = GAL_VideoSurface->format;
|
||||||
|
|
||||||
|
#ifdef _MGRM_PROCESSES
|
||||||
|
// we use concurrent tasks only under MiniGUI-Processes.
|
||||||
|
if (concurrentTasks_Init ())
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1154,6 +1161,12 @@ void GAL_VideoQuit (void)
|
|||||||
DestroyFreeClipRectList (&__mg_free_update_region_list);
|
DestroyFreeClipRectList (&__mg_free_update_region_list);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _MGRM_PROCESSES
|
||||||
|
// we use concurrent tasks only under MiniGUI-Processes.
|
||||||
|
concurrentTasks_Term ();
|
||||||
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user