Async graphics updates.
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@621
This commit is contained in:
parent
af01668b34
commit
b4fe560bd7
2 changed files with 98 additions and 49 deletions
|
@ -29,7 +29,7 @@
|
|||
|
||||
#define MAX_RES 2048
|
||||
|
||||
typedef void (* RENDER_Part_Handler)(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy);
|
||||
|
||||
|
||||
struct PalData {
|
||||
struct {
|
||||
|
@ -56,6 +56,7 @@ static struct {
|
|||
Bitu flags;
|
||||
float ratio;
|
||||
RENDER_Part_Handler part_handler;
|
||||
RENDER_Draw_Handler draw_handler;
|
||||
} src;
|
||||
struct {
|
||||
Bitu width;
|
||||
|
@ -224,36 +225,23 @@ void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue) {
|
|||
if (render.pal.last<entry) render.pal.last=entry;
|
||||
}
|
||||
|
||||
bool RENDER_StartUpdate(void) {
|
||||
void RENDER_DoUpdate(void) {
|
||||
if (render.frameskip.count<render.frameskip.max) {
|
||||
render.frameskip.count++;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
render.frameskip.count=0;
|
||||
if (render.src.bpp==8) Check_Palette();
|
||||
switch (render.op.type) {
|
||||
case OP_None:
|
||||
render.op.dest=render.op.pixels=GFX_StartUpdate();
|
||||
break;
|
||||
}
|
||||
if (render.op.dest) return true;
|
||||
else return false;
|
||||
GFX_DoUpdate();
|
||||
}
|
||||
|
||||
void RENDER_EndUpdate(void) {
|
||||
static void RENDER_DrawScreen(void * data) {
|
||||
switch (render.op.type) {
|
||||
case OP_None:
|
||||
/* Nothing to be done */
|
||||
render.op.pixels=0;
|
||||
render.op.dest=render.op.pixels=data;
|
||||
break;
|
||||
}
|
||||
GFX_EndUpdate();
|
||||
}
|
||||
|
||||
/* Update the data ready to be sent out for blitting onto the screen */
|
||||
void RENDER_Part(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) {
|
||||
(render.src.part_handler)(src,x,y,dx,dy);
|
||||
return;
|
||||
render.src.draw_handler(render.src.part_handler);
|
||||
}
|
||||
|
||||
static void RENDER_Resize(Bitu * width,Bitu * height) {
|
||||
|
@ -268,18 +256,21 @@ static void RENDER_Resize(Bitu * width,Bitu * height) {
|
|||
}
|
||||
}
|
||||
|
||||
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags) {
|
||||
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags,RENDER_Draw_Handler draw_handler) {
|
||||
if ((!width) || (!height) || (!pitch)) {
|
||||
render.active=false;return;
|
||||
}
|
||||
|
||||
GFX_Stop();
|
||||
render.src.width=width;
|
||||
render.src.height=height;
|
||||
render.src.bpp=bpp;
|
||||
render.src.pitch=pitch;
|
||||
render.src.ratio=ratio;
|
||||
render.src.flags=flags;
|
||||
render.src.draw_handler=draw_handler;
|
||||
|
||||
GFX_ModeCallBack callback;
|
||||
GFX_ModeCallBack mode_callback;
|
||||
switch (render.op.want_type) {
|
||||
|
||||
case OP_None:
|
||||
|
@ -297,16 +288,18 @@ normalop:
|
|||
break;
|
||||
}
|
||||
flags=0;
|
||||
callback=Render_Normal_CallBack;
|
||||
mode_callback=Render_Normal_CallBack;
|
||||
break;
|
||||
default:
|
||||
goto normalop;
|
||||
|
||||
}
|
||||
GFX_SetSize(width,height,bpp,flags,callback);
|
||||
GFX_SetSize(width,height,bpp,flags,mode_callback,RENDER_DrawScreen);
|
||||
GFX_Start();
|
||||
}
|
||||
|
||||
static void EnableScreenShot(void) {
|
||||
//TODO switch to a special screenshot part handler
|
||||
render.screenshot=true;
|
||||
}
|
||||
|
||||
|
@ -320,7 +313,6 @@ static void DecreaseFrameSkip(void) {
|
|||
LOG_MSG("Frame Skip at %d",render.frameskip.max);
|
||||
}
|
||||
|
||||
|
||||
void RENDER_Init(Section * sec) {
|
||||
Section_prop * section=static_cast<Section_prop *>(sec);
|
||||
snapshots_dir=section->Get_string("snapshots");
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <SDL.h>
|
||||
#include "SDL.h"
|
||||
#include "SDL_Thread.h"
|
||||
|
||||
#include "dosbox.h"
|
||||
#include "video.h"
|
||||
|
@ -31,9 +32,11 @@
|
|||
#include "debug.h"
|
||||
|
||||
//#define DISABLE_JOYSTICK
|
||||
#define C_GFXTHREADED 1 //Enabled by default
|
||||
|
||||
struct SDL_Block {
|
||||
bool active; //If this isn't set don't draw
|
||||
bool drawing;
|
||||
Bitu width;
|
||||
Bitu height;
|
||||
Bitu bpp;
|
||||
|
@ -42,6 +45,11 @@ struct SDL_Block {
|
|||
bool full_screen;
|
||||
SDL_Surface * surface;
|
||||
SDL_Joystick * joy;
|
||||
SDL_cond *cond;
|
||||
SDL_mutex *mutex;
|
||||
SDL_Thread *thread;
|
||||
SDL_sem *sem;
|
||||
GFX_DrawCallBack draw_callback;
|
||||
struct {
|
||||
bool autolock;
|
||||
bool autoenable;
|
||||
|
@ -58,17 +66,17 @@ static void CaptureMouse(void);
|
|||
static void ResetScreen(void) {
|
||||
GFX_Stop();
|
||||
if (sdl.full_screen) {
|
||||
/* First get the original resolution */
|
||||
sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,sdl.bpp,SDL_HWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN);
|
||||
} else {
|
||||
if (sdl.flags & GFX_FIXED_BPP) sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,sdl.bpp,SDL_HWSURFACE);
|
||||
else sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,0,SDL_HWSURFACE);
|
||||
}
|
||||
if (sdl.surface==0) {
|
||||
E_Exit("SDL:Would be nice if I could get a surface.");
|
||||
E_Exit("SDL:Can't get a surface.");
|
||||
}
|
||||
|
||||
SDL_WM_SetCaption(VERSION,VERSION);
|
||||
/* also fill up gfx_info structure */
|
||||
|
||||
Bitu flags=MODE_SET;
|
||||
if (sdl.full_screen) flags|=MODE_FULLSCREEN;
|
||||
if (sdl.mode_callback) sdl.mode_callback(sdl.surface->w,sdl.surface->h,sdl.surface->format->BitsPerPixel,sdl.surface->pitch,flags);
|
||||
|
@ -76,20 +84,18 @@ static void ResetScreen(void) {
|
|||
}
|
||||
|
||||
|
||||
void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu flags,GFX_ModeCallBack callback) {
|
||||
void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu flags,GFX_ModeCallBack mode_callback, GFX_DrawCallBack draw_callback){
|
||||
GFX_Stop();
|
||||
sdl.width=width;
|
||||
sdl.height=height;
|
||||
sdl.bpp=bpp;
|
||||
sdl.flags=flags;
|
||||
sdl.mode_callback=callback;
|
||||
sdl.mode_callback=mode_callback;
|
||||
sdl.draw_callback=draw_callback;
|
||||
ResetScreen();
|
||||
GFX_Start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void CaptureMouse(void) {
|
||||
sdl.mouse.locked=!sdl.mouse.locked;
|
||||
if (sdl.mouse.locked) {
|
||||
|
@ -112,29 +118,57 @@ static void SwitchFullScreen(void) {
|
|||
|
||||
ResetScreen();
|
||||
}
|
||||
//only prototype existed
|
||||
|
||||
void GFX_SwitchFullScreen(void) {
|
||||
SwitchFullScreen();
|
||||
}
|
||||
|
||||
void * GFX_StartUpdate(void) {
|
||||
if (sdl.active) {
|
||||
if (SDL_MUSTLOCK(sdl.surface)) if (SDL_LockSurface(sdl.surface)) return 0;
|
||||
return sdl.surface->pixels;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
static void SDL_DrawScreen(void) {
|
||||
sdl.drawing=true;
|
||||
|
||||
if (SDL_MUSTLOCK(sdl.surface)) {
|
||||
if (SDL_LockSurface(sdl.surface)) E_Exit("SDL:Can't lock surface");
|
||||
}
|
||||
sdl.draw_callback(sdl.surface->pixels);
|
||||
|
||||
if (SDL_MUSTLOCK(sdl.surface)) {
|
||||
SDL_UnlockSurface(sdl.surface);
|
||||
}
|
||||
SDL_Flip(sdl.surface);
|
||||
sdl.drawing=false;
|
||||
}
|
||||
|
||||
void GFX_EndUpdate(void) {
|
||||
if (SDL_MUSTLOCK(sdl.surface)) SDL_UnlockSurface(sdl.surface );
|
||||
if (sdl.full_screen) SDL_Flip(sdl.surface);
|
||||
else SDL_UpdateRect(sdl.surface,0,0,0,0);
|
||||
|
||||
int SDL_DisplayThread(void * data) {
|
||||
while (!SDL_SemWait(sdl.sem)) {
|
||||
if (!sdl.active) continue;
|
||||
SDL_mutexP(sdl.mutex);
|
||||
SDL_DrawScreen();
|
||||
SDL_mutexV(sdl.mutex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void GFX_DoUpdate(void) {
|
||||
if (!sdl.active) return;
|
||||
if (sdl.drawing) return;
|
||||
#if C_GFXTHREADED
|
||||
SDL_SemPost(sdl.sem);
|
||||
#else
|
||||
SDL_DrawScreen();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) {
|
||||
/* I should probably not change the GFX_PalEntry :) */
|
||||
#if C_GFXTHREADED
|
||||
if (SDL_mutexP(sdl.mutex)) {
|
||||
E_Exit("SDL:Can't lock Mutex");
|
||||
};
|
||||
#endif
|
||||
/* I should probably not change the GFX_PalEntry :) */
|
||||
if (sdl.full_screen) {
|
||||
if (!SDL_SetPalette(sdl.surface,SDL_PHYSPAL,(SDL_Color *)entries,start,count)) {
|
||||
E_Exit("SDL:Can't set palette");
|
||||
|
@ -144,6 +178,11 @@ void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) {
|
|||
E_Exit("SDL:Can't set palette");
|
||||
}
|
||||
}
|
||||
#if C_GFXTHREADED
|
||||
if (SDL_mutexV(sdl.mutex)) {
|
||||
E_Exit("SDL:Can't release Mutex");
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue) {
|
||||
|
@ -151,9 +190,15 @@ Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue) {
|
|||
}
|
||||
|
||||
void GFX_Stop() {
|
||||
#if C_GFXTHREADED
|
||||
SDL_mutexP(sdl.mutex);
|
||||
#endif
|
||||
sdl.active=false;
|
||||
}
|
||||
#if C_GFXTHREADED
|
||||
SDL_mutexV(sdl.mutex);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void GFX_Start() {
|
||||
sdl.active=true;
|
||||
|
@ -163,6 +208,12 @@ static void GUI_ShutDown(Section * sec) {
|
|||
GFX_Stop();
|
||||
if (sdl.mouse.locked) CaptureMouse();
|
||||
if (sdl.full_screen) SwitchFullScreen();
|
||||
#if C_GFXTHREADED
|
||||
SDL_KillThread(sdl.thread);
|
||||
SDL_DestroyMutex(sdl.mutex);
|
||||
SDL_DestroySemaphore(sdl.sem);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void GUI_StartUp(Section * sec) {
|
||||
|
@ -176,7 +227,13 @@ static void GUI_StartUp(Section * sec) {
|
|||
sdl.mouse.autoenable=section->Get_bool("autolock");
|
||||
sdl.mouse.autolock=false;
|
||||
sdl.mouse.sensitivity=section->Get_int("sensitivity");
|
||||
GFX_SetSize(640,400,8,0,0);
|
||||
#if C_GFXTHREADED
|
||||
sdl.mutex=SDL_CreateMutex();
|
||||
sdl.sem=SDL_CreateSemaphore(0);
|
||||
sdl.thread=SDL_CreateThread(&SDL_DisplayThread,0);
|
||||
#endif
|
||||
/* Initialize screen for first time */
|
||||
GFX_SetSize(640,400,8,0,0,0);
|
||||
SDL_EnableKeyRepeat(250,30);
|
||||
|
||||
/* Get some Keybinds */
|
||||
|
|
Loading…
Add table
Reference in a new issue