#include "PlatformPrecomp.h" #include "video_gl.h" #include "dink/misc_util.h" #include #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; 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)); } else { #ifdef _DEBUG //LogMsg("loading DDRAW bmp from file"); #endif pSurf->m_pSurf->LoadFile(pName, SoftSurface::eColorKeyType(trans), false); } //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); } 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; 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"); 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; 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(); }