DinkSmallwoodHD/source/video_gl.cpp
seth 04f68e8125 * (Windows) Added support for -game <dmod directory> parm to load a DMOD from anywhere on your HD. It also sets
the active DMOD dir to the DMODs parent directory for that session.  Automatic state autosave, save/continue and quicksave/quickload work as expected by saving data to its directory
* (bugfix) Save states now properly load even if the DMOD directory has been cut and pasted to a new place
* (bugfix) Full state saves now properly setup backgrounds with correct vision modifications instead of assuming it was 0
- Due to minor changes in the save state stuff, I've versioned it so the game will refuse to load old versions (as always, this doesn't affect the normal save files, just the full state saves HD does)
* (DinkC) fill_screen works better and colors 0 and 255 are no longer sometimes reversed
* (bugfix) M can now be used to turn off the map, previously it only worked to turn it on
* (bugfix) Status bar no longer incorrectly draws over full screen bitmaps (like the map in Mystery Island) and is properly reconstructed in full save states


git-svn-id: svn://rtsoft.com/rtsvn/projects/RTDink@1484 353e56fe-9613-0410-8469-b96ad8e6f29c
2017-09-16 15:16:26 +00:00

398 lines
No EOL
9.7 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(640, 480, 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)
{
IDirectDrawSurface * pSurf;
pSurf = new IDirectDrawSurface;
pSurf->m_mode = mode;
pSurf->m_pSurf = new SoftSurface;
bool bUseCheckerboardFix = GetApp()->GetVar("checkerboard_fix")->GetUINT32() != 0;
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 (m_pSurf->GetSurfaceType() == SoftSurface::SURFACE_RGB || m_pSurf->GetSurfaceType() == SoftSurface::SURFACE_RGBA)
{
if (pFX->dwFillColor == 0)
{
pFX->dwFillColor = 255;
}
else if (pFX->dwFillColor == 255)
{
pFX->dwFillColor = 0;
}
}
m_pSurf->FillColor(g_palette.GetPalette()[pFX->dwFillColor]);
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();
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();
}