mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-09-25 02:33:59 +08:00
use async. update for shadow engine
This commit is contained in:
+75
-48
@@ -1157,7 +1157,6 @@ static int open_drm_device(GAL_VideoDevice *device)
|
||||
|
||||
device->hidden->driver_ops = load_external_driver (device->hidden,
|
||||
driver_name, fd);
|
||||
free (driver_name);
|
||||
|
||||
/* get capabilities */
|
||||
{
|
||||
@@ -1206,10 +1205,12 @@ static int open_drm_device(GAL_VideoDevice *device)
|
||||
device->hidden->dev_fd = fd;
|
||||
if (device->hidden->driver_ops) {
|
||||
device->hidden->driver = device->hidden->driver_ops->create_driver(fd);
|
||||
if (device->hidden->driver == NULL)
|
||||
_WRN_PRINTF("Failed to create DRM driver: %s\n", driver_name);
|
||||
}
|
||||
free(driver_name);
|
||||
|
||||
if (device->hidden->driver == NULL) {
|
||||
_WRN_PRINTF("failed to create DRM driver\n");
|
||||
device->hidden->driver_ops = NULL;
|
||||
|
||||
/* check whether supports dumb buffer */
|
||||
@@ -1272,6 +1273,15 @@ static GAL_VideoDevice *DRM_CreateDevice(int devindex)
|
||||
if (mgIsServer)
|
||||
#endif /* defined _MGRM_PROCESSES */
|
||||
{
|
||||
if (GetMgEtcIntValue("drm", "update_interval",
|
||||
&device->hidden->update_interval) < 0) {
|
||||
device->hidden->update_interval = 20;
|
||||
}
|
||||
else if (device->hidden->update_interval < 0 ||
|
||||
device->hidden->update_interval > 50) {
|
||||
device->hidden->update_interval = 20;
|
||||
}
|
||||
|
||||
char tmp [8];
|
||||
if (GetMgEtcValue ("drm", "double_buffering", tmp, 8) < 0) {
|
||||
device->hidden->dbl_buff = 0;
|
||||
@@ -1491,19 +1501,6 @@ static int drm_find_crtc(DrmVideoData* vdata,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int get_crtc_index(drmModeRes *res, uint32_t id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < res->count_crtcs; ++i) {
|
||||
if (res->crtcs[i] == id)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* drm_setup_connector:
|
||||
* Set up a single connector.
|
||||
@@ -1542,9 +1539,6 @@ static int drm_setup_connector(DrmVideoData* vdata,
|
||||
return ret;
|
||||
}
|
||||
|
||||
vdata->crtc_idx = get_crtc_index(res, info->crtc);
|
||||
_DBG_PRINTF("CRTC found: id: %u; idx: %d\n",
|
||||
info->crtc, vdata->crtc_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1810,6 +1804,40 @@ static void DRM_CopyVideoInfoToSharedRes(_THIS)
|
||||
}
|
||||
#endif /* _MGRM_PROCESSES */
|
||||
|
||||
static int get_crtc_index(DrmVideoData* vdata)
|
||||
{
|
||||
#if 1
|
||||
int pipe = -1;
|
||||
drmModeRes *res;
|
||||
|
||||
res = drmModeGetResources(vdata->dev_fd);
|
||||
if (!res)
|
||||
goto done;
|
||||
|
||||
for (int i = 0; i < res->count_crtcs; i++) {
|
||||
if (vdata->saved_info->crtc == res->crtcs[i]) {
|
||||
pipe = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
drmModeFreeResources(res);
|
||||
|
||||
done:
|
||||
vdata->crtc_idx = pipe;
|
||||
return pipe;
|
||||
#else
|
||||
int i;
|
||||
|
||||
for (i = 0; i < res->count_crtcs; ++i) {
|
||||
if (res->crtcs[i] == id)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int drm_setup_scanout_buffer (DrmVideoData* vdata,
|
||||
uint32_t handle, uint32_t drm_format,
|
||||
uint32_t width, uint32_t height, uint32_t pitch, uint32_t offset)
|
||||
@@ -1847,6 +1875,14 @@ static int drm_setup_scanout_buffer (DrmVideoData* vdata,
|
||||
drmModeFreeCrtc(vdata->saved_crtc);
|
||||
vdata->saved_crtc = NULL;
|
||||
}
|
||||
else {
|
||||
if (get_crtc_index(vdata) < 0) {
|
||||
_WRN_PRINTF("Invalid return value of get_crtc_index()\n");
|
||||
}
|
||||
else {
|
||||
_DBG_PRINTF("CRTC index: %d\n", vdata->crtc_idx);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1931,22 +1967,6 @@ static int drm_setup_cursor_plane (DrmVideoData* vdata, uint32_t drm_format,
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
int pipe = -1;
|
||||
drmModeRes *res;
|
||||
|
||||
res = drmModeGetResources(vdata->dev_fd);
|
||||
if (!res) return ret;
|
||||
for (i = 0; i < res->count_crtcs; i++) {
|
||||
if (vdata->saved_info->crtc == res->crtcs[i]) {
|
||||
pipe = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
drmModeFreeResources(res);
|
||||
assert (pipe >= 0);
|
||||
#endif
|
||||
|
||||
plane_res = drmModeGetPlaneResources (vdata->dev_fd);
|
||||
if (!plane_res) {
|
||||
_WRN_PRINTF( "drmModeGetPlaneResources failed: %m\n");
|
||||
@@ -2540,19 +2560,21 @@ static void* task_do_update(void *data)
|
||||
}
|
||||
}
|
||||
#else
|
||||
memset(&vbl, 0, sizeof(vbl));
|
||||
vbl.request.type = DRM_VBLANK_RELATIVE;
|
||||
if (this->hidden->cap_vblank_high_crtc)
|
||||
vbl.request.type |=
|
||||
(this->hidden->crtc_idx << DRM_VBLANK_HIGH_CRTC_SHIFT);
|
||||
vbl.request.sequence = 1;
|
||||
vbl.request.signal = 0;
|
||||
_DBG_PRINTF("VBL type: 0x%08x\n", vbl.request.type);
|
||||
if (drmWaitVBlank(this->hidden->dev_fd, &vbl)) {
|
||||
_WRN_PRINTF("Failed drmWaitVBlank(%d): %m\n", this->hidden->crtc_idx);
|
||||
}
|
||||
else {
|
||||
vbl_ok = TRUE;
|
||||
if (this->hidden->crtc_idx >= 0) {
|
||||
memset(&vbl, 0, sizeof(vbl));
|
||||
vbl.request.type = DRM_VBLANK_RELATIVE;
|
||||
if (this->hidden->cap_vblank_high_crtc)
|
||||
vbl.request.type |=
|
||||
(this->hidden->crtc_idx << DRM_VBLANK_HIGH_CRTC_SHIFT);
|
||||
vbl.request.sequence = 1;
|
||||
vbl.request.signal = 0;
|
||||
_DBG_PRINTF("VBL type: 0x%08x\n", vbl.request.type);
|
||||
if (drmWaitVBlank(this->hidden->dev_fd, &vbl)) {
|
||||
_WRN_PRINTF("Failed drmWaitVBlank(%d): %m\n", this->hidden->crtc_idx);
|
||||
}
|
||||
else {
|
||||
vbl_ok = TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2573,12 +2595,13 @@ static void* task_do_update(void *data)
|
||||
vbl.reply.tval_sec, vbl.reply.tval_usec);
|
||||
}
|
||||
else {
|
||||
usleep(20 * 1000); // 20ms
|
||||
usleep(this->hidden->update_interval * 1000);
|
||||
}
|
||||
|
||||
sem_wait(this->hidden->update_lock);
|
||||
if (RECTH(this->hidden->update_rect)) {
|
||||
update_real_screen_memcpy(this);
|
||||
/* TODO: update cursor under compositing schema */
|
||||
drmModeClip clip = {
|
||||
this->hidden->update_rect.left,
|
||||
this->hidden->update_rect.top,
|
||||
@@ -3754,6 +3777,10 @@ static BOOL DRM_SyncUpdate(_THIS)
|
||||
this->hidden->driver_ops->flush_driver(this->hidden->driver);
|
||||
}
|
||||
|
||||
_DBG_PRINTF("called: %d, %d, %d, %d\n",
|
||||
bound.left, bound.top,
|
||||
bound.right, bound.bottom);
|
||||
|
||||
{
|
||||
drmModeClip clip = { bound.left, bound.top,
|
||||
bound.right, bound.bottom };
|
||||
|
||||
@@ -104,6 +104,7 @@ typedef struct GAL_PrivateVideoData {
|
||||
uint32_t cap_vblank_high_crtc:1;
|
||||
uint32_t dbl_buff:1;
|
||||
uint32_t scanout_buff_id;
|
||||
int update_interval;
|
||||
int crtc_idx;
|
||||
|
||||
void* exdrv_handle;
|
||||
|
||||
@@ -54,6 +54,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <error.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define _DEBUG
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -143,8 +147,28 @@ static void refresh_by_using_pixman(ShadowFBHeader *shadowfb_header,
|
||||
pixman_image_set_transform(realfb_info->src_img, NULL);
|
||||
pixman_image_set_clip_region32(realfb_info->dst_img, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef _DEBUG
|
||||
static double get_elapsed_seconds(const struct timespec *ts_from,
|
||||
const struct timespec *ts_to)
|
||||
{
|
||||
struct timespec ts_curr;
|
||||
time_t ds;
|
||||
long dns;
|
||||
|
||||
if (ts_to == NULL) {
|
||||
clock_gettime(CLOCK_REALTIME, &ts_curr);
|
||||
ts_to = &ts_curr;
|
||||
}
|
||||
|
||||
ds = ts_to->tv_sec - ts_from->tv_sec;
|
||||
dns = ts_to->tv_nsec - ts_from->tv_nsec;
|
||||
return ds + dns * 1.0E-9;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void refresh_ccw_32bpp(ShadowFBHeader* shadowfb_header,
|
||||
RealFBInfo* realfb_info, void* update)
|
||||
{
|
||||
@@ -155,6 +179,11 @@ static void refresh_ccw_32bpp(ShadowFBHeader* shadowfb_header,
|
||||
int dst_width, dst_height;
|
||||
int x, y;
|
||||
|
||||
#ifdef _DEBUG
|
||||
struct timespec ts_start;
|
||||
clock_gettime(CLOCK_REALTIME, &ts_start);
|
||||
#endif
|
||||
|
||||
_get_dst_rect_ccw(&dst_update, &src_update, realfb_info);
|
||||
dst_width = RECTW(dst_update);
|
||||
dst_height = RECTH(dst_update);
|
||||
@@ -183,6 +212,11 @@ static void refresh_ccw_32bpp(ShadowFBHeader* shadowfb_header,
|
||||
src_bits += 4;
|
||||
dst_line -= realfb_info->pitch;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
double elapsed = get_elapsed_seconds(&ts_start, NULL);
|
||||
_MG_PRINTF("Cosumed time to rotate dirty rect (ccw): %f (seconds)\n", elapsed);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void refresh_cw_32bpp(ShadowFBHeader* shadowfb_header,
|
||||
@@ -195,6 +229,11 @@ static void refresh_cw_32bpp(ShadowFBHeader* shadowfb_header,
|
||||
int dst_width, dst_height;
|
||||
int x, y;
|
||||
|
||||
#ifdef _DEBUG
|
||||
struct timespec ts_start;
|
||||
clock_gettime(CLOCK_REALTIME, &ts_start);
|
||||
#endif
|
||||
|
||||
_get_dst_rect_cw(&dst_update, &src_update, realfb_info);
|
||||
dst_width = RECTW(dst_update);
|
||||
dst_height = RECTH(dst_update);
|
||||
@@ -223,6 +262,11 @@ static void refresh_cw_32bpp(ShadowFBHeader* shadowfb_header,
|
||||
src_bits += 4;
|
||||
dst_line += realfb_info->pitch;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
double elapsed = get_elapsed_seconds(&ts_start, NULL);
|
||||
_MG_PRINTF("Cosumed time to rotate dirty rect (cw): %f (seconds)\n", elapsed);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -255,6 +299,7 @@ static GAL_Surface *SHADOW_SetVideoMode (_THIS, GAL_Surface *current, int width,
|
||||
static int SHADOW_SetColors (_THIS, int firstcolor, int ncolors, GAL_Color *colors);
|
||||
static void SHADOW_VideoQuit (_THIS);
|
||||
static BOOL SHADOW_SyncUpdate (_THIS);
|
||||
static BOOL SHADOW_SyncUpdateAsync (_THIS);
|
||||
static BOOL SHADOW_SyncUpdateConcurrently (_THIS);
|
||||
|
||||
/* Hardware surface functions */
|
||||
@@ -307,6 +352,10 @@ static void SHADOW_UpdateRects (_THIS, int numrects, GAL_Rect *rects)
|
||||
#ifdef _MGRM_PROCESSES
|
||||
_sysvipc_sem_op (this->hidden->semid, 0, -1);
|
||||
#endif
|
||||
|
||||
if (this->hidden->async_update) {
|
||||
pthread_mutex_lock(&this->hidden->update_lock);
|
||||
}
|
||||
bound = _shadowfbheader->dirty_rect;
|
||||
|
||||
for (i = 0; i < numrects; i++) {
|
||||
@@ -328,6 +377,9 @@ static void SHADOW_UpdateRects (_THIS, int numrects, GAL_Rect *rects)
|
||||
}
|
||||
}
|
||||
|
||||
if (this->hidden->async_update) {
|
||||
pthread_mutex_unlock(&this->hidden->update_lock);
|
||||
}
|
||||
#ifdef _MGRM_PROCESSES
|
||||
_sysvipc_sem_op (this->hidden->semid, 0, 1);
|
||||
#endif
|
||||
@@ -539,6 +591,140 @@ static int RealEngine_Init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL SHADOW_SyncUpdateAsync (_THIS)
|
||||
{
|
||||
if (this->hidden->async_update) {
|
||||
pthread_mutex_lock(&this->hidden->update_lock);
|
||||
}
|
||||
|
||||
if (_shadowfbheader->dirty || _shadowfbheader->palette_changed) {
|
||||
GAL_VideoDevice *real_device;
|
||||
real_device = this->hidden->realfb_info->real_device;
|
||||
assert(real_device);
|
||||
|
||||
if (_shadowfbheader->palette_changed) {
|
||||
real_device->SetColors(real_device, _shadowfbheader->firstcolor,
|
||||
_shadowfbheader->ncolors,
|
||||
(GAL_Color*)((char*)_shadowfbheader +
|
||||
_shadowfbheader->palette_offset));
|
||||
SetRect(&_shadowfbheader->dirty_rect, 0, 0,
|
||||
_shadowfbheader->width, _shadowfbheader->height);
|
||||
}
|
||||
|
||||
GetBoundRect (&this->hidden->update_rect,
|
||||
&this->hidden->update_rect, &_shadowfbheader->dirty_rect);
|
||||
SetRect(&_shadowfbheader->dirty_rect, 0, 0, 0, 0);
|
||||
_shadowfbheader->dirty = FALSE;
|
||||
_shadowfbheader->palette_changed = FALSE;
|
||||
}
|
||||
|
||||
if (this->hidden->async_update) {
|
||||
pthread_mutex_unlock(&this->hidden->update_lock);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void *task_do_update(void *data)
|
||||
{
|
||||
_THIS = data;
|
||||
|
||||
if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL))
|
||||
goto error;
|
||||
|
||||
this->hidden->async_update = 1;
|
||||
sem_post(&this->hidden->sync_sem);
|
||||
|
||||
do {
|
||||
usleep(this->hidden->update_interval * 1000);
|
||||
|
||||
pthread_mutex_lock(&this->hidden->update_lock);
|
||||
if (RECTH(this->hidden->update_rect)) {
|
||||
|
||||
shadow_fb_ops.refresh(_shadowfbheader,
|
||||
this->hidden->realfb_info, &this->hidden->update_rect);
|
||||
|
||||
RECT dirty_rect;
|
||||
if (this->hidden->realfb_info->flags & _ROT_DIR_CW) {
|
||||
_get_dst_rect_cw(&dirty_rect, &(this->hidden->update_rect),
|
||||
this->hidden->realfb_info);
|
||||
}
|
||||
else if (this->hidden->realfb_info->flags & _ROT_DIR_CCW) {
|
||||
_get_dst_rect_ccw(&dirty_rect, &(this->hidden->update_rect),
|
||||
this->hidden->realfb_info);
|
||||
}
|
||||
else if (this->hidden->realfb_info->flags & _ROT_DIR_HFLIP) {
|
||||
dirty_rect = this->hidden->update_rect;
|
||||
_get_dst_rect_hflip (&dirty_rect, this->hidden->realfb_info);
|
||||
}
|
||||
else if (this->hidden->realfb_info->flags & _ROT_DIR_VFLIP) {
|
||||
dirty_rect = this->hidden->update_rect;
|
||||
_get_dst_rect_vflip (&dirty_rect, this->hidden->realfb_info);
|
||||
}
|
||||
else {
|
||||
dirty_rect = this->hidden->update_rect;
|
||||
}
|
||||
|
||||
GAL_Rect update_rect;
|
||||
update_rect.x = dirty_rect.left;
|
||||
update_rect.y = dirty_rect.top;
|
||||
update_rect.w = RECTW(dirty_rect);
|
||||
update_rect.h = RECTH(dirty_rect);
|
||||
|
||||
GAL_VideoDevice *real_device;
|
||||
real_device = this->hidden->realfb_info->real_device;
|
||||
if (real_device->UpdateRects)
|
||||
real_device->UpdateRects(real_device, 1, &update_rect);
|
||||
if (real_device->SyncUpdate)
|
||||
real_device->SyncUpdate(real_device);
|
||||
|
||||
SetRectEmpty(&this->hidden->update_rect);
|
||||
}
|
||||
pthread_mutex_unlock(&this->hidden->update_lock);
|
||||
|
||||
} while (1);
|
||||
|
||||
return NULL;
|
||||
|
||||
error:
|
||||
this->hidden->async_update = 0;
|
||||
sem_post(&this->hidden->sync_sem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int create_async_updater(_THIS)
|
||||
{
|
||||
if (sem_init(&this->hidden->sync_sem, 0, 0))
|
||||
return -1;
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
struct sched_param sp = { 90 };
|
||||
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
|
||||
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
|
||||
pthread_attr_setschedparam(&attr, &sp);
|
||||
|
||||
if (pthread_create(&this->hidden->update_thd, &attr,
|
||||
task_do_update, this))
|
||||
return -1;
|
||||
|
||||
sem_wait(&this->hidden->sync_sem);
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
return this->hidden->async_update ? 0 : -1;
|
||||
}
|
||||
|
||||
static void cancel_async_updater(_THIS)
|
||||
{
|
||||
if (this->hidden->async_update) {
|
||||
pthread_cancel(this->hidden->update_thd);
|
||||
pthread_join(this->hidden->update_thd, NULL);
|
||||
|
||||
sem_destroy(&this->hidden->sync_sem);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* multiple updaters */
|
||||
struct update_thd_args {
|
||||
_THIS;
|
||||
int number;
|
||||
@@ -727,6 +913,7 @@ static int create_extra_updaters(_THIS)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int SHADOW_VideoInit (_THIS, GAL_PixelFormat *vformat)
|
||||
{
|
||||
@@ -760,6 +947,35 @@ static int SHADOW_VideoInit (_THIS, GAL_PixelFormat *vformat)
|
||||
}
|
||||
#endif
|
||||
|
||||
char tmp[8];
|
||||
if (GetMgEtcValue ("shadow", "async_update", tmp, sizeof(tmp)) < 0) {
|
||||
this->hidden->async_update = 0;
|
||||
}
|
||||
else if (strcasecmp(tmp, "true") == 0 ||
|
||||
strcasecmp(tmp, "yes") == 0) {
|
||||
this->hidden->async_update = 1;
|
||||
}
|
||||
else {
|
||||
this->hidden->async_update = 0;
|
||||
}
|
||||
|
||||
if (this->hidden->async_update) {
|
||||
if (GetMgEtcIntValue("shadow", "update_interval",
|
||||
&this->hidden->update_interval) < 0) {
|
||||
this->hidden->update_interval = 20;
|
||||
}
|
||||
else if (this->hidden->update_interval < 0 ||
|
||||
this->hidden->update_interval > 50) {
|
||||
this->hidden->update_interval = 20;
|
||||
}
|
||||
|
||||
create_async_updater(this);
|
||||
if (this->hidden->async_update) {
|
||||
this->SyncUpdate = SHADOW_SyncUpdateAsync;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* code for multiple updaters */
|
||||
char nr_updaters[LEN_MODE+1] = "0";
|
||||
if (GetMgEtcValue ("shadow", "nr_updaters",
|
||||
nr_updaters, LEN_MODE) < 0) {
|
||||
@@ -777,6 +993,7 @@ static int SHADOW_VideoInit (_THIS, GAL_PixelFormat *vformat)
|
||||
perror ("NEWGAL>SHADOW: create_updaters");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We're done! */
|
||||
return 0;
|
||||
@@ -979,9 +1196,11 @@ static GAL_Surface *SHADOW_SetVideoMode(_THIS, GAL_Surface *current,
|
||||
current->pitch = _shadowfbheader->pitch;
|
||||
current->pixels = (char *)_shadowfbheader + _shadowfbheader->fb_offset;
|
||||
|
||||
#if 0 /* Code for multiple updaters */
|
||||
if (this->hidden->nr_updaters > 0) {
|
||||
this->SyncUpdate = SHADOW_SyncUpdateConcurrently;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _MGUSE_PIXMAN
|
||||
GAL_CreatePixmanImage(current);
|
||||
@@ -1052,6 +1271,7 @@ static GAL_Surface *SHADOW_SetVideoMode(_THIS, GAL_Surface *current,
|
||||
|
||||
static void SHADOW_VideoQuit (_THIS)
|
||||
{
|
||||
#if 0 /* Code for multiple updaters */
|
||||
if (this->hidden->nr_updaters > 0) {
|
||||
for (int i = 0; i < this->hidden->nr_updaters; i++) {
|
||||
pthread_cancel(this->hidden->update_thds[i]);
|
||||
@@ -1062,6 +1282,9 @@ static void SHADOW_VideoQuit (_THIS)
|
||||
|
||||
sem_destroy(&this->hidden->sync_sem);
|
||||
}
|
||||
#endif
|
||||
|
||||
cancel_async_updater(this);
|
||||
|
||||
if (_shadowfbheader) {
|
||||
_shadowfbheader->dirty = FALSE;
|
||||
|
||||
@@ -120,13 +120,13 @@ struct GAL_PrivateVideoData {
|
||||
int semid;
|
||||
#endif
|
||||
|
||||
int nr_updaters;
|
||||
|
||||
/* only valid when nr_updaters > 0 */
|
||||
RECT dirty_rcs[MAX_NR_UPDATERS];
|
||||
sem_t update_sems[MAX_NR_UPDATERS];
|
||||
pthread_t update_thds[MAX_NR_UPDATERS];
|
||||
sem_t sync_sem;
|
||||
/* async updater */
|
||||
int async_update;
|
||||
int update_interval;
|
||||
RECT update_rect;
|
||||
pthread_t update_thd;
|
||||
pthread_mutex_t update_lock;
|
||||
sem_t sync_sem;
|
||||
};
|
||||
|
||||
typedef struct _ShadowFBOps {
|
||||
|
||||
Reference in New Issue
Block a user