Menu work, move VOS queue interface

This commit is contained in:
elasota
2019-12-24 02:35:24 -05:00
parent 4c743c90b1
commit 3111609536
34 changed files with 828 additions and 92 deletions

View File

@@ -7,6 +7,7 @@
#include "HostDisplayDriver.h"
#include "HostSystemServices.h"
#include "HostVOSEventQueue.h"
#include "MenuManager.h"
#include "WindowManager.h"
int gpAppMain();
@@ -40,6 +41,7 @@ void GpAppInterfaceImpl::PL_IncrementTickCounter(uint32_t count)
void GpAppInterfaceImpl::PL_Render(IGpDisplayDriver *displayDriver)
{
PortabilityLayer::WindowManager::GetInstance()->RenderFrame(displayDriver);
PortabilityLayer::MenuManager::GetInstance()->RenderFrame(displayDriver);
}
void GpAppInterfaceImpl::PL_HostFileSystem_SetInstance(PortabilityLayer::HostFileSystem *instance)

View File

@@ -4,6 +4,7 @@
struct IGpDisplayDriver;
struct IGpFiber;
struct IGpVOSEventQueue;
struct GpDisplayDriverProperties
{
@@ -29,4 +30,6 @@ struct GpDisplayDriverProperties
RenderFunc_t m_renderFunc;
void *m_renderFuncContext;
IGpVOSEventQueue *m_eventQueue;
};

View File

@@ -1,5 +1,14 @@
#pragma once
namespace GpKeyModifiers
{
enum GpKeyModifier
{
kShift,
kCtrl,
};
}
namespace GpKeyIDSubsets
{
enum GpKeyIDSubset
@@ -43,9 +52,9 @@ namespace GpKeySpecials
typedef GpKeySpecials::GpKeySpecial GpKeySpecial_t;
namespace GpInputEventTypes
namespace GpKeyboardInputEventTypes
{
enum GpInputEventType
enum GpKeyboardInputEventType
{
kDown,
kUp,
@@ -53,19 +62,9 @@ namespace GpInputEventTypes
};
}
typedef GpInputEventTypes::GpInputEventType GpInputEventType_t;
typedef GpKeyboardInputEventTypes::GpKeyboardInputEventType GpKeyboardInputEventType_t;
namespace GpVOSEventTypes
{
enum GpVOSEventType
{
kInput,
};
}
typedef GpVOSEventTypes::GpVOSEventType GpVOSEventType_t;
struct GpInputEvent
struct GpKeyboardInputEvent
{
union KeyUnion
{
@@ -73,17 +72,66 @@ struct GpInputEvent
char m_asciiChar;
};
GpInputEventType_t m_eventType;
GpKeyboardInputEventType_t m_eventType;
GpKeyIDSubset_t m_keyIDSubset;
KeyUnion m_key;
};
namespace GpMouseEventTypes
{
enum GpMouseEventType
{
kUp,
kDown,
kMove,
kLeave,
};
}
typedef GpMouseEventTypes::GpMouseEventType GpMouseEventType_t;
namespace GpMouseButtons
{
enum GpMouseButton
{
kNone,
kLeft,
kMiddle,
kRight,
kX1,
kX2,
};
}
typedef GpMouseButtons::GpMouseButton GpMouseButton_t;
struct GpMouseInputEvent
{
int32_t m_x;
int32_t m_y;
GpMouseEventType_t m_eventType;
GpMouseButton_t m_button;
};
namespace GpVOSEventTypes
{
enum GpVOSEventType
{
kKeyboardInput,
kMouseInput,
};
}
typedef GpVOSEventTypes::GpVOSEventType GpVOSEventType_t;
struct GpVOSEvent
{
union EventUnion
{
GpInputEvent m_inputEvent;
GpKeyboardInputEvent m_keyboardInputEvent;
GpMouseInputEvent m_mouseInputEvent;
};
EventUnion m_event;
GpVOSEventType_t m_eventType;
};

View File

@@ -10,6 +10,7 @@
struct IGpFiber;
struct IGpColorCursor_Win32;
struct IGpVOSEventQueue;
struct GpWindowsGlobals
{
@@ -21,5 +22,6 @@ struct GpWindowsGlobals
IGpFiber *(*m_createFiberFunc)(LPVOID fiber);
IGpColorCursor_Win32 *(*m_loadColorCursorFunc)(const wchar_t *path);
void (*m_translateWindowsMessageFunc)(const MSG *msg, IGpVOSEventQueue *eventQueue);
};

View File

@@ -0,0 +1,11 @@
#pragma once
struct GpVOSEvent;
struct IGpVOSEventQueue
{
virtual const GpVOSEvent *GetNext() = 0;
virtual void DischargeOne() = 0;
virtual GpVOSEvent *QueueEvent() = 0;
};

View File

@@ -14,6 +14,7 @@ GpAppEnvironment::GpAppEnvironment()
, m_displayDriver(nullptr)
, m_audioDriver(nullptr)
, m_fontHandler(nullptr)
, m_vosEventQueue(nullptr)
, m_applicationFiber(nullptr)
, m_vosFiber(nullptr)
, m_suspendCallID(PortabilityLayer::HostSuspendCallID_Unknown)
@@ -100,6 +101,11 @@ void GpAppEnvironment::SetFontHandler(PortabilityLayer::HostFontHandler *fontHan
m_fontHandler = fontHandler;
}
void GpAppEnvironment::SetVOSEventQueue(GpVOSEventQueue *eventQueue)
{
m_vosEventQueue = eventQueue;
}
void GpAppEnvironment::StaticAppThreadFunc(void *context)
{
static_cast<GpAppEnvironment*>(context)->AppThreadFunc();
@@ -117,7 +123,7 @@ void GpAppEnvironment::InitializeApplicationState()
GpAppInterface_Get()->PL_InstallHostSuspendHook(GpAppEnvironment::StaticSuspendHookFunc, this);
GpAppInterface_Get()->PL_HostFontHandler_SetInstance(m_fontHandler);
GpAppInterface_Get()->PL_HostVOSEventQueue_SetInstance(&m_vosEventQueue);
GpAppInterface_Get()->PL_HostVOSEventQueue_SetInstance(m_vosEventQueue);
SynchronizeState();
}

View File

@@ -30,6 +30,7 @@ public:
void SetDisplayDriver(IGpDisplayDriver *displayDriver);
void SetAudioDriver(IGpAudioDriver *audioDriver);
void SetFontHandler(PortabilityLayer::HostFontHandler *fontHandler);
void SetVOSEventQueue(GpVOSEventQueue *eventQueue);
private:
enum ApplicationState
@@ -54,7 +55,7 @@ private:
IGpDisplayDriver *m_displayDriver;
IGpAudioDriver *m_audioDriver;
PortabilityLayer::HostFontHandler *m_fontHandler;
GpVOSEventQueue m_vosEventQueue;
GpVOSEventQueue *m_vosEventQueue;
IGpFiber *m_applicationFiber;
IGpFiber *m_vosFiber;

Binary file not shown.

View File

@@ -26,6 +26,7 @@ namespace
int GpMain::Run()
{
GpVOSEventQueue *eventQueue = new GpVOSEventQueue();
GpAppEnvironment *appEnvironment = new GpAppEnvironment();
GpDisplayDriverProperties ddProps;
@@ -50,6 +51,7 @@ int GpMain::Run()
ddProps.m_type = g_gpGlobalConfig.m_displayDriverType;
ddProps.m_osGlobals = g_gpGlobalConfig.m_osGlobals;
ddProps.m_eventQueue = eventQueue;
GpAudioDriverProperties adProps;
memset(&adProps, 0, sizeof(adProps));
@@ -69,6 +71,7 @@ int GpMain::Run()
appEnvironment->SetDisplayDriver(displayDriver);
appEnvironment->SetAudioDriver(audioDriver);
appEnvironment->SetFontHandler(fontHandler);
appEnvironment->SetVOSEventQueue(eventQueue);
// Start the display loop
displayDriver->Run();

View File

@@ -7,18 +7,83 @@
#include "GpFileSystem_Win32.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Win32.h"
#include "GpVOSEvent.h"
#include "IGpVOSEventQueue.h"
#include "HostFileSystem.h"
#include "GpWindows.h"
#include <stdio.h>
#include <windowsx.h>
GpWindowsGlobals g_gpWindowsGlobals;
extern "C" __declspec(dllimport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties);
extern "C" __declspec(dllimport) IGpDisplayDriver *GpDriver_CreateDisplayDriver_D3D11(const GpDisplayDriverProperties &properties);
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y)
{
if (GpVOSEvent *evt = eventQueue->QueueEvent())
{
evt->m_eventType = GpVOSEventTypes::kMouseInput;
GpMouseInputEvent &mEvent = evt->m_event.m_mouseInputEvent;
mEvent.m_button = button;
mEvent.m_x = x;
mEvent.m_y = y;
mEvent.m_eventType = eventType;
}
}
static void TranslateWindowsMessage(const MSG *msg, IGpVOSEventQueue *eventQueue)
{
WPARAM wParam = msg->wParam;
LPARAM lParam = msg->lParam;
switch (msg->message)
{
case WM_LBUTTONDOWN:
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kLeft, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_LBUTTONUP:
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kLeft, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_MBUTTONDOWN:
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kMiddle, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_MBUTTONUP:
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kMiddle, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_RBUTTONDOWN:
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kRight, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_RBUTTONUP:
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kRight, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_XBUTTONDOWN:
if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kX1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2)
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kX2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_XBUTTONUP:
if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kX1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2)
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kX2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_MOUSEMOVE:
PostMouseEvent(eventQueue, GpMouseEventTypes::kMove, GpMouseButtons::kNone, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
case WM_MOUSELEAVE:
PostMouseEvent(eventQueue, GpMouseEventTypes::kLeave, GpMouseButtons::kNone, 0, 0);
break;
default:
break;
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Win32::GetInstance());
@@ -32,6 +97,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
g_gpWindowsGlobals.m_createFiberFunc = GpFiber_Win32::Create;
g_gpWindowsGlobals.m_loadColorCursorFunc = GpColorCursor_Win32::Load;
g_gpWindowsGlobals.m_translateWindowsMessageFunc = TranslateWindowsMessage;
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_D3D11;
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;

View File

@@ -1,40 +1,40 @@
#include "GpPLGlueDisplayDriver.h"
#include "VirtualDirectory.h"
#include "IGpDisplayDriver.h"
GpPLGlueDisplayDriver::GpPLGlueDisplayDriver()
: m_displayDriver(nullptr)
{
}
void GpPLGlueDisplayDriver::GetDisplayResolution(unsigned int *width, unsigned int *height, GpPixelFormat_t *bpp)
{
m_displayDriver->GetDisplayResolution(width, height, bpp);
#include "VirtualDirectory.h"
#include "IGpDisplayDriver.h"
GpPLGlueDisplayDriver::GpPLGlueDisplayDriver()
: m_displayDriver(nullptr)
{
}
void GpPLGlueDisplayDriver::GetDisplayResolution(unsigned int *width, unsigned int *height, GpPixelFormat_t *bpp)
{
m_displayDriver->GetDisplayResolution(width, height, bpp);
}
IGpColorCursor *GpPLGlueDisplayDriver::LoadColorCursor(int cursorID)
{
return m_displayDriver->LoadColorCursor(cursorID);
}
void GpPLGlueDisplayDriver::SetColorCursor(IGpColorCursor *colorCursor)
{
m_displayDriver->SetColorCursor(colorCursor);
return m_displayDriver->LoadColorCursor(cursorID);
}
void GpPLGlueDisplayDriver::SetColorCursor(IGpColorCursor *colorCursor)
{
m_displayDriver->SetColorCursor(colorCursor);
}
void GpPLGlueDisplayDriver::SetStandardCursor(EGpStandardCursor_t standardCursor)
{
m_displayDriver->SetStandardCursor(standardCursor);
}
GpPLGlueDisplayDriver *GpPLGlueDisplayDriver::GetInstance()
{
return &ms_instance;
}
void GpPLGlueDisplayDriver::SetGpDisplayDriver(IGpDisplayDriver *displayDriver)
{
m_displayDriver = displayDriver;
}
GpPLGlueDisplayDriver GpPLGlueDisplayDriver::ms_instance;
m_displayDriver->SetStandardCursor(standardCursor);
}
GpPLGlueDisplayDriver *GpPLGlueDisplayDriver::GetInstance()
{
return &ms_instance;
}
void GpPLGlueDisplayDriver::SetGpDisplayDriver(IGpDisplayDriver *displayDriver)
{
m_displayDriver = displayDriver;
}
GpPLGlueDisplayDriver GpPLGlueDisplayDriver::ms_instance;

View File

@@ -3,10 +3,10 @@
#include <stdint.h>
#include "HostVOSEventQueue.h"
#include "GpVOSEvent.h"
#include "GpVOSEvent.h"
class GpVOSEventQueue final : public PortabilityLayer::HostVOSEventQueue
{
{
public:
GpVOSEventQueue();
~GpVOSEventQueue();
@@ -14,7 +14,7 @@ public:
const GpVOSEvent *GetNext() override;
void DischargeOne() override;
GpVOSEvent *QueueEvent();
GpVOSEvent *QueueEvent() override;
private:
static const size_t kMaxEvents = 10000;

View File

@@ -565,10 +565,29 @@ void GpDisplayDriverD3D11::Run()
if (msg.message == WM_QUIT)
break;
else if (msg.message == WM_MOUSEMOVE)
m_mouseIsInClientArea = true;
else if (msg.message == WM_MOUSELEAVE)
m_mouseIsInClientArea = false;
else
{
if (msg.message == WM_MOUSEMOVE)
{
if (!m_mouseIsInClientArea)
{
m_mouseIsInClientArea = true;
TRACKMOUSEEVENT tme;
ZeroMemory(&tme, sizeof(tme));
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = m_hwnd;
tme.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(&tme);
}
}
else if (msg.message == WM_MOUSELEAVE)
m_mouseIsInClientArea = false;
m_osGlobals->m_translateWindowsMessageFunc(&msg, m_properties.m_eventQueue);
}
}
else
{

View File

@@ -25,6 +25,7 @@ namespace PortabilityLayer
FontFamily *GetApplicationFont(int textSize, int variationFlags) const override;
RenderedFont *GetRenderedFont(HostFont *font, int size, FontHacks fontHacks) override;
RenderedFont *GetRenderedFontFromFamily(FontFamily *font, int size, int flags) override;
static FontManagerImpl *GetInstance();
@@ -157,6 +158,17 @@ namespace PortabilityLayer
return rfont;
}
RenderedFont *FontManagerImpl::GetRenderedFontFromFamily(FontFamily *fontFamily, int size, int flags)
{
const int variation = fontFamily->GetVariationForFlags(flags);
PortabilityLayer::HostFont *hostFont = fontFamily->GetFontForVariation(variation);
if (!hostFont)
return nullptr;
return PortabilityLayer::FontManager::GetInstance()->GetRenderedFont(hostFont, size, fontFamily->GetHacksForVariation(variation));
}
FontManagerImpl *FontManagerImpl::GetInstance()
{
return &ms_instance;

View File

@@ -18,6 +18,7 @@ namespace PortabilityLayer
virtual FontFamily *GetApplicationFont(int fontSize, int variationFlags) const = 0;
virtual RenderedFont *GetRenderedFont(HostFont *font, int size, FontHacks fontHacks) = 0;
virtual RenderedFont *GetRenderedFontFromFamily(FontFamily *fontFamily, int fontSize, int flags) = 0;
static FontManager *GetInstance();
};

View File

@@ -5,6 +5,7 @@
#include "HostFontHandler.h"
#include "HostFontRenderedGlyph.h"
#include "MacRoman.h"
#include "PLPasStr.h"
#include "RenderedFont.h"
#include "RenderedGlyphMetrics.h"
@@ -19,6 +20,7 @@ namespace PortabilityLayer
{
public:
bool GetGlyph(unsigned int character, const RenderedGlyphMetrics **outMetricsPtr, const void **outData) const override;
size_t MeasureString(const uint8_t *chars, size_t len) const override;
void Destroy() override;
@@ -59,6 +61,19 @@ namespace PortabilityLayer
return true;
}
size_t RenderedFontImpl::MeasureString(const uint8_t *chars, size_t len) const
{
size_t measure = 0;
for (size_t i = 0; i < len; i++)
{
const RenderedGlyphMetrics &metrics = m_metrics[chars[i]];
measure += metrics.m_advanceX;
}
return measure;
}
void RenderedFontImpl::Destroy()
{
this->~RenderedFontImpl();

View File

@@ -1,15 +1,12 @@
#pragma once
struct GpVOSEvent;
#include "IGpVOSEventQueue.h"
namespace PortabilityLayer
{
class HostVOSEventQueue
class HostVOSEventQueue : public IGpVOSEventQueue
{
public:
virtual const GpVOSEvent *GetNext() = 0;
virtual void DischargeOne() = 0;
static void SetInstance(HostVOSEventQueue *instance);
static HostVOSEventQueue *GetInstance();

View File

@@ -1,7 +1,60 @@
#include "MenuManager.h"
#include "PLBigEndian.h"
#include "DisplayDeviceManager.h"
#include "FontFamily.h"
#include "FontManager.h"
#include "HostDisplayDriver.h"
#include "HostFont.h"
#include "IGpDisplayDriver.h"
#include "MemoryManager.h"
#include "ResourceManager.h"
#include "SimpleGraphic.h"
#include "PLBigEndian.h"
#include "PLCore.h"
#include "PLPasStr.h"
#include "PLResources.h"
#include "PLQDOffscreen.h"
#include "RenderedFont.h"
#include "QDGraf.h"
#include "QDManager.h"
#include "QDPixMap.h"
#include "RGBAColor.h"
#include <stdint.h>
#include <assert.h>
namespace
{
const PortabilityLayer::RGBAColor gs_barTopLeftCornerGraphicPixels[] =
{
{ 0, 0, 0, 255 }, { 0, 0, 0, 255 }, { 0, 0, 0, 255 }, { 85, 85, 85, 255 }, { 170, 170, 170, 255 },
{ 0, 0, 0, 255 }, { 0, 0, 0, 255 }, { 85, 85, 85, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 },
{ 0, 0, 0, 255 }, { 85, 85, 85, 255 }, { 255, 255, 255, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 },
{ 85, 85, 85, 255 }, { 255, 255, 255, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 },
{ 170, 170, 170, 255 }, { 255, 255, 255, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 },
};
const PortabilityLayer::RGBAColor gs_barTopRightCornerGraphicPixels[] =
{
{ 170, 170, 170, 255 }, { 85, 85, 85, 255 }, { 0, 0, 0, 255 }, { 0, 0, 0, 255 }, { 0, 0, 0, 255 },
{ 255, 255, 255, 255 }, { 255, 255, 255, 255 }, { 85, 85, 85, 255 }, { 0, 0, 0, 255 }, { 0, 0, 0, 255 },
{ 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 255, 255, 255, 255 }, { 85, 85, 85, 255 }, { 0, 0, 0, 255 },
{ 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 255, 255, 255, 255 }, { 85, 85, 85, 255 },
{ 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 255, 255, 255, 255 }, { 85, 85, 85, 255 },
};
const PortabilityLayer::RGBAColor gs_barBrightColor = { 255, 255, 255, 255 };
const PortabilityLayer::RGBAColor gs_barMidColor = { 221, 221, 221, 255 };
const PortabilityLayer::RGBAColor gs_barDarkColor = { 102, 102, 102, 255 };
const PortabilityLayer::RGBAColor gs_barBottomEdgeColor = { 0, 0, 0, 255 };
const PortabilityLayer::RGBAColor gs_barNormalTextColor = { 0, 0, 0, 255 };
const PortabilityLayer::RGBAColor gs_barHighlightBrightColor = { 153, 153, 255, 255 };
const PortabilityLayer::RGBAColor gs_barHighlightMidColor = { 102, 102, 204, 255 };
const PortabilityLayer::RGBAColor gs_barHighlightDarkColor = { 51, 51, 102, 255 };
PortabilityLayer::SimpleGraphicInstanceRGBA<5, 5> gs_barTopLeftCornerGraphic(gs_barTopLeftCornerGraphicPixels);
PortabilityLayer::SimpleGraphicInstanceRGBA<5, 5> gs_barTopRightCornerGraphic(gs_barTopRightCornerGraphicPixels);
}
struct MenuItem
{
@@ -21,13 +74,20 @@ struct Menu
uint16_t height;
uint16_t commandID;
bool enabled;
bool isIcon;
PortabilityLayer::MMHandleBlock *stringBlobHandle;
Menu **prevMenu;
Menu **nextMenu;
// Refreshed on layout
size_t cumulativeOffset;
unsigned int menuIndex;
size_t numMenuItems;
// This must be the last item
MenuItem menuItems[1];
};
@@ -39,6 +99,9 @@ namespace PortabilityLayer
MenuManagerImpl();
~MenuManagerImpl();
virtual void Init() override;
virtual void Shutdown() override;
Menu **DeserializeMenu(const void *resData) const override;
Menu **GetMenuByID(int id) const override;
void InsertMenuBefore(Menu **insertingMenu, Menu **existingMenu) override;
@@ -49,18 +112,46 @@ namespace PortabilityLayer
void SetItemEnabled(Menu **menu, unsigned int index, bool enabled) override;
void SetItemChecked(Menu **menu, unsigned int index, bool checked) override;
void DrawMenuBar() override;
void RenderFrame(IGpDisplayDriver *displayDriver) override;
static MenuManagerImpl *GetInstance();
private:
void RefreshMenuLayout();
static const unsigned int kIconResID = 128;
static const unsigned int kMenuFontSize = 12;
static const unsigned int kMenuBarIconYOffset = 2;
static const unsigned int kMenuBarTextYOffset = 14;
static const unsigned int kMenuBarHeight = 20;
static const unsigned int kMenuBarItemPadding = 6;
static const unsigned int kMenuBarInitialPadding = 16;
static const int kMenuFontFlags = PortabilityLayer::FontFamilyFlag_Bold;
CGraf *m_menuBarGraf;
Menu **m_firstMenu;
Menu **m_lastMenu;
bool m_haveMenuLayout;
bool m_haveIcon;
uint8_t m_iconColors[16 * 16];
uint8_t m_iconMask[32];
SimpleGraphic *m_iconGraphic;
static MenuManagerImpl ms_instance;
};
MenuManagerImpl::MenuManagerImpl()
: m_firstMenu(nullptr)
: m_menuBarGraf(nullptr)
, m_firstMenu(nullptr)
, m_lastMenu(nullptr)
, m_haveMenuLayout(false)
, m_haveIcon(false)
, m_iconGraphic(nullptr)
{
}
@@ -68,6 +159,26 @@ namespace PortabilityLayer
{
}
void MenuManagerImpl::Init()
{
}
void MenuManagerImpl::Shutdown()
{
PortabilityLayer::QDManager *qdManager = PortabilityLayer::QDManager::GetInstance();
if (m_menuBarGraf)
qdManager->DisposeGWorld(m_menuBarGraf);
if (m_iconGraphic)
{
m_iconGraphic->~SimpleGraphic();
free(m_iconGraphic);
}
// GP TODO: Dispose of menus properly
}
Menu **MenuManagerImpl::DeserializeMenu(const void *resData) const
{
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
@@ -122,6 +233,9 @@ namespace PortabilityLayer
menu->height = header.height;
menu->commandID = header.commandID;
menu->enabled = ((enableFlags & 1) != 0);
menu->menuIndex = 0;
menu->cumulativeOffset = 0;
menu->isIcon = false;
uint8_t *stringDataStart = static_cast<uint8_t*>(stringData->m_contents);
uint8_t *stringDest = stringDataStart;
@@ -172,6 +286,8 @@ namespace PortabilityLayer
void MenuManagerImpl::InsertMenuBefore(Menu **insertingMenu, Menu **existingMenu)
{
m_haveMenuLayout = false;
Menu *insertingMenuPtr = *insertingMenu;
Menu *existingMenuPtr = *existingMenu;
@@ -188,6 +304,8 @@ namespace PortabilityLayer
void MenuManagerImpl::InsertMenuAfter(Menu **insertingMenu, Menu **existingMenu)
{
m_haveMenuLayout = false;
Menu *insertingMenuPtr = *insertingMenu;
Menu *existingMenuPtr = *existingMenu;
@@ -204,6 +322,8 @@ namespace PortabilityLayer
void MenuManagerImpl::InsertMenuAtEnd(Menu **insertingMenu)
{
m_haveMenuLayout = false;
if (m_firstMenu == nullptr)
{
m_firstMenu = m_lastMenu = insertingMenu;
@@ -217,6 +337,8 @@ namespace PortabilityLayer
void MenuManagerImpl::InsertMenuAtBeginning(Menu **insertingMenu)
{
m_haveMenuLayout = false;
if (m_firstMenu == nullptr)
{
m_firstMenu = m_lastMenu = insertingMenu;
@@ -255,6 +377,228 @@ namespace PortabilityLayer
menu->menuItems[index].checked = checked;
}
void MenuManagerImpl::DrawMenuBar()
{
if (!m_haveIcon)
{
ResourceManager *resManager = ResourceManager::GetInstance();
Handle icsHandle = GetResource('ics#', kIconResID);
Handle ics8Handle = GetResource('ics8', kIconResID);
if (icsHandle && ics8Handle)
{
typedef SimpleGraphicInstanceStandardPalette<16, 16> GraphicType_t;
void *storage = static_cast<GraphicType_t*>(malloc(sizeof(GraphicType_t)));
if (storage)
{
memcpy(m_iconMask, static_cast<const uint8_t*>(*icsHandle) + 32, 32);
memcpy(m_iconColors, static_cast<const uint8_t*>(*ics8Handle), 16 * 16);
GraphicType_t *graphic = new (storage) GraphicType_t(m_iconColors);
m_iconGraphic = graphic;
}
}
if (icsHandle)
ReleaseResource(icsHandle);
if (ics8Handle)
ReleaseResource(ics8Handle);
m_haveIcon = true;
}
unsigned int width;
GpPixelFormat_t pixelFormat;
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(&width, nullptr, &pixelFormat);
PortabilityLayer::QDManager *qdManager = PortabilityLayer::QDManager::GetInstance();
const Rect menuRect = Rect::Create(0, 0, kMenuBarHeight, width);
if (m_menuBarGraf == nullptr)
{
int depth = 0;
switch (pixelFormat)
{
case GpPixelFormats::k8BitStandard:
depth = 8;
break;
default:
PL_NotYetImplemented();
return;
}
if (qdManager->NewGWorld(&m_menuBarGraf, depth, menuRect, nullptr, nullptr, 0) != 0)
return;
}
CGraf *graf = m_menuBarGraf;
assert(graf);
if (static_cast<unsigned int>(graf->m_port.GetRect().right) != width)
{
if (!graf->m_port.Resize(menuRect))
return;
}
RefreshMenuLayout();
CGraf *oldGraf;
GDHandle oldDevice;
GetGWorld(&oldGraf, &oldDevice);
SetGWorld(m_menuBarGraf, nullptr);
PortabilityLayer::QDState *qdState = qdManager->GetState();
qdState->SetForeColor(gs_barMidColor);
PaintRect(&menuRect);
qdState->SetForeColor(gs_barBrightColor);
// Top stripe
{
const Rect rect = Rect::Create(0, 0, 1, static_cast<int16_t>(width) - 1);
PaintRect(&rect);
}
// Left stripe
{
const Rect rect = Rect::Create(0, 0, kMenuBarHeight - 1, 1);
PaintRect(&rect);
}
qdState->SetForeColor(gs_barDarkColor);
// Bottom stripe
{
const Rect rect = Rect::Create(kMenuBarHeight - 2, 1, kMenuBarHeight - 1, width);
PaintRect(&rect);
}
// Right stripe
{
const Rect rect = Rect::Create(0, width - 1, kMenuBarHeight - 1, width);
PaintRect(&rect);
}
qdState->SetForeColor(gs_barBottomEdgeColor);
// Bottom edge
{
const Rect rect = Rect::Create(kMenuBarHeight - 1, 0, kMenuBarHeight, width);
PaintRect(&rect);
}
PixMapHandle pixMap = m_menuBarGraf->m_port.GetPixMap();
// Round corners
gs_barTopLeftCornerGraphic.DrawToPixMap(pixMap, 0, 0);
gs_barTopRightCornerGraphic.DrawToPixMap(pixMap, static_cast<int16_t>(width) - static_cast<int16_t>(gs_barTopRightCornerGraphic.m_width), 0);
qdState->SetForeColor(gs_barNormalTextColor);
TextFont(systemFont);
TextSize(kMenuFontSize);
// Text items
{
Menu **menuHdl = m_firstMenu;
while (menuHdl)
{
Menu *menu = *menuHdl;
if (menu->stringBlobHandle)
{
size_t xCoordinate = menu->cumulativeOffset + (menu->menuIndex * 2) * kMenuBarItemPadding + kMenuBarInitialPadding;
if (menu->isIcon)
{
if (m_iconGraphic)
m_iconGraphic->DrawToPixMapWithMask(pixMap, m_iconMask, xCoordinate, kMenuBarIconYOffset);
}
else
{
qdState->m_penPos.h = xCoordinate;
qdState->m_penPos.v = kMenuBarTextYOffset;
DrawString(PLPasStr(static_cast<const uint8_t*>(menu->stringBlobHandle->m_contents)));
}
}
menuHdl = menu->nextMenu;
}
}
SetGWorld(oldGraf, oldDevice);
m_menuBarGraf->m_port.SetDirty(QDPortDirtyFlag_Contents);
}
void MenuManagerImpl::RenderFrame(IGpDisplayDriver *displayDriver)
{
if (m_menuBarGraf)
{
m_menuBarGraf->PushToDDSurface(displayDriver);
if (m_menuBarGraf->m_ddSurface)
{
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);
}
}
}
void MenuManagerImpl::RefreshMenuLayout()
{
if (m_haveMenuLayout)
return;
PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance();
PortabilityLayer::FontFamily *fontFamily = PortabilityLayer::FontManager::GetInstance()->GetSystemFont(kMenuFontSize, kMenuFontFlags);
if (!fontFamily)
return;
PortabilityLayer::RenderedFont *rfont = PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, kMenuFontSize, kMenuFontFlags);
if (!rfont)
return;
unsigned int index = 0;
size_t measuredWidth = 0;
Menu **menuHdl = m_firstMenu;
while (menuHdl)
{
Menu *menu = *menuHdl;
menu->menuIndex = index++;
menu->cumulativeOffset = measuredWidth;
const PLPasStr pascalStr = PLPasStr(static_cast<const uint8_t*>(menu->stringBlobHandle->m_contents));
if (pascalStr.Length() == 1 && pascalStr.UChars()[0] == 0x14)
{
measuredWidth += 16;
menu->isIcon = true;
}
else
measuredWidth += rfont->MeasureString(pascalStr.UChars(), pascalStr.Length());
menuHdl = menu->nextMenu;
}
m_haveMenuLayout = true;
}
MenuManagerImpl *MenuManagerImpl::GetInstance()
{
return &ms_instance;

View File

@@ -1,12 +1,16 @@
#pragma once
struct Menu;
struct Menu;
struct IGpDisplayDriver;
namespace PortabilityLayer
{
class MenuManager
{
public:
virtual void Init() = 0;
virtual void Shutdown() = 0;
virtual Menu **DeserializeMenu(const void *resData) const = 0;
virtual Menu **GetMenuByID(int id) const = 0;
virtual void InsertMenuBefore(Menu **insertingMenu, Menu **existingMenu) = 0;
@@ -17,6 +21,10 @@ namespace PortabilityLayer
virtual void SetItemEnabled(Menu **menu, unsigned int index, bool enabled) = 0;
virtual void SetItemChecked(Menu **menu, unsigned int index, bool checked) = 0;
virtual void DrawMenuBar() = 0;
virtual void RenderFrame(IGpDisplayDriver *displayDriver) = 0;
static MenuManager *GetInstance();
};
}

View File

@@ -19,6 +19,7 @@
#include "ResourceManager.h"
#include "MacFileInfo.h"
#include "MemoryManager.h"
#include "MenuManager.h"
#include "MemReaderStream.h"
#include "MMHandleBlock.h"
#include "ResTypeID.h"
@@ -61,6 +62,11 @@ static void TranslateVOSEvent(const GpVOSEvent *vosEvent, EventRecord *evt)
static void ImportVOSEvents()
{
PortabilityLayer::HostVOSEventQueue *evtQueue = PortabilityLayer::HostVOSEventQueue::GetInstance();
while (const GpVOSEvent *evt = evtQueue->GetNext())
{
evtQueue->DischargeOne();
}
}
void InitCursor()
@@ -864,6 +870,7 @@ void PL_Init()
PortabilityLayer::DisplayDeviceManager::GetInstance()->Init();
PortabilityLayer::AEManager::GetInstance()->Init();
PortabilityLayer::QDManager::GetInstance()->Init();
PortabilityLayer::MenuManager::GetInstance()->Init();
}
WindowPtr PL_GetPutInFrontWindowPtr()

View File

@@ -1,9 +1,9 @@
#include "PLEventQueue.h"
#include <stdint.h>
#include <stdint.h>
namespace PortabilityLayer
{
{
class EventQueueImpl final : public EventQueue
{
public:

View File

@@ -2,6 +2,7 @@
#include "PLResources.h"
#include "MenuManager.h"
#include "QDManager.h"
// Menu resource structure:
// uint16 menu ID
@@ -54,7 +55,7 @@ void DeleteMenu(int menuID)
void DrawMenuBar()
{
PL_NotYetImplemented_TODO("Menus");
PortabilityLayer::MenuManager::GetInstance()->DrawMenuBar();
}
void HiliteMenu(int menu)

View File

@@ -239,7 +239,7 @@ OSErr NewGWorld(GWorldPtr *gworld, int depth, Rect *bounds, CTabHandle colorTabl
void DisposeGWorld(GWorldPtr gworld)
{
PL_NotYetImplemented();
return PortabilityLayer::QDManager::GetInstance()->DisposeGWorld(gworld);
}
PixMapHandle GetGWorldPixMap(GWorldPtr gworld)

View File

@@ -227,6 +227,7 @@
<ClInclude Include="ResTypeIDCodec.h" />
<ClInclude Include="RGBAColor.h" />
<ClInclude Include="SharedTypes.h" />
<ClInclude Include="SimpleGraphic.h" />
<ClInclude Include="Vec2i.h" />
<ClInclude Include="VirtualDirectory.h" />
<ClInclude Include="RCPtr.h" />
@@ -296,6 +297,7 @@
<ClCompile Include="RandomNumberGenerator.cpp" />
<ClCompile Include="ResourceCompiledRef.cpp" />
<ClCompile Include="ResourceFile.cpp" />
<ClCompile Include="SimpleGraphic.cpp" />
<ClCompile Include="WindowDef.cpp" />
<ClCompile Include="WindowManager.cpp" />
<ClCompile Include="XModemCRC.cpp" />

View File

@@ -360,6 +360,9 @@
<ClInclude Include="MacRoman.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SimpleGraphic.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CFileStream.cpp">
@@ -539,5 +542,8 @@
<ClCompile Include="MacRoman.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SimpleGraphic.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,30 @@
#include "QDGraf.h"
#include "QDPixMap.h"
#include "QDPort.h"
#include "IGpDisplayDriver.h"
#include "IGpDisplayDriverSurface.h"
void CGraf::PushToDDSurface(IGpDisplayDriver *displayDriver)
{
const PixMap *pixMap = *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;
if (m_port.IsDirty(PortabilityLayer::QDPortDirtyFlag_Size))
{
if (m_ddSurface != nullptr)
m_ddSurface->Destroy();
m_ddSurface = nullptr;
m_port.ClearDirty(PortabilityLayer::QDPortDirtyFlag_Size);
}
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_pixelFormat);
if (m_port.IsDirty(PortabilityLayer::QDPortDirtyFlag_Contents) && m_ddSurface != nullptr)
{
m_ddSurface->UploadEntire(pixMap->m_data, pixMap->m_pitch);
m_port.ClearDirty(PortabilityLayer::QDPortDirtyFlag_Contents);
}
}

View File

@@ -8,9 +8,10 @@
struct PixMap;
struct Rect;
struct IGpDisplayDriver;
struct IGpDisplayDriverSurface;
struct CGraf
struct CGraf final
{
CGraf()
: m_port(PortabilityLayer::QDPortType_CGraf)
@@ -37,6 +38,8 @@ struct CGraf
return m_port.Resize(rect);
}
void PushToDDSurface(IGpDisplayDriver *displayDriver);
// Must be the first item
PortabilityLayer::QDPort m_port;

View File

@@ -17,6 +17,7 @@ namespace PortabilityLayer
void GetPort(QDPort **port, GDevice ***gdHandle) override;
void SetPort(QDPort *gw, GDevice **gdHandle) override;
int NewGWorld(CGraf **gw, int depth, const Rect &bounds, ColorTable **colorTable, GDevice **device, int flags) override;
void DisposeGWorld(CGraf *gw) override;
QDState *GetState() override;
static QDManagerImpl *GetInstance();
@@ -93,6 +94,12 @@ namespace PortabilityLayer
return noErr;
}
void QDManagerImpl::DisposeGWorld(CGraf *gw)
{
gw->~CGraf();
MemoryManager::GetInstance()->Release(gw);
}
QDState *QDManagerImpl::GetState()
{
return m_port->GetState();

View File

@@ -17,6 +17,7 @@ namespace PortabilityLayer
virtual void GetPort(QDPort **gw, GDevice ***gdHandle) = 0;
virtual void SetPort(QDPort *gw, GDevice **gdHandle) = 0;
virtual int NewGWorld(CGraf **gw, int depth, const Rect &bounds, ColorTable **colorTable, GDevice **device, int flags) = 0;
virtual void DisposeGWorld(CGraf *gw) = 0;
virtual QDState *GetState() = 0;

View File

@@ -1,4 +1,6 @@
#pragma once
#pragma once
#include <stdint.h>
namespace PortabilityLayer
{
@@ -8,6 +10,7 @@ namespace PortabilityLayer
{
public:
virtual bool GetGlyph(unsigned int character, const RenderedGlyphMetrics **outMetricsPtr, const void **outData) const = 0;
virtual size_t MeasureString(const uint8_t *chars, size_t len) const = 0;
virtual void Destroy() = 0;
};

View File

@@ -0,0 +1,100 @@
#include "SimpleGraphic.h"
#include "QDStandardPalette.h"
#include "QDPixMap.h"
#include "SharedTypes.h"
namespace PortabilityLayer
{
SimpleGraphic::SimpleGraphic(unsigned int width, unsigned int height, const RGBAColor *pixelData, uint8_t *standardPaletteData)
: m_width(width)
, m_height(height)
, m_pixelData(pixelData)
, m_standardPaletteData(standardPaletteData)
{
const unsigned int numPixels = width * height;
for (unsigned int i = 0; i < numPixels; i++)
standardPaletteData[i] = PortabilityLayer::StandardPalette::MapColorAnalytic(pixelData[i]);
}
SimpleGraphic::SimpleGraphic(unsigned int width, unsigned int height, const uint8_t *standardPaletteData, RGBAColor *pixelData)
: m_width(width)
, m_height(height)
, m_pixelData(pixelData)
, m_standardPaletteData(standardPaletteData)
{
const unsigned int numPixels = width * height;
for (unsigned int i = 0; i < numPixels; i++)
pixelData[i] = PortabilityLayer::StandardPalette::GetInstance()->GetColors()[standardPaletteData[i]];
}
void SimpleGraphic::DrawToPixMap(PixMap **pixMapH, int16_t x, int16_t y)
{
DrawToPixMapWithMask(pixMapH, nullptr, x, y);
}
void SimpleGraphic::DrawToPixMapWithMask(PixMap **pixMapH, const uint8_t *maskData, int16_t x, int16_t y)
{
if (!pixMapH)
return;
PixMap *pixMap = *pixMapH;
void *pixMapData = pixMap->m_data;
const size_t destPitch = pixMap->m_pitch;
const Rect pixMapRect = pixMap->m_rect;
const int32_t right = x + static_cast<int32_t>(m_width);
const int32_t bottom = y + static_cast<int32_t>(m_height);
// Simple graphics must be entirely in bounds
if (x < 0 || y < 0 || right > pixMapRect.right || bottom > pixMapRect.bottom)
return;
const size_t destXOffset = (x - pixMapRect.left);
const size_t destYOffset = (y - pixMapRect.top);
const size_t srcHeight = m_height;
const size_t srcWidth = m_width;
size_t maskOffset = 0;
switch (pixMap->m_pixelFormat)
{
case GpPixelFormats::k8BitStandard:
{
uint8_t *destFirstPixel = static_cast<uint8_t*>(pixMapData) + destXOffset + destYOffset * destPitch;
const uint8_t *srcPixel = m_standardPaletteData;
for (size_t row = 0; row < srcHeight; row++)
{
uint8_t *destRowFirstPixel = destFirstPixel + row * destPitch;
if (maskData)
{
for (size_t col = 0; col < srcWidth; col++)
{
if (maskData[maskOffset / 8] & (0x80 >> (maskOffset & 7)))
destRowFirstPixel[col] = *srcPixel;
srcPixel++;
maskOffset++;
}
}
else
{
for (size_t col = 0; col < srcWidth; col++)
{
destRowFirstPixel[col] = *srcPixel;
srcPixel++;
}
}
}
}
break;
default:
PL_NotYetImplemented();
break;
}
}
}

View File

@@ -0,0 +1,56 @@
#pragma once
#include "RGBAColor.h"
struct PixMap;
namespace PortabilityLayer
{
struct SimpleGraphic
{
unsigned int m_width;
unsigned int m_height;
const RGBAColor *m_pixelData;
const uint8_t *m_standardPaletteData;
void DrawToPixMap(PixMap **pixMap, int16_t x, int16_t y);
void DrawToPixMapWithMask(PixMap **pixMap, const uint8_t *maskData, int16_t x, int16_t y);
protected:
SimpleGraphic(unsigned int width, unsigned int height, const RGBAColor *pixelData, uint8_t *standardPaletteData);
SimpleGraphic(unsigned int width, unsigned int height, const uint8_t *pixelData, RGBAColor *standardPaletteData);
};
template<unsigned int TWidth, unsigned int THeight>
struct SimpleGraphicInstanceRGBA final : public SimpleGraphic
{
uint8_t m_standardPaletteDataInstance[TWidth * THeight];
explicit SimpleGraphicInstanceRGBA(const RGBAColor *data);
};
template<unsigned int TWidth, unsigned int THeight>
struct SimpleGraphicInstanceStandardPalette final : public SimpleGraphic
{
RGBAColor m_pixelDataInstance[TWidth * THeight];
explicit SimpleGraphicInstanceStandardPalette(const uint8_t *data);
};
}
namespace PortabilityLayer
{
template<unsigned int TWidth, unsigned int THeight>
inline SimpleGraphicInstanceRGBA<TWidth, THeight>::SimpleGraphicInstanceRGBA(const RGBAColor *data)
: SimpleGraphic(TWidth, THeight, data, m_standardPaletteDataInstance)
{
}
template<unsigned int TWidth, unsigned int THeight>
inline SimpleGraphicInstanceStandardPalette<TWidth, THeight>::SimpleGraphicInstanceStandardPalette(const uint8_t *data)
: SimpleGraphic(TWidth, THeight, data, m_pixelDataInstance)
{
}
}

View File

@@ -311,31 +311,13 @@ namespace PortabilityLayer
void WindowManagerImpl::RenderWindow(WindowImpl *window, IGpDisplayDriver *displayDriver)
{
GDevice *device = *window->GetDevice();
CGraf &graf = window->m_graf;
graf.PushToDDSurface(displayDriver);
const PixMap *pixMap = *graf.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;
if (graf.m_port.IsDirty(QDPortDirtyFlag_Size))
{
if (graf.m_ddSurface != nullptr)
graf.m_ddSurface->Destroy();
graf.m_ddSurface = nullptr;
graf.m_port.ClearDirty(QDPortDirtyFlag_Size);
}
if (graf.m_ddSurface == nullptr)
graf.m_ddSurface = displayDriver->CreateSurface(pixMap->m_rect.right - pixMap->m_rect.left, pixMap->m_rect.bottom - pixMap->m_rect.top, pixMap->m_pixelFormat);
if (graf.m_port.IsDirty(QDPortDirtyFlag_Contents) && graf.m_ddSurface != nullptr)
{
graf.m_ddSurface->UploadEntire(pixMap->m_data, pixMap->m_pitch);
graf.m_port.ClearDirty(QDPortDirtyFlag_Contents);
}
displayDriver->DrawSurface(graf.m_ddSurface, window->m_wmX, window->m_wmY, width, height);
}