Registered User
Join Date: Sep 2007
Location: Melbourne/Australia
Posts: 4,400
|
Thanks guys
Thought the coders might like to see the before and after shots
Original SDL based renderer:
PHP Code:
enum SCREEN_TYPES {
SCREEN_SURFACE,
SCREEN_SURFACE_DDRAW,
SCREEN_OVERLAY,
SCREEN_OPENGL
};
enum PRIORITY_LEVELS {
PRIORITY_LEVEL_LOWER,
PRIORITY_LEVEL_NORMAL,
PRIORITY_LEVEL_HIGHER,
PRIORITY_LEVEL_HIGHEST
};
struct SDL_Block {
bool active; //If this isn't set don't draw
bool updating;
struct {
Bit32u width;
Bit32u height;
Bitu flags;
GFX_Modes mode;
double scalex,scaley;
GFX_ResetCallBack reset;
} draw;
bool wait_on_error;
struct {
Bit32u width,height,bpp;
bool fixed;
bool fullscreen;
bool doublebuf;
SCREEN_TYPES type;
SCREEN_TYPES want_type;
double hwscale;
} desktop;
struct {
PRIORITY_LEVELS focus;
PRIORITY_LEVELS nofocus;
} priority;
SDL_Rect clip;
SDL_Surface * surface;
SDL_Overlay * overlay;
SDL_cond *cond;
struct {
bool autolock;
bool autoenable;
bool requestlock;
bool locked;
Bitu sensitivity;
} mouse;
};
static SDL_Block sdl;
<SNIP>
bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch) {
if (!sdl.active || sdl.updating) return false;
sdl.updating=true;
switch (sdl.desktop.type) {
case SCREEN_SURFACE:
if (SDL_MUSTLOCK(sdl.surface)) {
if (SDL_LockSurface(sdl.surface)) {
// LOG_MSG("SDL Lock failed");
sdl.updating=false;
return false;
}
}
pixels=(Bit8u *)sdl.surface->pixels;
pixels+=sdl.clip.y*sdl.surface->pitch;
pixels+=sdl.clip.x*sdl.surface->format->BytesPerPixel;
pitch=sdl.surface->pitch;
return true;
#if defined(HAVE_DDRAW_H) && defined(WIN32)
case SCREEN_SURFACE_DDRAW:
if (SDL_LockSurface(sdl.blit.surface)) {
// LOG_MSG("SDL Lock failed");
sdl.updating=false;
return false;
}
pixels=(Bit8u *)sdl.blit.surface->pixels;
pitch=sdl.blit.surface->pitch;
return true;
#endif
case SCREEN_OVERLAY:
SDL_LockYUVOverlay(sdl.overlay);
pixels=(Bit8u *)*(sdl.overlay->pixels);
pitch=*(sdl.overlay->pitches);
return true;
#if C_OPENGL
case SCREEN_OPENGL:
pixels=(Bit8u *)sdl.opengl.framebuf;
pitch=sdl.opengl.pitch;
return true;
#endif
}
return false;
}
void GFX_EndUpdate(void) {
int ret;
if (!sdl.updating) return;
sdl.updating=false;
switch (sdl.desktop.type) {
case SCREEN_SURFACE:
if (SDL_MUSTLOCK(sdl.surface)) {
SDL_UnlockSurface(sdl.surface);
}
SDL_Flip(sdl.surface);
break;
#if defined(HAVE_DDRAW_H) && defined(WIN32)
case SCREEN_SURFACE_DDRAW:
if (SDL_MUSTLOCK(sdl.blit.surface)) {
SDL_UnlockSurface(sdl.blit.surface);
}
ret=IDirectDrawSurface3_Blt(
sdl.surface->hwdata->dd_writebuf,&sdl.blit.rect,
sdl.blit.surface->hwdata->dd_surface,0,
DDBLT_WAIT, NULL);
switch (ret) {
case DD_OK:
break;
case DDERR_SURFACELOST:
IDirectDrawSurface3_Restore(sdl.blit.surface->hwdata->dd_surface);
break;
default:
LOG_MSG("DDRAW:Failed to blit, error %X",ret);
}
SDL_Flip(sdl.surface);
break;
#endif
case SCREEN_OVERLAY:
SDL_UnlockYUVOverlay(sdl.overlay);
SDL_DisplayYUVOverlay(sdl.overlay,&sdl.clip);
break;
#if C_OPENGL
case SCREEN_OPENGL:
glBindTexture(GL_TEXTURE_2D, sdl.opengl.texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
sdl.draw.width, sdl.draw.height, GL_BGRA_EXT,
GL_UNSIGNED_INT_8_8_8_8_REV, sdl.opengl.framebuf);
glCallList(sdl.opengl.displaylist);
SDL_GL_SwapBuffers();
break;
#endif
}
}
void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) {
/* I should probably not change the GFX_PalEntry :) */
if (sdl.surface->flags & SDL_HWPALETTE) {
if (!SDL_SetPalette(sdl.surface,SDL_PHYSPAL,(SDL_Color *)entries,start,count)) {
E_Exit("SDL:Can't set palette");
}
} else {
if (!SDL_SetPalette(sdl.surface,SDL_LOGPAL,(SDL_Color *)entries,start,count)) {
E_Exit("SDL:Can't set palette");
}
}
}
static Bit8u laltstate = SDL_KEYUP;
static Bit8u raltstate = SDL_KEYUP;
void GFX_Events() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_ACTIVEEVENT:
if (event.active.state & SDL_APPINPUTFOCUS) {
if (event.active.gain) {
if (sdl.desktop.fullscreen && !sdl.mouse.locked)
CaptureMouse();
SetPriority(sdl.priority.focus);
} else {
if (sdl.mouse.locked)
CaptureMouse();
SetPriority(sdl.priority.nofocus);
}
}
break;
case SDL_MOUSEMOTION:
HandleMouseMotion(&event.motion);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
HandleMouseButton(&event.button);
break;
case SDL_VIDEORESIZE:
// HandleVideoResize(&event.resize);
break;
case SDL_QUIT:
throw(0);
break;
#ifdef WIN32
case SDL_KEYDOWN:
case SDL_KEYUP:
// ignore event alt+tab
if (event.key.keysym.sym==SDLK_LALT) laltstate = event.key.type;
if (event.key.keysym.sym==SDLK_RALT) raltstate = event.key.type;
if (((event.key.keysym.sym==SDLK_TAB)) &&
((laltstate==SDL_KEYDOWN) || (raltstate==SDL_KEYDOWN))) break;
#endif
default:
void MAPPER_CheckEvent(SDL_Event * event);
MAPPER_CheckEvent(&event);
}
}
}
New native AGA version:
PHP Code:
/** Global Hardware window */
static struct Window *_hardwareWindow = NULL;
/** Hardware screen */
static struct Screen *_hardwareScreen = NULL;
// Hardware double buffering.
static struct ScreenBuffer *_hardwareScreenBuffer[2];
static BYTE _currentScreenBuffer = 0;
// AGA C2P.
static void *c2p[2] = {NULL, NULL};
static UWORD emptypointer[] = {
0x0000, 0x0000, /* reserved, must be NULL */
0x0000, 0x0000, /* 1 row of image data */
0x0000, 0x0000 /* reserved, must be NULL */
};
// These settings are for PAL HIGH RES!
#define AGA_VIDEO_DEPTH 8
#define AGA_MAX_VIDEO_WIDTH 640
#define AGA_MAX_VIDEO_HEIGHT 512
struct AGA_Block {
bool active; //If this isn't set don't draw
struct {
Bit32u width;
Bit32u height;
} draw;
Bit8u * surface;
};
static AGA_Block aga;
void GFX_SetTitle(Bits cycles,Bits frameskip,bool paused){
// TODO - will be used by RTG version.
}
static struct Screen* CreateHardwareScreen(ULONG modeId, int width, int height) {
return OpenScreenTags(NULL,
SA_Depth, AGA_VIDEO_DEPTH,
SA_DisplayID, modeId,
SA_Top, 0,
SA_Left, 0,
SA_Width, width,
SA_Height, height,
SA_Type, CUSTOMSCREEN,
SA_Quiet, TRUE,
SA_ShowTitle, FALSE,
SA_Draggable, FALSE,
SA_Exclusive, TRUE,
SA_AutoScroll, FALSE,
TAG_END);
}
static struct Window* CreateHardwareWindow(int width, int height) {
return OpenWindowTags(NULL,
WA_Left, 0,
WA_Top, 0,
WA_Width, width,
WA_Height, height,
SA_AutoScroll, FALSE,
WA_CustomScreen, (ULONG)_hardwareScreen,
WA_Backdrop, TRUE,
WA_Borderless, TRUE,
WA_DragBar, FALSE,
WA_Activate, TRUE,
WA_SimpleRefresh, TRUE,
WA_NoCareRefresh, TRUE,
WA_ReportMouse, TRUE,
WA_RMBTrap, TRUE,
WA_IDCMP, IDCMP_RAWKEY|IDCMP_MOUSEMOVE|IDCMP_MOUSEBUTTONS,
TAG_END);
}
static void GFX_ResetMode() {
aga.draw.width=0;
aga.draw.height=0;
if (aga.surface) {
free(aga.surface);
aga.surface = NULL;
}
if (_hardwareWindow) {
ClearPointer(_hardwareWindow);
CloseWindow(_hardwareWindow);
_hardwareWindow = NULL;
}
if (_hardwareScreenBuffer[0]) {
ChangeScreenBuffer (_hardwareScreen, _hardwareScreenBuffer[0]);
WaitTOF();
WaitTOF();
FreeScreenBuffer (_hardwareScreen, _hardwareScreenBuffer[0]);
_hardwareScreenBuffer[0] = NULL;
}
if (_hardwareScreenBuffer[1]) {
FreeScreenBuffer (_hardwareScreen, _hardwareScreenBuffer[1]);
_hardwareScreenBuffer[1] = NULL;
}
if (_hardwareScreen) {
CloseScreen(_hardwareScreen);
_hardwareScreen = NULL;
}
if (c2p[0]) {
c2p8_deinit_stub(c2p[0]);
c2p[0] = NULL;
}
if (c2p[1]) {
c2p8_deinit_stub(c2p[1]);
c2p[1] = NULL;
}
aga.active = false;
}
void GFX_SetSize(Bitu width, Bitu height) {
ULONG modeId = INVALID_ID;
DisplayInfoHandle handle;
struct DisplayInfo dispinfo;
struct DimensionInfo dimsinfo;
#ifdef C_DEBUG
LOG_DEBUG("GFX_SetSize(width=%d, height=%d)\n", width, height);
#endif
// Check args.
if (width == 0) {
LOG_ERROR("Width cannot be zero");
E_Exit("Failed to create a rendering output");
}
if (height == 0) {
LOG_ERROR("Height cannot be zero");
E_Exit("Failed to create a rendering output");
}
if (width > AGA_MAX_VIDEO_WIDTH) {
LOG_ERROR("Width cannot be greater than %d", AGA_MAX_VIDEO_WIDTH);
E_Exit("Failed to create a rendering output");
}
if (height > AGA_MAX_VIDEO_HEIGHT) {
LOG_ERROR("Height cannot be greater than %d", AGA_MAX_VIDEO_HEIGHT);
E_Exit("Failed to create a rendering output");
}
if ((aga.draw.width == width) && (aga.draw.height == height)) {
// Nothing to do...
#ifdef C_DEBUG
LOG_DEBUG("GFX_SetSize: Skipping pointless resolution switch");
#endif
return;
}
// Free any existing mode.
GFX_ResetMode();
// Reset.
aga.draw.width=width;
aga.draw.height=height;
// Automatically choose the best mode.
modeId = BestModeID(BIDTAG_NominalWidth, width,
BIDTAG_NominalHeight, height,
BIDTAG_DesiredWidth, width,
BIDTAG_DesiredHeight, height,
BIDTAG_Depth, AGA_VIDEO_DEPTH,
BIDTAG_MonitorID, PAL_MONITOR_ID,
TAG_END);
// Verify the mode choosen.
if (modeId != INVALID_ID) {
if ((handle = FindDisplayInfo(modeId)) == NULL) {
LOG_ERROR("Couldn't find Display Info for requested mode");
E_Exit("Failed to create a rendering output");
}
if (GetDisplayInfoData(handle, (UBYTE *)&dispinfo, sizeof(dispinfo), DTAG_DISP,0) == 0) {
LOG_ERROR("Couldn't get Display Info Data for requested mode");
E_Exit("Failed to create a rendering output");
}
if (GetDisplayInfoData(handle, (UBYTE *)&dimsinfo, sizeof(dimsinfo), DTAG_DIMS, 0) == 0) {
LOG_ERROR("Couldn't get Display Info Data for requested mode");
E_Exit("Failed to create a rendering output");
}
if (dimsinfo.MaxDepth != AGA_VIDEO_DEPTH) {
modeId = INVALID_ID;
}
if ((dimsinfo.Nominal.MaxX + 1) != width) {
modeId = INVALID_ID;
}
if ((dimsinfo.Nominal.MaxY + 1) < height) {
modeId = INVALID_ID;
}
}
if (modeId == INVALID_ID) {
LOG_ERROR("Couldn't find a Screen Mode for the requested resolution (%d * %d)\n", width, height);
E_Exit("Failed to create a rendering output");
}
_hardwareScreen = CreateHardwareScreen(modeId, width, height);
if (!_hardwareScreen ) {
LOG_ERROR("Couldn't create a Hardware Screen for the requested mode");
E_Exit("Failed to create a rendering output");
}
// Setup double buffering.
_hardwareScreenBuffer[0] = AllocScreenBuffer (_hardwareScreen, NULL, SB_SCREEN_BITMAP);
if (!_hardwareScreenBuffer[0]) {
LOG_ERROR("Couldn't set up double buffering for the requested mode");
E_Exit("Failed to create a rendering output");
}
_hardwareScreenBuffer[1] = AllocScreenBuffer (_hardwareScreen, NULL, 0);
if (!_hardwareScreenBuffer[1]) {
LOG_ERROR("Couldn't set up double buffering for the requested mode");
E_Exit("Failed to create a rendering output");
}
_currentScreenBuffer = 1;
// Setup C2P.
c2p[0] = c2p8_reloc_stub(_hardwareScreenBuffer[0]->sb_BitMap);
c2p[1] = c2p8_reloc_stub(_hardwareScreenBuffer[1]->sb_BitMap);
// Create the hardware window.
_hardwareWindow = CreateHardwareWindow(width, height);
if (!_hardwareWindow) {
LOG_ERROR("Couldn't create a Hardware Window for the requested mode");
E_Exit("Failed to create a rendering output");
}
SetPointer(_hardwareWindow, emptypointer, 1, 1, 0, 0);
// Create a new chunky back buffer.
aga.surface = (Bit8u *)malloc(width * height);
if (!aga.surface) {
LOG_ERROR("Couldn't allocate buffer for requested mode");
E_Exit("Failed to create a rendering output");
}
memset(aga.surface, 0, width * height);
// Good to go!
aga.active = true;
}
void GFX_UpdatePalette(Bitu numberOfEntries, Bitu paletteDirtyStart, GFX_PalEntry * currentPalette) {
int i;
ULONG agaPalette[numberOfEntries*3 + 2];
if (aga.active) {
for ( i=0; i < numberOfEntries; i++ ) {
agaPalette[i*3+1] = currentPalette[paletteDirtyStart + i].r<<24;
agaPalette[i*3+2] = currentPalette[paletteDirtyStart + i].g<<24;
agaPalette[i*3+3] = currentPalette[paletteDirtyStart + i].b<<24;
}
agaPalette[0] = (numberOfEntries << 16) + paletteDirtyStart;
// Terminator: NEEDED
agaPalette[((numberOfEntries * 3) + 1)] = 0x00000000;
LoadRGB32(&_hardwareScreen->ViewPort, agaPalette);
}
}
bool GFX_StartUpdate(Bit8u * & pixels) {
if (!aga.active) {
// Just in case GFX_SetSize() hasn't been called yet.
return false;
}
pixels = aga.surface;
return true;
}
void GFX_EndUpdate(void) {
c2p8_stub(c2p[_currentScreenBuffer], _hardwareScreenBuffer[_currentScreenBuffer]->sb_BitMap, (UBYTE*)aga.surface, (aga.draw.width * aga.draw.height));
if (ChangeScreenBuffer(_hardwareScreen, _hardwareScreenBuffer[_currentScreenBuffer])) {
// Flip.
_currentScreenBuffer = _currentScreenBuffer ^ 1;
}
}
void GFX_Events() {
if (aga.active) {
struct IntuiMessage *imsg;
while (imsg = (struct IntuiMessage *)GetMsg(_hardwareWindow->UserPort)) {
ReplyMsg((struct Message *)imsg);
switch (imsg->Class) {
case IDCMP_MOUSEMOVE:
// TODO
break;
case IDCMP_MOUSEBUTTONS:
// TODO
break;
case IDCMP_RAWKEY:
int code = imsg->Code;
bool pressed = (code & IECODE_UP_PREFIX) ? false : true;
code &= ~IECODE_UP_PREFIX;
KEYBOARD_AddKey(keycode_lookup[code], pressed);
}
}
}
}
static void GUI_ShutDown(Section * sec) {
LOG_DEBUG("GUI shutdown called");
// Free any existing mode.
GFX_ResetMode();
}
|