1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

UpdateF, dx reinit

This commit is contained in:
Brian Fiete 2022-05-15 08:00:55 -07:00
parent fa2cb7ba56
commit e87bf5b029
24 changed files with 1029 additions and 415 deletions

View file

@ -45,7 +45,8 @@ namespace Beefy
#endif
{
public delegate void UpdateDelegate(bool batchStart);
public delegate void DrawDelegate();
public delegate void UpdateFDelegate(float updatePct);
public delegate void DrawDelegate(bool forceDraw);
public static BFApp sApp;
public int32 mUpdateCnt;
@ -106,7 +107,7 @@ namespace Beefy
static extern void BFApp_Shutdown();
[CallingConvention(.Stdcall), CLink]
static extern void BFApp_SetCallbacks(void* updateDelegate, void* drawDelegate);
static extern void BFApp_SetCallbacks(void* updateDelegate, void* updateFDelegate, void* drawDelegate);
[CallingConvention(.Stdcall), CLink]
static extern char8* BFApp_GetInstallDir();
@ -132,7 +133,11 @@ namespace Beefy
[CallingConvention(.Stdcall), CLink]
public static extern void* BFApp_GetSoundManager();
[CallingConvention(.Stdcall), CLink]
public static extern int BFApp_GetCriticalThreadId(int32 idx);
UpdateDelegate mUpdateDelegate ~ delete _;
UpdateFDelegate mUpdateFDelegate ~ delete _;
DrawDelegate mDrawDelegate ~ delete _;
#if STUDIO_CLIENT
@ -165,9 +170,9 @@ namespace Beefy
}
#endif
static void Static_Draw()
static void Static_Draw(bool forceDraw)
{
sApp.Draw();
sApp.Draw(forceDraw);
}
static void Static_Update(bool batchStart)
@ -175,6 +180,11 @@ namespace Beefy
sApp.Update(batchStart);
}
static void Static_UpdateF(float updatePct)
{
sApp.UpdateF(updatePct);
}
float mLastUpdateDelta; // In seconds
public this()
@ -198,9 +208,10 @@ namespace Beefy
BFApp_SetRefreshRate(mRefreshRate);
mUpdateDelegate = new => Static_Update;
mUpdateFDelegate = new => Static_UpdateF;
mDrawDelegate = new => Static_Draw;
#endif
BFApp_SetCallbacks(mUpdateDelegate.GetFuncPtr(), mDrawDelegate.GetFuncPtr());
BFApp_SetCallbacks(mUpdateDelegate.GetFuncPtr(), mUpdateFDelegate.GetFuncPtr(), mDrawDelegate.GetFuncPtr());
}
#if STUDIO_CLIENT
@ -515,6 +526,14 @@ namespace Beefy
structuredData.Load(resFileName);
mResourceManager.ParseConfigData(structuredData);
}
for (int32 i = 0; true; i++)
{
int threadId = BFApp_GetCriticalThreadId(i);
if (threadId == 0)
break;
GC.ExcludeThreadId(threadId);
}
}
public void InitGraphics()
@ -671,6 +690,14 @@ namespace Beefy
//Utils.BFRT_CPP("gBFGC.MutatorSectionExit()");
}
public virtual void UpdateF(float updatePct)
{
for (int32 windowIdx = 0; windowIdx < mWindows.Count; windowIdx++)
{
mWindows[windowIdx].UpdateF(updatePct);
}
}
public virtual void DoDraw()
{
}
@ -695,12 +722,11 @@ namespace Beefy
}
#endif
public virtual void Draw()
public virtual void Draw(bool forceDraw)
{
#if STUDIO_CLIENT
#endif
PerfTimer.ZoneStart("BFApp.Draw");
PerfTimer.Message("Client Draw Start");
@ -716,7 +742,8 @@ namespace Beefy
for (BFWindow window in mWindows)
{
if ((window.mVisible) && ((window.mIsDirty) || (mAutoDirty)))
if ((window.mVisible) &&
((window.mIsDirty) || (mAutoDirty) || (forceDraw)))
{
window.PreDraw(mGraphics);
if (mColorMatrix != null)

View file

@ -664,6 +664,11 @@ namespace Beefy
public virtual void Update()
{
}
public virtual void UpdateF(float updatePct)
{
}
}
#else
public class BFWindow : BFWindowBase, IStudioClientWindow

View file

@ -19,6 +19,11 @@ namespace Beefy.theme.dark
public bool mAllowOpen = true;
public bool mIsReversed;
public this()
{
mAlwaysUpdateF = true;
}
public override void Draw(Graphics g)
{
base.Draw(g);
@ -52,9 +57,9 @@ namespace Beefy.theme.dark
mRot = mIsOpen ? (Math.PI_f / 2) : 0;
}
public override void Update()
public override void UpdateF(float updatePct)
{
base.Update();
base.UpdateF(updatePct);
int childCount = mItem.mChildItems.Count;
@ -62,15 +67,17 @@ namespace Beefy.theme.dark
if ((mIsOpen) && (mRot < Math.PI_f / 2))
{
mRot = Math.Min(Math.PI_f / 2, mRot + rotSpeed);
mRot = Math.Min(Math.PI_f / 2, mRot + rotSpeed * updatePct);
mItem.mListView.mListSizeDirty = true;
MarkDirty();
mWidgetWindow.mTempWantsUpdateF = true;
}
else if ((!mIsOpen) && (mRot > 0))
{
mRot = (float)Math.Max(0, mRot - rotSpeed);
mRot = (float)Math.Max(0, mRot - rotSpeed * updatePct);
mItem.mListView.mListSizeDirty = true;
MarkDirty();
mWidgetWindow.mTempWantsUpdateF = true;
}
float x;
@ -876,6 +883,25 @@ namespace Beefy.theme.dark
}
}
}
public override void UpdateFAll(float updatePct)
{
if (mVisible)
{
base.UpdateFAll(updatePct);
if (mChildItems != null)
{
for (int32 anIdx = 0; anIdx < mChildItems.Count; anIdx++)
{
Widget child = mChildItems[anIdx];
Debug.Assert(child.mParent == this);
Debug.Assert(child.mWidgetWindow == mWidgetWindow);
child.UpdateFAll(updatePct);
}
}
}
}
}
public class DarkListView : ListView

View file

@ -37,9 +37,9 @@ namespace Beefy.utils
get { return mPct != 1.0f; }
}
public void Update()
public void Update(float updatePct = 1.0f)
{
mPct = Math.Min(1.0f, mPct + mSpeed * mSpeedScale);
mPct = Math.Min(1.0f, mPct + mSpeed * mSpeedScale * updatePct);
}
public void Set(double val, bool immediate = false)

View file

@ -788,7 +788,12 @@ namespace Beefy.widgets
public override void UpdateAll()
{
base.UpdateAll();
UpdateListSize();
}
public override void UpdateFAll(float updatePct)
{
base.UpdateFAll(updatePct);
UpdateListSize();
}
@ -802,7 +807,7 @@ namespace Beefy.widgets
public void UpdateListSize()
{
// Do this in UpdateAll to give children a change to resize items
// Do this in UpdateAll to give children a chance to resize items
if (mListSizeDirty)
{
float listWidth = GetListWidth();

View file

@ -50,6 +50,7 @@ namespace Beefy.widgets
mScrollContentContainer.mClipGfx = true;
mScrollContentContainer.mClipMouse = true;
AddWidget(mScrollContentContainer);
mAlwaysUpdateF = true;
}
public ~this()
@ -248,10 +249,18 @@ namespace Beefy.widgets
{
base.Update();
}
public override void UpdateF(float updatePct)
{
base.UpdateF(updatePct);
if ((mHorzPos.IsMoving) || (mVertPos.IsMoving))
{
mHorzPos.Update();
mVertPos.Update();
mWidgetWindow.mTempWantsUpdateF = true;
mHorzPos.Update(updatePct);
mVertPos.Update(updatePct);
UpdateContentPosition();
MarkDirty();
}

View file

@ -39,6 +39,7 @@ namespace Beefy.widgets
public float mWidth;
public float mHeight;
public int32 mUpdateCnt;
public double mUpdateCntF;
public String mIdStr ~ delete _;
public List<Widget> mChildWidgets;
public MouseFlag mMouseFlags;
@ -56,6 +57,7 @@ namespace Beefy.widgets
public bool mDeferredDelete;
public Insets mMouseInsets ~ delete _;
public bool mAutoFocus;
public bool mAlwaysUpdateF;
public float X { get { return mX; } set { mX = value; } }
public float Y { get { return mY; } set { mY = value; } }
@ -455,6 +457,14 @@ namespace Beefy.widgets
public virtual void Update()
{
mUpdateCnt++;
if ((mAlwaysUpdateF) && (mWidgetWindow != null))
UpdateF((float)(mUpdateCnt - mUpdateCntF));
mUpdateCntF = mUpdateCnt;
}
public virtual void UpdateF(float updatePct)
{
mUpdateCntF += updatePct;
}
public void DeferDelete()
@ -487,6 +497,31 @@ namespace Beefy.widgets
}
}
public virtual void UpdateFAll(float updatePct)
{
UpdateF(updatePct);
if (mDeferredDelete)
{
delete this;
return;
}
// Removed self?
if (mWidgetWindow == null)
return;
if (mChildWidgets != null)
{
for (int32 anIdx = 0; anIdx < mChildWidgets.Count; anIdx++)
{
Widget child = mChildWidgets[anIdx];
Debug.Assert(child.mParent == this);
Debug.Assert(child.mWidgetWindow == mWidgetWindow);
child.UpdateFAll(updatePct);
}
}
}
public virtual void Resize(float x, float y, float width, float height)
{
Debug.Assert(width >= 0);

View file

@ -62,6 +62,8 @@ namespace Beefy.widgets
public bool mHasMouseInside;
public bool mHasProxyMouseInside;
public bool mIsKeyDownHandled;
public bool mWantsUpdateF;
public bool mTempWantsUpdateF;
public int32 mContentClientWidth;
public int32 mContentClientHeight;
@ -153,9 +155,19 @@ namespace Beefy.widgets
return;
base.Update();
RehupMouse(false);
mTempWantsUpdateF = false;
mRootWidget.UpdateAll();
}
public override void UpdateF(float updatePct)
{
if (mRootWidget == null)
return;
base.Update();
if (mWantsUpdateF || mTempWantsUpdateF)
mRootWidget.UpdateFAll(updatePct);
}
public override int32 CloseQuery()
{
bool hadFalse = false;

View file

@ -133,6 +133,8 @@ namespace System
public extern static void SetMaxPausePercentage(int maxPausePercentage); // 0 = disabled. Defaults to 20.
[CallingConvention(.Cdecl)]
extern static void AddPendingThread(void* internalThread);
[CallingConvention(.Cdecl)]
public extern static void ExcludeThreadId(int thereadId);
#else
public static void Collect(bool async = true) {}
private static void MarkAllStaticMembers() {}
@ -144,6 +146,7 @@ namespace System
public static void SetCollectFreeThreshold(int freeBytes) {}
public static void SetMaxPausePercentage(int maxPausePercentage) {}
static void AddPendingThread(void* internalThreadInfo) {}
public static void ExcludeThreadId(int thereadId) {}
#endif
static void MarkDerefedObject(Object* obj)

View file

@ -1429,6 +1429,9 @@ bool BFGC::ScanThreads()
thread = mThreadList[threadIdx++];
}
if (thread->mExcluded)
continue;
if (!thread->mRunning)
{
AutoCrit autoCrit(mCritSect);
@ -2367,11 +2370,12 @@ void BFGC::SuspendThreads()
auto curThreadId = GetCurrentThreadId();
for (auto thread : mThreadList)
{
if ((thread->mThreadId != curThreadId) && (thread->mRunning) && (thread->WantsSuspend()))
if ((thread->mThreadId != curThreadId) && (!thread->mExcluded) && (thread->mRunning) && (thread->WantsSuspend()))
{
// We must lock this before suspending so we can access mStackMarkableObjects
// Otherwise we could deadlock
thread->mCritSect.Lock();
thread->mSuspended = true;
BfpThreadResult result;
BfpThread_Suspend(thread->mThreadHandle, &result);
@ -2386,11 +2390,12 @@ void BFGC::ResumeThreads()
auto curThreadId = GetCurrentThreadId();
for (auto thread : mThreadList)
{
if ((thread->mThreadId != curThreadId) && (thread->mRunning) && (thread->WantsSuspend()))
if ((thread->mThreadId != curThreadId) && (thread->mSuspended) && (thread->mRunning) && (thread->WantsSuspend()))
{
// Previously locked in SuspendThreads
thread->mCritSect.Unlock();
thread->mSuspended = false;
BfpThread_Resume(thread->mThreadHandle, NULL);
}
}
@ -2743,6 +2748,16 @@ void BFGC::SetMaxRawDeferredObjectFreePercentage(intptr maxPercentage)
mMaxRawDeferredObjectFreePercentage = maxPercentage;
}
void BFGC::ExcludeThreadId(intptr threadId)
{
Beefy::AutoCrit autoCrit(mCritSect);
for (auto thread : mThreadList)
{
if (thread->mThreadId == threadId)
thread->mExcluded = true;
}
}
using namespace bf::System;
void GC::Run()
@ -2832,6 +2847,11 @@ BFRT_EXPORT void bf::System::GC::SetMaxRawDeferredObjectFreePercentage(intptr ma
gBFGC.SetMaxRawDeferredObjectFreePercentage(maxPercentage);
}
BFRT_EXPORT void bf::System::GC::ExcludeThreadId(intptr threadId)
{
gBFGC.ExcludeThreadId(threadId);
}
#else // BF_GC_SUPPORTED
void* BfObjectAllocate(intptr size, bf::System::Type* type)

View file

@ -181,6 +181,8 @@ public:
intptr mStackStart;
intptr mLastStackPtr;
bool mRunning;
bool mExcluded;
bool mSuspended;
Beefy::Array<bf::System::Object*> mStackMarkableObjects;
ThreadInfo()
@ -192,6 +194,8 @@ public:
mTEB = NULL;
mStackStart = NULL;
mRunning = true;
mExcluded = false;
mSuspended = false;
}
~ThreadInfo();
@ -424,6 +428,7 @@ public:
void SetCollectFreeThreshold(int freeBytes);
void SetMaxPausePercentage(int maxPausePercentage);
void SetMaxRawDeferredObjectFreePercentage(intptr maxPercentage);
void ExcludeThreadId(intptr threadId);
};
extern BFGC gBFGC;
@ -488,6 +493,7 @@ namespace bf
BFRT_EXPORT static void SetCollectFreeThreshold(intptr freeBytes);
BFRT_EXPORT static void SetMaxPausePercentage(intptr maxPausePercentage);
BFRT_EXPORT static void SetMaxRawDeferredObjectFreePercentage(intptr maxPercentage);
BFRT_EXPORT static void ExcludeThreadId(intptr threadId);
};
}
}

View file

@ -19,10 +19,11 @@ BFApp::BFApp()
mTitle = "Beefy Application";
mRefreshRate = 60;
mLastProcessTick = BFTickCount();
mFrameTimeAcc = 0;
mPhysFrameTimeAcc = 0;
mDrawEnabled = true;
mUpdateFunc = NULL;
mUpdateFFunc = NULL;
mDrawFunc = NULL;
gBFApp = this;
@ -43,6 +44,12 @@ BFApp::BFApp()
mRunning = false;
mRenderDevice = NULL;
mVSynched = false;
mVSyncActive = false;
mForceNextDraw = false;
mUpdateCnt = 0;
mUpdateCntF = 0;
mClientUpdateCntF = 0;
}
BFApp::~BFApp()
@ -90,10 +97,16 @@ void BFApp::Update(bool batchStart)
mPendingWindowDeleteList.clear();
}
void BFApp::UpdateF(float updatePct)
{
mUpdateFFunc(updatePct);
}
void BFApp::Draw()
{
gPerfManager->ZoneStart("BFApp::Draw");
mDrawFunc();
mDrawFunc(mForceNextDraw);
mForceNextDraw = false;
gPerfManager->ZoneEnd();
}
@ -103,18 +116,39 @@ void BFApp::Process()
{
//Beefy::DebugTimeGuard suspendTimeGuard(30, "BFApp::Process");
RenderWindow* headRenderWindow = NULL;
float physRefreshRate = 0;
if (!mRenderDevice->mRenderWindowList.IsEmpty())
{
headRenderWindow = mRenderDevice->mRenderWindowList[0];
physRefreshRate = headRenderWindow->GetRefreshRate();
}
if (physRefreshRate <= 0)
physRefreshRate = 60.0f;
float ticksPerFrame = 1;
float physTicksPerFrame = 1000.0f / physRefreshRate;
if (mInProcess)
return; // No reentry
mInProcess = true;
int updates;
uint32 tickNow = BFTickCount();
const int vSyncTestingPeriod = 250;
if (mRefreshRate != 0)
bool didVBlankWait = false;
if (mVSyncActive)
{
float ticksPerFrame = 1000.0f / mRefreshRate;
// Have a time limit in the cases we miss the vblank
if (mVSyncEvent.WaitFor((int)(physTicksPerFrame + 1)))
didVBlankWait = true;
}
if (mRefreshRate > 0)
ticksPerFrame = 1000.0f / mRefreshRate;
int ticksSinceLastProcess = tickNow - mLastProcessTick;
mUpdateSampleCount++;
@ -132,60 +166,37 @@ void BFApp::Process()
mVSynched = false;
}
else
{
if (!mVSyncFailed)
mVSynched = true;
}
mUpdateSampleCount = 0;
mUpdateSampleTimes = 0;
}
mFrameTimeAcc += tickNow - mLastProcessTick;
mPhysFrameTimeAcc += tickNow - mLastProcessTick;
bool vSynched = mVSynched;
if (vSynched)
if (didVBlankWait)
{
// For the startup, try not to go hyper during those first samplings
if (mUpdateSampleTimes <= vSyncTestingPeriod)
// Try to keep time synced with vblank
if (mPhysFrameTimeAcc < physTicksPerFrame * 2)
{
if (ticksSinceLastProcess < ticksPerFrame / 1.5)
vSynched = false;
float timeAdjust = physTicksPerFrame - mPhysFrameTimeAcc + 0.001f;
mPhysFrameTimeAcc += timeAdjust;
}
}
if (vSynched)
{
updates = std::max(1, (int)(mFrameTimeAcc / ticksPerFrame + 0.5f));
mFrameTimeAcc = std::max(0.0f, mFrameTimeAcc - ticksPerFrame * updates);
}
else
{
updates = std::max(0, (int)(mFrameTimeAcc / ticksPerFrame));
mFrameTimeAcc = mFrameTimeAcc - ticksPerFrame * updates;
}
if (updates > mRefreshRate)
{
// If more than 1 second of updates is queued, just re-sync
updates = 1;
mFrameTimeAcc = 0;
}
/*if (updates > 2)
OutputDebugStrF("Updates: %d TickDelta: %d\n", updates, tickNow - mLastProcessTick);*/
// Compensate for "slow start" by limiting the number of catchup-updates we can do when starting the app
int maxUpdates = BF_MIN(mNumPhysUpdates + 1, mMaxUpdatesPerDraw);
updates = BF_MIN(updates, maxUpdates);
/*if (updates > 2)
OutputDebugStrF("Updates: %d TickDelta: %d\n", updates, tickNow - mLastProcessTick);*/
}
else
updates = 1; // RefreshRate of 0 means to update as fast as possible
if (updates == 0)
while (mPhysFrameTimeAcc >= physTicksPerFrame)
{
// Yield
BfpThread_Sleep(1);
mPhysFrameTimeAcc -= physTicksPerFrame;
mUpdateCntF += physTicksPerFrame / ticksPerFrame;
}
static uint32 lastUpdate = BFTickCount();
@ -202,17 +213,46 @@ void BFApp::Process()
}
#endif
if (updates > 0)
mNumPhysUpdates++;
for (int updateNum = 0; updateNum < updates; updateNum++)
int didUpdateCnt = 0;
if (mClientUpdateCntF - mUpdateCntF > physRefreshRate / 2)
{
if (!mRunning)
break;
Update(updateNum == 0);
// Too large of a difference, just sync
mClientUpdateCntF = mUpdateCntF - 1;
}
if ((mRunning) && (updates > 0))
while ((int)mClientUpdateCntF < (int)mUpdateCntF)
{
Update(didUpdateCnt == 0);
didUpdateCnt++;
mClientUpdateCntF = (int)mClientUpdateCntF + 1.000001;
if (didUpdateCnt >= maxUpdates)
break;
}
// Only attempt UpdateF updates if our rates aren't nearl) the same
if ((mRefreshRate != 0) && (fabs(physRefreshRate - mRefreshRate) / (float)mRefreshRate > 0.1f))
{
float updateFAmt = (float)(mUpdateCntF - mClientUpdateCntF);
if ((updateFAmt > 0.05f) && (updateFAmt < 1.0f) && (didUpdateCnt < maxUpdates))
{
UpdateF(updateFAmt);
didUpdateCnt++;
mClientUpdateCntF = mUpdateCntF;
}
}
if (didUpdateCnt > 0)
mNumPhysUpdates++;
if ((mRunning) && (didUpdateCnt == 0))
{
BfpThread_Sleep(1);
}
if ((mRunning) &&
((didUpdateCnt != 0) || (mForceNextDraw)))
Draw();
#ifdef PERIODIC_PERF_TIMING
@ -229,6 +269,8 @@ void BFApp::Process()
void BFApp::RemoveWindow(BFWindow* window)
{
AutoCrit autoCrit(mCritSect);
auto itr = std::find(mWindowList.begin(), mWindowList.end(), window);
if (itr == mWindowList.end()) // Allow benign failure (double removal)
return;

View file

@ -1,12 +1,14 @@
#pragma once
#include "Common.h"
#include "util/CritSect.h"
#include <list>
NS_BF_BEGIN;
typedef void (*BFApp_UpdateFunc)(bool batchStart);
typedef void (*BFApp_DrawFunc)();
typedef void (*BFApp_UpdateFFunc)(float updatePct);
typedef void (*BFApp_DrawFunc)(bool forceDraw);
class BFApp;
class BFSoundManager;
@ -50,12 +52,15 @@ public:
class BFApp
{
public:
CritSect mCritSect;
String mTitle;
String mInstallDir;
String mDataDir;
bool mDrawEnabled;
float mRefreshRate;
int mMaxUpdatesPerDraw;
double mUpdateCntF;
double mClientUpdateCntF;
bool mInProcess;
bool mRunning;
@ -63,16 +68,20 @@ public:
int mSysDialogCnt;
int mUpdateCnt;
int mNumPhysUpdates;
SyncEvent mVSyncEvent;
volatile bool mVSyncActive;
bool mVSynched;
bool mVSyncFailed;
bool mForceNextDraw;
int mUpdateSampleCount;
int mUpdateSampleTimes;
uint32 mLastProcessTick;
float mFrameTimeAcc;
float mPhysFrameTimeAcc;
BFApp_UpdateFunc mUpdateFunc;
BFApp_UpdateFFunc mUpdateFFunc;
BFApp_DrawFunc mDrawFunc;
int mCursor;
@ -81,6 +90,7 @@ public:
public:
virtual void Update(bool batchStart);
virtual void UpdateF(float updatePct);
virtual void Draw();
virtual void Process();
virtual void PhysSetCursor() = 0;
@ -114,6 +124,8 @@ public:
virtual FileStream* OpenBinaryFile(const StringImpl& fileName);
virtual BFSoundManager* GetSoundManager() { return NULL; }
virtual intptr GetCriticalThreadId(int idx) { return 0; }
};
extern BFApp* gBFApp;

View file

@ -210,9 +210,10 @@ BF_EXPORT const char* BF_CALLTYPE BFApp_GetDataDir()
return gBFApp->mDataDir.c_str();
}
BF_EXPORT void BF_CALLTYPE BFApp_SetCallbacks(BFApp_UpdateFunc updateFunc, BFApp_DrawFunc drawFunc)
BF_EXPORT void BF_CALLTYPE BFApp_SetCallbacks(BFApp_UpdateFunc updateFunc, BFApp_UpdateFFunc updateFFunc, BFApp_DrawFunc drawFunc)
{
gBFApp->mUpdateFunc = updateFunc;
gBFApp->mUpdateFFunc = updateFFunc;
gBFApp->mDrawFunc = drawFunc;
//public delegate void UpdateProc();
}
@ -276,6 +277,11 @@ BF_EXPORT BFSoundManager* BF_CALLTYPE BFApp_GetSoundManager()
return gBFApp->GetSoundManager();
}
BF_EXPORT intptr BF_CALLTYPE BFApp_GetCriticalThreadId(int idx)
{
return gBFApp->GetCriticalThreadId(idx);
}
///
BF_EXPORT void BF_CALLTYPE BFWindow_SetCallbacks(BFWindow* window, BFWindow_MovedFunc movedFunc, BFWindow_CloseQueryFunc closeQueryFunc, BFWindow_ClosedFunc closedFunc,

View file

@ -62,6 +62,7 @@ RenderDevice::RenderDevice() :
mCurRenderTarget = NULL;
mCurDrawLayer = NULL;
mPhysRenderWindow = NULL;
mApp = NULL;
}
RenderDevice::~RenderDevice()

View file

@ -76,6 +76,8 @@ public:
virtual void SetAsTarget() = 0;
virtual void Resized() = 0;
virtual void Present() = 0;
virtual float GetRefreshRate() { return 60.0f; }
virtual bool WaitForVBlank() { return false; }
};
const int DRAWBUFFER_IDXBUFFER_SIZE = 8*1024;
@ -175,6 +177,14 @@ public:
mElementData = NULL;
mNumElements = 0;
}
VertexDefinition(VertexDefinition* src)
{
mElementData = new VertexDefData[src->mNumElements];
mNumElements = src->mNumElements;
memcpy(mElementData, src->mElementData, sizeof(VertexDefData) * mNumElements);
}
virtual ~VertexDefinition()
{
delete [] mElementData;
@ -262,6 +272,7 @@ class RenderDevice
public:
Array<DrawBatch*> mDrawBatchPool;
BFApp* mApp;
RenderWindow* mPhysRenderWindow;
RenderState* mPhysRenderState;
int mResizeCount;

View file

@ -18,6 +18,7 @@ using namespace DirectX;
//#include <D3DX11async.h>
//#include <D3DX10math.h>
//#include <DxErr.h>
#include <dxgi1_3.h>
#pragma warning(pop)
#include "util/AllocDebug.h"
@ -192,6 +193,7 @@ void DXShaderParam::SetFloat4(float x, float y, float z, float w)
DXShader::DXShader()
{
//? mD3DEffect = NULL;
mVertexDef = NULL;
mD3DPixelShader = NULL;
mD3DVertexShader = NULL;
mD3DLayout = NULL;
@ -201,25 +203,235 @@ DXShader::DXShader()
DXShader::~DXShader()
{
DXShaderParamMap::iterator itr = mParamsMap.begin();
while (itr != mParamsMap.end())
{
delete itr->second;
++itr;
}
if (mD3DLayout != NULL)
mD3DLayout->Release();
if (mD3DVertexShader != NULL)
mD3DVertexShader->Release();
if (mD3DPixelShader != NULL)
mD3DPixelShader->Release();
if (mConstBuffer != NULL)
mConstBuffer->Release();
delete mVertexDef;
ReleaseNative();
//? if (mD3DEffect != NULL)
//? mD3DEffect->Release();
}
void DXShader::ReleaseNative()
{
if (mD3DLayout != NULL)
mD3DLayout->Release();
mD3DLayout = NULL;
if (mD3DVertexShader != NULL)
mD3DVertexShader->Release();
mD3DVertexShader = NULL;
if (mD3DPixelShader != NULL)
mD3DPixelShader->Release();
mD3DPixelShader = NULL;
if (mConstBuffer != NULL)
mConstBuffer->Release();
mConstBuffer = NULL;
}
extern "C"
typedef HRESULT(WINAPI* Func_D3DX10CompileFromFileW)(LPCWSTR pSrcFile, CONST D3D10_SHADER_MACRO* pDefines, LPD3D10INCLUDE pInclude,
LPCSTR pFunctionName, LPCSTR pProfile, UINT Flags1, UINT Flags2, ID3D10Blob** ppShader, ID3D10Blob** ppErrorMsgs);
static Func_D3DX10CompileFromFileW gFunc_D3DX10CompileFromFileW;
static bool LoadDXShader(const StringImpl& filePath, const StringImpl& entry, const StringImpl& profile, ID3D10Blob** outBuffer)
{
HRESULT hr;
String outObj = filePath + "_" + entry + "_" + profile;
bool useCache = false;
auto srcDate = ::BfpFile_GetTime_LastWrite(filePath.c_str());
auto cacheDate = ::BfpFile_GetTime_LastWrite(outObj.c_str());
if (cacheDate >= srcDate)
useCache = true;
if (!useCache)
{
if (gFunc_D3DX10CompileFromFileW == NULL)
{
auto lib = LoadLibraryA("D3DCompiler_47.dll");
if (lib != NULL)
gFunc_D3DX10CompileFromFileW = (Func_D3DX10CompileFromFileW)::GetProcAddress(lib, "D3DCompileFromFile");
}
if (gFunc_D3DX10CompileFromFileW == NULL)
useCache = true;
}
if (!useCache)
{
if (gFunc_D3DX10CompileFromFileW == NULL)
{
auto lib = LoadLibraryA("D3DCompiler_47.dll");
if (lib != NULL)
gFunc_D3DX10CompileFromFileW = (Func_D3DX10CompileFromFileW)::GetProcAddress(lib, "D3DCompileFromFile");
}
ID3D10Blob* errorMessage = NULL;
auto dxResult = gFunc_D3DX10CompileFromFileW(UTF8Decode(filePath).c_str(), NULL, NULL, entry.c_str(), profile.c_str(),
D3D10_SHADER_DEBUG | D3D10_SHADER_ENABLE_STRICTNESS, 0, outBuffer, &errorMessage);
if (DXFAILED(dxResult))
{
if (errorMessage != NULL)
{
BF_FATAL(StrFormat("Vertex shader load failed: %s", (char*)errorMessage->GetBufferPointer()).c_str());
errorMessage->Release();
}
else
BF_FATAL("Shader load failed");
return false;
}
auto ptr = (*outBuffer)->GetBufferPointer();
int size = (int)(*outBuffer)->GetBufferSize();
FILE* fp = fopen(outObj.c_str(), "wb");
if (fp != NULL)
{
fwrite(ptr, 1, size, fp);
fclose(fp);
}
return true;
}
FILE* fp = fopen(outObj.c_str(), "rb");
if (fp == NULL)
{
BF_FATAL("Failed to load compiled shader");
return false;
}
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
fseek(fp, 0, SEEK_SET);
D3D10CreateBlob(size, outBuffer);
auto ptr = (*outBuffer)->GetBufferPointer();
fread(ptr, 1, size, fp);
fclose(fp);
return true;
}
bool DXShader::Load()
{
//HRESULT hr;
ID3D10Blob* errorMessage = NULL;
ID3D10Blob* vertexShaderBuffer = NULL;
ID3D10Blob* pixelShaderBuffer = NULL;
LoadDXShader(mSrcPath + ".fx", "VS", "vs_4_0", &vertexShaderBuffer);
LoadDXShader(mSrcPath + ".fx", "PS", "ps_4_0", &pixelShaderBuffer);
defer(
{
vertexShaderBuffer->Release();
pixelShaderBuffer->Release();
});
mHas2DPosition = false;
mVertexSize = 0;
mD3DLayout = NULL;
static const char* semanticNames[] = {
"POSITION",
"POSITION",
"COLOR",
"TEXCOORD",
"NORMAL",
"BINORMAL",
"TANGENT",
"BLENDINDICES",
"BLENDWEIGHT",
"DEPTH",
"FOG",
"POINTSIZE",
"SAMPLE",
"TESSELLATEFACTOR" };
static const DXGI_FORMAT dxgiFormat[] = {
DXGI_FORMAT_R32_FLOAT/*VertexElementFormat_Single*/,
DXGI_FORMAT_R32G32_FLOAT/*VertexElementFormat_Vector2*/,
DXGI_FORMAT_R32G32B32_FLOAT/*VertexElementFormat_Vector3*/,
DXGI_FORMAT_R32G32B32A32_FLOAT/*VertexElementFormat_Vector4*/,
DXGI_FORMAT_R8G8B8A8_UNORM/*VertexElementFormat_Color*/,
DXGI_FORMAT_R8G8B8A8_UINT/*VertexElementFormat_Byte4*/,
DXGI_FORMAT_R16G16_UINT/*VertexElementFormat_Short2*/,
DXGI_FORMAT_R16G16B16A16_UINT/*VertexElementFormat_Short4*/,
DXGI_FORMAT_R16G16_UNORM/*VertexElementFormat_NormalizedShort2*/,
DXGI_FORMAT_R16G16B16A16_UNORM/*VertexElementFormat_NormalizedShort4*/,
DXGI_FORMAT_R16G16_FLOAT/*VertexElementFormat_HalfVector2*/,
DXGI_FORMAT_R16G16B16A16_FLOAT/*VertexElementFormat_HalfVector4*/
};
static const int dxgiSize[] = {
sizeof(float) * 1/*VertexElementFormat_Single*/,
sizeof(float) * 2/*VertexElementFormat_Vector2*/,
sizeof(float) * 3/*VertexElementFormat_Vector3*/,
sizeof(float) * 4/*VertexElementFormat_Vector4*/,
sizeof(uint32)/*VertexElementFormat_Color*/,
sizeof(uint8) * 4/*VertexElementFormat_Byte4*/,
sizeof(uint16) * 2/*VertexElementFormat_Short2*/,
sizeof(uint16) * 4/*VertexElementFormat_Short4*/,
sizeof(uint16) * 2/*VertexElementFormat_NormalizedShort2*/,
sizeof(uint16) * 4/*VertexElementFormat_NormalizedShort4*/,
sizeof(uint16) * 2/*VertexElementFormat_HalfVector2*/,
sizeof(uint16) * 4/*VertexElementFormat_HalfVector4*/
};
D3D11_INPUT_ELEMENT_DESC layout[64];
for (int elementIdx = 0; elementIdx < mVertexDef->mNumElements; elementIdx++)
{
VertexDefData* vertexDefData = &mVertexDef->mElementData[elementIdx];
if (vertexDefData->mUsage == VertexElementUsage_Position2D)
mHas2DPosition = true;
D3D11_INPUT_ELEMENT_DESC* elementDesc = &layout[elementIdx];
elementDesc->SemanticName = semanticNames[vertexDefData->mUsage];
elementDesc->SemanticIndex = vertexDefData->mUsageIndex;
elementDesc->Format = dxgiFormat[vertexDefData->mFormat];
elementDesc->InputSlot = 0;
elementDesc->AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
elementDesc->InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
elementDesc->InstanceDataStepRate = 0;
mVertexSize += dxgiSize[vertexDefData->mFormat];
}
/* =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = sizeof(layout) / sizeof(layout[0]);*/
HRESULT result = mRenderDevice->mD3DDevice->CreateInputLayout(layout, mVertexDef->mNumElements, vertexShaderBuffer->GetBufferPointer(),
vertexShaderBuffer->GetBufferSize(), &mD3DLayout);
DXCHECK(result);
if (FAILED(result))
return false;
// Create the vertex shader from the buffer.
result = mRenderDevice->mD3DDevice->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &mD3DVertexShader);
DXCHECK(result);
if (FAILED(result))
return false;
// Create the pixel shader from the buffer.
result = mRenderDevice->mD3DDevice->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &mD3DPixelShader);
DXCHECK(result);
if (FAILED(result))
return false;
Init();
return true;
}
void DXShader::ReinitNative()
{
ReleaseNative();
Load();
}
ShaderParam* DXShader::GetShaderParam(const StringImpl& name)
{
DXShaderParamMap::iterator itr = mParamsMap.find(name);
@ -249,7 +461,7 @@ DXTexture::DXTexture()
mRenderDevice = NULL;
mD3DDepthBuffer = NULL;
mD3DDepthStencilView = NULL;
mImageData = NULL;
mContentBits = NULL;
}
DXTexture::~DXTexture()
@ -258,7 +470,7 @@ DXTexture::~DXTexture()
((DXRenderDevice*)mRenderDevice)->mTextureMap.Remove(mPath);
//OutputDebugStrF("DXTexture::~DXTexture %@\n", this);
delete mImageData;
delete mContentBits;
if (mD3DResourceView != NULL)
mD3DResourceView->Release();
if (mD3DDepthStencilView != NULL)
@ -267,6 +479,8 @@ DXTexture::~DXTexture()
mD3DDepthBuffer->Release();
if (mD3DTexture != NULL)
mD3DTexture->Release();
if (mRenderDevice != NULL)
mRenderDevice->mTextures.Remove(this);
}
void DXTexture::ReleaseNative()
@ -297,6 +511,44 @@ void DXTexture::ReleaseNative()
void DXTexture::ReinitNative()
{
ReleaseNative();
int aWidth = 0;
int aHeight = 0;
D3D11_SUBRESOURCE_DATA resData;
resData.pSysMem = mContentBits;
resData.SysMemPitch = mWidth * 4;
resData.SysMemSlicePitch = mWidth * mHeight * 4;
// Create the target texture
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = mWidth;
desc.Height = mHeight;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
//OutputDebugStrF("Creating texture\n");
auto dxRenderDevice = (DXRenderDevice*)mRenderDevice;
DXCHECK(dxRenderDevice->mD3DDevice->CreateTexture2D(&desc, (mContentBits != NULL) ? &resData : NULL, &mD3DTexture));
D3D11_SHADER_RESOURCE_VIEW_DESC srDesc;
srDesc.Format = desc.Format;
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srDesc.Texture2D.MostDetailedMip = 0;
srDesc.Texture2D.MipLevels = 1;
DXCHECK(dxRenderDevice->mD3DDevice->CreateShaderResourceView(mD3DTexture, &srDesc, &mD3DResourceView));
OutputDebugStrF("DXTexture::ReinitNative %p\n", this);
}
void DXTexture::PhysSetAsTarget()
@ -338,12 +590,24 @@ void DXTexture::Blt(ImageData* imageData, int x, int y)
box.front = 0;
box.back = 1;
mRenderDevice->mD3DDeviceContext->UpdateSubresource(mD3DTexture, 0, &box, imageData->mBits, imageData->mWidth * sizeof(uint32), 0);
if (mContentBits != NULL)
{
for (int yOfs = 0; yOfs < imageData->mHeight; yOfs++)
memcpy(mContentBits + x + (y + yOfs) * mWidth, imageData->mBits + yOfs * imageData->mWidth, imageData->mWidth * 4);
}
}
void DXTexture::SetBits(int destX, int destY, int destWidth, int destHeight, int srcPitch, uint32* bits)
{
D3D11_BOX box = { (UINT)destX, (UINT)destY, (UINT)0, (UINT)(destX + destWidth), (UINT)(destY + destHeight), 1 };
mRenderDevice->mD3DDeviceContext->UpdateSubresource(mD3DTexture, 0, &box, bits, srcPitch * sizeof(uint32), 0);
if (mContentBits != NULL)
{
for (int y = 0; y < destHeight; y++)
memcpy(mContentBits + destX + (destY + y) * mWidth, bits + (y * srcPitch), destWidth * 4);
}
}
void DXTexture::GetBits(int srcX, int srcY, int srcWidth, int srcHeight, int destPitch, uint32* bits)
@ -532,6 +796,8 @@ void DXRenderDevice::PhysSetRenderState(RenderState* renderState)
{
HRESULT result = NULL;
if (mMatrix2DBuffer == NULL)
{
D3D11_BUFFER_DESC matrixBufferDesc;
matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
matrixBufferDesc.ByteWidth = sizeof(float[4]);
@ -540,12 +806,8 @@ void DXRenderDevice::PhysSetRenderState(RenderState* renderState)
matrixBufferDesc.MiscFlags = 0;
matrixBufferDesc.StructureByteStride = 0;
static ID3D11Buffer* matrixBuffer = NULL;
if (matrixBuffer == NULL)
{
// Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class.
result = mD3DDevice->CreateBuffer(&matrixBufferDesc, NULL, &matrixBuffer);
result = mD3DDevice->CreateBuffer(&matrixBufferDesc, NULL, &mMatrix2DBuffer);
if (FAILED(result))
{
return;
@ -554,7 +816,7 @@ void DXRenderDevice::PhysSetRenderState(RenderState* renderState)
// Lock the constant buffer so it can be written to.
D3D11_MAPPED_SUBRESOURCE mappedResource;
result = mD3DDeviceContext->Map(matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
result = mD3DDeviceContext->Map(mMatrix2DBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
return;
@ -568,10 +830,10 @@ void DXRenderDevice::PhysSetRenderState(RenderState* renderState)
dataPtr[3] = 0;
// Unlock the constant buffer.
mD3DDeviceContext->Unmap(matrixBuffer, 0);
mD3DDeviceContext->Unmap(mMatrix2DBuffer, 0);
//float params[4] = {mCurRenderTarget->mWidth, mCurRenderTarget->mHeight, 0, 0};
mD3DDeviceContext->VSSetConstantBuffers(0, 1, &matrixBuffer);
mD3DDeviceContext->VSSetConstantBuffers(0, 1, &mMatrix2DBuffer);
}
}
@ -1003,7 +1265,7 @@ void DXRenderState::ReleaseNative()
void DXRenderState::ReinitNative()
{
ReleaseNative();
}
void DXRenderState::InvalidateRasterizerState()
@ -1264,6 +1526,8 @@ DXRenderWindow::DXRenderWindow(DXRenderDevice* renderDevice, WinBFWindow* window
mD3DRenderTargetView = NULL;
mD3DDepthBuffer = NULL;
mD3DDepthStencilView = NULL;
mRefreshRate = 0;
mFrameWaitObject = NULL;
mRenderDevice = renderDevice;
mDXRenderDevice = renderDevice;
@ -1275,30 +1539,31 @@ DXRenderWindow::DXRenderWindow(DXRenderDevice* renderDevice, WinBFWindow* window
ReinitNative();
}
DXRenderWindow::~DXRenderWindow()
{
ReleaseNative();
}
void DXRenderWindow::ReleaseNative()
{
if (mFrameWaitObject != NULL)
::CloseHandle(mFrameWaitObject);
mFrameWaitObject = NULL;
if (mD3DRenderTargetView != NULL)
{
mD3DRenderTargetView->Release();
mD3DRenderTargetView = NULL;
}
if (mD3DBackBuffer != NULL)
{
mD3DBackBuffer->Release();
mD3DBackBuffer = NULL;
}
if (mDXSwapChain != NULL)
{
mDXSwapChain->Release();
mDXSwapChain = NULL;
}
if (mD3DRenderTargetView != NULL)
mD3DRenderTargetView->Release();
mD3DRenderTargetView = NULL;
if (mD3DDepthStencilView != NULL)
mD3DDepthStencilView->Release();
mD3DDepthStencilView = NULL;
}
void DXRenderWindow::ReinitNative()
@ -1314,8 +1579,8 @@ void DXRenderWindow::ReinitNative()
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Windowed = mWindowed ? TRUE : FALSE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;// DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH /*| DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT*/;
IDXGIDevice* pDXGIDevice = NULL;
mDXRenderDevice->mD3DDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDXGIDevice);
@ -1324,6 +1589,14 @@ void DXRenderWindow::ReinitNative()
pDXGIDevice->Release();
pDXGIDevice = NULL;
// IDXGISwapChain2* swapChain2 = NULL;
// mDXSwapChain->QueryInterface(__uuidof(IDXGISwapChain2), (void**)&swapChain2);
// if (swapChain2 != NULL)
// {
// mFrameWaitObject = swapChain2->GetFrameLatencyWaitableObject();
// swapChain2->Release();
// }
DXCHECK(mDXSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mD3DBackBuffer));
DXCHECK(mDXRenderDevice->mD3DDevice->CreateRenderTargetView(mD3DBackBuffer, NULL, &mD3DRenderTargetView));
@ -1406,7 +1679,14 @@ void DXRenderWindow::Resized()
mD3DDepthBuffer->Release();
mD3DRenderTargetView->Release();
mD3DDepthStencilView->Release();
DXCHECK(mDXSwapChain->ResizeBuffers(0, mWidth, mHeight, DXGI_FORMAT_UNKNOWN, 0));
HRESULT hr = mDXSwapChain->ResizeBuffers(0, mWidth, mHeight, DXGI_FORMAT_UNKNOWN,
DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH /*| DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT*/);
if ((hr == DXGI_ERROR_DEVICE_REMOVED) || (hr == DXGI_ERROR_DEVICE_RESET))
((DXRenderDevice*)mRenderDevice)->mNeedsReinitNative = true;
else
DXCHECK(hr);
D3D11_TEXTURE2D_DESC descDepth;
ZeroMemory(&descDepth, sizeof(descDepth));
@ -1435,8 +1715,10 @@ void DXRenderWindow::Resized()
void DXRenderWindow::Present()
{
mDXSwapChain->Present((mWindow->mFlags & BFWINDOW_VSYNC) ? 1 : 0, 0);
//DXCHECK();
HRESULT hr = mDXSwapChain->Present((mWindow->mFlags & BFWINDOW_VSYNC) ? 1 : 0, 0);
if ((hr == DXGI_ERROR_DEVICE_REMOVED) || (hr == DXGI_ERROR_DEVICE_RESET))
((DXRenderDevice*)mRenderDevice)->mNeedsReinitNative = true;
}
void DXRenderWindow::CopyBitsTo(uint32* dest, int width, int height)
@ -1476,21 +1758,102 @@ void DXRenderWindow::CopyBitsTo(uint32* dest, int width, int height)
texture->Release();
}
float DXRenderWindow::GetRefreshRate()
{
if (mRefreshRate == 0)
{
mRefreshRate = -1;
IDXGIOutput* output = NULL;
mDXSwapChain->GetContainingOutput(&output);
if (output != NULL)
{
DXGI_OUTPUT_DESC outputDesc;
output->GetDesc(&outputDesc);
MONITORINFOEXW info;
info.cbSize = sizeof(info);
// get the associated monitor info
if (GetMonitorInfoW(outputDesc.Monitor, &info) != 0)
{
// using the CCD get the associated path and display configuration
UINT32 requiredPaths, requiredModes;
if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &requiredPaths, &requiredModes) == ERROR_SUCCESS)
{
std::vector<DISPLAYCONFIG_PATH_INFO> paths(requiredPaths);
std::vector<DISPLAYCONFIG_MODE_INFO> modes2(requiredModes);
if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &requiredPaths, paths.data(), &requiredModes, modes2.data(), nullptr) == ERROR_SUCCESS)
{
// iterate through all the paths until find the exact source to match
for (auto& p : paths)
{
DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName;
sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
sourceName.header.size = sizeof(sourceName);
sourceName.header.adapterId = p.sourceInfo.adapterId;
sourceName.header.id = p.sourceInfo.id;
if (DisplayConfigGetDeviceInfo(&sourceName.header) == ERROR_SUCCESS)
{
// find the matched device which is associated with current device
// there may be the possibility that display may be duplicated and windows may be one of them in such scenario
// there may be two callback because source is same target will be different
// as window is on both the display so either selecting either one is ok
if (wcscmp(info.szDevice, sourceName.viewGdiDeviceName) == 0)
{
// get the refresh rate
UINT numerator = p.targetInfo.refreshRate.Numerator;
UINT denominator = p.targetInfo.refreshRate.Denominator;
mRefreshRate = (float)numerator / (float)denominator;
break;
}
}
}
}
}
}
output->Release();
}
}
return mRefreshRate;
}
bool DXRenderWindow::WaitForVBlank()
{
IDXGIOutput* output = NULL;
mDXSwapChain->GetContainingOutput(&output);
if (output == NULL)
return false;
bool success = output->WaitForVBlank() == 0;
return success;
}
///
DXRenderDevice::DXRenderDevice()
{
mD3DDevice = NULL;
mNeedsReinitNative = false;
mMatrix2DBuffer = NULL;
}
DXRenderDevice::~DXRenderDevice()
{
for (auto& kv : mTextureMap)
kv.mValue->mRenderDevice = NULL;
for (auto window : mRenderWindowList)
((DXRenderWindow*)window)->ReleaseNative();
for (auto shader : mShaders)
shader->ReleaseNative();
for (auto renderState : mRenderStates)
renderState->ReleaseNative();
for (auto texture : mTextures)
{
texture->ReleaseNative();
texture->mRenderDevice = NULL;
}
ReleaseNative();
mD3DVertexBuffer->Release();
mD3DIndexBuffer->Release();
delete mDefaultRenderState;
}
@ -1498,6 +1861,7 @@ bool DXRenderDevice::Init(BFApp* app)
{
BP_ZONE("DXRenderDevice::Init");
mApp = app;
WinBFApp* winApp = (WinBFApp*) app;
D3D_FEATURE_LEVEL featureLevelArr[] =
@ -1626,6 +1990,9 @@ void DXRenderDevice::ReleaseNative()
{
mD3DVertexBuffer->Release();
mD3DVertexBuffer = NULL;
if (mMatrix2DBuffer != NULL)
mMatrix2DBuffer->Release();
mMatrix2DBuffer = NULL;
mD3DIndexBuffer->Release();
mD3DIndexBuffer = NULL;
mD3DNormalBlendState->Release();
@ -1636,20 +2003,37 @@ void DXRenderDevice::ReleaseNative()
mD3DWrapSamplerState = NULL;
mD3DDeviceContext->Release();
mD3DDeviceContext = NULL;
// ID3D11Debug* debug = NULL;
// mD3DDevice->QueryInterface(__uuidof(ID3D11Debug), (void**)&debug);
// if (debug != NULL)
// {
// debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
// debug->Release();
// }
mD3DDevice->Release();
mD3DDevice = NULL;
}
void DXRenderDevice::ReinitNative()
{
Init(NULL);
AutoCrit autoCrit(mApp->mCritSect);
if (mMatrix2DBuffer != NULL)
mMatrix2DBuffer->Release();
mMatrix2DBuffer = NULL;
Init(mApp);
for (auto window : mRenderWindowList)
((DXRenderWindow*)window)->ReinitNative();
for (auto kv : mRenderStates)
kv->ReinitNative();
for (auto kv : mRenderStates)
kv->ReinitNative();
for (auto shader : mShaders)
shader->ReinitNative();
for (auto renderState : mRenderStates)
renderState->ReinitNative();
for (auto tex : mTextures)
tex->ReinitNative();
}
void DXRenderDevice::FrameStart()
@ -1918,6 +2302,10 @@ Texture* DXRenderDevice::LoadTexture(ImageData* imageData, int flags)
DXCHECK(mD3DDevice->CreateShaderResourceView(d3DTexture, &srDesc, &d3DShaderResourceView));
DXTexture* aTexture = new DXTexture();
aTexture->mContentBits = new uint32[aWidth * aHeight];
memcpy(aTexture->mContentBits, imageData->mBits, aWidth * aHeight * 4);
aTexture->mRenderDevice = this;
aTexture->mWidth = aWidth;
aTexture->mHeight = aHeight;
@ -1976,203 +2364,20 @@ Texture* DXRenderDevice::CreateDynTexture(int width, int height)
return aTexture;
}
extern "C"
typedef HRESULT (WINAPI* Func_D3DX10CompileFromFileW)(LPCWSTR pSrcFile, CONST D3D10_SHADER_MACRO* pDefines, LPD3D10INCLUDE pInclude,
LPCSTR pFunctionName, LPCSTR pProfile, UINT Flags1, UINT Flags2, ID3D10Blob** ppShader, ID3D10Blob** ppErrorMsgs);
static Func_D3DX10CompileFromFileW gFunc_D3DX10CompileFromFileW;
static bool LoadDXShader(const StringImpl& filePath, const StringImpl& entry, const StringImpl& profile, ID3D10Blob** outBuffer)
{
HRESULT hr;
String outObj = filePath + "_" + entry + "_" + profile;
bool useCache = false;
auto srcDate = ::BfpFile_GetTime_LastWrite(filePath.c_str());
auto cacheDate = ::BfpFile_GetTime_LastWrite(outObj.c_str());
if (cacheDate >= srcDate)
useCache = true;
if (!useCache)
{
if (gFunc_D3DX10CompileFromFileW == NULL)
{
auto lib = LoadLibraryA("D3DCompiler_47.dll");
if (lib != NULL)
gFunc_D3DX10CompileFromFileW = (Func_D3DX10CompileFromFileW)::GetProcAddress(lib, "D3DCompileFromFile");
}
if (gFunc_D3DX10CompileFromFileW == NULL)
useCache = true;
}
if (!useCache)
{
if (gFunc_D3DX10CompileFromFileW == NULL)
{
auto lib = LoadLibraryA("D3DCompiler_47.dll");
if (lib != NULL)
gFunc_D3DX10CompileFromFileW = (Func_D3DX10CompileFromFileW)::GetProcAddress(lib, "D3DCompileFromFile");
}
ID3D10Blob* errorMessage = NULL;
auto dxResult = gFunc_D3DX10CompileFromFileW(UTF8Decode(filePath).c_str(), NULL, NULL, entry.c_str(), profile.c_str(),
D3D10_SHADER_DEBUG | D3D10_SHADER_ENABLE_STRICTNESS, 0, outBuffer, &errorMessage);
if (DXFAILED(dxResult))
{
if (errorMessage != NULL)
{
BF_FATAL(StrFormat("Vertex shader load failed: %s", (char*)errorMessage->GetBufferPointer()).c_str());
errorMessage->Release();
}
else
BF_FATAL("Shader load failed");
return false;
}
auto ptr = (*outBuffer)->GetBufferPointer();
int size = (int)(*outBuffer)->GetBufferSize();
FILE* fp = fopen(outObj.c_str(), "wb");
if (fp != NULL)
{
fwrite(ptr, 1, size, fp);
fclose(fp);
}
return true;
}
FILE* fp = fopen(outObj.c_str(), "rb");
if (fp == NULL)
{
BF_FATAL("Failed to load compiled shader");
return false;
}
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
fseek(fp, 0, SEEK_SET);
D3D10CreateBlob(size, outBuffer);
auto ptr = (*outBuffer)->GetBufferPointer();
fread(ptr, 1, size, fp);
fclose(fp);
return true;
}
Shader* DXRenderDevice::LoadShader(const StringImpl& fileName, VertexDefinition* vertexDefinition)
{
BP_ZONE("DXRenderDevice::LoadShader");
//HRESULT hr;
ID3D10Blob* errorMessage = NULL;
ID3D10Blob* vertexShaderBuffer = NULL;
ID3D10Blob* pixelShaderBuffer = NULL;
LoadDXShader(fileName + ".fx", "VS", "vs_4_0", &vertexShaderBuffer);
LoadDXShader(fileName + ".fx", "PS", "ps_4_0", &pixelShaderBuffer);
DXShader* dxShader = new DXShader();
dxShader->mVertexSize = 0;
dxShader->mD3DLayout = NULL;
static const char* semanticNames[] = {
"POSITION",
"POSITION",
"COLOR",
"TEXCOORD",
"NORMAL",
"BINORMAL",
"TANGENT",
"BLENDINDICES",
"BLENDWEIGHT",
"DEPTH",
"FOG",
"POINTSIZE",
"SAMPLE",
"TESSELLATEFACTOR"};
static const DXGI_FORMAT dxgiFormat[] = {
DXGI_FORMAT_R32_FLOAT/*VertexElementFormat_Single*/,
DXGI_FORMAT_R32G32_FLOAT/*VertexElementFormat_Vector2*/,
DXGI_FORMAT_R32G32B32_FLOAT/*VertexElementFormat_Vector3*/,
DXGI_FORMAT_R32G32B32A32_FLOAT/*VertexElementFormat_Vector4*/,
DXGI_FORMAT_R8G8B8A8_UNORM/*VertexElementFormat_Color*/,
DXGI_FORMAT_R8G8B8A8_UINT/*VertexElementFormat_Byte4*/,
DXGI_FORMAT_R16G16_UINT/*VertexElementFormat_Short2*/,
DXGI_FORMAT_R16G16B16A16_UINT/*VertexElementFormat_Short4*/,
DXGI_FORMAT_R16G16_UNORM/*VertexElementFormat_NormalizedShort2*/,
DXGI_FORMAT_R16G16B16A16_UNORM/*VertexElementFormat_NormalizedShort4*/,
DXGI_FORMAT_R16G16_FLOAT/*VertexElementFormat_HalfVector2*/,
DXGI_FORMAT_R16G16B16A16_FLOAT/*VertexElementFormat_HalfVector4*/
};
static const int dxgiSize[] = {
sizeof(float) * 1/*VertexElementFormat_Single*/,
sizeof(float) * 2/*VertexElementFormat_Vector2*/,
sizeof(float) * 3/*VertexElementFormat_Vector3*/,
sizeof(float) * 4/*VertexElementFormat_Vector4*/,
sizeof(uint32)/*VertexElementFormat_Color*/,
sizeof(uint8) * 4/*VertexElementFormat_Byte4*/,
sizeof(uint16) * 2/*VertexElementFormat_Short2*/,
sizeof(uint16) * 4/*VertexElementFormat_Short4*/,
sizeof(uint16) * 2/*VertexElementFormat_NormalizedShort2*/,
sizeof(uint16) * 4/*VertexElementFormat_NormalizedShort4*/,
sizeof(uint16) * 2/*VertexElementFormat_HalfVector2*/,
sizeof(uint16) * 4/*VertexElementFormat_HalfVector4*/
};
D3D11_INPUT_ELEMENT_DESC layout[64];
for (int elementIdx = 0; elementIdx < vertexDefinition->mNumElements; elementIdx++)
dxShader->mRenderDevice = this;
dxShader->mSrcPath = fileName;
dxShader->mVertexDef = new VertexDefinition(vertexDefinition);
if (!dxShader->Load())
{
VertexDefData* vertexDefData = &vertexDefinition->mElementData[elementIdx];
if (vertexDefData->mUsage == VertexElementUsage_Position2D)
dxShader->mHas2DPosition = true;
D3D11_INPUT_ELEMENT_DESC* elementDesc = &layout[elementIdx];
elementDesc->SemanticName = semanticNames[vertexDefData->mUsage];
elementDesc->SemanticIndex = vertexDefData->mUsageIndex;
elementDesc->Format = dxgiFormat[vertexDefData->mFormat];
elementDesc->InputSlot = 0;
elementDesc->AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
elementDesc->InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
elementDesc->InstanceDataStepRate = 0;
dxShader->mVertexSize += dxgiSize[vertexDefData->mFormat];
delete dxShader;
return NULL;
}
/* =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = sizeof(layout) / sizeof(layout[0]);*/
HRESULT result = mD3DDevice->CreateInputLayout(layout, vertexDefinition->mNumElements, vertexShaderBuffer->GetBufferPointer(),
vertexShaderBuffer->GetBufferSize(), &dxShader->mD3DLayout);
DXCHECK(result);
if (FAILED(result))
return NULL;
// Create the vertex shader from the buffer.
result = mD3DDevice->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &dxShader->mD3DVertexShader);
DXCHECK(result);
if (FAILED(result))
return NULL;
// Create the pixel shader from the buffer.
result = mD3DDevice->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &dxShader->mD3DPixelShader);
DXCHECK(result);
if (FAILED(result))
return NULL;
vertexShaderBuffer->Release();
pixelShaderBuffer->Release();
dxShader->Init();
mShaders.Add(dxShader);
return dxShader;
}

View file

@ -63,7 +63,7 @@ public:
ID3D11RenderTargetView* mD3DRenderTargetView;
ID3D11Texture2D* mD3DDepthBuffer;
ID3D11DepthStencilView* mD3DDepthStencilView;
ImageData* mImageData;
uint32* mContentBits;
public:
DXTexture();
@ -96,6 +96,10 @@ typedef std::map<String, DXShaderParam*> DXShaderParamMap;
class DXShader : public Shader
{
public:
DXRenderDevice* mRenderDevice;
String mSrcPath;
VertexDefinition* mVertexDef;
ID3D11InputLayout* mD3DLayout;
ID3D11VertexShader* mD3DVertexShader;
ID3D11PixelShader* mD3DPixelShader;
@ -107,6 +111,10 @@ public:
DXShader();
~DXShader();
void ReleaseNative();
void ReinitNative();
bool Load();
virtual ShaderParam* GetShaderParam(const StringImpl& name) override;
};
@ -144,6 +152,8 @@ public:
ID3D11RenderTargetView* mD3DRenderTargetView;
ID3D11Texture2D* mD3DDepthBuffer;
ID3D11DepthStencilView* mD3DDepthStencilView;
HANDLE mFrameWaitObject;
float mRefreshRate;
bool mResizePending;
bool mWindowed;
int mPendingWidth;
@ -164,6 +174,8 @@ public:
virtual void Present() override;
void CopyBitsTo(uint32* dest, int width, int height);
virtual float GetRefreshRate() override;
virtual bool WaitForVBlank() override;
};
typedef std::vector<DXDrawBatch*> DXDrawBatchVector;
@ -285,8 +297,9 @@ public:
ID3D11BlendState* mD3DNormalBlendState;
ID3D11SamplerState* mD3DDefaultSamplerState;
ID3D11SamplerState* mD3DWrapSamplerState;
bool mHasVSync;
bool mNeedsReinitNative;
ID3D11Buffer* mMatrix2DBuffer;
ID3D11Buffer* mD3DVertexBuffer;
ID3D11Buffer* mD3DIndexBuffer;
int mVtxByteIdx;
@ -294,6 +307,7 @@ public:
HashSet<DXRenderState*> mRenderStates;
HashSet<DXTexture*> mTextures;
HashSet<DXShader*> mShaders;
Dictionary<String, DXTexture*> mTextureMap;
Dictionary<int, ID3D11Buffer*> mBufferMap;

View file

@ -600,6 +600,9 @@ LRESULT WinBFWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
switch (uMsg)
{
case WM_DISPLAYCHANGE:
((DXRenderWindow*)mRenderWindow)->mRefreshRate = 0;
break;
case WM_SIZE:
mRenderWindow->Resized();
if (mMovedFunc != NULL)
@ -986,7 +989,6 @@ LRESULT WinBFWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
{
mIsMenuKeyHandled = false;
int keyCode = (int) wParam;
if (keyCode == VK_APPS)
@ -997,6 +999,11 @@ LRESULT WinBFWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
mIsKeyDown[keyCode] = true;
// if ((keyCode == 192) && (mIsKeyDown[VK_MENU]))
// {
// ((DXRenderDevice*)mRenderWindow->mRenderDevice)->mNeedsReinitNative = true;
// }
for (auto kv : *menuIDMap)
{
WinBFMenu* aMenu = kv.mValue;
@ -1275,10 +1282,71 @@ WinBFApp::WinBFApp()
mInMsgProc = false;
mDSoundManager = NULL;
mDInputManager = NULL;
mVSyncThreadId = 0;
mClosing = false;
mVSyncActive = false;
mVSyncThread = BfpThread_Create(VSyncThreadProcThunk, (void*)this, 128 * 1024, BfpThreadCreateFlag_StackSizeReserve, &mVSyncThreadId);
BfpThread_SetPriority(mVSyncThread, BfpThreadPriority_High, NULL);
}
void BFP_CALLTYPE WinBFApp::VSyncThreadProcThunk(void* ptr)
{
((WinBFApp*)ptr)->VSyncThreadProc();
}
void WinBFApp::VSyncThreadProc()
{
while (!mClosing)
{
bool didWait = false;
IDXGIOutput* output = NULL;
//
{
AutoCrit autoCrit(mCritSect);
if ((mRenderDevice != NULL) && (!mRenderDevice->mRenderWindowList.IsEmpty()))
{
auto renderWindow = (DXRenderWindow*)mRenderDevice->mRenderWindowList[0];
renderWindow->mDXSwapChain->GetContainingOutput(&output);
}
}
if (output != NULL)
{
DWORD start = GetTickCount();
bool success = output->WaitForVBlank() == 0;
int elapsed = (int)(GetTickCount() - start);
if (elapsed >= 20)
{
NOP;
}
if (success)
{
didWait = true;
mVSyncActive = true;
mVSyncEvent.Set();
}
output->Release();
}
if (!didWait)
{
mVSyncActive = false;
BfpThread_Sleep(20);
}
}
}
WinBFApp::~WinBFApp()
{
mClosing = true;
BfpThread_WaitFor(mVSyncThread, -1);
BfpThread_Release(mVSyncThread);
delete mRenderDevice;
delete mDSoundManager;
delete mDInputManager;
@ -1288,6 +1356,8 @@ void WinBFApp::Init()
{
BP_ZONE("WinBFApp::Init");
AutoCrit autoCrit(mCritSect);
mRunning = true;
mInMsgProc = false;
@ -1311,6 +1381,19 @@ void WinBFApp::Run()
}
}
void WinBFApp::Process()
{
BFApp::Process();
auto dxRenderDevice = (DXRenderDevice*)mRenderDevice;
if (dxRenderDevice->mNeedsReinitNative)
{
dxRenderDevice->mNeedsReinitNative = false;
dxRenderDevice->ReinitNative();
mForceNextDraw = true;
}
}
void WinBFApp::Draw()
{
mRenderDevice->FrameStart();
@ -1392,6 +1475,8 @@ void WinBFApp::GetWorkspaceRectFrom(int fromX, int fromY, int fromWidth, int fro
BFWindow* WinBFApp::CreateNewWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags)
{
AutoCrit autoCrit(mCritSect);
BFWindow* aWindow = new WinBFWindow(parent, title, x, y, width, height, windowFlags);
mWindowList.push_back(aWindow);
@ -2025,6 +2110,13 @@ BFSoundManager* WinBFApp::GetSoundManager()
return mDSoundManager;
}
intptr WinBFApp::GetCriticalThreadId(int idx)
{
if (idx == 0)
return mVSyncThreadId;
return 0;
}
void WinBFWindow::ModalsRemoved()
{
::EnableWindow(mHWnd, TRUE);

View file

@ -98,8 +98,14 @@ public:
StringToUIntMap mClipboardFormatMap;
DSoundManager* mDSoundManager;
DInputManager* mDInputManager;
BfpThreadId mVSyncThreadId;
BfpThread* mVSyncThread;
volatile bool mClosing;
protected:
void VSyncThreadProc();
static void BFP_CALLTYPE VSyncThreadProcThunk(void* ptr);
virtual void Draw() override;
virtual void PhysSetCursor() override;
@ -111,6 +117,7 @@ public:
virtual void Init() override;
virtual void Run() override;
virtual void Process() override;
virtual void GetDesktopResolution(int& width, int& height) override;
virtual void GetWorkspaceRect(int& x, int& y, int& width, int& height) override;
@ -129,6 +136,8 @@ public:
virtual BFSysBitmap* LoadSysBitmap(const WCHAR* fileName) override;
virtual BFSoundManager* GetSoundManager() override;
virtual intptr GetCriticalThreadId(int idx) override;
};
NS_BF_END;

View file

@ -11767,7 +11767,6 @@ namespace IDE
public override void Init()
{
scope AutoBeefPerf("IDEApp.Init");
//int zag = 123;
if (mVerbosity == .Default)
@ -14203,7 +14202,7 @@ namespace IDE
//mDebugger.InitiateHotResolve(.ActiveMethods | .Allocations);
}
public override void Draw()
public override void Draw(bool forceDraw)
{
scope AutoBeefPerf("IDEApp.Draw");
#if CLI
@ -14213,7 +14212,7 @@ namespace IDE
if (mBfResolveSystem != null)
{
mBfResolveSystem.PerfZoneStart("IDEApp.Draw");
base.Draw();
base.Draw(forceDraw);
mBfResolveSystem.PerfZoneEnd();
if (mBfResolveSystem.mIsTiming)
{
@ -14222,7 +14221,7 @@ namespace IDE
}
}
else
base.Draw();
base.Draw(forceDraw);
}
public void DrawSquiggle(Graphics g, float x, float y, float width)

View file

@ -3,11 +3,15 @@ using Beefy.gfx;
using System;
using Beefy.events;
using Beefy.widgets;
using System.Collections;
using System.Diagnostics;
namespace IDE.ui
{
class AboutDialog : IDEDialog
{
static AboutDialog gAboutDialog;
const int cWidth = 320;
const int cHeight = 240;
const int cRandSize = 3777;
@ -21,6 +25,14 @@ namespace IDE.ui
uint8[cRandSize] mRand;
int mRandIdx;
Stopwatch mStopwatch = new .()..Start() ~ delete _;
struct Entry
{
public double mUpdateCntF;
public float mTimeMS;
}
List<Entry> mEntries = new .() ~ delete _;
struct CColor
{
public uint8 r;
@ -70,6 +82,22 @@ namespace IDE.ui
Color colorOut = Color.ToNative(Color.Lerp(mainColors[(int)colorPos], mainColors[(int)colorPos + 1], colorPos - (int)colorPos));
mPalette[i] = colorOut;
}
/*mWindowFlags |= .Resizable;
mWindowFlags &= ~.Modal;*/
gAboutDialog = this;
}
~this()
{
gAboutDialog = null;
}
public override void AddedToParent()
{
base.AddedToParent();
mWidgetWindow.mWantsUpdateF = true;
}
public override void CalcSize()
@ -140,12 +168,12 @@ namespace IDE.ui
mImage.SetBits(0, 0, cWidth, cHeight, cWidth, newBits);
float ang = Math.Min(mUpdateCnt * 0.006f, Math.PI_f / 2);
float ang = Math.Min((float)(mUpdateCntF * 0.006f), Math.PI_f / 2);
g.SetFont(mBigFont);
g.DrawString("Beef IDE", 0, GS!(20) + (1.0f - Math.Sin(ang))*GS!(300), .Centered, mWidth);
float angMed = Math.Min(mUpdateCnt * 0.0055f, Math.PI_f / 2);
float alpha = Math.Clamp(mUpdateCnt * 0.007f - 1.3f, 0, 1.0f);
float angMed = Math.Min((float)(mUpdateCntF * 0.0055f), Math.PI_f / 2);
float alpha = Math.Clamp((float)(mUpdateCntF * 0.007f) - 1.3f, 0, 1.0f);
using (g.PushColor(Color.Get(alpha)))
{
@ -164,6 +192,33 @@ namespace IDE.ui
}
g.DrawQuad(mImage, 0, 0, 0.0f, 0.0f, mWidth, mHeight, 1.0f, 1.0f);
/*if (gAboutDialog == this)
{
/*Entry entry;
entry.mTimeMS = mStopwatch.ElapsedMicroseconds / 1000.0f;
entry.mUpdateCntF = mUpdateCntF;*/
mEntries.Add(Entry() {mTimeMS = mStopwatch.ElapsedMicroseconds / 1000.0f, mUpdateCntF = mUpdateCntF});
if (mEntries.Count == 100)
{
float prevTime = 0;
for (var entry in mEntries)
{
Debug.WriteLine($"Entry Time:{entry.mTimeMS - prevTime:0.00} UpdateCntF:{entry.mUpdateCntF:0.00}");
prevTime = entry.mTimeMS;
if (@entry.Index == 20)
break;
}
mEntries.Clear();
}
}
using (g.PushColor(0xFFFFFFFF))
g.FillRect(Math.Cos((float)(mUpdateCntF * 0.2f)) * 600 + mWidth / 2, 0, 8, mHeight);*/
}
public override void Update()
@ -177,6 +232,12 @@ namespace IDE.ui
DoFire();
}
public override void UpdateF(float updatePct)
{
base.UpdateF(updatePct);
MarkDirty();
}
public override void KeyDown(KeyCode keyCode, bool isRepeat)
{
base.KeyDown(keyCode, isRepeat);

View file

@ -6508,7 +6508,7 @@ namespace IDE.ui
}
}
public void UpdateCollapse()
public void UpdateCollapse(float updatePct)
{
MarkDirty();
@ -6564,9 +6564,12 @@ namespace IDE.ui
{
if (emitEmbed.mIsOpen)
{
emitEmbed.mOpenPct = Math.Min(1.0f, emitEmbed.mOpenPct + 0.1f);
emitEmbed.mOpenPct = Math.Min(1.0f, emitEmbed.mOpenPct + 0.1f * updatePct);
if (emitEmbed.mOpenPct != 1.0f)
{
mCollapseNeedsUpdate = true;
mWidgetWindow.mTempWantsUpdateF = true;
}
if (emitEmbed.mView == null)
{
@ -6577,7 +6580,7 @@ namespace IDE.ui
}
else
{
emitEmbed.mOpenPct = Math.Max(0.0f, emitEmbed.mOpenPct - 0.1f);
emitEmbed.mOpenPct = Math.Max(0.0f, emitEmbed.mOpenPct - 0.1f * updatePct);
if (emitEmbed.mOpenPct == 0.0f)
{
if (emitEmbed.mView != null)
@ -6587,7 +6590,10 @@ namespace IDE.ui
}
}
else
{
mCollapseNeedsUpdate = true;
mWidgetWindow.mTempWantsUpdateF = true;
}
}
}
}
@ -6664,13 +6670,14 @@ namespace IDE.ui
var entry = mOrderedCollapseEntries[animIdx];
if ((entry.mIsOpen) && (entry.mOpenPct < 1.0f))
{
entry.mOpenPct = Math.Min(entry.mOpenPct + animSpeed, 1.0f);
entry.mOpenPct = Math.Min(entry.mOpenPct + animSpeed * updatePct, 1.0f);
mWidgetWindow.mTempWantsUpdateF = true;
}
if ((!entry.mIsOpen) && (entry.mOpenPct > 0))
{
entry.mOpenPct = Math.Max(entry.mOpenPct - animSpeed, 0.0f);
entry.mOpenPct = Math.Max(entry.mOpenPct - animSpeed * updatePct, 0.0f);
mWidgetWindow.mTempWantsUpdateF = true;
if (entry.mOpenPct == 0.0f)
FinishCollapseClose(animIdx, entry);
}

View file

@ -639,6 +639,7 @@ namespace IDE.ui
mNavigationBar = new NavigationBar(this);
AddWidget(mNavigationBar);
}
mAlwaysUpdateF = true;
}
public ~this()
{
@ -6811,13 +6812,19 @@ namespace IDE.ui
UpdateQueuedEmitShowData();
if (ewc.mCollapseNeedsUpdate)
ewc.UpdateCollapse();
// Process after mQueuedCollapseData so mCharIdSpan is still valid
ProcessDeferredResolveResults(0);
}
public override void UpdateF(float updatePct)
{
base.UpdateF(updatePct);
var ewc = (SourceEditWidgetContent)mEditWidget.Content;
if (ewc.mCollapseNeedsUpdate)
ewc.UpdateCollapse(updatePct);
}
public void UpdateQueuedEmitShowData()
{
var compiler = ResolveCompiler;