DinkSmallwoodHD/source/video_gl.cpp
seth 20f8a6a856 * Mobile GUI tweaks
* Added option to disable screen scroll transitions, one of my Android test devices has the slowest glread in the world, it's like 1 full second to walk to the next screen because of it.  This might make dmods that 
use timing (Myster island camera sequence for example) easier though, not sure.
* Fixed issue where behavior of two load_sequence commands in a row on the same sequence differed from 1.08 (in 1.08, max frame is set to the second one as long as the first one wasn't actually loaded yet.  key now shows up in TGKA)
* Fixed regression where offsets in Mayhem were incorrect on the hand mouse pointer
* Upped max frames per seq to 100 instead of 50, fixes Echoes of the Ancient.  I should probably make it dynamic but changing one const number is much easier!
* Now gives a clear warning in the log.txt if a seq tries to go beyond what it can handle and will truncate it (better than breaking the whole sequence as it did before)
* Added support for a weird bmp header type, fixes incorrect palette issue in the dmod The Orb of Darkness
* Fixed life/exp/health to correctly interpolate between values like the original dink, huge thanks to Dan's detailed bug report on this, he even made a mod which made testing the fix a breeze!

git-svn-id: svn://rtsoft.com/rtsvn/projects/RTDink@1520 353e56fe-9613-0410-8469-b96ad8e6f29c
2017-10-08 04:12:51 +00:00

425 lines
No EOL
10 KiB
C++

#include "PlatformPrecomp.h"
#include "video_gl.h"
#include "dink/misc_util.h"
#include <cassert>
#include "Renderer/SoftSurface.h"
#include "App.h"
LPDIRECTDRAWSURFACE lpDDSBack = NULL; // DirectDraw back surface
SoftSurface g_palette;
extern LPDIRECTDRAWSURFACE lpDDSBackGround;
bool InitializeVideoSystem()
{
assert(!lpDDSBack);
lpDDSBack = InitOffscreenSurface(C_DINK_SCREENSIZE_X, C_DINK_SCREENSIZE_Y, IDirectDrawSurface::MODE_PRIMARY_GL);
g_palette.Init(8,8, SoftSurface::SURFACE_PALETTE_8BIT);
g_palette.SetPaletteFromBMP("dink/tiles/palette.bmp", SoftSurface::COLOR_KEY_NONE);
return true;
}
void KillVideoEngine()
{
SAFE_DELETE(lpDDSBack);
}
void dderror(int hErr){};
IDirectDrawSurface * LoadBitmapIntoSurface(const char *pName, eTransparencyType trans, IDirectDrawSurface::eMode mode, byte *pMem, bool bUseCheckerboardFix)
{
IDirectDrawSurface * pSurf;
pSurf = new IDirectDrawSurface;
pSurf->m_mode = mode;
pSurf->m_pSurf = new SoftSurface;
//bUseCheckerboardFix = true;
pSurf->m_pSurf->SetForceBlackAndWhiteOnBmpPalettes(true);
if (pMem)
{
#ifdef _DEBUG
//LogMsg("loading DDRAW bmp from mem");
#endif
//if this is set, ignore the filename
pSurf->m_pSurf->LoadFileFromMemory(pMem, SoftSurface::eColorKeyType(trans), 0, false, bUseCheckerboardFix);
} else
{
#ifdef _DEBUG
//LogMsg("loading DDRAW bmp from file");
#endif
pSurf->m_pSurf->LoadFile(pName, SoftSurface::eColorKeyType(trans), false, bUseCheckerboardFix);
}
//LogMsg("loaded bitmap");
switch( mode)
{
case IDirectDrawSurface::MODE_SHADOW_GL:
break;
}
return pSurf;
}
void GetSizeOfSurface(IDirectDrawSurface *pdds, int *pX, int *pY)
{
if (pdds->m_pSurf)
{
*pX = pdds->m_pSurf->GetWidth();
*pY = pdds->m_pSurf->GetHeight();
return;
} else
{
assert(!"Bad surface");
return;
}
}
IDirectDrawSurface * InitOffscreenSurface(int x, int y, IDirectDrawSurface::eMode mode, bool bHiColor, SoftSurface *pSurfaceToCopyFrom)
{
IDirectDrawSurface *pdds;
pdds = new IDirectDrawSurface;
pdds->m_mode = mode;
switch (mode)
{
case IDirectDrawSurface::MODE_NORMAL:
case IDirectDrawSurface::MODE_SHADOW_GL:
pdds->m_pSurf = new SoftSurface;
if (bHiColor)
{
pdds->m_pSurf->Init(x,y, SoftSurface::SURFACE_RGBA);
pdds->m_pSurf->SetHasPremultipliedAlpha(true);
pdds->m_pSurf->SetUsesAlpha(true);
} else
{
pdds->m_pSurf->Init(x,y, SoftSurface::SURFACE_PALETTE_8BIT);
pdds->m_pSurf->SetPaletteFromBMP("dink/tiles/palette.bmp", SoftSurface::COLOR_KEY_NONE);
}
if (pSurfaceToCopyFrom)
{
pdds->m_pSurf->Blit(0,0,pSurfaceToCopyFrom);
}
if (mode == IDirectDrawSurface::MODE_SHADOW_GL)
{
pdds->m_pGLSurf = new Surface;
pdds->m_pGLSurf->SetSmoothing(GetApp()->GetVar("smoothing")->GetUINT32() != 0);
if (GetApp()->GetVar("smoothing")->GetUINT32())
{
pdds->m_pGLSurf->SetTextureType(Surface::TYPE_GUI);
} else
{
pdds->m_pGLSurf->SetTextureType(Surface::TYPE_NO_SMOOTHING);
}
pdds->m_pGLSurf->InitBlankSurface(x,y);
}
break;
case IDirectDrawSurface::MODE_PRIMARY_GL:
break;
}
return pdds;
}
IDirectDrawSurface::IDirectDrawSurface()
{
m_pSurf = NULL;
m_mode = MODE_NORMAL;
m_pGLSurf = NULL;
m_gameTickOfLastUse = 0;
}
IDirectDrawSurface::~IDirectDrawSurface()
{
SAFE_DELETE(m_pSurf);
SAFE_DELETE(m_pGLSurf);
}
glColorBytes RGBA_TO_GLCOLOR(const unsigned int color)
{
return glColorBytes(GET_RED(color), GET_GREEN(color), GET_BLUE(color), GET_ALPHA(color));
}
unsigned int GLCOLOR_TO_RGBA(const glColorBytes glColor)
{
return MAKE_RGBA(glColor.r, glColor.g, glColor.b, glColor.a);
}
Surface * IDirectDrawSurface::GetGLSuface()
{
assert(m_mode == MODE_SHADOW_GL && "We're only using this for item icons, and they always would be gl shadowed!");
UpdateShadowSurface();
return m_pGLSurf;
}
int IDirectDrawSurface::Blt( rtRect32 *pDestRect, IDirectDrawSurface * pSrcSurf, rtRect32 *pSrcRect, uint32 flags, DDBLTFX *pFX )
{
if (pSrcSurf)
{
pSrcSurf->UpdateLastUsedTime();
}
switch (m_mode)
{
case MODE_SHADOW_GL:
case MODE_NORMAL:
if (flags & DDBLT_COLORFILL)
{
assert(pFX);
assert(pDestRect == NULL && "Well, we only support modifying the entire screen");
//don't ask me why, but the original directx had these backwards. Palette is correct
if (pFX->dwFillColor == 0)
{
pFX->dwFillColor = 255;
}
else if (pFX->dwFillColor == 255)
{
pFX->dwFillColor = 0;
}
if (m_pSurf->GetSurfaceType() == SoftSurface::SURFACE_RGB || m_pSurf->GetSurfaceType() == SoftSurface::SURFACE_RGBA)
{
m_pSurf->FillColor(g_palette.GetPalette()[pFX->dwFillColor]);
}
else
{
//sort of a hack for 8 bit index passing
glColorBytes palIndex(pFX->dwFillColor, 0, 0, 255);
m_pSurf->FillColor(palIndex);
}
return DD_OK;
}
if (pSrcSurf && pSrcSurf->m_pSurf && pSrcSurf->m_pSurf->GetSurfaceType() != SoftSurface::SURFACE_NONE)
{
//assert(!"Dumbass alert");
m_pSurf->Blit(pDestRect->left, pDestRect->top, pSrcSurf->m_pSurf, pSrcRect->left, pSrcRect->top, pSrcRect->right-pSrcRect->left, pSrcRect->bottom-pSrcRect->top);
}
break;
case MODE_PRIMARY_GL:
{
if (flags & DDBLT_COLORFILL)
{
assert(pFX);
DrawRect(*pDestRect, GLCOLOR_TO_RGBA(g_palette.GetPalette()[pFX->dwFillColor]));
return DD_OK;
}
if (!pSrcSurf)
{
assert(!"huh?!");
return DD_OK;
}
if (pSrcSurf->m_mode == MODE_SHADOW_GL)
{
//blit from a GL surface instead
pSrcSurf->UpdateShadowSurface();
pSrcSurf->m_pGLSurf->BlitEx(rtRectf(*pDestRect) + rtRectf(0,0, 0.5f, 0.5f), rtRectf(*pSrcRect));
break;
}
SoftSurface s;
s.Init(pSrcRect->GetWidth(), pSrcRect->GetHeight(), SoftSurface::SURFACE_RGBA);
//s.FillColor(glColorBytes(0,0,0,0));
s.Blit(0,0, pSrcSurf->m_pSurf, pSrcRect->left,pSrcRect->top, pSrcRect->GetWidth(), pSrcRect->GetHeight());
if (pSrcSurf->m_pSurf->GetUsesAlpha())
{
s.SetUsesAlpha(true);
}
g_globalBatcher.BlitRawImage(pDestRect->left,pDestRect->top, s);
}
break;
}
return DD_OK;
}
void IDirectDrawSurface::UpdateShadowSurface()
{
assert(m_mode == MODE_SHADOW_GL && "Don't call this on other modes!");
assert(m_pSurf);
if (m_pSurf->GetModified())
{
//init the surface if needed
if (!m_pGLSurf)
{
m_pGLSurf = new Surface;
m_pGLSurf->SetSmoothing(GetApp()->GetVar("smoothing")->GetUINT32() != 0);
if (GetApp()->GetVar("smoothing")->GetUINT32())
{
m_pGLSurf->SetTextureType(Surface::TYPE_GUI);
} else
{
m_pGLSurf->SetTextureType(Surface::TYPE_NO_SMOOTHING);
}
m_pGLSurf->InitBlankSurface(m_pSurf->GetWidth(),m_pSurf->GetHeight());
}
if (m_pSurf->GetSurfaceType() == SoftSurface::SURFACE_PALETTE_8BIT)
{
SoftSurface s;
s.Init(m_pSurf->GetWidth(), m_pSurf->GetHeight(), SoftSurface::SURFACE_RGBA);
s.FillColor(glColorBytes(0,0,0,0));
s.Blit(0,0, m_pSurf);
s.FlipY();
//put it on the GL surface
m_pGLSurf->UpdateSurfaceRect(rtRect(0,0, s.GetWidth(), s.GetHeight()), s.GetPixelData());
m_pGLSurf->SetUsesAlpha(m_pSurf->GetUsesAlpha());
if (s.GetHasPremultipliedAlpha())
{
m_pGLSurf->SetBlendingMode(Surface::BLENDING_PREMULTIPLIED_ALPHA);
}
// if (m_pSurf) m_pSurf->SetModified(false); //WARNING: Seth changed on 8/21/2017, seems like this fixes issue with constantly re-initting surfaces
// SAFE_FREE(m_pSurf);
}
else
{
assert(m_pSurf);
assert(m_pGLSurf);
assert(m_pSurf->GetSurfaceType() == SoftSurface::SURFACE_RGBA);
//m_pSurf->FillColor(glColorBytes(0,0,0,0));
if (m_pSurf->GetPixelData())
{
m_pSurf->FlipY();
m_pGLSurf->UpdateSurfaceRect(rtRect(0,0, m_pSurf->GetWidth(), m_pSurf->GetHeight()), m_pSurf->GetPixelData(), true);
m_pSurf->FlipY();
m_pGLSurf->SetUsesAlpha(m_pSurf->GetUsesAlpha());
if (m_pSurf->GetHasPremultipliedAlpha())
{
m_pGLSurf->SetBlendingMode(Surface::BLENDING_PREMULTIPLIED_ALPHA);
}
}
}
if (m_pSurf) m_pSurf->SetModified(false);
//assert(m_pGLSurf->GetBlendingMode() == Surface::BLENDING_PREMULTIPLIED_ALPHA);
}
}
int IDirectDrawSurface::BltFast( int x, int y, IDirectDrawSurface *pSrcSurf, rtRect32 *pSrcRect, uint32 dwTrans )
{
if (pSrcSurf)
{
pSrcSurf->UpdateLastUsedTime();
}
switch (m_mode)
{
case MODE_SHADOW_GL:
case MODE_NORMAL:
if (pSrcSurf->m_mode == MODE_PRIMARY_GL)
{
//we need to copy from what is already on the screen
m_pSurf->BlitFromScreen(x, y, pSrcRect->left, pSrcRect->top, pSrcRect->GetWidth(), pSrcRect->GetHeight());
//m_pSurf->Blit(x, y, lpDDSBackGround->m_pSurf, pSrcRect->left, pSrcRect->top, pSrcRect->GetWidth(), pSrcRect->GetHeight());
//m_pSurf->SetUsesAlpha(false);
} else
{
m_pSurf->Blit(x, y, pSrcSurf->m_pSurf, pSrcRect->left, pSrcRect->top, pSrcRect->GetWidth(), pSrcRect->GetHeight());
}
break;
case MODE_PRIMARY_GL:
if (!pSrcSurf)
{
assert(!"Shit!");
return DD_OK;
}
if (pSrcSurf->m_mode == MODE_SHADOW_GL)
{
//blit from a GL surface instead
pSrcSurf->UpdateShadowSurface();
//skip if too big for surface
if (
(pSrcRect->GetHeight()+y > C_DINK_SCREENSIZE_Y) ||
(pSrcRect->GetWidth()+x > C_DINK_SCREENSIZE_X)
)
{
#ifdef _DEBUG
//LogMsg("Skipping blit, original Dink 1.08 would have rejected it for not fitting");
#endif
break;
}
//pSrcSurf->m_pGLSurf->SetBlendingMode(Surface::BLENDING_NORMAL);
pSrcSurf->m_pGLSurf->BlitEx(rtRectf(x, y, x+pSrcRect->GetWidth(), y +pSrcRect->GetHeight())+ rtRectf(0,0, 0.5f, 0.5f), rtRectf(*pSrcRect));
break;
}
SoftSurface s;
s.Init(pSrcRect->GetWidth(), pSrcRect->GetHeight(), SoftSurface::SURFACE_RGBA);
s.Blit(0,0, pSrcSurf->m_pSurf, pSrcRect->left,pSrcRect->top, pSrcRect->GetWidth(), pSrcRect->GetHeight());
if (pSrcSurf->m_pSurf->GetUsesAlpha())
{
s.SetUsesAlpha(true);
}
g_globalBatcher.BlitRawImage(x,y, s);
break;
}
return DD_OK;
}
void IDirectDrawSurface::UpdateLastUsedTime()
{
m_gameTickOfLastUse = GetBaseApp()->GetGameTick();
}