Lots of Android fixes and stubs. Increase SDL log level on Android. Add GL context loss handling.

This commit is contained in:
elasota
2020-10-20 23:43:02 -04:00
parent f26f631ae2
commit 23b69cf0ee
32 changed files with 609 additions and 173 deletions

View File

@@ -322,6 +322,11 @@ bool GpFileSystem_Win32::IsVirtualDirectoryLooseResources(PortabilityLayer::Virt
return false;
}
void GpFileSystem_Win32::SetMainThreadRelay(IGpThreadRelay *relay)
{
(void)relay;
}
bool GpFileSystem_Win32::ValidateFilePath(const char *str, size_t length) const
{
for (size_t i = 0; i < length; i++)

View File

@@ -23,6 +23,8 @@ public:
bool IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const override;
void SetMainThreadRelay(IGpThreadRelay *relay) override;
const wchar_t *GetBasePath() const;
static GpFileSystem_Win32 *GetInstance();

View File

@@ -2,6 +2,7 @@
#include "GpFileSystem_Android.h"
#include "GpIOStream.h"
#include "HostDirectoryCursor.h"
#include "IGpThreadRelay.h"
#include "VirtualDirectory.h"
#include "SDL.h"
@@ -254,7 +255,32 @@ void GpFileStream_Android_File::Flush()
fflush(m_f);
}
static bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution, bool &isAsset)
bool GpFileSystem_Android::ResolvePathInDownloadsDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution, bool &isAsset)
{
JNIEnv *jni = static_cast<JNIEnv *>(SDL_AndroidGetJNIEnv());
jstring fname = jni->NewStringUTF(paths[0]);
jobject resultName = jni->CallObjectMethod(m_activity, this->m_selectSourceExportPathMID, fname);
int n = 0;
jstring resultPath = static_cast<jstring>(resultName);
jni->DeleteLocalRef(fname);
const char *pathStrChars = jni->GetStringUTFChars(resultPath, nullptr);
resolution = std::string(pathStrChars, static_cast<size_t>(jni->GetStringUTFLength(resultPath)));
jni->ReleaseStringUTFChars(resultPath, pathStrChars);
jni->DeleteLocalRef(resultPath);
resolution = SDL_AndroidGetExternalStoragePath();
resolution += "/SourceCode.zip";
isAsset = false;
return true;
}
bool GpFileSystem_Android::ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution, bool &isAsset)
{
const char *prefsAppend = nullptr;
@@ -285,6 +311,8 @@ static bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, c
case PortabilityLayer::VirtualDirectories::kPrefs:
prefsAppend = "Prefs";
break;
case PortabilityLayer::VirtualDirectories::kSourceExport:
return ResolvePathInDownloadsDirectory(virtualDirectory, paths, numPaths, resolution, isAsset);
default:
return false;
};
@@ -308,6 +336,7 @@ static bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, c
GpFileSystem_Android::GpFileSystem_Android()
: m_activity(nullptr)
, m_relay(nullptr)
{
}
@@ -323,6 +352,7 @@ void GpFileSystem_Android::InitJNI()
jclass activityClassLR = static_cast<jclass>(jni->GetObjectClass(activityLR));
m_scanAssetDirectoryMID = jni->GetMethodID(activityClassLR, "scanAssetDirectory", "(Ljava/lang/String;)[Ljava/lang/String;");
m_selectSourceExportPathMID = jni->GetMethodID(activityClassLR, "selectSourceExportPath", "(Ljava/lang/String;)Ljava/lang/String;");
m_activity = jni->NewGlobalRef(activityLR);
@@ -407,7 +437,8 @@ GpIOStream *GpFileSystem_Android::OpenFileNested(PortabilityLayer::VirtualDirect
bool canWrite = false;
bool needResetPosition = false;
switch (createDisposition) {
switch (createDisposition)
{
case GpFileCreationDispositions::kCreateOrOverwrite:
mode = "w+b";
break;
@@ -506,6 +537,25 @@ bool GpFileSystem_Android::DeleteFile(PortabilityLayer::VirtualDirectory_t virtu
}
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths)
{
ScanDirectoryNestedContext ctx;
ctx.m_this = this;
ctx.m_returnValue = nullptr;
ctx.m_virtualDirectory = virtualDirectory;
ctx.m_paths = paths;
ctx.m_numPaths = numPaths;
m_relay->Invoke(ScanDirectoryNestedThunk, &ctx);
return ctx.m_returnValue;
}
void GpFileSystem_Android::ScanDirectoryNestedThunk(void *context)
{
ScanDirectoryNestedContext *ctx = static_cast<ScanDirectoryNestedContext*>(context);
ctx->m_returnValue = ctx->m_this->ScanDirectoryNestedInternal(ctx->m_virtualDirectory, ctx->m_paths, ctx->m_numPaths);
}
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanDirectoryNestedInternal(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths)
{
if (virtualDirectory == PortabilityLayer::VirtualDirectories::kGameData || virtualDirectory == PortabilityLayer::VirtualDirectories::kApplicationData)
return ScanAssetDirectory(virtualDirectory, paths, numPaths);
@@ -564,6 +614,11 @@ bool GpFileSystem_Android::IsVirtualDirectoryLooseResources(PortabilityLayer::Vi
return false;
}
void GpFileSystem_Android::SetMainThreadRelay(IGpThreadRelay *relay)
{
m_relay = relay;
}
GpFileSystem_Android *GpFileSystem_Android::GetInstance()
{
return &ms_instance;
@@ -647,6 +702,7 @@ void GpDirectoryCursor_POSIX::Destroy()
PortabilityLayer::HostDirectoryCursor *GpFileSystem_Android::ScanAssetDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths)
{
std::string resolvedPath;
std::vector<std::string> subPaths;
bool isAsset = true;

View File

@@ -5,6 +5,7 @@
#include "GpCoreDefs.h"
#include <jni.h>
#include <string>
class GpFileSystem_Android final : public PortabilityLayer::HostFileSystem
{
@@ -26,14 +27,35 @@ public:
bool IsVirtualDirectoryLooseResources(PortabilityLayer::VirtualDirectory_t virtualDir) const override;
void SetMainThreadRelay(IGpThreadRelay *relay) override;
static GpFileSystem_Android *GetInstance();
private:
struct ScanDirectoryNestedContext
{
GpFileSystem_Android *m_this;
PortabilityLayer::HostDirectoryCursor *m_returnValue;
PortabilityLayer::VirtualDirectory_t m_virtualDirectory;
char const *const *m_paths;
size_t m_numPaths;
};
static void ScanDirectoryNestedThunk(void *context);
PortabilityLayer::HostDirectoryCursor *ScanDirectoryNestedInternal(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
PortabilityLayer::HostDirectoryCursor *ScanAssetDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
PortabilityLayer::HostDirectoryCursor *ScanStorageDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
bool ResolvePathInDownloadsDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution, bool &isAsset);
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution, bool &isAsset);
IGpThreadRelay *m_relay;
jobject m_activity;
jmethodID m_scanAssetDirectoryMID;
jmethodID m_selectSourceExportPathMID;
static GpFileSystem_Android ms_instance;
};

View File

@@ -30,6 +30,8 @@ IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &pr
int main(int argc, char* argv[])
{
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_WARN);
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return -1;

View File

@@ -9,7 +9,7 @@
android:installLocation="auto">
<!-- OpenGL ES 2.0 -->
<uses-feature android:glEsVersion="0x00020000" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<!-- Touchscreen support -->
<uses-feature

View File

@@ -1,8 +1,17 @@
package org.thecodedeposit.aerofoil;
import org.libsdl.app.SDLActivity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
public class GpActivity extends SDLActivity
{
@@ -27,4 +36,28 @@ public class GpActivity extends SDLActivity
return new String[0];
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
if (requestCode == 1111 && resultCode == RESULT_OK && intent != null)
{
Uri uri = intent.getData();
int n = 0;
}
else
{
super.onActivityResult(requestCode, resultCode, intent);
}
}
public String selectSourceExportPath(String fname)
{
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT)
.setType("application/zip")
.addCategory(Intent.CATEGORY_OPENABLE)
.putExtra(Intent.EXTRA_TITLE, "SourceCode.zip");
startActivityForResult(intent, 1111);
return "";
}
}

View File

@@ -629,15 +629,17 @@ GLuint GpGLShader<TShaderType>::GetID() const
class GpDisplayDriverSurface_GL2 : public IGpDisplayDriverSurface
{
public:
GpDisplayDriverSurface_GL2(GpDisplayDriver_SDL_GL2 *driver, size_t width, size_t height, size_t pitch, GpGLTexture *texture, GpPixelFormat_t pixelFormat);
GpDisplayDriverSurface_GL2(GpDisplayDriver_SDL_GL2 *driver, size_t width, size_t height, size_t pitch, GpGLTexture *texture, GpPixelFormat_t pixelFormat, IGpDisplayDriver::SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext);
~GpDisplayDriverSurface_GL2();
static GpDisplayDriverSurface_GL2 *Create(GpDisplayDriver_SDL_GL2 *driver, size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat);
static GpDisplayDriverSurface_GL2 *Create(GpDisplayDriver_SDL_GL2 *driver, size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, GpDisplayDriverSurface_GL2 *prevSurface, IGpDisplayDriver::SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext);
void Upload(const void *data, size_t x, size_t y, size_t width, size_t height, size_t pitch);
void UploadEntire(const void *data, size_t pitch);
void Destroy();
bool RecreateAll();
size_t GetImageWidth() const;
size_t GetPaddedTextureWidth() const;
size_t GetHeight() const;
@@ -645,7 +647,8 @@ public:
GpGLTexture *GetTexture() const;
private:
bool Init();
bool Init(GpDisplayDriverSurface_GL2 *prevSurface);
bool RecreateSingle();
GLenum ResolveGLFormat() const;
GLenum ResolveGLInternalFormat() const;
GLenum ResolveGLType() const;
@@ -657,6 +660,13 @@ private:
size_t m_paddedTextureWidth;
size_t m_pitch;
size_t m_height;
GpDisplayDriver_SDL_GL2 *m_driver;
GpDisplayDriverSurface_GL2 *m_next;
GpDisplayDriverSurface_GL2 *m_prev;
IGpDisplayDriver::SurfaceInvalidateCallback_t m_invalidateCallback;
void *m_invalidateContext;
};
class GpCursor_SDL2 final : public IGpCursor
@@ -714,7 +724,7 @@ public:
void Run() override;
void Shutdown() override;
void GetDisplayResolution(unsigned int *width, unsigned int *height) override;
IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat) override;
IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext) override;
void DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height, const GpDisplayDriverSurfaceEffects *effects) override;
IGpCursor *CreateBWCursor(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY) override;
IGpCursor *CreateColorCursor(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY) override;
@@ -733,6 +743,8 @@ public:
void ApplyPrefs(const void *identifier, size_t identifierSize, const void *contents, size_t contentsSize, uint32_t version) override;
bool SavePrefs(void *context, WritePrefsFunc_t writeFunc) override;
void UnlinkSurface(GpDisplayDriverSurface_GL2 *surface, GpDisplayDriverSurface_GL2 *prev, GpDisplayDriverSurface_GL2 *next);
const GpGLFunctions *GetGLFunctions() const;
template<GLuint TShaderType> GpComPtr<GpGLShader<TShaderType> > CreateShader(const char *shaderSrc);
@@ -776,15 +788,6 @@ private:
GpGLFunctions m_gl;
GpDisplayDriverProperties m_properties;
GpComPtr<GpGLRenderTargetView> m_virtualScreenTextureRTV;
GpComPtr<GpGLTexture> m_virtualScreenTexture;
GpComPtr<GpGLVertexArray> m_quadVertexArray;
GpComPtr<GpGLBuffer> m_quadVertexBufferKeepalive;
GpComPtr<GpGLBuffer> m_quadIndexBuffer;
GpComPtr<GpGLTexture> m_paletteTexture;
struct DrawQuadProgram
{
GpComPtr<GpGLProgram> m_program;
@@ -815,17 +818,31 @@ private:
bool Link(GpDisplayDriver_SDL_GL2 *driver, const GpGLShader<GL_VERTEX_SHADER> *vertexShader, const GpGLShader<GL_FRAGMENT_SHADER> *pixelShader);
};
BlitQuadProgram m_scaleQuadProgram;
BlitQuadProgram m_copyQuadProgram;
struct InstancedResources
{
GpComPtr<GpGLRenderTargetView> m_virtualScreenTextureRTV;
GpComPtr<GpGLTexture> m_virtualScreenTexture;
DrawQuadProgram m_drawQuadPaletteNoFlickerProgram;
DrawQuadProgram m_drawQuadPaletteFlickerProgram;
DrawQuadProgram m_drawQuadRGBProgram;
DrawQuadProgram m_drawQuad15BitProgram;
DrawQuadProgram m_drawQuadPaletteICCNoFlickerProgram;
DrawQuadProgram m_drawQuadPaletteICCFlickerProgram;
DrawQuadProgram m_drawQuadRGBICCProgram;
DrawQuadProgram m_drawQuad15BitICCProgram;
GpComPtr<GpGLVertexArray> m_quadVertexArray;
GpComPtr<GpGLBuffer> m_quadVertexBufferKeepalive;
GpComPtr<GpGLBuffer> m_quadIndexBuffer;
GpComPtr<GpGLTexture> m_paletteTexture;
BlitQuadProgram m_scaleQuadProgram;
BlitQuadProgram m_copyQuadProgram;
DrawQuadProgram m_drawQuadPaletteNoFlickerProgram;
DrawQuadProgram m_drawQuadPaletteFlickerProgram;
DrawQuadProgram m_drawQuadRGBProgram;
DrawQuadProgram m_drawQuad15BitProgram;
DrawQuadProgram m_drawQuadPaletteICCNoFlickerProgram;
DrawQuadProgram m_drawQuadPaletteICCFlickerProgram;
DrawQuadProgram m_drawQuadRGBICCProgram;
DrawQuadProgram m_drawQuad15BitICCProgram;
};
InstancedResources m_res;
SDL_Window *m_window;
SDL_GLContext m_glContext;
@@ -834,6 +851,7 @@ private:
SDL_Cursor *m_iBeamCursor;
SDL_Cursor *m_arrowCursor;
bool m_cursorIsHidden;
bool m_contextLost;
bool m_isResettingSwapChain;
@@ -872,10 +890,16 @@ private:
std::chrono::time_point<std::chrono::high_resolution_clock>::duration m_syncTimeBase;
GpRingBuffer<CompactedPresentHistoryItem, 60> m_presentHistory;
GpDisplayDriverSurface_GL2 *m_firstSurface;
GpDisplayDriverSurface_GL2 *m_lastSurface;
uint8_t m_paletteStorage[256 * 4 + GP_SYSTEM_MEMORY_ALIGNMENT];
uint8_t *m_paletteData;
};
GpDisplayDriverSurface_GL2::GpDisplayDriverSurface_GL2(GpDisplayDriver_SDL_GL2 *driver, size_t width, size_t height, size_t pitch, GpGLTexture *texture, GpPixelFormat_t pixelFormat)
GpDisplayDriverSurface_GL2::GpDisplayDriverSurface_GL2(GpDisplayDriver_SDL_GL2 *driver, size_t width, size_t height, size_t pitch, GpGLTexture *texture, GpPixelFormat_t pixelFormat, IGpDisplayDriver::SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext)
: m_gl(driver->GetGLFunctions())
, m_texture(texture)
, m_pixelFormat(pixelFormat)
@@ -883,6 +907,11 @@ GpDisplayDriverSurface_GL2::GpDisplayDriverSurface_GL2(GpDisplayDriver_SDL_GL2 *
, m_paddedTextureWidth(0)
, m_height(height)
, m_pitch(pitch)
, m_driver(driver)
, m_prev(nullptr)
, m_next(nullptr)
, m_invalidateCallback(invalidateCallback)
, m_invalidateContext(invalidateContext)
{
size_t paddingPixels = 0;
@@ -915,9 +944,15 @@ GpDisplayDriverSurface_GL2::GpDisplayDriverSurface_GL2(GpDisplayDriver_SDL_GL2 *
GpDisplayDriverSurface_GL2::~GpDisplayDriverSurface_GL2()
{
if (m_prev)
m_prev->m_next = m_next;
if (m_next)
m_next->m_prev = m_prev;
m_driver->UnlinkSurface(this, m_prev, m_next);
}
GpDisplayDriverSurface_GL2 *GpDisplayDriverSurface_GL2::Create(GpDisplayDriver_SDL_GL2 *driver, size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat)
GpDisplayDriverSurface_GL2 *GpDisplayDriverSurface_GL2::Create(GpDisplayDriver_SDL_GL2 *driver, size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, GpDisplayDriverSurface_GL2 *prevSurface, IGpDisplayDriver::SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext)
{
GpComPtr<GpGLTexture> texture = GpComPtr<GpGLTexture>(GpGLTexture::Create(driver));
if (!texture)
@@ -927,8 +962,8 @@ GpDisplayDriverSurface_GL2 *GpDisplayDriverSurface_GL2::Create(GpDisplayDriver_S
if (!surface)
return nullptr;
new (surface) GpDisplayDriverSurface_GL2(driver, width, height, pitch, texture, pixelFormat);
if (!surface->Init())
new (surface) GpDisplayDriverSurface_GL2(driver, width, height, pitch, texture, pixelFormat, invalidateCallback, invalidateContext);
if (!surface->Init(prevSurface))
{
surface->Destroy();
return nullptr;
@@ -967,6 +1002,23 @@ void GpDisplayDriverSurface_GL2::Destroy()
free(this);
}
bool GpDisplayDriverSurface_GL2::RecreateAll()
{
for (GpDisplayDriverSurface_GL2 *scan = this; scan; scan = scan->m_next)
{
scan->m_invalidateCallback(scan->m_invalidateContext);
scan->m_texture = nullptr;
}
for (GpDisplayDriverSurface_GL2 *scan = this; scan; scan = scan->m_next)
{
if (!scan->RecreateSingle())
return false;
}
return true;
}
size_t GpDisplayDriverSurface_GL2::GetImageWidth() const
{
return m_imageWidth;
@@ -993,7 +1045,7 @@ GpGLTexture *GpDisplayDriverSurface_GL2::GetTexture() const
}
bool GpDisplayDriverSurface_GL2::Init()
bool GpDisplayDriverSurface_GL2::Init(GpDisplayDriverSurface_GL2 *prevSurface)
{
CheckGLError(*m_gl);
@@ -1011,6 +1063,12 @@ bool GpDisplayDriverSurface_GL2::Init()
return true;
}
bool GpDisplayDriverSurface_GL2::RecreateSingle()
{
m_texture = GpGLTexture::Create(m_driver);
return m_texture != nullptr;
}
GLenum GpDisplayDriverSurface_GL2::ResolveGLFormat() const
{
switch (m_pixelFormat)
@@ -1101,6 +1159,9 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties
, m_iBeamCursor(nullptr)
, m_arrowCursor(nullptr)
, m_cursorIsHidden(false)
, m_contextLost(true)
, m_lastSurface(nullptr)
, m_firstSurface(nullptr)
{
m_bgColor[0] = 0.f;
m_bgColor[1] = 0.f;
@@ -1118,6 +1179,12 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties
m_waitCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT);
m_iBeamCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
m_arrowCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
m_paletteData = m_paletteStorage;
while (reinterpret_cast<uintptr_t>(m_paletteData) % GP_SYSTEM_MEMORY_ALIGNMENT != 0)
m_paletteData++;
memset(m_paletteData, 255, 256 * 4);
}
template<class T>
@@ -1724,7 +1791,45 @@ void GpDisplayDriver_SDL_GL2::Run()
m_vosEvent = m_properties.m_systemServices->CreateThreadEvent(true, false);
m_vosFiber = new GpFiber_SDL(nullptr, m_vosEvent);
m_window = SDL_CreateWindow(GP_APPLICATION_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_windowWidthPhysical, m_windowHeightPhysical, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
if (m_isFullScreenDesired)
{
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
m_isFullScreen = true;
}
else
windowFlags |= SDL_WINDOW_RESIZABLE;
m_window = SDL_CreateWindow(GP_APPLICATION_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_windowWidthPhysical, m_windowHeightPhysical, windowFlags);
if (m_isFullScreen)
{
m_windowModeRevertWidth = m_windowWidthPhysical;
m_windowModeRevertHeight = m_windowHeightPhysical;
int windowWidth = 0;
int windowHeight = 0;
SDL_GetWindowSize(m_window, &windowWidth, &windowHeight);
m_windowWidthPhysical = windowWidth;
m_windowHeightPhysical = windowHeight;
uint32_t desiredWidth = windowWidth;
uint32_t desiredHeight = windowHeight;
uint32_t virtualWidth = m_windowWidthVirtual;
uint32_t virtualHeight = m_windowHeightVirtual;
float pixelScaleX = m_pixelScaleX;
float pixelScaleY = m_pixelScaleY;
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
m_windowWidthVirtual = virtualWidth;
m_windowHeightVirtual = virtualHeight;
m_pixelScaleX = pixelScaleX;
m_pixelScaleY = pixelScaleY;
}
}
const bool obstructiveTextInput = m_properties.m_systemServices->IsTextInputObstructive();
@@ -1736,8 +1841,6 @@ void GpDisplayDriver_SDL_GL2::Run()
if (!m_gl.LookUpFunctions())
return;
InitResources(m_windowWidthVirtual, m_windowHeightVirtual);
for (;;)
{
SDL_Event msg;
@@ -1750,8 +1853,11 @@ void GpDisplayDriver_SDL_GL2::Run()
}
//else if (msg.type == SDL_MOUSELEAVE) // Does SDL support this??
// m_mouseIsInClientArea = false;
else if (msg.type == SDL_RENDER_DEVICE_RESET || msg.type == SDL_RENDER_TARGETS_RESET)
m_contextLost = true;
TranslateSDLMessage(&msg, m_properties.m_eventQueue, m_pixelScaleX, m_pixelScaleY, obstructiveTextInput);
}
else
{
@@ -1761,6 +1867,9 @@ void GpDisplayDriver_SDL_GL2::Run()
BecomeFullScreen();
else
BecomeWindowed();
m_contextLost = true;
continue;
}
int clientWidth = 0;
@@ -1784,7 +1893,6 @@ void GpDisplayDriver_SDL_GL2::Run()
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
bool resizedOK = ResizeOpenGLWindow(m_windowWidthPhysical, m_windowHeightPhysical, desiredWidth, desiredHeight, logger);
resizedOK = resizedOK && InitBackBuffer(virtualWidth, virtualHeight);
if (!resizedOK)
break; // Critical video driver error, exit
@@ -1803,9 +1911,30 @@ void GpDisplayDriver_SDL_GL2::Run()
resizeEvent->m_event.m_resolutionChangedEvent.m_newWidth = m_windowWidthVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_newHeight = m_windowHeightVirtual;
}
m_contextLost = true;
continue;
}
}
if (m_contextLost)
{
// Drop everything and reset
m_res.~InstancedResources();
new (&m_res) InstancedResources();
if (m_firstSurface)
m_firstSurface->RecreateAll();
if (!InitBackBuffer(m_windowWidthVirtual, m_windowHeightVirtual))
break;
InitResources(m_windowWidthVirtual, m_windowHeightVirtual);
m_contextLost = false;
continue;
}
GpDisplayDriverTickStatus_t tickStatus = PresentFrameAndSync();
if (tickStatus == GpDisplayDriverTickStatuses::kFatalFault || tickStatus == GpDisplayDriverTickStatuses::kApplicationTerminated)
break;
@@ -1830,9 +1959,16 @@ void GpDisplayDriver_SDL_GL2::GetDisplayResolution(unsigned int *width, unsigned
*height = m_windowHeightVirtual;
}
IGpDisplayDriverSurface *GpDisplayDriver_SDL_GL2::CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat)
IGpDisplayDriverSurface *GpDisplayDriver_SDL_GL2::CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext)
{
return GpDisplayDriverSurface_GL2::Create(this, width, height, pitch, pixelFormat);
GpDisplayDriverSurface_GL2 *surface = GpDisplayDriverSurface_GL2::Create(this, width, height, pitch, pixelFormat, m_lastSurface, invalidateCallback, invalidateContext);
if (surface)
{
m_lastSurface = surface;
if (m_firstSurface == nullptr)
m_firstSurface = surface;
}
return surface;
}
void GpDisplayDriver_SDL_GL2::DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height, const GpDisplayDriverSurfaceEffects *effects)
@@ -1840,7 +1976,7 @@ void GpDisplayDriver_SDL_GL2::DrawSurface(IGpDisplayDriverSurface *surface, int3
if (!effects)
effects = &gs_defaultEffects;
GpGLVertexArray *vaPtr = m_quadVertexArray;
GpGLVertexArray *vaPtr = m_res.m_quadVertexArray;
size_t vbStride = sizeof(float) * 2;
size_t zero = 0;
@@ -1854,16 +1990,16 @@ void GpDisplayDriver_SDL_GL2::DrawSurface(IGpDisplayDriverSurface *surface, int3
if (m_useICCProfile)
{
if (effects->m_flicker)
program = &m_drawQuadPaletteICCFlickerProgram;
program = &m_res.m_drawQuadPaletteICCFlickerProgram;
else
program = &m_drawQuadPaletteICCNoFlickerProgram;
program = &m_res.m_drawQuadPaletteICCNoFlickerProgram;
}
else
{
if (effects->m_flicker)
program = &m_drawQuadPaletteFlickerProgram;
program = &m_res.m_drawQuadPaletteFlickerProgram;
else
program = &m_drawQuadPaletteNoFlickerProgram;
program = &m_res.m_drawQuadPaletteNoFlickerProgram;
}
}
else if (pixelFormat == GpPixelFormats::kRGB555)
@@ -1937,7 +2073,7 @@ void GpDisplayDriver_SDL_GL2::DrawSurface(IGpDisplayDriverSurface *surface, int3
GLint vpos[1] = { program->m_vertexPosUVLocation };
m_quadVertexArray->Activate(vpos);
m_res.m_quadVertexArray->Activate(vpos);
m_gl.ActiveTexture(GL_TEXTURE0);
m_gl.BindTexture(GL_TEXTURE_2D, glSurface->GetTexture()->GetID());
@@ -1946,11 +2082,11 @@ void GpDisplayDriver_SDL_GL2::DrawSurface(IGpDisplayDriverSurface *surface, int3
if (pixelFormat == GpPixelFormats::k8BitStandard || pixelFormat == GpPixelFormats::k8BitCustom)
{
m_gl.ActiveTexture(GL_TEXTURE1);
m_gl.BindTexture(GL_TEXTURE_2D, m_paletteTexture->GetID());
m_gl.BindTexture(GL_TEXTURE_2D, m_res.m_paletteTexture->GetID());
m_gl.Uniform1i(program->m_pixelPaletteTextureLocation, 1);
}
m_gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_quadIndexBuffer->GetID());
m_gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_res.m_quadIndexBuffer->GetID());
m_gl.DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
m_gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -1965,7 +2101,7 @@ void GpDisplayDriver_SDL_GL2::DrawSurface(IGpDisplayDriverSurface *surface, int3
m_gl.ActiveTexture(GL_TEXTURE0);
m_gl.BindTexture(GL_TEXTURE_2D, 0);
m_quadVertexArray->Deactivate(vpos);
m_res.m_quadVertexArray->Deactivate(vpos);
m_gl.UseProgram(0);
@@ -2032,8 +2168,11 @@ void GpDisplayDriver_SDL_GL2::SetStandardCursor(EGpStandardCursor_t standardCurs
void GpDisplayDriver_SDL_GL2::UpdatePalette(const void *paletteData)
{
m_gl.BindTexture(GL_TEXTURE_2D, m_paletteTexture->GetID());
m_gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, paletteData);
memcpy(m_paletteData, paletteData, 256 * 4);
m_gl.BindTexture(GL_TEXTURE_2D, m_res.m_paletteTexture->GetID());
m_gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
m_gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_paletteData);
m_gl.BindTexture(GL_TEXTURE_2D, 0);
}
@@ -2093,6 +2232,15 @@ bool GpDisplayDriver_SDL_GL2::SavePrefs(void *context, WritePrefsFunc_t writeFun
return true;
}
void GpDisplayDriver_SDL_GL2::UnlinkSurface(GpDisplayDriverSurface_GL2 *surface, GpDisplayDriverSurface_GL2 *prev, GpDisplayDriverSurface_GL2 *next)
{
if (m_lastSurface == surface)
m_lastSurface = prev;
if (m_firstSurface == surface)
m_firstSurface = next;
}
const GpGLFunctions *GpDisplayDriver_SDL_GL2::GetGLFunctions() const
{
return &m_gl;
@@ -2154,8 +2302,8 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t virtualWidth, uint32_t virt
{
const uint16_t indexBufferData[] = { 0, 1, 2, 1, 3, 2 };
m_quadIndexBuffer = GpGLBuffer::Create(this);
if (!m_quadIndexBuffer)
m_res.m_quadIndexBuffer = GpGLBuffer::Create(this);
if (!m_res.m_quadIndexBuffer)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriver_SDL_GL2::InitResources: CreateBuffer for draw quad index buffer failed");
@@ -2163,7 +2311,7 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t virtualWidth, uint32_t virt
return false;
}
m_gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_quadIndexBuffer->GetID());
m_gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_res.m_quadIndexBuffer->GetID());
m_gl.BufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexBufferData), indexBufferData, GL_STATIC_DRAW);
m_gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
@@ -2178,8 +2326,8 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t virtualWidth, uint32_t virt
1.f, 1.f,
};
m_quadVertexBufferKeepalive = GpGLBuffer::Create(this);
if (!m_quadVertexBufferKeepalive)
m_res.m_quadVertexBufferKeepalive = GpGLBuffer::Create(this);
if (!m_res.m_quadVertexBufferKeepalive)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriver_SDL_GL2::InitResources: GpGLBuffer::Create for draw quad vertex buffer failed");
@@ -2187,12 +2335,12 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t virtualWidth, uint32_t virt
return false;
}
m_gl.BindBuffer(GL_ARRAY_BUFFER, m_quadVertexBufferKeepalive->GetID());
m_gl.BindBuffer(GL_ARRAY_BUFFER, m_res.m_quadVertexBufferKeepalive->GetID());
m_gl.BufferData(GL_ARRAY_BUFFER, sizeof(vertexBufferData), vertexBufferData, GL_STATIC_DRAW);
m_gl.BindBuffer(GL_ARRAY_BUFFER, 0);
m_quadVertexArray = GpGLVertexArray::Create(this);
if (!m_quadVertexBufferKeepalive)
m_res.m_quadVertexArray = GpGLVertexArray::Create(this);
if (!m_res.m_quadVertexBufferKeepalive)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriver_SDL_GL2::InitResources: GpGLVertexArray::Create for draw quad vertex buffer failed");
@@ -2202,7 +2350,7 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t virtualWidth, uint32_t virt
GpGLVertexArraySpec specs[] =
{
m_quadVertexBufferKeepalive,
m_res.m_quadVertexBufferKeepalive,
0, // index
2, // size
GL_FLOAT, // type
@@ -2211,7 +2359,7 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t virtualWidth, uint32_t virt
0
};
if (!m_quadVertexArray->InitWithSpecs(specs, sizeof(specs) / sizeof(specs[0])))
if (!m_res.m_quadVertexArray->InitWithSpecs(specs, sizeof(specs) / sizeof(specs[0])))
{
if (logger)
logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriver_SDL_GL2::InitResources: InitWithSpecs for draw quad vertex buffer failed");
@@ -2232,31 +2380,22 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t virtualWidth, uint32_t virt
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> scaleQuadPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_scaleQuadP_GL2);
GpComPtr<GpGLShader<GL_FRAGMENT_SHADER>> copyQuadPixelShader = CreateShader<GL_FRAGMENT_SHADER>(GpBinarizedShaders::g_copyQuadP_GL2);
if (!m_drawQuadPaletteFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteFlickerPixelShader)
|| !m_drawQuadPaletteNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteFlickerPixelShader)
if (!m_res.m_drawQuadPaletteFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteFlickerPixelShader)
|| !m_res.m_drawQuadPaletteNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteFlickerPixelShader)
//|| !m_drawQuadRGBProgram.Link(this, drawQuadVertexShader, drawQuadRGBPixelShader)
//|| !m_drawQuad15BitProgram.Link(this, drawQuadVertexShader, drawQuad15BitPixelShader)
|| !m_drawQuadPaletteICCFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteICCFPixelShader)
|| !m_drawQuadPaletteICCNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteICCNFPixelShader)
|| !m_res.m_drawQuadPaletteICCFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteICCFPixelShader)
|| !m_res.m_drawQuadPaletteICCNoFlickerProgram.Link(this, drawQuadVertexShader, drawQuadPaletteICCNFPixelShader)
//|| !m_drawQuadRGBICCProgram.Link(this, drawQuadVertexShader, drawQuadRGBICCPixelShader)
//|| !m_drawQuad15BitICCProgram.Link(this, drawQuadVertexShader, drawQuad15BitICCPixelShader)
|| !m_scaleQuadProgram.Link(this, drawQuadVertexShader, scaleQuadPixelShader)
|| !m_copyQuadProgram.Link(this, drawQuadVertexShader, copyQuadPixelShader))
|| !m_res.m_scaleQuadProgram.Link(this, drawQuadVertexShader, scaleQuadPixelShader)
|| !m_res.m_copyQuadProgram.Link(this, drawQuadVertexShader, copyQuadPixelShader))
return false;
// Palette texture
{
uint8_t initialDataBytes[256][4];
for (int i = 0; i < 256; i++)
{
for (int ch = 0; ch < 4; ch++)
initialDataBytes[i][ch] = 255;
}
m_paletteTexture = GpGLTexture::Create(this);
if (!m_paletteTexture)
m_res.m_paletteTexture = GpGLTexture::Create(this);
if (!m_res.m_paletteTexture)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriver_SDL_GL2::InitResources: GpGLTexture::Create failed");
@@ -2264,9 +2403,9 @@ bool GpDisplayDriver_SDL_GL2::InitResources(uint32_t virtualWidth, uint32_t virt
return false;
}
m_gl.BindTexture(GL_TEXTURE_2D, m_paletteTexture->GetID());
m_gl.BindTexture(GL_TEXTURE_2D, m_res.m_paletteTexture->GetID());
m_gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
m_gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, initialDataBytes);
m_gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_paletteData);
m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -2387,14 +2526,10 @@ bool GpDisplayDriver_SDL_GL2::ResizeOpenGLWindow(uint32_t &windowWidth, uint32_t
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "ResizeOpenGLWindow: %i x %i", static_cast<int>(desiredWidth), static_cast<int>(desiredHeight));
if (desiredWidth < 640)
desiredWidth = 640;
else if (desiredWidth > 32768)
if (desiredWidth > 32768)
desiredWidth = 32768;
if (desiredHeight < 480)
desiredHeight = 480;
else if (desiredHeight > 32768)
if (desiredHeight > 32768)
desiredHeight = 32768;
if (logger)
@@ -2416,8 +2551,8 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height)
logger->Printf(IGpLogDriver::Category_Information, "GpDisplayDriver_SDL_GL2::InitBackBuffer");
{
m_virtualScreenTexture = GpGLTexture::Create(this);
if (!m_virtualScreenTexture)
m_res.m_virtualScreenTexture = GpGLTexture::Create(this);
if (!m_res.m_virtualScreenTexture)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriver_SDL_GL2::InitBackBuffer: GpGLTexture::Create for virtual screen texture failed");
@@ -2425,7 +2560,7 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height)
return false;
}
m_gl.BindTexture(GL_TEXTURE_2D, m_virtualScreenTexture->GetID());
m_gl.BindTexture(GL_TEXTURE_2D, m_res.m_virtualScreenTexture->GetID());
m_gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -2436,9 +2571,9 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height)
}
{
m_virtualScreenTextureRTV = GpGLRenderTargetView::Create(this);
m_res.m_virtualScreenTextureRTV = GpGLRenderTargetView::Create(this);
if (!m_virtualScreenTextureRTV)
if (!m_res.m_virtualScreenTextureRTV)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Error, "GpDisplayDriver_SDL_GL2::InitBackBuffer: GpGLRenderTargetView::Create for virtual screen texture failed");
@@ -2446,8 +2581,8 @@ bool GpDisplayDriver_SDL_GL2::InitBackBuffer(uint32_t width, uint32_t height)
return false;
}
m_gl.BindFramebuffer(GL_FRAMEBUFFER, m_virtualScreenTextureRTV->GetID());
m_gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_virtualScreenTexture->GetID(), 0);
m_gl.BindFramebuffer(GL_FRAMEBUFFER, m_res.m_virtualScreenTextureRTV->GetID());
m_gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_res.m_virtualScreenTexture->GetID(), 0);
GLenum status = m_gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
@@ -2471,7 +2606,7 @@ void GpDisplayDriver_SDL_GL2::ScaleVirtualScreen()
const bool isIntegralScale = (m_pixelScaleX == floor(m_pixelScaleX) && m_pixelScaleY == floor(m_pixelScaleY));
const BlitQuadProgram &program = isIntegralScale ? m_copyQuadProgram : m_scaleQuadProgram;
const BlitQuadProgram &program = isIntegralScale ? m_res.m_copyQuadProgram : m_res.m_scaleQuadProgram;
{
const float twoDivWidth = 2.0f / static_cast<float>(m_windowWidthPhysical);
@@ -2514,13 +2649,13 @@ void GpDisplayDriver_SDL_GL2::ScaleVirtualScreen()
GLint attribLocations[] = { program.m_vertexPosUVLocation };
m_quadVertexArray->Activate(attribLocations);
m_res.m_quadVertexArray->Activate(attribLocations);
m_gl.ActiveTexture(GL_TEXTURE0 + 0);
m_gl.BindTexture(GL_TEXTURE_2D, m_virtualScreenTexture->GetID());
m_gl.BindTexture(GL_TEXTURE_2D, m_res.m_virtualScreenTexture->GetID());
m_gl.Uniform1i(program.m_pixelSurfaceTextureLocation, 0);
m_gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_quadIndexBuffer->GetID());
m_gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_res.m_quadIndexBuffer->GetID());
m_gl.DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
m_gl.UseProgram(0);
@@ -2528,7 +2663,7 @@ void GpDisplayDriver_SDL_GL2::ScaleVirtualScreen()
m_gl.ActiveTexture(GL_TEXTURE0 + 0);
m_gl.BindTexture(GL_TEXTURE_2D, 0);
m_quadVertexArray->Deactivate(attribLocations);
m_res.m_quadVertexArray->Deactivate(attribLocations);
m_gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
@@ -2631,7 +2766,7 @@ GpDisplayDriverTickStatus_t GpDisplayDriver_SDL_GL2::PresentFrameAndSync()
}
//ID3D11RenderTargetView *const rtv = m_backBufferRTV;
GpGLRenderTargetView *const vsRTV = m_virtualScreenTextureRTV;
GpGLRenderTargetView *const vsRTV = m_res.m_virtualScreenTextureRTV;
m_gl.BindFramebuffer(GL_FRAMEBUFFER, vsRTV->GetID());

View File

@@ -326,25 +326,24 @@ public:
void AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualHeight, float &pixelScaleX, float &pixelScaleY) override
{
if (physicalWidth < 640)
physicalWidth = 640;
if (physicalHeight < 480)
physicalHeight = 480;
double minMul = 1.0;
if (isAutoScale)
if (isAutoScale || physicalWidth < 640 && physicalHeight < 480)
{
double xMul = static_cast<double>(physicalWidth) / 640.0;
double yMul = static_cast<double>(physicalHeight) / 480.0;
double granularity = 2.0;
minMul = std::min(xMul, yMul);
xMul = floor(xMul * granularity) / granularity;
yMul = floor(yMul * granularity) / granularity;
if (minMul >= 1.0)
{
double granularity = 2.0;
minMul = std::max<double>(1.0, std::min(xMul, yMul));
xMul = floor(xMul * granularity) / granularity;
yMul = floor(yMul * granularity) / granularity;
minMul = std::min(xMul, yMul);
}
}
virtualWidth = physicalWidth / minMul;

View File

@@ -13,11 +13,14 @@
#include "WindowManager.h"
int gpAppMain();
void gpAppInit();
class GpAppInterfaceImpl final : public GpAppInterface
{
public:
void ApplicationInit() override;
int ApplicationMain() override;
void PL_IncrementTickCounter(uint32_t count) override;
void PL_Render(IGpDisplayDriver *displayDriver) override;
void PL_HostFileSystem_SetInstance(PortabilityLayer::HostFileSystem *instance) override;
@@ -32,6 +35,10 @@ public:
bool PL_AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY) override;
};
void GpAppInterfaceImpl::ApplicationInit()
{
gpAppInit();
}
int GpAppInterfaceImpl::ApplicationMain()
{

View File

@@ -19,6 +19,7 @@
#include "IGpDisplayDriver.h"
#include "GpIOStream.h"
#include "House.h"
#include "MenuManager.h"
#include "RenderedFont.h"
#include "ResolveCachingColor.h"
#include "WindowManager.h"
@@ -425,6 +426,12 @@ void PreloadFonts()
StepLoadScreen(1);
}
void gpAppInit()
{
// This is called before the display driver is initialized
InstallResolutionHandler();
}
//-------------------------------------------------------------- main
// Here is main(). The first function called when Glider PRO comes up.
@@ -439,7 +446,9 @@ int gpAppMain()
ToolBoxInit();
CheckOurEnvirons();
InstallResolutionHandler();
if (thisMac.isTouchscreen)
PortabilityLayer::MenuManager::GetInstance()->SetMenuTouchScreenStyle(true);
if (!thisMac.hasColor)
RedAlert(kErrNeedColorQD);

View File

@@ -224,7 +224,10 @@ void OpenMainWindow (void)
mainWindowRect.bottom - mainWindowRect.top, false);
const short mainWindowLeft = (thisMac.fullScreen.left + thisMac.fullScreen.right + thisMac.constrainedScreen.left - thisMac.constrainedScreen.right) / 2;
const short mainWindowTop = (thisMac.fullScreen.top + thisMac.fullScreen.bottom + thisMac.constrainedScreen.top - thisMac.constrainedScreen.bottom) / 2 + kScoreboardTall;
short mainWindowTop = (thisMac.fullScreen.top + thisMac.fullScreen.bottom + thisMac.constrainedScreen.top - thisMac.constrainedScreen.bottom) / 2;
if (!PortabilityLayer::MenuManager::GetInstance()->IsMenuTouchScreenStyle())
mainWindowTop += kScoreboardTall;
MoveWindow(boardWindow, mainWindowLeft, 0, true);
MoveWindow(mainWindow, mainWindowLeft, mainWindowTop, true); // thisMac.menuHigh

View File

@@ -711,7 +711,7 @@ bool ExportSourceToStream (GpIOStream *stream)
void DoExportSourceCode (void)
{
GpIOStream *stream = PortabilityLayer::HostFileSystem::GetInstance()->OpenFile(PortabilityLayer::VirtualDirectories::kPrefs, "SourceExport.zip", true, GpFileCreationDispositions::kCreateOrOverwrite);
GpIOStream *stream = PortabilityLayer::HostFileSystem::GetInstance()->OpenFile(PortabilityLayer::VirtualDirectories::kSourceExport, "SourceExport.zip", true, GpFileCreationDispositions::kCreateOrOverwrite);
if (!stream)
return;

View File

@@ -26,13 +26,14 @@ struct GpDisplayDriverSurfaceEffects
// Display drivers are responsible for timing and calling the game tick function.
struct IGpDisplayDriver
{
public:
typedef void (*SurfaceInvalidateCallback_t) (void *context);
virtual void Run() = 0;
virtual void Shutdown() = 0;
virtual void GetDisplayResolution(unsigned int *width, unsigned int *height) = 0;
virtual IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat) = 0;
virtual IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext) = 0;
virtual void DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height, const GpDisplayDriverSurfaceEffects *effects) = 0;
virtual IGpCursor *CreateBWCursor(size_t width, size_t height, const void *pixelData, const void *maskData, size_t hotSpotX, size_t hotSpotY) = 0;

View File

@@ -0,0 +1,8 @@
#pragma once
struct IGpThreadRelay
{
typedef void (*Callback_t) (void *context);
virtual void Invoke(Callback_t callback, void *context) const = 0;
};

View File

@@ -1248,7 +1248,7 @@ void GpDisplayDriverD3D11::GetDisplayResolution(unsigned int *width, unsigned in
*height = m_windowHeightVirtual;
}
IGpDisplayDriverSurface *GpDisplayDriverD3D11::CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat)
IGpDisplayDriverSurface *GpDisplayDriverD3D11::CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, IGpDisplayDriver::SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext)
{
return GpDisplayDriverSurfaceD3D11::Create(m_device, m_deviceContext, width, height, pixelFormat);
}

View File

@@ -41,7 +41,7 @@ public:
void GetDisplayResolution(unsigned int *width, unsigned int *height) override;
IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat) override;
IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, IGpDisplayDriver::SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext) override;
void DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height, const GpDisplayDriverSurfaceEffects *effects) override;
IGpCursor *CreateColorCursor(size_t width, size_t height, const void *pixelDataRGBA, size_t hotSpotX, size_t hotSpotY) override;

View File

@@ -34,6 +34,7 @@ GpAppEnvironment::~GpAppEnvironment()
void GpAppEnvironment::Init()
{
GpAppInterface_Get()->ApplicationInit();
}
GpDisplayDriverTickStatus_t GpAppEnvironment::Tick(IGpFiber *vosFiber)
@@ -196,7 +197,7 @@ void GpAppEnvironment::DispatchSystemCall(PortabilityLayer::HostSuspendCallID ca
m_delaySuspendTicks = 1;
break;
case PortabilityLayer::HostSuspendCallID_CallOnVOSThread:
args[0].m_functionPtr(static_cast<const PortabilityLayer::HostSuspendCallArgument*>(args[1].m_constPointer), static_cast<PortabilityLayer::HostSuspendCallArgument*>(args[2].m_pointer));
args[0].m_functionPtr(args[1].m_pointer);
m_applicationState = ApplicationState_Running;
break;
default:

View File

@@ -1,18 +1,18 @@
#pragma once
#ifndef __PL_BINHEX4_H__
#pragma once
#ifndef __PL_BINHEX4_H__
#define __PL_BINHEX4_H__
class GpIOStream;
namespace PortabilityLayer
{
class MacFileMem;
namespace BinHex4
{
MacFileMem *LoadHQX(GpIOStream *stream);
};
}
#endif
class GpIOStream;
namespace PortabilityLayer
{
class MacFileMem;
namespace BinHex4
{
MacFileMem *LoadHQX(GpIOStream *stream);
};
}
#endif

View File

@@ -37,6 +37,7 @@ struct IGpDisplayDriver;
class GpAppInterface
{
public:
virtual void ApplicationInit() = 0;
virtual int ApplicationMain() = 0;
virtual void PL_IncrementTickCounter(uint32_t count) = 0;
virtual void PL_Render(IGpDisplayDriver *displayDriver) = 0;

View File

@@ -6,6 +6,7 @@
#include <stdint.h>
class GpIOStream;
struct IGpThreadRelay;
namespace PortabilityLayer
{
@@ -31,6 +32,8 @@ namespace PortabilityLayer
GpIOStream *OpenFile(VirtualDirectory_t virtualDirectory, const char *path, bool writeAccess, GpFileCreationDisposition_t createDisposition);
virtual void SetMainThreadRelay(IGpThreadRelay *relay) = 0;
private:
static HostFileSystem *ms_instance;
};

View File

@@ -13,6 +13,6 @@ namespace PortabilityLayer
size_t m_size;
void *m_pointer;
const void *m_constPointer;
void (*m_functionPtr)(const HostSuspendCallArgument *args, HostSuspendCallArgument *returnValue);
void (*m_functionPtr)(void *context);
};
}

View File

@@ -1,17 +1,17 @@
#pragma once
#ifndef __PL_HOST_API_CALL_ID_H__
#define __PL_HOST_API_CALL_ID_H__
namespace PortabilityLayer
{
enum HostSuspendCallID
{
HostSuspendCallID_Unknown,
HostSuspendCallID_Delay,
#pragma once
#ifndef __PL_HOST_API_CALL_ID_H__
#define __PL_HOST_API_CALL_ID_H__
namespace PortabilityLayer
{
enum HostSuspendCallID
{
HostSuspendCallID_Unknown,
HostSuspendCallID_Delay,
HostSuspendCallID_CallOnVOSThread,
HostSuspendCallID_ForceSyncFrame
};
}
#endif
HostSuspendCallID_ForceSyncFrame
};
}
#endif

View File

@@ -159,6 +159,9 @@ namespace PortabilityLayer
void RenderFrame(IGpDisplayDriver *displayDriver) override;
void SetMenuTouchScreenStyle(bool isTouchScreen) override;
bool IsMenuTouchScreenStyle() const override;
static MenuManagerImpl *GetInstance();
private:
@@ -199,13 +202,18 @@ namespace PortabilityLayer
void ProcessMouseMoveToMenuBar(const Vec2i &point);
void ProcessMouseMoveToMenu(const Vec2i &point);
bool IsYInMenuBarRange(int32_t y) const;
static bool ItemIsSeparator(const Menu &menu, const MenuItem &item);
static const unsigned int kIconResID = 128;
static const unsigned int kMenuFontSize = 12;
static const unsigned int kTouchScreenMenuFontSize = 24;
static const unsigned int kMenuBarIconYOffset = 2;
static const unsigned int kMenuBarTextYOffset = 14;
static const unsigned int kTouchScreenMenuBarTextYOffset = 26;
static const unsigned int kMenuBarHeight = 20;
static const unsigned int kTouchscreenMenuBarHeight = 38;
static const unsigned int kMenuBarItemPadding = 6;
static const unsigned int kMenuBarInitialPadding = 16;
@@ -223,6 +231,7 @@ namespace PortabilityLayer
static const unsigned int kMenuItemLeftPadding = 16 + 2 + 2; // 2 for left border, 16 for icon, 2 for spacing
static const int kMenuFontFlags = PortabilityLayer::FontFamilyFlag_Bold;
static const int kTouchScreenMenuFontFlags = PortabilityLayer::FontFamilyFlag_None;
DrawSurface *m_menuBarGraf;
@@ -231,6 +240,7 @@ namespace PortabilityLayer
bool m_haveMenuBarLayout;
bool m_haveIcon;
bool m_menuBarVisible;
bool m_isTouchScreen;
uint8_t m_iconColors[16 * 16];
uint8_t m_iconMask[32];
@@ -252,6 +262,7 @@ namespace PortabilityLayer
, m_haveIcon(false)
, m_iconGraphic(nullptr)
, m_menuBarVisible(false)
, m_isTouchScreen(false)
{
}
@@ -634,7 +645,7 @@ namespace PortabilityLayer
bool MenuManagerImpl::IsPointInMenuBar(const Vec2i &point) const
{
return point.m_y >= 0 && static_cast<uint32_t>(point.m_y) < kMenuBarHeight;
return IsYInMenuBarRange(point.m_y);
}
uint16_t MenuManagerImpl::GetMenuBarHeight() const
@@ -829,7 +840,9 @@ namespace PortabilityLayer
PortabilityLayer::QDManager *qdManager = PortabilityLayer::QDManager::GetInstance();
const Rect menuRect = Rect::Create(0, 0, kMenuBarHeight, width);
const int16_t menuHeight = m_isTouchScreen ? kTouchscreenMenuBarHeight : kMenuBarHeight;
const Rect menuRect = Rect::Create(0, 0, menuHeight, width);
if (m_menuBarGraf == nullptr)
{
@@ -863,7 +876,7 @@ namespace PortabilityLayer
// Left stripe
{
const Rect rect = Rect::Create(0, 0, kMenuBarHeight - 1, 1);
const Rect rect = Rect::Create(0, 0, menuHeight - 1, 1);
m_menuBarGraf->FillRect(rect, barBrightColor);
}
@@ -871,13 +884,13 @@ namespace PortabilityLayer
// Bottom stripe
{
const Rect rect = Rect::Create(kMenuBarHeight - 2, 1, kMenuBarHeight - 1, width);
const Rect rect = Rect::Create(menuHeight - 2, 1, menuHeight - 1, width);
m_menuBarGraf->FillRect(rect, barDarkColor);
}
// Right stripe
{
const Rect rect = Rect::Create(0, width - 1, kMenuBarHeight - 1, width);
const Rect rect = Rect::Create(0, width - 1, menuHeight - 1, width);
m_menuBarGraf->FillRect(rect, barDarkColor);
}
@@ -885,7 +898,7 @@ namespace PortabilityLayer
// Bottom edge
{
const Rect rect = Rect::Create(kMenuBarHeight - 1, 0, kMenuBarHeight, width);
const Rect rect = Rect::Create(menuHeight - 1, 0, menuHeight, width);
m_menuBarGraf->FillRect(rect, barBottomEdgeColor);
}
@@ -917,20 +930,31 @@ namespace PortabilityLayer
// Middle
{
ResolveCachingColor barHighlightMidColor = gs_barHighlightMidColor;
const Rect rect = Rect::Create(1, left, kMenuBarHeight - 2, right);
const Rect rect = Rect::Create(1, left, menuHeight - 2, right);
m_menuBarGraf->FillRect(rect, barHighlightMidColor);
}
{
ResolveCachingColor barHighlightDarkColor = gs_barHighlightDarkColor;
const Rect rect = Rect::Create(kMenuBarHeight - 2, left, kMenuBarHeight - 1, right);
const Rect rect = Rect::Create(menuHeight - 2, left, menuHeight - 1, right);
m_menuBarGraf->FillRect(rect, barHighlightDarkColor);
}
}
// Text items
ResolveCachingColor barNormalTextColor = gs_barNormalTextColor;
PortabilityLayer::RenderedFont *sysFont = GetSystemFont(kMenuFontSize, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *sysFont = nullptr;
unsigned int textYOffset = 0;
if (m_isTouchScreen)
{
sysFont = GetApplicationFont(kTouchScreenMenuFontSize, kTouchScreenMenuFontFlags, true);
textYOffset = kTouchScreenMenuBarTextYOffset;
}
else
{
sysFont = GetSystemFont(kMenuFontSize, kMenuFontFlags, true);
textYOffset = kMenuBarTextYOffset;
}
{
Menu **menuHdl = m_firstMenu;
@@ -951,7 +975,7 @@ namespace PortabilityLayer
{
if (menuHdl != selectedMenuHdl)
{
const Point itemPos = Point::Create(static_cast<int16_t>(xCoordinate), kMenuBarTextYOffset);
const Point itemPos = Point::Create(static_cast<int16_t>(xCoordinate), textYOffset);
graf->DrawString(itemPos, PLPasStr(static_cast<const uint8_t*>(menu->stringBlobHandle->m_contents)), barNormalTextColor, sysFont);
}
}
@@ -971,7 +995,7 @@ namespace PortabilityLayer
size_t xCoordinate = menu->cumulativeOffset + (menu->menuIndex * 2) * kMenuBarItemPadding + kMenuBarInitialPadding;
const Point itemPos = Point::Create(static_cast<int16_t>(xCoordinate), kMenuBarTextYOffset);
const Point itemPos = Point::Create(static_cast<int16_t>(xCoordinate), textYOffset);
graf->DrawString(itemPos, PLPasStr(static_cast<const uint8_t*>(menu->stringBlobHandle->m_contents)), barHighlightTextColor, sysFont);
}
}
@@ -1001,7 +1025,16 @@ namespace PortabilityLayer
const PixMap *pixMap = *m_menuBarGraf->m_port.GetPixMap();
const size_t width = pixMap->m_rect.right - pixMap->m_rect.left;
const size_t height = pixMap->m_rect.bottom - pixMap->m_rect.top;
displayDriver->DrawSurface(m_menuBarGraf->m_ddSurface, 0, 0, width, height, nullptr);
int32_t y = 0;
if (m_isTouchScreen)
{
unsigned int displayHeight = 0;
displayDriver->GetDisplayResolution(nullptr, &displayHeight);
y = static_cast<int32_t>(displayHeight) - kTouchscreenMenuBarHeight;
}
displayDriver->DrawSurface(m_menuBarGraf->m_ddSurface, 0, y, width, height, nullptr);
}
}
@@ -1030,6 +1063,16 @@ namespace PortabilityLayer
}
}
void MenuManagerImpl::SetMenuTouchScreenStyle(bool isTouchScreenStyle)
{
m_isTouchScreen = isTouchScreenStyle;
}
bool MenuManagerImpl::IsMenuTouchScreenStyle() const
{
return m_isTouchScreen;
}
void MenuManagerImpl::RefreshMenuBarLayout()
{
if (m_haveMenuBarLayout)
@@ -1037,11 +1080,29 @@ namespace PortabilityLayer
PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance();
PortabilityLayer::FontFamily *fontFamily = PortabilityLayer::FontManager::GetInstance()->GetSystemFont(kMenuFontSize, kMenuFontFlags);
PortabilityLayer::FontFamily *fontFamily = nullptr;
unsigned int fontSize = 0;
unsigned int fontFlags = 0;
if (m_isTouchScreen)
{
fontSize = kTouchScreenMenuFontSize;
fontFlags = PortabilityLayer::FontFamilyFlag_None;
fontFamily = PortabilityLayer::FontManager::GetInstance()->GetApplicationFont(kTouchScreenMenuFontSize, PortabilityLayer::FontFamilyFlag_None);
}
else
{
fontSize = kMenuFontSize;
fontFlags = kMenuFontFlags;
fontFamily = PortabilityLayer::FontManager::GetInstance()->GetSystemFont(kMenuFontSize, kMenuFontFlags);
}
if (!fontFamily)
return;
PortabilityLayer::RenderedFont *rfont = PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, kMenuFontSize, true, kMenuFontFlags);
PortabilityLayer::RenderedFont *rfont = PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, fontSize, true, fontFlags);
if (!rfont)
return;
@@ -1137,7 +1198,7 @@ namespace PortabilityLayer
if (point.m_y < 0)
return;
if (!m_menuSelectionState.IsPopup() && point.m_y < static_cast<int>(kMenuBarHeight))
if (!m_menuSelectionState.IsPopup() && IsYInMenuBarRange(point.m_y))
{
m_menuSelectionState.ClearSelection();
ProcessMouseMoveToMenuBar(point);
@@ -1235,6 +1296,18 @@ namespace PortabilityLayer
m_menuSelectionState.ClearSelection();
}
bool MenuManagerImpl::IsYInMenuBarRange(int32_t y) const
{
if (m_isTouchScreen)
{
unsigned int displayHeight = 0;
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(nullptr, &displayHeight);
return y >= (static_cast<int32_t>(displayHeight - kTouchscreenMenuBarHeight)) && y < static_cast<int32_t>(displayHeight);
}
else
return y >= 0 && y < static_cast<int32_t>(kMenuBarHeight);
}
bool MenuManagerImpl::ItemIsSeparator(const Menu &menu, const MenuItem &item)
{
const uint8_t *strBlob = static_cast<const uint8_t*>(menu.stringBlobHandle->m_contents);

View File

@@ -54,6 +54,9 @@ namespace PortabilityLayer
virtual void RenderFrame(IGpDisplayDriver *displayDriver) = 0;
virtual void SetMenuTouchScreenStyle(bool isTouchScreenStyle) = 0;
virtual bool IsMenuTouchScreenStyle() const = 0;
static MenuManager *GetInstance();
};
}

View File

@@ -21,6 +21,7 @@
#include "HostVOSEventQueue.h"
#include "IGpCursor.h"
#include "IGpDisplayDriver.h"
#include "IGpThreadRelay.h"
#include "InputManager.h"
#include "ResourceManager.h"
#include "MacFileInfo.h"
@@ -47,6 +48,29 @@
#include <assert.h>
#include <algorithm>
class PLMainThreadRelay final : public IGpThreadRelay
{
public:
void Invoke(Callback_t callback, void *context) const override;
static PLMainThreadRelay *GetInstance();
private:
static PLMainThreadRelay ms_instance;
};
void PLMainThreadRelay::Invoke(Callback_t callback, void *context) const
{
PLSysCalls::RunOnVOSThread(callback, context);
}
PLMainThreadRelay *PLMainThreadRelay::GetInstance()
{
return &ms_instance;
}
PLMainThreadRelay PLMainThreadRelay::ms_instance;
static bool ConvertFilenameToSafePStr(const char *str, uint8_t *pstr)
{
const char *strBase = str;
@@ -650,6 +674,8 @@ void PL_Init()
PortabilityLayer::DisplayDeviceManager::GetInstance()->Init();
PortabilityLayer::QDManager::GetInstance()->Init();
PortabilityLayer::MenuManager::GetInstance()->Init();
PortabilityLayer::HostFileSystem::GetInstance()->SetMainThreadRelay(PLMainThreadRelay::GetInstance());
}
WindowPtr PL_GetPutInFrontWindowPtr()

View File

@@ -189,4 +189,13 @@ namespace PLSysCalls
{
PortabilityLayer::SuspendApplication(PortabilityLayer::HostSuspendCallID_ForceSyncFrame, nullptr, nullptr);
}
void RunOnVOSThread(void(*callback)(void *context), void *context)
{
PortabilityLayer::HostSuspendCallArgument args[2];
args[0].m_functionPtr = callback;
args[1].m_pointer = context;
PortabilityLayer::SuspendApplication(PortabilityLayer::HostSuspendCallID_CallOnVOSThread, args, nullptr);
}
}

View File

@@ -8,4 +8,5 @@ namespace PLSysCalls
{
void Sleep(uint32_t ticks);
void ForceSyncFrame();
void RunOnVOSThread(void(*callback)(void *context), void *context);
}

View File

@@ -28,7 +28,7 @@ void DrawSurface::PushToDDSurface(IGpDisplayDriver *displayDriver)
}
if (m_ddSurface == nullptr)
m_ddSurface = displayDriver->CreateSurface(pixMap->m_rect.right - pixMap->m_rect.left, pixMap->m_rect.bottom - pixMap->m_rect.top, pixMap->m_pitch, pixMap->m_pixelFormat);
m_ddSurface = displayDriver->CreateSurface(pixMap->m_rect.right - pixMap->m_rect.left, pixMap->m_rect.bottom - pixMap->m_rect.top, pixMap->m_pitch, pixMap->m_pixelFormat, DrawSurface::StaticOnDriverInvalidate, this);
if (m_port.IsDirty(PortabilityLayer::QDPortDirtyFlag_Contents) && m_ddSurface != nullptr)
{
@@ -36,3 +36,13 @@ void DrawSurface::PushToDDSurface(IGpDisplayDriver *displayDriver)
m_port.ClearDirty(PortabilityLayer::QDPortDirtyFlag_Contents);
}
}
void DrawSurface::StaticOnDriverInvalidate(void *context)
{
static_cast<DrawSurface*>(context)->OnDriverInvalidate();
}
void DrawSurface::OnDriverInvalidate()
{
m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents);
}

View File

@@ -89,4 +89,8 @@ struct DrawSurface
PortabilityLayer::RGBAColor m_cachedAAColor;
PortabilityLayer::QDPort m_port;
private:
static void StaticOnDriverInvalidate(void *context);
void OnDriverInvalidate();
};

View File

@@ -17,6 +17,8 @@ namespace PortabilityLayer
kCursors,
kHighScores,
kLogs,
kSourceExport,
};
}

View File

@@ -1434,6 +1434,7 @@ namespace PortabilityLayer
void WindowManagerImpl::HandleScreenResolutionChange(uint32_t prevWidth, uint32_t prevHeight, uint32_t newWidth, uint32_t newHeight)
{
const uint32_t menuBarHeight = PortabilityLayer::MenuManager::GetInstance()->GetMenuBarHeight();
const bool menuIsTouchScreen = PortabilityLayer::MenuManager::GetInstance()->IsMenuTouchScreenStyle();
for (PortabilityLayer::WindowImpl *window = m_windowStackTop; window != nullptr; window = window->GetWindowBelow())
{
@@ -1457,17 +1458,37 @@ namespace PortabilityLayer
int64_t newY = 0;
int32_t currentY = window->GetPosition().m_y;
if (currentY < static_cast<int32_t>(menuBarHeight))
newY = currentY;
else
if (!menuIsTouchScreen)
{
if (newHeight <= (paddedHeight + menuBarHeight) || prevHeight <= paddedHeight + menuBarHeight)
newY = (static_cast<int64_t>(newHeight) - paddedHeight - menuBarHeight) / 2 + menuBarHeight;
if (currentY < static_cast<int32_t>(menuBarHeight))
newY = currentY;
else
{
uint32_t prevClearanceY = prevHeight - paddedHeight - menuBarHeight;
uint32_t newClearanceY = newHeight - paddedHeight - menuBarHeight;
newY = (static_cast<int64_t>(currentY) - static_cast<int64_t>(menuBarHeight) - chromePadding[WindowChromeSides::kTop]) * static_cast<int64_t>(newClearanceY) / static_cast<int64_t>(prevClearanceY) + menuBarHeight + chromePadding[WindowChromeSides::kTop];
if (newHeight <= (paddedHeight + menuBarHeight) || prevHeight <= paddedHeight + menuBarHeight)
newY = (static_cast<int64_t>(newHeight) - paddedHeight - menuBarHeight) / 2 + menuBarHeight;
else
{
uint32_t prevClearanceY = prevHeight - paddedHeight - menuBarHeight;
uint32_t newClearanceY = newHeight - paddedHeight - menuBarHeight;
newY = (static_cast<int64_t>(currentY) - static_cast<int64_t>(menuBarHeight) - chromePadding[WindowChromeSides::kTop]) * static_cast<int64_t>(newClearanceY) / static_cast<int64_t>(prevClearanceY) + menuBarHeight + chromePadding[WindowChromeSides::kTop];
}
}
}
else
{
uint32_t heightWithoutMenu = surfaceRect.Height() - menuBarHeight;
if (currentY + static_cast<int32_t>(paddedHeight) >= heightWithoutMenu)
newY = currentY;
else
{
if (newHeight <= (paddedHeight + menuBarHeight) || prevHeight <= paddedHeight + menuBarHeight)
newY = (static_cast<int64_t>(newHeight) - paddedHeight - menuBarHeight) / 2 + menuBarHeight;
else
{
uint32_t prevClearanceY = prevHeight - paddedHeight - menuBarHeight;
uint32_t newClearanceY = newHeight - paddedHeight - menuBarHeight;
newY = (static_cast<int64_t>(currentY) - static_cast<int64_t>(menuBarHeight) - chromePadding[WindowChromeSides::kTop]) * static_cast<int64_t>(newClearanceY) / static_cast<int64_t>(prevClearanceY) + chromePadding[WindowChromeSides::kTop];
}
}
}